[ros-diffs] [janderwald] 44667: - Fix broken check for storing the number of transferred bytes. - Fix broken logic in GetOverlappedResult - Patch by Alex

janderwald at svn.reactos.org janderwald at svn.reactos.org
Sun Dec 20 12:57:21 CET 2009


Author: janderwald
Date: Sun Dec 20 12:57:21 2009
New Revision: 44667

URL: http://svn.reactos.org/svn/reactos?rev=44667&view=rev
Log:
- Fix broken check for storing the number of transferred bytes. 
- Fix broken logic in GetOverlappedResult
- Patch by Alex

Modified:
    trunk/reactos/dll/win32/kernel32/file/deviceio.c

Modified: trunk/reactos/dll/win32/kernel32/file/deviceio.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/file/deviceio.c?rev=44667&r1=44666&r2=44667&view=diff
==============================================================================
--- trunk/reactos/dll/win32/kernel32/file/deviceio.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/file/deviceio.c [iso-8859-1] Sun Dec 20 12:57:21 2009
@@ -1,18 +1,17 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS system libraries
- * FILE:            lib/kernel32/file/deviceio.c
- * PURPOSE:         Device I/O and Overlapped Result functions
- * PROGRAMMER:      Ariadne (ariadne at xs4all.nl)
- * UPDATE HISTORY:
- *                  Created 01/11/98
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            kernel32/file/deviceio.c
+ * PURPOSE:         Device I/O Base Client Functionality
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu at reactos.org)
  */
+
+/* INCLUDES *******************************************************************/
 
 #include <k32.h>
 #include <wine/debug.h>
 
-WINE_DEFAULT_DEBUG_CHANNEL(kernel32file);
+/* FUNCTIONS ******************************************************************/
 
 /*
  * @implemented
@@ -21,131 +20,146 @@
 WINAPI
 DeviceIoControl(IN HANDLE hDevice,
                 IN DWORD dwIoControlCode,
-                IN LPVOID lpInBuffer  OPTIONAL,
-                IN DWORD nInBufferSize  OPTIONAL,
-                OUT LPVOID lpOutBuffer  OPTIONAL,
-                IN DWORD nOutBufferSize  OPTIONAL,
-                OUT LPDWORD lpBytesReturned  OPTIONAL,
-                IN LPOVERLAPPED lpOverlapped  OPTIONAL)
+                IN LPVOID lpInBuffer OPTIONAL,
+                IN DWORD nInBufferSize OPTIONAL,
+                OUT LPVOID lpOutBuffer OPTIONAL,
+                IN DWORD nOutBufferSize OPTIONAL,
+                OUT LPDWORD lpBytesReturned OPTIONAL,
+                IN LPOVERLAPPED lpOverlapped OPTIONAL)
 {
-   BOOL FsIoCtl;
-   NTSTATUS Status;
-
-   FsIoCtl = ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM);
-
-   if (lpBytesReturned != NULL)
-     {
-        *lpBytesReturned = 0;
-     }
-
-   if (lpOverlapped != NULL)
-     {
-        PVOID ApcContext;
-
+    BOOL FsIoCtl;
+    NTSTATUS Status;
+    PVOID ApcContext;
+    IO_STATUS_BLOCK Iosb;
+
+    /* Check what kind of IOCTL to send */
+    FsIoCtl = ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM);
+
+    /* CHeck for async */
+    if (lpOverlapped != NULL)
+    {
+        /* Set pending status */
         lpOverlapped->Internal = STATUS_PENDING;
+
+        
+        /* Check if there's an APC context */
         ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
 
+        
+        /* Send file system control? */
         if (FsIoCtl)
-          {
-             Status = NtFsControlFile(hDevice,
-                                      lpOverlapped->hEvent,
-                                      NULL,
-                                      ApcContext,
-                                      (PIO_STATUS_BLOCK)lpOverlapped,
-                                      dwIoControlCode,
-                                      lpInBuffer,
-                                      nInBufferSize,
-                                      lpOutBuffer,
-                                      nOutBufferSize);
-          }
-        else
-          {
-             Status = NtDeviceIoControlFile(hDevice,
-                                            lpOverlapped->hEvent,
-                                            NULL,
-                                            ApcContext,
-                                            (PIO_STATUS_BLOCK)lpOverlapped,
-                                            dwIoControlCode,
-                                            lpInBuffer,
-                                            nInBufferSize,
-                                            lpOutBuffer,
-                                            nOutBufferSize);
-          }
-
-        /* return FALSE in case of failure and pending operations! */
-        if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
-          {
-             SetLastErrorByStatus(Status);
-             return FALSE;
-          }
-
-        if (lpBytesReturned != NULL)
-          {
-             *lpBytesReturned = lpOverlapped->InternalHigh;
-          }
-     }
-   else
-     {
-        IO_STATUS_BLOCK Iosb;
-
+        {
+            /* Send it */
+            Status = NtFsControlFile(hDevice,
+                                     lpOverlapped->hEvent,
+                                     NULL,
+                                     ApcContext,
+                                     (PIO_STATUS_BLOCK)lpOverlapped,
+                                     dwIoControlCode,
+                                     lpInBuffer,
+                                     nInBufferSize,
+                                     lpOutBuffer,
+                                     nOutBufferSize);
+        }
+        else
+        {
+            /* Otherwise send a device control */
+            Status = NtDeviceIoControlFile(hDevice,
+                                           lpOverlapped->hEvent,
+                                           NULL,
+                                           ApcContext,
+                                           (PIO_STATUS_BLOCK)lpOverlapped,
+                                           dwIoControlCode,
+                                           lpInBuffer,
+                                           nInBufferSize,
+                                           lpOutBuffer,
+                                           nOutBufferSize);
+        }
+
+        /* Check for or information instead of failure */
+        if (!(NT_ERROR(Status)) && (lpBytesReturned))
+        {
+            /* Protect with SEH */
+            _SEH2_TRY
+            {
+                /* Return the bytes */
+                *lpBytesReturned = lpOverlapped->InternalHigh;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Return zero bytes */
+                *lpBytesReturned = 0;
+            }
+            _SEH2_END;
+        }
+
+        /* Now check for any kind of failure except pending*/
+        if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING))
+        {
+            /* Fail */
+            SetLastErrorByStatus(Status);
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Sync case -- send file system code? */
         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 */
+        {
+            /* Do it */
+            Status = NtFsControlFile(hDevice,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     &Iosb,
+                                     dwIoControlCode,
+                                     lpInBuffer,
+                                     nInBufferSize,
+                                     lpOutBuffer,
+                                     nOutBufferSize);
+        }
+        else
+        {
+            /* Send device code instead */
+            Status = NtDeviceIoControlFile(hDevice,
+                                           NULL,
+                                           NULL,
+                                           NULL,
+                                           &Iosb,
+                                           dwIoControlCode,
+                                           lpInBuffer,
+                                           nInBufferSize,
+                                           lpOutBuffer,
+                                           nOutBufferSize);
+        }
+
+        /* Now check if the operation isn't done yet */
         if (Status == STATUS_PENDING)
-          {
-             Status = NtWaitForSingleObject(hDevice,
-                                            FALSE,
-                                            NULL);
-             if (NT_SUCCESS(Status))
-               {
-                  Status = Iosb.Status;
-               }
-          }
-
+        {
+            /* Wait for it and get the final status */
+            Status = NtWaitForSingleObject(hDevice, FALSE, NULL);
+            if (NT_SUCCESS(Status)) Status = Iosb.Status;
+        }
+
+        /* Check for success */
         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) */
-            if (!lpBytesReturned)
-            {
-                ERR("Bad caller: lpBytesReturned must not be NULL\n");
-            }
-             *lpBytesReturned = Iosb.Information;
-          }
-        else
-          {
-             SetLastErrorByStatus(Status);
-             return FALSE;
-          }
-     }
-
-   return TRUE;
+        {
+            /* Return the byte count */
+            *lpBytesReturned = Iosb.Information;
+        }
+        else
+        {
+            /* Check for informational or warning failure */
+            if (!NT_ERROR(Status)) *lpBytesReturned = Iosb.Information;
+
+            /* Return a failure */
+            SetLastErrorByStatus(Status);
+            return FALSE;
+        }
+    }
+
+    /* Return success */
+    return TRUE;
 }
 
 
@@ -154,55 +168,62 @@
  */
 BOOL
 WINAPI
-GetOverlappedResult (
-  IN HANDLE   hFile,
-	IN LPOVERLAPPED	lpOverlapped,
-	OUT LPDWORD		lpNumberOfBytesTransferred,
-	IN BOOL		bWait
-	)
+GetOverlappedResult(IN HANDLE hFile,
+                    IN LPOVERLAPPED lpOverlapped,
+                    OUT LPDWORD lpNumberOfBytesTransferred,
+                    IN BOOL bWait)
 {
-	DWORD WaitStatus;
-  HANDLE hObject;
-
-  if (lpOverlapped->Internal == STATUS_PENDING)
-  {
-    if (!bWait)
-    {
-      /* can't use SetLastErrorByStatus(STATUS_PENDING) here,
-      since STATUS_PENDING translates to ERROR_IO_PENDING */
-      SetLastError(ERROR_IO_INCOMPLETE);
-      return FALSE;
-    }
-
-    hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;
-
-    /* Wine delivers pending APC's while waiting, but Windows does
-    not, nor do we... */
-    WaitStatus = WaitForSingleObject(hObject, INFINITE);
-
-    if (WaitStatus == WAIT_FAILED)
-    {
-      WARN("Wait failed!\n");
-      /* WaitForSingleObjectEx sets the last error */
-      return FALSE;
-    }
-  }
-
-  if (!lpNumberOfBytesTransferred)
-  {
-      ERR("Bad caller: lpNumberOfBytesTransferred must not be NULL\n");
-  }
-  *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
-
-  if (!NT_SUCCESS(lpOverlapped->Internal))
-  {
-    SetLastErrorByStatus(lpOverlapped->Internal);
-    return FALSE;
-  }
-
-	return TRUE;
+    DWORD WaitStatus;
+    HANDLE hObject;
+
+
+    /* Check for pending operation */
+    if (lpOverlapped->Internal == STATUS_PENDING)
+    {
+        /* Check if the caller is okay with waiting */
+        if (!bWait)
+        {
+            /* Set timeout */
+            WaitStatus = WAIT_TIMEOUT;
+        }
+        else
+        {
+            /* Wait for the result */
+            hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;
+            WaitStatus = WaitForSingleObject(hObject, INFINITE);
+        }
+
+
+        /* Check for timeout */
+        if (WaitStatus == WAIT_TIMEOUT)
+        {
+            /* We have to override the last error with INCOMPLETE instead */
+            SetLastError(ERROR_IO_INCOMPLETE);
+            return FALSE;
+        }
+
+
+        /* Fail if we had an error -- the last error is already set */
+        if (WaitStatus != 0) return FALSE;
+    }
+
+
+    /* Return bytes transferred */
+    *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh;
+
+
+    /* Check for failure during I/O */
+    if (!NT_SUCCESS(lpOverlapped->Internal))
+    {
+        /* Set the error and fail */
+        SetLastErrorByStatus(lpOverlapped->Internal);
+        return FALSE;
+    }
+
+
+    /* All done */
+    return TRUE;
 }
 
 /* EOF */
 
-




More information about the Ros-diffs mailing list