overlapped io is not in signalled state

xxxxx@flounder.com wrote:

OVERLAPPED ov = {0};

Using memset is so 1975ish. Use ::ZeroMemory.

:wink:

Of course ZeroMemory is a macro defined as RtlZeroMemory, which is in
turn a macro defined as memset, but I agree that the spelling is more
appropriate…

–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Yes, I knew that, but the ways in which we speak determines how we think.
And if the goal is tp zero memory, why do something as complex as memset,
when what is desired is to zero memory? Beter still, if you can do
sonething that causes the compiler to generate the code inline, why not
take advantage of the syntactic conciseness and efficiency?

It has been said that C is a language that gives you the power of
programming in assembly code with all the syntactic elegance of
programming in assembly code.

joe

xxxxx@flounder.com wrote:
> OVERLAPPED ov = {0};
>
> Using memset is so 1975ish. Use ::ZeroMemory.

:wink:

Of course ZeroMemory is a macro defined as RtlZeroMemory, which is in
turn a macro defined as memset, but I agree that the spelling is more
appropriate…

–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I guess that the meset is not the only 1975ish artifact you have in the code
.

OVERLAPPED ov;
OVERLAPPED ov = { 0 };

memset(&ov, 0, sizeof(OVERLAPPED));

delete the above line

ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ov->hEvent == NULL)
{
unsigned int code = GetLastError();

RTFM! The documentation CLEARLY states that the return type of
GetLastError is a DWORD!!! So why in the world would you declare an
ā€˜unsigned int’ variable to hold it? What strange power entitles you to
use bae implementation types i stead of the specified result type?

char errmsg[256];

char is a nearly dead type left over from the 1960s. The correct type to
use would be TCHAR or WCHAR.

GetErrorMessage(code, errmsg, sizeof(errmsg));

The correct call would be
GetErrorMessage(code, errmsg, _countof(errmsg));

SET_LAST_ERROR_STRING(ā€œCreateEvent failed, error: 0x%x, error
string: %sā€, code, errmsg);

There’s something seriously wrong here. Could it be that the ā€œLast error
messageā€ variable is a GLOBAL variable? This isn’t a PDP-11; it is
Microsoft Windows, which means you should never use global variables to
pass back results! That is, if you have a global variable called
char LastErrorString[256];
then I would state that the code is a completely unmaintainable pile
of…well anyway, it’s damned poor code.

If the declaration is
__declspec(thread) chat LastErrorString[MAX_ERROR_STRING];

return false;
}

success = WriteFile(g_hDriver, data, sizeToWrite, (PULONG)
sizeWritten, &ov);

And where, prsy tell, is the declaration of sizeWriiten? And why are you
casting it to a PULONG? RTFM!!! The documentation CLEARLY states that
this should be an LPDWORD, or, more properly, a PDWORD. So what led you
to cast it as a PULONG? And why are you casting it? If you need a cast
to make it compile, then your code is already broken. The correct code
would be
DWORD sizeWritten;
…
WriteFile(driver, data, sizeToWrite, &sizeWritten, &ov);

since you neglected showing the declaration of the variable, it is hard to
guess what you wrote.

And why in the world would the driver handle be a global? This looks like
1975 PDP-11 code. Have you heard of ā€œparametersā€? Are you aware that
passing scalar parameters is so close to free as to be largely unworthy of
debate?

if(success == 0)
{
unsigned int err = GetLastError();

Same comment as above. Why write a different type than the documentation
specifies?

if(err != ERROR_IO_PENDING)
{
return false;
}
}

while(0 == GetOverlappedResult(g_hDriver, ov, bytesReturned, FALSE))

All this says is to poll, thus consuming all available CPU cycles, until
GetOverlappedResult sucessfully reurns. But why poll? Why not make the
last parameter TRUE? RTFM! It clearly states that this operation returns
a BOOL, and of the many totally silly idioms I find in programming,
comparing a BOOL to a literal value to get, let’s see, a BOOL, is among
the silliest. It’s already a BOOL, so you don’t need to compare it to
anything!

But why poll at all? Just call it; if it returns TRUE then the I/O has
complete, and if FALSE, something is seriously wrong.

{

code = GetLastError();
if(code != ERROR_IO_INCOMPLETE)
{
//error
GetErrorMessage(code,errmsg, sizeof(errmsg));
SET_LAST_ERROR_STRING(ā€œGetOverlappedResult failed. error:
0x%x, error string: %s,Bytes returned %xā€, code,
errmsg,*bytesReturned);

return false;
}

If you want a timeout, do a WaitForSingleObject on the ov.hEvent handle
and give a timeout. If the return value of WFSO is WAIT_TIMEOUT, you deal
with your timeout, otherwise, it will be WAIT_OBJECT_0. Rolling your own
timeout by polling makes no sense.

if(GetTickCount() > endtime)
{
if(CancelIo(g_hDriver) == 0)
{
code = GetLastError();
GetErrorMessage(code, errmsg, sizeof(errmsg));
SET_LAST_ERROR_STRING(ā€œCancelIO failed. error: 0x%x,
error
string: %sā€, code, errmsg);
return false;
}
SET_LAST_ERROR_STRING(ā€œTimed out waiting for asynchronous IO
to finishā€);
return false;
}
Every one of those return statements (except the one where CreateEvent
fails) leak an event object.
Note that if there is no error, you still have a handle leak!

The correct methodology is shown below:
***************************************************
/*
THIS CODE IS SUPPLIED ā€˜AS IS’. THE AUTHOR OF THIS CODE PROVIDES THIS
FOR REFERENCE AND DESCRIPTIVE PURPOSES ONLY. USERS OF THIS CODE ARE
RESPONSIBLE FOR VERIFYING THAT IT IS SUITABLE [Standard industry
disclaimers included by reference]
*/
BOOL WriteToMyDevice(HANDLE device, LPVOID data, DWORD count)
{
OVERLAPPED ov = { 0 };
ov.hEvent = CreateEvent(…); //… means I’m not going to retype the
obvious
if(ov.hEvent == NULL)
{
… deal with error
return FALSE;
}
else
{
BOOL result = InnerWrite(handle, data, count, &ov);
CloseHandle(ov.hEvent);
return result;
} // WriteToMyDevice

BOOL InnerWrite(HANDLE device, LPVOID data, DWORD count, LPOVERLAPPED ov)
{
DWORD sizeWritten;
if(! WriteFile(device, data, count, &sizeWritten, ov)
{ /* WriteFile failed */
if(GetLastError() != ERROR_IO_PENDING)
{ /* Bad failure */
… deal with error
return FALSE;
} /* Bad failure */
else
{ /* I/O pending */
switch(WaitForSingleObject, ov->hEvent, MY_DEVICE_TIMEOUT)
{ /* WFSO */
case WAIT_OBJECT_0:
{ /* device complete */
If( ! GetOverlappedResult(device, ov,
&sizeWritten, TRUE))
{ /* GOR failed */
… deal with error
return FALSE;
} /* GOR failed */

return TRUE;
} /* device complete */
case WAIT_TIMEOUT:
… deal with timeout
return FALSE;
default:
… deal with WFSO failure
return FALSE;
} /* WFSO */
} /* I/O pending */
} /* WriteFile failed */
return TRUE;
} //InnerWrite;

Notes on why this code is better:
The two-tiered approach makes it impossible to leak handles
No global handle variable is required
No polling is done to check for completion; thread blocks until
completion
Data types are correct
No explicit zeroing of the OVERLAPPED structure is required
No ugly goto statements are required to avoid event handle leaks
Code is easier to understand

Things left as An Exercise For The Reader:
Eliminate any global variables, such as error message buffers
Write using 2012, not 1975, character set
If number of bytes written is required by caller, add LPDWORD/PDWORD
parameter to both functions and use this instead of the local
variable address, &sizeWritten
If an error buffer is used, pass in a pointer to a TCHAR, DWORD pair
(that is, a struct) that is the buffer. Better still, write in C++
and use ATL::CString or std::string reference parameter to the error
buffer, where this string is a local variable for the caller.
*********************************************************************************

}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Note that for most drivers, what happens after you complete the IRP should
be of no interest whatsoever to you. None. Zero. Zip. Zilch. It is
the role of the I/O Manager to mediate between the application and your
driver, and I cannot imagine a reason for caring if its action is to mark
a suspended thread to run, set an event, queue up an APC, or post an event
to an I/O Completion port. This should be as totally uninteresting to you
as the details of your ISR are to your application programmers.

If you are a lower-level driver in a stack, what happens when you complete
the IRP is ENTIRELY the responsibilit of the driver that called you. It
might pass the IRP down again, or complete a pending IRP it was holding,
or dance a polka, and YOU DON’T CARE!

Also, completion routines are a concept completely internal to the
implementation of your driver, and from your viewpoint have precisely
NOTHING to do with the API interface, which is where the event in the
OVERLAPPED structure comes into play. This will not be set until the IRP
is returned to the I/O Manager, so if you have an IRP that is sent
downward multiple times before its completion routine returns
STATUS_SUCCESS and lets the IRP float upward, all the way back to the I/O
Manager, the OVERLAPPED.hEvent doesn’t even enter the dicussion. The I/O
Manager could care less about what you are doing to that IRP. The first
stack location has (and I think it is implemented this way) a function in
the I/O Manager set as the completion routine, so until that stack fully
unwinds and the IRP floats up to the I/O Manager, none of the API
artifacts, such as OVERLAPPED.hEvent, Byte counts, return values for
GetLastError(), etc. are relevant.

It’s called ā€œabstractionā€ and it’s a pretty powerful tool.
joe

The request will always be in my driver. I use the request to call
WdfRequestSend call. For which I have a iocompletion routine. So only when
the WdfRequestCompleteWithInformation call is made then the event is set
?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> I am sorry to put it that way. Yes, the implementation is as u specified

above. WdfRequestSend returns immediately. If the completion routine is
not called immediately, the control returns to user mode. I call
getoverlappedresult method and wait for either timeout / event completion
like below

while(0 == GetOverlappedResult(g_hDriver, ov, bytesReturned, FALSE))
{
code = GetLastError();
if(code != ERROR_IO_INCOMPLETE)
{
//error
GetErrorMessage(code,errmsg, sizeof(errmsg));
SET_LAST_ERROR_STRING(ā€œGetOverlappedResult failed. error:
0x%x,
error string: %s,Bytes returned %xā€, code, errmsg,*bytesReturned);

return false;
}

if(GetTickCount() > endtime)
{
if(CancelIo(g_hDriver) == 0)
{
code = GetLastError();
GetErrorMessage(code, errmsg, sizeof(errmsg));
SET_LAST_ERROR_STRING(ā€œCancelIO failed. error: 0x%x, error
string: %sā€, code, errmsg);
return false;
}
SET_LAST_ERROR_STRING(ā€œTimed out waiting for asynchronous IO
to
finishā€);
return false;
}
}

But the problem is the first time I am calling getoverlappedresult, the
result is 0 with error code overlapped io is not in signalled state.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Note that I already pointed out the numerous deficiencies in this code.
Rewrite it, and report if there are further problems.
joe

Hi,

Thanks for the support. I have modified the code. But here is the additional data.

  1. WdfRequestSend is sent with options set to WDF_REQUEST_SEND_OPTION_TIMEOUT with a timeout of 10 seconds.
  2. The EvtReqCompletion routine attached to the request gets called before 10 sec. WdfRequestCompleteWithInformation is sent with status as 0.
  3. I am using SourceUSB to capture the usb packets. The capture log shows the transaction has succeded.
  4. But the GetOverlappedResult always returns 997 as the error code. Is there something wrong with the way I am sending the request completion routine. Even though the errro code is 997 the function is returning the number of bytes written as correct value.

now the code looks like this

success = WriteFile(g_hDriver, data, sizeToWrite, (PULONG) sizeWritten, &ov);

if(success == 0)
{
unsigned int err = GetLastError();
if(err != ERROR_IO_PENDING)
{
return false;
}
}

if (!GetOverlappedResult(g_hDriver, ov, bytesReturned, TRUE))
{
if(CancelIo(g_hDriver) == 0)
{
code = GetLastError();
GetErrorMessage(code, errmsg, sizeof(errmsg));
SET_LAST_ERROR_STRING(ā€œCancelIO failed. error: 0x%x, error string: %sā€, code, rmsg);

GetOverlappedResult(g_hDriver, ov, bytesReturned, TRUE);
}
}

//success = WriteFile(g_hDriver, data, sizeToWrite, (PULONG) sizeWritten, &ov);

This MUST BE:

DWORD sizeWritten;
success = WriteFile(g_hDriver, data, sizeToWrite, &sizeWritten, &ov);

DON’T USE CASTS IF YOU DON’T UNDERSTAND WHY THE CODE DOES NOT COMPILE.

Also, use the same variable for written size in WriteFile and GetOverlappedResult.

997 IS ERROR_IO_PENDING. WHAT ELSE DO YOU EXPECT IF AN IO HAVE NOT COMPLETED YET?

Thanks for pointing out the wrong casting.
But as I mentioned previously, the request has got completed. EvtReqCompletion completion routine will only be called on event success / failure / timeout right? If anyone of these things happen and WdfRequestCompleteWithInformation is filled before returning from the function that means the IO is services right? Correct me if I am wrong. As mentioned the USB logs have shown that the transaction has got completed. (IN transfer as successful)

You need to fix the rest of the bugs in this code.

  • S (Msft)

From: xxxxx@gmail.com
Sent: 7/26/2012 3:35
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] overlapped io is not in signalled state

Hi,

Thanks for the support. I have modified the code. But here is the additional data.

  1. WdfRequestSend is sent with options set to WDF_REQUEST_SEND_OPTION_TIMEOUT with a timeout of 10 seconds.
  2. The EvtReqCompletion routine attached to the request gets called before 10 sec. WdfRequestCompleteWithInformation is sent with status as 0.
  3. I am using SourceUSB to capture the usb packets. The capture log shows the transaction has succeded.
  4. But the GetOverlappedResult always returns 997 as the error code. Is there something wrong with the way I am sending the request completion routine. Even though the errro code is 997 the function is returning the number of bytes written as correct value.

now the code looks like this

success = WriteFile(g_hDriver, data, sizeToWrite, (PULONG) sizeWritten, &ov);

if(success == 0)
{
unsigned int err = GetLastError();
if(err != ERROR_IO_PENDING)
{
return false;
}
}

if (!GetOverlappedResult(g_hDriver, ov, bytesReturned, TRUE))
{
if(CancelIo(g_hDriver) == 0)
{
code = GetLastError();
GetErrorMessage(code, errmsg, sizeof(errmsg));
SET_LAST_ERROR_STRING(ā€œCancelIO failed. error: 0x%x, error string: %sā€, code, rmsg);

GetOverlappedResult(g_hDriver, ov, bytesReturned, TRUE);
}
}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

xxxxx@gmail.com wrote:

  1. But the GetOverlappedResult always returns 997 as the error code.

Why do you think that? You never check this. The code you have posted
does not call GetLastError if GetOverlappedResult returns an error.
Instead, you immediately call CancelIo, which causes you to lose the
error value from GetOverlappedResult. (And, by the way, the CancelIo
call is unnecessary.)

GetOverlappedResult will NEVER return 997 (ERROR_IO_PENDING) when its
last parameter is TRUE. Your statement above is false.

Can you PLEASE copy and paste your EXACT code instead of retyping it?
We KNOW the code you are posting is not real, because that code will not
compile. For example, the second and third parameters to
GetOverlappedResult must have ā€œ&ā€, and you don’t have them.

–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

You are confusing an internal driver concept from WDF, called a ā€œeventā€ in
WDF-speak, with a user API-level object called an ā€œEventā€. To the best of
my knowledge, the only things these two concepts share are the letter
sequence E-V-E-N-T.
joe

Thanks for pointing out the wrong casting.
But as I mentioned previously, the request has got completed.
EvtReqCompletion completion routine will only be called on event success /
failure / timeout right? If anyone of these things happen and
WdfRequestCompleteWithInformation is filled before returning from the
function that means the IO is services right? Correct me if I am wrong. As
mentioned the USB logs have shown that the transaction has got completed.
(IN transfer as successful)


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> You need to fix the rest of the bugs in this code.

  • S (Msft)

From: xxxxx@gmail.com
Sent: 7/26/2012 3:35
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] overlapped io is not in signalled state

Hi,

Thanks for the support. I have modified the code. But here is the
additional data.

  1. WdfRequestSend is sent with options set to
    WDF_REQUEST_SEND_OPTION_TIMEOUT with a timeout of 10 seconds.
  2. The EvtReqCompletion routine attached to the request gets called
    before
    10 sec. WdfRequestCompleteWithInformation is sent with status as 0. 3. I
    am using SourceUSB to capture the usb packets. The capture log
    shows
    the transaction has succeded.
  3. But the GetOverlappedResult always returns 997 as the error code. Is
    there something wrong with the way I am sending the request completion
    routine. Even though the errro code is 997 the function is returning the
    number of bytes written as correct value.

now the code looks like this

success = WriteFile(g_hDriver, data, sizeToWrite, (PULONG) sizeWritten,
&ov);

As I pointed out in another context, WriteFile is a BOOL-returning
function, so it is completely silly to compare a BOOL value to a literal
to get a BOOL value. What is the type of ā€˜success’? If it is not BOOL,
your code is wrnong. If it is BOOL, you don’t compare it to anything,
since it is already the correct type. As I also pointed out, the PULONG
cast is erroneous as written, and if a cast is required for correct
compilation then you code is already broken. Gratuitous casts like this
have a 99.9999999% chance of being unnecessay. Casting is something that
is done only with careful forethought; if you start sprinkling them around
like pixie dust, you’re going to create more than one fatal error. For
example, when an operation like WriteFile fails for error code (if I
remember crrectly) 998, invald adress parameter, it means the I/O
operation was never started, so waiting for it to complete is pointless,
because it never even got to your driver! Gratuitous casts can cause
problems like this, which we could see if you showed us the declaration of
the variable!

if(success == 0)
{
unsigned int err = GetLastError();

DWORD err;

if(err != ERROR_IO_PENDING)
{
return false;
}
}

if (!GetOverlappedResult(g_hDriver, ov, bytesReturned, TRUE)) {
if(CancelIo(g_hDriver) == 0)

CacelIo is also BOOL. What is the problem in the concept that a BOOL is
already a BOOL and does not need to be compared to anything to get a BOOL?

and why do you presume a FALSE value from GetOverlappedResult means the
I/O needs to be canceled? For that matter, why are you canceling all I/O
for this handle in this thread? Te IRP could have been completed with
STATUS_DEVICE_IS_ON_FIRE, and that means the I/O does not need to be
canceled, because it has already completed. So you end up cancelling all
remaining operations on this handle for this thread, which may not be at
all what was intended.

{
code = GetLastError();
GetErrorMessage(code, errmsg, sizeof(errmsg));
SET_LAST_ERROR_STRING(ā€œCancelIO failed. error: 0x%x,
error
string: %sā€, code, rmsg);

GetOverlappedResult(g_hDriver, ov, bytesReturned, TRUE);

So why are you calling it again, and not testing the result? True, you
have to wait for the CancelIo, but what if there was more than one I/O
pending? And why do you use ā€˜ov’ when it has to be ā€˜&ov’? Is there a
difference bewteen sizeWritten and bytesReturned, and if so, what is it?
And you don’t show the declarations of these variables, so how are we
expected to understand the code? NEVER show a code sample unless you show
us the declarations of every variable and tell us the scope (e.g., global,
class member, static class member, local, static local, parameter…)

I would never attempt to debug a driver with an application that is so
wrong. You have to first write a correct application before you start
worrying about how your driver is interacting with it.
joe

}
}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

> xxxxx@gmail.com wrote:

> 3. But the GetOverlappedResult always returns 997 as the error code.

Why do you think that? You never check this. The code you have posted
does not call GetLastError if GetOverlappedResult returns an error.
Instead, you immediately call CancelIo, which causes you to lose the
error value from GetOverlappedResult. (And, by the way, the CancelIo
call is unnecessary.)

GetOverlappedResult will NEVER return 997 (ERROR_IO_PENDING) when its
last parameter is TRUE. Your statement above is false.

Can you PLEASE copy and paste your EXACT code instead of retyping it?
We KNOW the code you are posting is not real, because that code will not
compile. For example, the second and third parameters to
GetOverlappedResult must have ā€œ&ā€, and you don’t have them.

One of the most common newbie mistakes is seeing a parameter must be an
LPDWORD and immediately assuming there must be a variable of type LPDWORD.
I used to teach Advanced Windows System Programming, and here are some
examples of the kind of code EXPERIENCED C/C++ (most with at least five
years’ experience) would wrtie

BOOL SomeAPI(LPDWORD result); // the documented spec

DWORD r;
SomeAPI(r);
Student: (to self) oh,dear, I got a compilation error,
SomeAPI (LPDWORD) r);

Student: This code doesn’t seem to work, what did I do wrong?
Me: Did you check the return result? What did GetLastError tell you?

or,
Student (to self): oh, dear, it failed to compile. Oh, I see, I used the
wrong type for the parameter! I can fix that

LPDWORD r;
SomeAPI(r);

Student: I don’t get it; it compiled correctly, but it doesn’t work
Me: Did you check the retrun type and see what GetLastError says?

LPDWORD r;
r = new DWORD; // or, (LPDWORD) malloc(sizeof(DWORD));
SomeAPI(r);
…
delete r; // or free(r);

(it’s the ones who write malloc/ free in C++ that hit me like fresh lemons
on sensitive teeth)

But usually by this time they’ve taken my advice about checking the return
result and calling GetLastError, so the code becomes

LPDWORD r;
r = new DWORD;
if(! SomeAPI(r) )
{
…report error
return FALSE;
}
…
delete r;

Me: so one every error you leak a little storage…

LPDWORD r;
r= new DWORD;
if(! SomeAPI(r))
{
…report error
delete r;
return FALSE;
}

–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

>> xxxxx@gmail.com wrote:

>> 3. But the GetOverlappedResult always returns 997 as the error code.
> Why do you think that? You never check this. The code you have posted
does not call GetLastError if GetOverlappedResult returns an error.
Instead, you immediately call CancelIo, which causes you to lose the
error value from GetOverlappedResult. (And, by the way, the CancelIo
call is unnecessary.)
> GetOverlappedResult will NEVER return 997 (ERROR_IO_PENDING) when its
last parameter is TRUE. Your statement above is false.
> Can you PLEASE copy and paste your EXACT code instead of retyping it?
We KNOW the code you are posting is not real, because that code will
not
> compile. For example, the second and third parameters to
> GetOverlappedResult must have ā€œ&ā€, and you don’t have them.

One of the most common newbie mistakes is seeing a parameter must be an
LPDWORD and immediately assuming there must be a variable of type LPDWORD.
I used to teach Advanced Windows System Programming, and here are some
examples of the kind of code EXPERIENCED C/C++ (most with at least five
years’ experience) would write

*****
See Oops, below; it explains why these lines appear quoted. It just takes
too long to remove the ā€œ>ā€ quotes on an iPad

The version of Safari that comes with IOS 5 has a serious bug
*******

BOOL SomeAPI(LPDWORD result); // the documented spec

DWORD r;
SomeAPI(r);
Student: (to self) oh,dear, I got a compilation error,
SomeAPI (LPDWORD) r);

Student: This code doesn’t seem to work, what did I do wrong?
Me: Did you check the return result? What did GetLastError tell you?

or,
Student (to self): oh, dear, it failed to compile. Oh, I see, I used
the
wrong type for the parameter! I can fix that

LPDWORD r;
SomeAPI(r);

Student: I don’t get it; it compiled correctly, but it doesn’t work
Me: Did you check the retrun type and see what GetLastError says?

LPDWORD r;
r = new DWORD; // or, (LPDWORD) malloc(sizeof(DWORD));
SomeAPI(r);
…
delete r; // or free(r);

(it’s the ones who write malloc/ free in C++ that hit me like fresh
lemons
on sensitive teeth)

But usually by this time they’ve taken my advice about checking the
return
result and calling GetLastError, so the code becomes

LPDWORD r;
r = new DWORD;
if(! SomeAPI(r) )
{
…report error
return FALSE;
}
…
delete r;

Me: so one every error you leak a little storage…

LPDWORD r;
r= new DWORD;
if(! SomeAPI(r))
{
…report error
delete r;
return FALSE;
}

****
OOPS! A slip of the finger on the iPad and I sent this prematurely. Let
me finish it… On the iPad, if I reposition the caret, the keyboard locks
up. So instead of simple edits, I have to first click OUT of the body
(say, to the Subject, cc, or bcc fields), then click back into the body.
And if I don’t get the caret in precisely the right place, I have to
repeat! This seems to be some JavaScript problem. It was in scrolling
back that one of my fingers accidentally hit the send button, sending this
prematurely)
*****

Me: so you have to remember to delete to object before every ā€˜return’?
Clueless student: What’s wrong with that?
Me: you have just created an unmaintainable mess

So the student rewrites it, as above, except for
BOOL retval;
…
retval = FALSE; //?used to be return false
goto exit;
…
exit:
delete r;
return retval;

Me: And how is this unmaintainable mess an improvement over the last
unmaintainable mess?

Some will immediately arrive at this solution, some have to traversed the
above tortuous path:

DWORD r;
LPDWORD pr;
pr = &r;
SomeAPI(pr);

Me: Why did you introduce the completely useless variable ā€˜pr’
Clueless student: the API says it wants an LPDWORD parameter

I taught this course for fifteen years, easily 6-8 times a year. That’s
hundreds of students (class size varied from 3 to 20, averaging about 10)

It is appalling to me how many students, multi-year veteran C programmers,
failed to (or how very few students knew to) write the obvious:

DWORD r;
if(!SomeAPI(&r)) …

This is why, when I see a newbie post, I demand to see the declarations of
all the variables.
joe

> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
> —
> NTDEV is sponsored by OSR
> For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer