mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:42:57 +00:00
- fixed DeviceIoControl to properly wait on completion for synchronous operations
- prevent completion port notification by not passing an APC context to the kernel when the low-order bit of the event handle is set (for asynchronous operations) svn path=/trunk/; revision=15045
This commit is contained in:
parent
496308ed56
commit
f16e5b9e1d
1 changed files with 114 additions and 100 deletions
|
@ -20,71 +20,39 @@
|
||||||
*/
|
*/
|
||||||
BOOL
|
BOOL
|
||||||
STDCALL
|
STDCALL
|
||||||
DeviceIoControl(
|
DeviceIoControl(IN HANDLE hDevice,
|
||||||
HANDLE hDevice,
|
IN DWORD dwIoControlCode,
|
||||||
DWORD dwIoControlCode,
|
IN LPVOID lpInBuffer OPTIONAL,
|
||||||
LPVOID lpInBuffer,
|
IN DWORD nInBufferSize OPTIONAL,
|
||||||
DWORD nInBufferSize,
|
OUT LPVOID lpOutBuffer OPTIONAL,
|
||||||
LPVOID lpOutBuffer,
|
IN DWORD nOutBufferSize OPTIONAL,
|
||||||
DWORD nOutBufferSize,
|
OUT LPDWORD lpBytesReturned OPTIONAL,
|
||||||
LPDWORD lpBytesReturned,
|
IN LPOVERLAPPED lpOverlapped OPTIONAL)
|
||||||
LPOVERLAPPED lpOverlapped
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
NTSTATUS errCode = 0;
|
BOOL FsIoCtl;
|
||||||
HANDLE hEvent = NULL;
|
NTSTATUS Status;
|
||||||
PIO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
IO_STATUS_BLOCK IIosb;
|
|
||||||
|
|
||||||
BOOL bFsIoControlCode = FALSE;
|
FsIoCtl = ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM);
|
||||||
|
|
||||||
DPRINT("DeviceIoControl(hDevice %x dwIoControlCode %d lpInBuffer %x "
|
if (lpBytesReturned != NULL)
|
||||||
"nInBufferSize %d lpOutBuffer %x nOutBufferSize %d "
|
|
||||||
"lpBytesReturned %x lpOverlapped %x)\n",
|
|
||||||
hDevice,dwIoControlCode,lpInBuffer,nInBufferSize,lpOutBuffer,
|
|
||||||
nOutBufferSize,lpBytesReturned,lpOverlapped);
|
|
||||||
|
|
||||||
if (lpBytesReturned == NULL)
|
|
||||||
{
|
{
|
||||||
DPRINT("DeviceIoControl() - returning STATUS_INVALID_PARAMETER\n");
|
*lpBytesReturned = 0;
|
||||||
SetLastErrorByStatus (STATUS_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// TODO: Review and approve this change by RobD. IoCtrls for Serial.sys were
|
|
||||||
// going to NtFsControlFile instead of NtDeviceIoControlFile.
|
|
||||||
// Don't know at this point if anything else is affected by this change.
|
|
||||||
//
|
|
||||||
// if (((dwIoControlCode >> 16) & FILE_DEVICE_FILE_SYSTEM) == FILE_DEVICE_FILE_SYSTEM) {
|
|
||||||
//
|
|
||||||
|
|
||||||
if ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM) {
|
|
||||||
|
|
||||||
bFsIoControlCode = TRUE;
|
|
||||||
DPRINT("DeviceIoControl() - FILE_DEVICE_FILE_SYSTEM == TRUE %x %x\n", dwIoControlCode, dwIoControlCode >> 16);
|
|
||||||
} else {
|
|
||||||
bFsIoControlCode = FALSE;
|
|
||||||
DPRINT("DeviceIoControl() - FILE_DEVICE_FILE_SYSTEM == FALSE %x %x\n", dwIoControlCode, dwIoControlCode >> 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lpOverlapped != NULL)
|
if (lpOverlapped != NULL)
|
||||||
{
|
{
|
||||||
hEvent = lpOverlapped->hEvent;
|
PVOID ApcContext;
|
||||||
|
|
||||||
lpOverlapped->Internal = STATUS_PENDING;
|
lpOverlapped->Internal = STATUS_PENDING;
|
||||||
IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped;
|
ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IoStatusBlock = &IIosb;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bFsIoControlCode == TRUE)
|
if (FsIoCtl)
|
||||||
{
|
{
|
||||||
errCode = NtFsControlFile (hDevice,
|
Status = NtFsControlFile(hDevice,
|
||||||
hEvent,
|
lpOverlapped->hEvent,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
ApcContext,
|
||||||
IoStatusBlock,
|
(PIO_STATUS_BLOCK)lpOverlapped,
|
||||||
dwIoControlCode,
|
dwIoControlCode,
|
||||||
lpInBuffer,
|
lpInBuffer,
|
||||||
nInBufferSize,
|
nInBufferSize,
|
||||||
|
@ -93,11 +61,11 @@ DeviceIoControl(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errCode = NtDeviceIoControlFile (hDevice,
|
Status = NtDeviceIoControlFile(hDevice,
|
||||||
hEvent,
|
lpOverlapped->hEvent,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
ApcContext,
|
||||||
IoStatusBlock,
|
(PIO_STATUS_BLOCK)lpOverlapped,
|
||||||
dwIoControlCode,
|
dwIoControlCode,
|
||||||
lpInBuffer,
|
lpInBuffer,
|
||||||
nInBufferSize,
|
nInBufferSize,
|
||||||
|
@ -105,28 +73,74 @@ DeviceIoControl(
|
||||||
nOutBufferSize);
|
nOutBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errCode == STATUS_PENDING)
|
/* return FALSE in case of failure and pending operations! */
|
||||||
|
if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
DPRINT("DeviceIoControl() - STATUS_PENDING\n");
|
SetLastErrorByStatus(Status);
|
||||||
if (NtWaitForSingleObject(hDevice,FALSE,NULL) < 0)
|
|
||||||
{
|
|
||||||
*lpBytesReturned = IoStatusBlock->Information;
|
|
||||||
SetLastErrorByStatus (errCode);
|
|
||||||
DPRINT("DeviceIoControl() - STATUS_PENDING wait failed.\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!NT_SUCCESS(errCode))
|
|
||||||
{
|
|
||||||
SetLastErrorByStatus (errCode);
|
|
||||||
DPRINT("DeviceIoControl() - ERROR: %x\n", errCode);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lpOverlapped)
|
if (lpBytesReturned != NULL)
|
||||||
|
{
|
||||||
*lpBytesReturned = lpOverlapped->InternalHigh;
|
*lpBytesReturned = lpOverlapped->InternalHigh;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*lpBytesReturned = IoStatusBlock->Information;
|
{
|
||||||
|
IO_STATUS_BLOCK Iosb;
|
||||||
|
|
||||||
|
if (FsIoCtl)
|
||||||
|
{
|
||||||
|
Status = NtFsControlFile(hDevice,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&Iosb,
|
||||||
|
dwIoControlCode,
|
||||||
|
lpInBuffer,
|
||||||
|
nInBufferSize,
|
||||||
|
lpOutBuffer,
|
||||||
|
nOutBufferSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = NtDeviceIoControlFile(hDevice,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&Iosb,
|
||||||
|
dwIoControlCode,
|
||||||
|
lpInBuffer,
|
||||||
|
nInBufferSize,
|
||||||
|
lpOutBuffer,
|
||||||
|
nOutBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait in case operation is pending */
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
Status = NtWaitForSingleObject(hDevice,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = Iosb.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* lpBytesReturned must not be NULL here, in fact Win doesn't
|
||||||
|
check that case either and crashes (only after the operation
|
||||||
|
completed) */
|
||||||
|
*lpBytesReturned = Iosb.Information;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLastErrorByStatus(Status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue