I recently sent a request for help because ReadFile
kept crashing for me. The moderator sent me some code
which cured my problem. My next step was to
experiment to see what I had originally done wrong.
(For further info see ReadFile crashes by toolmanx.)

I started by replacing each item back to the way I
had originally written it to make sure dwRead was my
only problem since the moderator's code made several
code changes to mine. dwRead was my only problem. I
initialized with several different int values
finally even using my original "0". It still worked.

The only change that caused failure was using LPDWORD
as written in Win32.HLP instead of plain DWORD. That
apparently was my mistake. I copied Win32.HLP
verbatum. My understanding, correct me if I'm wrong,
is, LPDWORD indicates to the compiler that dwRead is
a pointer, not just a variable.

The moderator had also added an "&" in front of
dwRead in the function. This tells me that I am asking
for the address of dwRead, not what is in the location of
dwRead. That made sense to me and was reinforced
because BCC32 would error if I sent a pointer in
the function without the ampersand.

My next step was to try to find out why LPDWORD wouldn't
work. The compiler would not accept
"LPDWORD dwRead = 0;" or "LPDWORD dwRead = 16;"
I was trying to put an int into a DWORD pointer. So
I tried a cast (DWORD*)16;(16 is the number of bytes in
my file I'm reading). The compiler accepted that
and gave me an exe. The exe crashes just like in the
old days.

I've read a lot of pointer tutorials but
I'm missing something here. Also, why I couldn't use
ReadFile as written in Win32.HLP bothers me too. Is
this a problem in more than one API? I'll be experimenting
using many other API's in the future as part of my
learning process. Do I have to watch out for this
every time I try to use a new API? Obviously I need
to understand what is happening when using LPDWORD
otherwise I'll be blindly trying DWORD in place of
LPDWORD everytime I get a failure on new functions.

Lastly so I don't force a moderator to write a
long and tedious explanation, let me note what
I think I know about pointers. Pointers point to
an address in memory. When the API uses LPDWORD,
it wants a pointer. Since dwRead works only using
DWORd, that tells me that it wants a variable, at
least that's what works. Why does the API make it
look like it wants a pointer when a variable is
what it wants?

>For further info see ReadFile crashes by toolmanx.

I'm sorry but I've no time nor inclination to go hunting for some previous post/thread of yours - could you please provide a link if you want to provide more context?

>Also, why I couldn't use ReadFile as written in Win32.HLP bothers me too

You can; and it works exactly as written. But the documentation is written with the assumption that you are quite familiar and comfortable with the fundamentals. LPDWORD is just a pointer to a DWORD. Since you're specifically after the value that will be stored in the memory pointed to by that LPDWORD it needs to actually point to some meaningful, writable part of memory to be usable by your program. Simply declaring a DWORD* or or its LPDWORD alias and using it directly is not enough - that's why you declare a DWORD variable and pass a reference to it.

>So I tried a cast...compiler accepted...exe crashes

Of course it does: you tell the compiler to STFU and it does and naturally the exe crashes because the compiler was trying to tell you not to try and force it do what you forced it to do.

>(DWORD*)16;(16 is the number of bytes in my file I'm reading)

That's not good at all: you just asked your program to start writing at memory address 16. God only knows what normally resides there but it's not going to be happy when your 16 bytes of data attempt to usurp it from its rightful position in memory.

ReadFile wants a DWORD address because it's going to write some information there, specifically the number of bytes read by its read operation. When you pass the value of a DWORD and force the compiler to accept it by casting away your last chance to fix it, you're telling ReadFile that value is actually an address in memory that it can write to, with the disastrous results you've seen. Consider:

#include <windows.h>
#include <tchar.h>

int main()
{
 static const int STR_LEN = 1024;
TCHAR buff[STR_LEN];

DWORD dwRead = 0; //initialise DWORD variable to value of zero

wsprintf(buff,_T("The value of dwRead is: %d\nThe address of dwRead is: %d"),
         dwRead,&dwRead);
         
MessageBox(0,buff,_T("Variable value and variable address are different"),
           MB_OK);
}

If you pass the value of dwRead (set to zero in this example) to ReadFile then that api function will attempt to write to the memory address starting at zero and will crash.

So declare the required variable (ie allocate storage) and pass a reference to that to ReadFile as, presumably, has already been suggested. If you absolutely must use a DWORD pointer directly then you'll have to allocate memory for it, eg(assumes c++, for c use malloc/free):

DWORD *pRead; /*same as LPDWORD lp just means long pointer*/
pRead = new DWORD;
ReadFile(..,pRead,..);
delete pRead;
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.