Problems writing to a stream

Nov 2, 2010 at 4:31pm
Hi all,

I'm back again with more i/o issues! Everything I read suggests that this should work, but I said that last time and the answer was relatively simple, hopefully this goes the same way!

Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
                 	LPVOID lpData = NULL;
                        LPSTREAM lpAttachStream;

for(int i = 6; (i < text_file.size()); i++)
			{
				ULONG ulAttachNum = 0;
				LPSTREAM lpAttachStream;

				hr = lpMessage->CreateAttach(NULL, 0, &ulAttachNum, &attachment);
				if (FAILED(hr))
					break;

				hr =   lpMessage->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY, (LPUNKNOWN *)&lpAttachStream);
				CreateStreamOnHGlobal(NULL, TRUE, &lpAttachStream);
                                HANDLE hFile = CreateFile(text_file[i].c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0,NULL);
				
		   	
	
			// Free the buffer.
			// LocalFree( lpMsgBuf );

				if ( hFile != INVALID_HANDLE_VALUE) 
				{
					 //alocate memory on global
					nBytes = GetFileSize( hFile, NULL);
					if ( ( hMem = GlobalAlloc( GMEM_MOVEABLE, nBytes)) != NULL) 
					{
						//read file content in global allocated mem
						if ( ( lpData = GlobalLock( hMem)) != NULL) 
						{
							ReadFile( hFile, lpData, nBytes, &nBytes, NULL);
							GlobalUnlock( hMem);
						}
					}
					::CloseHandle( hFile);
				}
				
				ULONG ulBytesWritten = 0;
				ULONG ulSize = 0;

				// Write the body to the stream
				hr = lpAttachStream->Write((const void*)lpData, (ULONG)&ulSize, (ULONG*)&ulBytesWritten);

// Commit the stream
				hr = lpAttachStream->Commit(NULL);
	
				if (FAILED(hr))
				{
					MessageBox(NULL,"Unable to commit stream",NULL,MB_OK);
		
				}

				// Release the memory
				hr = lpAttachStream->Release();
	
				// free global alocated memory
				if ( hMem) 
					GlobalFree( hMem);
	
				if (FAILED(hr))
				{
					MessageBox(NULL,"Unable to release memory",NULL,MB_OK);
					// goto cleanup;
				}

				// Save the changes to the message
				lpMessage->SaveChanges(KEEP_OPEN_READWRITE);


The problem is with the last line. I just get access violation, which suggest I have an issue with my streams but I can't figure it out. Everything previous to that statement, appears to go ok during debugging, its just this one line.

Any thoughts?

Thanks in advance,

Darren
Last edited on Nov 2, 2010 at 7:23pm
Nov 2, 2010 at 4:45pm
Hi Darren,

I don't see where you initialize lpAttachStream, which is a huge problem as you can imagine.

I don't see a definition for hFile, nBytes, or hMem (but you may have left them out of your post.)

Also, if hFile does equal INVALID_HANDLE_VALUE, lpData will never be initialized, causing another huge problem occuring on the last line.

I hope that helps!

Kooth
Nov 2, 2010 at 6:46pm
Hi Kooth,

Thanks very much for your response. The code is quite large, which is the main reason why I did not paste it all in, however I am happy to if it helps. Otherwise, here is some answers to your questions.

lpAttachStream, is an LPSTREAM, its defined at the top of the code I pasted in (LPSTREAM lpAttachStream;). hFile is also defined in the code as a handle ( HANDLE hFile = CreateFile(text_file[i].c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0,NULL); ).

nBytes is a DWORD, its defined at the top. hMem also defined at the top is HGLOBAL.

I checked the return code by doing GetLastError() and its returning fine, saying successful. Whether lpData has the correct data in it, I have no idea as I don't know enough about streams to know if that is right.

Is my code for the write() routine ok? The interface that the write is being performed on is LPSTREAM, I checked the syntax, and it should be (const void *pv, ULONG cb, ULONG *pcbWritten). Is this a problem with the lpData portion, am I not casting it correctly etc?

THanks for your help!

Darren
Nov 2, 2010 at 7:01pm
Thanks for your update. You still need to initialize lpAttachStream: It is pointing nowhere and that is causing your access violation.
Nov 2, 2010 at 7:22pm
Hi Kooth,

The following code initializes lpAttachStream:

hr = lpMessage->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY, (LPUNKNOWN *)&lpAttachStream);

I'm going to edit the first post and put the entire loop in so it makes it more readable.

Nov 2, 2010 at 8:05pm
That helps alot! My guess is you should do some more error checking (like the return from OpenProperty() for example), as this might point to the error.
Nov 2, 2010 at 8:41pm
Hi Kooth,

Right now, I'm running everything through Debug and watching the return codes. For all of hte code except the last function's, the return codes are S_OK. I do need to add error checking, and will add it after I get the code right.

So from that I think I can assume the functions are working right? Or do I need some different error checking going on?
Nov 3, 2010 at 9:32am
I think I found the issue. For some reason I was thinking that the ulSize parameter was an OUT, that was given to me after the stream was written. It is in fact an input.

Write((const void*)lpData, (ULONG)&ulSize, (ULONG*)&ulBytesWritten);

I have done a sizeof(lpData) but its still bombing on that line. lpData is an LPVOID that contains a stream of bytes read from a file. I'm wondering how I get the size of the stream? Here is the parameter from MSDN:

"The number of bytes of data to attempt to write into the stream. This value can be zero."

Any help please?

Darren
Nov 3, 2010 at 9:50am
The problem was the function CreateStreamOnHGlobal it was completely unneccesary! Thanks for all your help :)
Topic archived. No new replies allowed.