Fix NtSignalAndwaitForSingleObject: Use SEH when appropriate, use direct Mutant release call, query handle info and write fixmes when permission checking needed, optimize failure cases, fix horrid tab/space formatting mismatches
Modified: trunk/reactos/include/ndk/extypes.h
Modified: trunk/reactos/ntoskrnl/ob/wait.c

Modified: trunk/reactos/include/ndk/extypes.h
--- trunk/reactos/include/ndk/extypes.h	2005-08-07 09:24:10 UTC (rev 17149)
+++ trunk/reactos/include/ndk/extypes.h	2005-08-07 09:40:00 UTC (rev 17150)
@@ -22,6 +22,9 @@
 
 #define INVALID_HANDLE_VALUE (HANDLE)-1
 
+/* Increments */
+#define MUTANT_INCREMENT 1
+
 /* Callback Object Access Rights */
 #define CALLBACK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x0001)
 #define CALLBACK_EXECUTE    (STANDARD_RIGHTS_EXECUTE|SYNCHRONIZE|0x0001)

Modified: trunk/reactos/ntoskrnl/ob/wait.c
--- trunk/reactos/ntoskrnl/ob/wait.c	2005-08-07 09:24:10 UTC (rev 17149)
+++ trunk/reactos/ntoskrnl/ob/wait.c	2005-08-07 09:40:00 UTC (rev 17150)
@@ -196,105 +196,135 @@
 }
 
 
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
 NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
-			       IN HANDLE WaitableObjectHandle,
-			       IN BOOLEAN Alertable,
-			       IN PLARGE_INTEGER TimeOut  OPTIONAL)
+                               IN HANDLE WaitableObjectHandle,
+                               IN BOOLEAN Alertable,
+                               IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
-   KPROCESSOR_MODE PreviousMode;
-   DISPATCHER_HEADER* hdr;
-   PVOID SignalObj;
-   PVOID WaitObj;
-   LARGE_INTEGER SafeTimeOut;
-   NTSTATUS Status = STATUS_SUCCESS;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    PDISPATCHER_HEADER Header;
+    PVOID SignalObj;
+    PVOID WaitObj;
+    LARGE_INTEGER SafeTimeOut;
+    OBJECT_HANDLE_INFORMATION HandleInfo;
+    NTSTATUS Status = STATUS_SUCCESS;
 
-   PreviousMode = ExGetPreviousMode();
+    /* Capture timeout */
+    if(!TimeOut && PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
+            ProbeForRead(TimeOut,
+                         sizeof(LARGE_INTEGER),
+                         sizeof(ULONG));
+            /* Make a copy on the stack */
+            SafeTimeOut = *TimeOut;
+            TimeOut = &SafeTimeOut;
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
 
-   if(TimeOut != NULL && PreviousMode != KernelMode)
-   {
-     _SEH_TRY
-     {
-       ProbeForRead(TimeOut,
-                    sizeof(LARGE_INTEGER),
-                    sizeof(ULONG));
-       /* make a copy on the stack */
-       SafeTimeOut = *TimeOut;
-       TimeOut = &SafeTimeOut;
-     }
-     _SEH_HANDLE
-     {
-       Status = _SEH_GetExceptionCode();
-     }
-     _SEH_END;
+        if(!NT_SUCCESS(Status)) return Status;
+    }
 
-     if(!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-   }
+    /* Start by getting the signal object*/
+    Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
+                                       0,
+                                       NULL,
+                                       PreviousMode,
+                                       &SignalObj,
+                                       &HandleInfo);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
 
-   Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
-				      0,
-				      NULL,
-				      PreviousMode,
-				      &SignalObj,
-				      NULL);
-   if (!NT_SUCCESS(Status))
-     {
-	return Status;
-     }
+    /* Now get the wait object */
+    Status = ObReferenceObjectByHandle(WaitableObjectHandle,
+                                       SYNCHRONIZE,
+                                       NULL,
+                                       PreviousMode,
+                                       &WaitObj,
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(SignalObj);
+        return Status;
+    }
 
-   Status = ObReferenceObjectByHandle(WaitableObjectHandle,
-				      SYNCHRONIZE,
-				      NULL,
-				      PreviousMode,
-				      &WaitObj,
-				      NULL);
-   if (!NT_SUCCESS(Status))
-     {
-	ObDereferenceObject(SignalObj);
-	return Status;
-     }
+    /* FIXME: Use DefaultObject from ObjectHeader */
+    Header = (PDISPATCHER_HEADER)SignalObj;
+    
+    /* Check dispatcher type */
+    /* FIXME: Check Object Type instead! */
+    switch (Header->Type)
+    {
+        case EventNotificationObject:
+        case EventSynchronizationObject:
+            /* Set the Event */
+            /* FIXME: Check permissions */
+            KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE);
+            break;
 
-   hdr = (DISPATCHER_HEADER *)SignalObj;
-   switch (hdr->Type)
-     {
-      case EventNotificationObject:
-      case EventSynchronizationObject:
-	KeSetEvent(SignalObj,
-		   EVENT_INCREMENT,
-		   TRUE);
-	break;
+        case MutantObject:
+            /* Release the Mutant. This can raise an exception*/
+             _SEH_TRY
+            {
+                KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE);
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+                goto Quickie;
+            }
+            _SEH_END;
+            break;
 
-      case MutantObject:
-	KeReleaseMutex(SignalObj,
-		       TRUE);
-	break;
+        case SemaphoreObject:
+            /* Release the Semaphore. This can raise an exception*/
+            /* FIXME: Check permissions */
+             _SEH_TRY
+            {
+                KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE);
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+                goto Quickie;
+            }
+            _SEH_END;
+            break;
 
-      case SemaphoreObject:
-	KeReleaseSemaphore(SignalObj,
-			   SEMAPHORE_INCREMENT,
-			   1,
-			   TRUE);
-	break;
+        default:
+            Status = STATUS_OBJECT_TYPE_MISMATCH;
+            goto Quickie;
+    }
 
-      default:
-	ObDereferenceObject(SignalObj);
-	ObDereferenceObject(WaitObj);
-	return STATUS_OBJECT_TYPE_MISMATCH;
-     }
+    /* Now wait. Also SEH this since it can also raise an exception */
+    _SEH_TRY
+    {
+        Status = KeWaitForSingleObject(WaitObj,
+                                       UserRequest,
+                                       PreviousMode,
+                                       Alertable,
+                                       TimeOut);
+    }
+    _SEH_HANDLE
+    {
+        Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
 
-   Status = KeWaitForSingleObject(WaitObj,
-				  UserRequest,
-				  PreviousMode,
-				  Alertable,
-				  TimeOut);
-
-   ObDereferenceObject(SignalObj);
-   ObDereferenceObject(WaitObj);
-
-   return Status;
+    /* We're done here */
+Quickie:
+    ObDereferenceObject(SignalObj);
+    ObDereferenceObject(WaitObj);
+    return Status;
 }
 
 /* EOF */