Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / ntoskrnl / ob / obwait.c
index fdd7928..99e5a56 100644 (file)
@@ -49,12 +49,12 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
                          IN BOOLEAN Alertable,
                          IN PLARGE_INTEGER TimeOut OPTIONAL)
 {
-    PKWAIT_BLOCK WaitBlockArray = NULL;
+    PKWAIT_BLOCK WaitBlockArray;
     HANDLE Handles[MAXIMUM_WAIT_OBJECTS], KernelHandle;
     PVOID Objects[MAXIMUM_WAIT_OBJECTS];
     PVOID WaitObjects[MAXIMUM_WAIT_OBJECTS];
-    ULONG i = 0, ReferencedObjects = 0, j;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    ULONG i, ReferencedObjects, j;
+    KPROCESSOR_MODE PreviousMode;
     LARGE_INTEGER SafeTimeOut;
     BOOLEAN LockInUse;
     PHANDLE_TABLE_ENTRY HandleEntry;
@@ -65,30 +65,25 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
     NTSTATUS Status;
     PAGED_CODE();
 
-    /* Enter a critical region since we'll play with handles */
-    LockInUse = TRUE;
-    KeEnterCriticalRegion();
-
     /* Check for valid Object Count */
     if ((ObjectCount > MAXIMUM_WAIT_OBJECTS) || !(ObjectCount))
     {
         /* Fail */
-        Status = STATUS_INVALID_PARAMETER_1;
-        goto Quickie;
+        return STATUS_INVALID_PARAMETER_1;
     }
 
     /* Check for valid Wait Type */
     if ((WaitType != WaitAll) && (WaitType != WaitAny))
     {
         /* Fail */
-        Status = STATUS_INVALID_PARAMETER_3;
-        goto Quickie;
+        return STATUS_INVALID_PARAMETER_3;
     }
 
     /* Enter SEH */
+    PreviousMode = ExGetPreviousMode();
     _SEH2_TRY
     {
-        /* Check if the call came from user mode */
+        /* Probe for user mode */
         if (PreviousMode != KernelMode)
         {
             /* Check if we have a timeout */
@@ -99,26 +94,32 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
                 TimeOut = &SafeTimeOut;
             }
 
-            /* Probe all the handles */
+             /* Probe all the handles */
             ProbeForRead(HandleArray,
                          ObjectCount * sizeof(HANDLE),
                          sizeof(HANDLE));
         }
 
-       /*
-        * Make a copy so we don't have to guard with SEH later and keep
-        * track of what objects we referenced if dereferencing pointers
-        * suddenly fails
-        */
+        /*
+         * Make a copy so we don't have to guard with SEH later and keep
+         * track of what objects we referenced if dereferencing pointers
+         * suddenly fails
+         */
         RtlCopyMemory(Handles,
                       HandleArray,
                       ObjectCount * sizeof(HANDLE));
     }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) //ExSystemExceptionFilter()
     {
+        /* Cover up for kernel mode */
+        if (PreviousMode == KernelMode)
+        {
+            /* But don't fail silently */
+            DbgPrint("Mon dieu! Covering up for BAD driver passing invalid pointer (0x%p)! Hon hon hon!\n", HandleArray);
+        }
+
         /* Return the exception code */
-        Status = _SEH2_GetExceptionCode();
-        _SEH2_YIELD(goto Quickie);
+        _SEH2_YIELD(return _SEH2_GetExceptionCode());
     }
     _SEH2_END;
 
@@ -133,16 +134,26 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
         if (!WaitBlockArray)
         {
             /* Fail */
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto Quickie;
+            return STATUS_INSUFFICIENT_RESOURCES;
         }
     }
+    else
+    {
+        /* No need for the array  */
+        WaitBlockArray = NULL;   
+    }
+
+    /* Enter a critical region since we'll play with handles */
+    LockInUse = TRUE;
+    KeEnterCriticalRegion();
 
     /* Start the loop */
+    i = 0;
+    ReferencedObjects = 0;
     do
     {
         /* Use the right Executive Handle */
-        if (ObIsKernelHandle(Handles[i], PreviousMode))
+        if (ObpIsKernelHandle(Handles[i], PreviousMode))
         {
             /* Use the System Handle Table and decode */
             HandleTable = ObpKernelHandleTable;
@@ -165,6 +176,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
         {
             /* Fail, handle is invalid */
             Status = STATUS_INVALID_HANDLE;
+            DPRINT1("Invalid handle %p passed to NtWaitForMultipleObjects\n", Handles[i]);
             goto Quickie;
         }
 
@@ -174,6 +186,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
         {
             /* Unlock the entry and fail */
             ExUnlockHandleTableEntry(HandleTable, HandleEntry);
+            DPRINT1("Handle does not have SYNCHRONIZE access\n");
             Status = STATUS_ACCESS_DENIED;
             goto Quickie;
         }
@@ -228,6 +241,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
                 {
                     /* Fail */
                     Status = STATUS_INVALID_PARAMETER_MIX;
+                    DPRINT1("Passed a duplicate object to NtWaitForMultipleObjects\n");
                     goto Quickie;
                 }
             }
@@ -237,7 +251,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
         } while (i < ObjectCount);
     }
 
-    /* Now we can finally wait. Use SEH since it can raise an exception */
+    /* Now we can finally wait. Always use SEH since it can raise an exception */
     _SEH2_TRY
     {
         /* We're done playing with handles */
@@ -254,7 +268,9 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
                                           TimeOut,
                                           WaitBlockArray);
     }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ?
+                 EXCEPTION_EXECUTE_HANDLER :
+                 EXCEPTION_CONTINUE_SEARCH)
     {
         /* Get the exception code */
         Status = _SEH2_GetExceptionCode();
@@ -355,11 +371,12 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle,
                       IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
     PVOID Object, WaitableObject;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode;
     LARGE_INTEGER SafeTimeOut;
     NTSTATUS Status;
 
     /* Check if we came with a timeout from user mode */
+    PreviousMode = ExGetPreviousMode();
     if ((TimeOut) && (PreviousMode != KernelMode))
     {
         /* Enter SEH for proving */
@@ -407,7 +424,9 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle,
                                            Alertable,
                                            TimeOut);
         }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ?
+                     EXCEPTION_EXECUTE_HANDLER :
+                     EXCEPTION_CONTINUE_SEARCH)
         {
             /* Get the exception code */
             Status = _SEH2_GetExceptionCode();
@@ -417,6 +436,10 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle,
         /* Dereference the Object */
         ObDereferenceObject(Object);
     }
+    else
+    {
+        DPRINT1("Failed to reference the handle with status 0x%x\n", Status);
+    }
 
     /* Return the status */
     return Status;
@@ -452,7 +475,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
                                IN BOOLEAN Alertable,
                                IN PLARGE_INTEGER TimeOut OPTIONAL)
 {
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    KPROCESSOR_MODE PreviousMode;
     POBJECT_TYPE Type;
     PVOID SignalObj, WaitObj, WaitableObject;
     LARGE_INTEGER SafeTimeOut;
@@ -460,6 +483,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
     NTSTATUS Status;
 
     /* Check if we came with a timeout from user mode */
+    PreviousMode = ExGetPreviousMode();
     if ((TimeOut) && (PreviousMode != KernelMode))
     {
         /* Enter SEH for probing */
@@ -535,7 +559,10 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
             /* Release the mutant */
             KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE);
         }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        _SEH2_EXCEPT(((_SEH2_GetExceptionCode() == STATUS_ABANDONED) ||
+                      (_SEH2_GetExceptionCode() == STATUS_MUTANT_NOT_OWNED)) ?
+                      EXCEPTION_EXECUTE_HANDLER :
+                      EXCEPTION_CONTINUE_SEARCH)
         {
             /* Get the exception code */
             Status = _SEH2_GetExceptionCode();
@@ -559,7 +586,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
             /* Release the semaphore */
             KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE);
         }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_SEMAPHORE_LIMIT_EXCEEDED) ?
+                     EXCEPTION_EXECUTE_HANDLER :
+                     EXCEPTION_CONTINUE_SEARCH)
         {
             /* Get the exception code */
             Status = _SEH2_GetExceptionCode();
@@ -585,7 +614,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
                                            Alertable,
                                            TimeOut);
         }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ?
+                     EXCEPTION_EXECUTE_HANDLER :
+                     EXCEPTION_CONTINUE_SEARCH)
         {
             /* Get the exception code */
             Status = _SEH2_GetExceptionCode();