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 */