Waiting for overlapped IO result

Below piece of code is copied from the latest DDK docs (relevant part only).
I don’t see any reason why to wait for overlapped event when bRet is TRUE.
DeviceIoControl returned synchronously so overlapped event should be already
signaled and there is no need to wait. Is it correct assumption or am I too
tired and missing something obvious?

Yes, I know the call is benign and can’t cause any problem; just unnecessary
and makes code confusing. I’m just trying to fix old code made by coworkers
who copied there samples as-is and wonder why it was written this way. The
most confusing thing is there is no wait when bRet is FALSE and
GetLastError() returns ERROR_IO_PENDING which can lead (and did) to later
stack corruption. Well, it is another story, I’ll file bug report later.

bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);

if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}

Best regards,

Michal Vodicka
STMicroelectronics Design and Application s.r.o.
[michal.vodicka@st.com, http:://www.st.com]

You should either…

* Use synchronous I/O. Remove the overlapped structure, and invoke the
I/O control synchronously.

* Use asynchronous I/O. There are exhaustive docs on how async I/O
works. If you want for the event immediately after DeviceIoControl,
you’re just emulating synchronous behavior. Either do it synchronously
or do it asynchronously.

You should NOT…

* Issue async operations, but not record the fact that you did so. Not
tracking pending I/O requests can (and usually does) lead to corrupted
stacks, corrupted heaps, leaked memory, or all of the above.

* Touch memory that is the subject of a pending I/O request.

There are exhaustive docs on how to do all of this correctly. Read the
SDK docs on async/overlapped I/O, and abide by these absolutely
carved-in-stone rules when it comes to async I/O:

* Keep track of operations you have issued. Use reference counts,
linked lists, whatever it takes.

* Never, ever touch memory that has been handed to the kernel, while the
kernel is busy reading/writing it.

* Never mangle the contents of an OVERLAPPED structure while an I/O
request is pending.

* ALWAYS make sure that you properly wait for I/O operations to complete
before considering an object closed. Either cancel the request, or
close the handle (which implicitly cancels all open requests on the
handle), and then wait for the completions. How you wait for them
depends on which completion mechanism (APC, I/O completion port, event,
etc.) that you are using. But you MUST do this, or you WILL corrupt
memory, and usually under the most difficult-to-debug scenarios (strange
access patterns, heavy system/app load, etc.)

– arlie

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
Sent: Wednesday, September 24, 2003 10:41 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Waiting for overlapped IO result

Below piece of code is copied from the latest DDK docs (relevant part
only). I don’t see any reason why to wait for overlapped event when bRet
is TRUE. DeviceIoControl returned synchronously so overlapped event
should be already signaled and there is no need to wait. Is it correct
assumption or am I too tired and missing something obvious?

Yes, I know the call is benign and can’t cause any problem; just
unnecessary and makes code confusing. I’m just trying to fix old code
made by coworkers who copied there samples as-is and wonder why it was
written this way. The most confusing thing is there is no wait when bRet
is FALSE and
GetLastError() returns ERROR_IO_PENDING which can lead (and did) to
later stack corruption. Well, it is another story, I’ll file bug report
later.

bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);

if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}

Best regards,

Michal Vodicka
STMicroelectronics Design and Application s.r.o. [michal.vodicka@st.com,
http:://www.st.com]


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@sublinear.org To
unsubscribe send a blank email to xxxxx@lists.osr.com

Well, Arlie, I know it all. I use overlapped IO for years at both driver and
application side. The code isn’t mine, it was copied directly from DDK docs.
My question was different: why it is written the way which doesn’t make
sense or if it does make sense to anybody. Below I copy whole code fragment
from DDK. It violates at least your last point as it doesn’t wait for async
result. Unfortunately, it seems as complete sample and was used as such by
somebody who wrote the old code I work on now. The result was hard-to-find
stack overwrite.

As for sync versus async, you’re right in principle but situation can be
more complicated. In this case the device has to be opened for overlapped
access because it used for both async read/write and IOCTLs which are
handled synchronously. I guess it is better to emulate sync behaviour for
IOCTLs than open two handles for one device. When device is opened for
overlapped access, overlapped structure can’t be removed according to
Platform SDK:


If hDevice was opened with the FILE_FLAG_OVERLAPPED flag, lpOverlapped must
point to a valid OVERLAPPED structure. In this case, the operation is
performed as an overlapped (asynchronous) operation. If the device was
opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the function
fails in unpredictable ways.

DDK code:

DWORD cbRet;
BOOL bRet;
IO_BLOCK IoBlock;
OVERLAPPED overlapped;
BOOL bRet ;

IoBlock.uOffset = (BYTE)byOffset;
IoBlock.uLength = (BYTE)byNbOfReg;
IoBlock.pbyData = pbyData;

memset(&overlapped, 0, sizeof(OVERLAPPED));
overlapped.hEvent = CreateEvent(
NULL, // pointer to security attributes,
// WIN95 ignores this parameter
FALSE, // automatic reset
FALSE, // initialize to not signaled
NULL); // pointer to the event-object name

bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);

if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}

CloseHandle(overlapped.hEvent);

Best regards,

Michal Vodicka
STMicroelectronics Design and Application s.r.o.
[michal.vodicka@st.com, http:://www.st.com]


From: xxxxx@sublinear.org[SMTP:xxxxx@sublinear.org]
Reply To: xxxxx@lists.osr.com
Sent: Thursday, September 25, 2003 5:40 AM
To: xxxxx@lists.osr.com
Subject: [ntdev] RE: Waiting for overlapped IO result

You should either…

* Use synchronous I/O. Remove the overlapped structure, and invoke the
I/O control synchronously.

* Use asynchronous I/O. There are exhaustive docs on how async I/O
works. If you want for the event immediately after DeviceIoControl,
you’re just emulating synchronous behavior. Either do it synchronously
or do it asynchronously.

You should NOT…

* Issue async operations, but not record the fact that you did so. Not
tracking pending I/O requests can (and usually does) lead to corrupted
stacks, corrupted heaps, leaked memory, or all of the above.

* Touch memory that is the subject of a pending I/O request.

There are exhaustive docs on how to do all of this correctly. Read the
SDK docs on async/overlapped I/O, and abide by these absolutely
carved-in-stone rules when it comes to async I/O:

* Keep track of operations you have issued. Use reference counts,
linked lists, whatever it takes.

* Never, ever touch memory that has been handed to the kernel, while the
kernel is busy reading/writing it.

* Never mangle the contents of an OVERLAPPED structure while an I/O
request is pending.

* ALWAYS make sure that you properly wait for I/O operations to complete
before considering an object closed. Either cancel the request, or
close the handle (which implicitly cancels all open requests on the
handle), and then wait for the completions. How you wait for them
depends on which completion mechanism (APC, I/O completion port, event,
etc.) that you are using. But you MUST do this, or you WILL corrupt
memory, and usually under the most difficult-to-debug scenarios (strange
access patterns, heavy system/app load, etc.)

– arlie

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
Sent: Wednesday, September 24, 2003 10:41 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Waiting for overlapped IO result

Below piece of code is copied from the latest DDK docs (relevant part
only). I don’t see any reason why to wait for overlapped event when bRet
is TRUE. DeviceIoControl returned synchronously so overlapped event
should be already signaled and there is no need to wait. Is it correct
assumption or am I too tired and missing something obvious?

Yes, I know the call is benign and can’t cause any problem; just
unnecessary and makes code confusing. I’m just trying to fix old code
made by coworkers who copied there samples as-is and wonder why it was
written this way. The most confusing thing is there is no wait when bRet
is FALSE and
GetLastError() returns ERROR_IO_PENDING which can lead (and did) to
later stack corruption. Well, it is another story, I’ll file bug report
later.

bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);

if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}

Best regards,

Michal Vodicka
STMicroelectronics Design and Application s.r.o. [michal.vodicka@st.com,
http:://www.st.com]


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@sublinear.org To
unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: michal.vodicka@st.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

There is one case where you STILL have to wait for the completion before
assuming that the operation is complete, even when you receive a TRUE
(for Win32) or STATUS_SUCCESS (for native) return code. That is when
you have the file handle bound to an I/O completion port. If that is
the case, then the completion status will always be queued to the
completion port.

There is a way to inhibit that, per-call, though. I think you set the
lowest bit of the Overlapped.Event handle.

Yeah, if you need to mix calls on a single HANDLE, emulating sync
behavior with an event isn’t a bad way to do it. You might even be
better off using APC completions and SleepEx (INFINITE, TRUE), although
that takes a little more footwork.

– arlie

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
Sent: Thursday, September 25, 2003 1:24 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] RE: Waiting for overlapped IO result

Well, Arlie, I know it all. I use overlapped IO for years at both driver
and application side. The code isn’t mine, it was copied directly from
DDK docs. My question was different: why it is written the way which
doesn’t make sense or if it does make sense to anybody. Below I copy
whole code fragment from DDK. It violates at least your last point as it
doesn’t wait for async result. Unfortunately, it seems as complete
sample and was used as such by somebody who wrote the old code I work on
now. The result was hard-to-find stack overwrite.

As for sync versus async, you’re right in principle but situation can be
more complicated. In this case the device has to be opened for
overlapped access because it used for both async read/write and IOCTLs
which are handled synchronously. I guess it is better to emulate sync
behaviour for IOCTLs than open two handles for one device. When device
is opened for overlapped access, overlapped structure can’t be removed
according to Platform SDK:


If hDevice was opened with the FILE_FLAG_OVERLAPPED flag, lpOverlapped
must point to a valid OVERLAPPED structure. In this case, the operation
is performed as an overlapped (asynchronous) operation. If the device
was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the
function fails in unpredictable ways.

DDK code:

DWORD cbRet;
BOOL bRet;
IO_BLOCK IoBlock;
OVERLAPPED overlapped;
BOOL bRet ;

IoBlock.uOffset = (BYTE)byOffset;
IoBlock.uLength = (BYTE)byNbOfReg;
IoBlock.pbyData = pbyData;

memset(&overlapped, 0, sizeof(OVERLAPPED));
overlapped.hEvent = CreateEvent(
NULL, // pointer to security attributes,
// WIN95 ignores this parameter
FALSE, // automatic reset
FALSE, // initialize to not signaled
NULL); // pointer to the event-object name

bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);

if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}

CloseHandle(overlapped.hEvent);

Best regards,

Michal Vodicka
STMicroelectronics Design and Application s.r.o. [michal.vodicka@st.com,
http:://www.st.com]


From: xxxxx@sublinear.org[SMTP:xxxxx@sublinear.org]
Reply To: xxxxx@lists.osr.com
Sent: Thursday, September 25, 2003 5:40 AM
To: xxxxx@lists.osr.com
Subject: [ntdev] RE: Waiting for overlapped IO result

You should either…

* Use synchronous I/O. Remove the overlapped structure, and invoke
the I/O control synchronously.

* Use asynchronous I/O. There are exhaustive docs on how async I/O
works. If you want for the event immediately after DeviceIoControl,
you’re just emulating synchronous behavior. Either do it
synchronously or do it asynchronously.

You should NOT…

* Issue async operations, but not record the fact that you did so.
Not tracking pending I/O requests can (and usually does) lead to
corrupted stacks, corrupted heaps, leaked memory, or all of the above.

* Touch memory that is the subject of a pending I/O request.

There are exhaustive docs on how to do all of this correctly. Read
the SDK docs on async/overlapped I/O, and abide by these absolutely
carved-in-stone rules when it comes to async I/O:

* Keep track of operations you have issued. Use reference counts,
linked lists, whatever it takes.

* Never, ever touch memory that has been handed to the kernel, while
the kernel is busy reading/writing it.

* Never mangle the contents of an OVERLAPPED structure while an I/O
request is pending.

* ALWAYS make sure that you properly wait for I/O operations to
complete before considering an object closed. Either cancel the
request, or close the handle (which implicitly cancels all open
requests on the handle), and then wait for the completions. How you
wait for them depends on which completion mechanism (APC, I/O
completion port, event,
etc.) that you are using. But you MUST do this, or you WILL corrupt
memory, and usually under the most difficult-to-debug scenarios
(strange
access patterns, heavy system/app load, etc.)

– arlie

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
Sent: Wednesday, September 24, 2003 10:41 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Waiting for overlapped IO result

Below piece of code is copied from the latest DDK docs (relevant part
only). I don’t see any reason why to wait for overlapped event when
bRet is TRUE. DeviceIoControl returned synchronously so overlapped
event should be already signaled and there is no need to wait. Is it
correct assumption or am I too tired and missing something obvious?

Yes, I know the call is benign and can’t cause any problem; just
unnecessary and makes code confusing. I’m just trying to fix old code
made by coworkers who copied there samples as-is and wonder why it was

written this way. The most confusing thing is there is no wait when
bRet is FALSE and
GetLastError() returns ERROR_IO_PENDING which can lead (and did) to
later stack corruption. Well, it is another story, I’ll file bug
report later.

bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);

if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}

Best regards,

Michal Vodicka
STMicroelectronics Design and Application s.r.o.
[michal.vodicka@st.com, http:://www.st.com]


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@sublinear.org To
unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: michal.vodicka@st.com To
unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@sublinear.org To
unsubscribe send a blank email to xxxxx@lists.osr.com

> ----------

From: xxxxx@sublinear.org[SMTP:xxxxx@sublinear.org]
Reply To: xxxxx@lists.osr.com
Sent: Friday, September 26, 2003 1:43 AM
To: xxxxx@lists.osr.com
Subject: [ntdev] RE: Waiting for overlapped IO result

There is one case where you STILL have to wait for the completion before
assuming that the operation is complete, even when you receive a TRUE
(for Win32) or STATUS_SUCCESS (for native) return code. That is when
you have the file handle bound to an I/O completion port. If that is
the case, then the completion status will always be queued to the
completion port.

Good to know, thanks. In my case it is pure device handle so there shouldn’t
be a need for waiting. Anyway, I prefer paranoid checking so added following
line for TRUE results:

TASSERT(WaitForSingleObject(Overlapped.hEvent, 0) == WAIT_OBJECT_0);

No overhead in release code and alert if something is wrong in debug.

There is a way to inhibit that, per-call, though. I think you set the
lowest bit of the Overlapped.Event handle.

Yeah, if you need to mix calls on a single HANDLE, emulating sync
behavior with an event isn’t a bad way to do it. You might even be
better off using APC completions and SleepEx (INFINITE, TRUE), although
that takes a little more footwork.

Interesting idea. I only don’t see how to do it for IOCTLs as there is no
DeviceIoControlEx function.

Best regards,

Michal Vodicka
STMicroelectronics Design and Application s.r.o.
[michal.vodicka@st.com, http:://www.st.com]