mirror of
https://github.com/reactos/reactos.git
synced 2025-06-05 09:20:30 +00:00
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
svn path=/trunk/; revision=17150
This commit is contained in:
parent
09e2e1a5cb
commit
1479011f30
2 changed files with 120 additions and 87 deletions
|
@ -22,6 +22,9 @@ extern NTOSAPI POBJECT_TYPE ExTimerType;
|
||||||
|
|
||||||
#define INVALID_HANDLE_VALUE (HANDLE)-1
|
#define INVALID_HANDLE_VALUE (HANDLE)-1
|
||||||
|
|
||||||
|
/* Increments */
|
||||||
|
#define MUTANT_INCREMENT 1
|
||||||
|
|
||||||
/* Callback Object Access Rights */
|
/* Callback Object Access Rights */
|
||||||
#define CALLBACK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x0001)
|
#define CALLBACK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x0001)
|
||||||
#define CALLBACK_EXECUTE (STANDARD_RIGHTS_EXECUTE|SYNCHRONIZE|0x0001)
|
#define CALLBACK_EXECUTE (STANDARD_RIGHTS_EXECUTE|SYNCHRONIZE|0x0001)
|
||||||
|
|
|
@ -196,105 +196,135 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
|
NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
|
||||||
IN HANDLE WaitableObjectHandle,
|
IN HANDLE WaitableObjectHandle,
|
||||||
IN BOOLEAN Alertable,
|
IN BOOLEAN Alertable,
|
||||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
DISPATCHER_HEADER* hdr;
|
PDISPATCHER_HEADER Header;
|
||||||
PVOID SignalObj;
|
PVOID SignalObj;
|
||||||
PVOID WaitObj;
|
PVOID WaitObj;
|
||||||
LARGE_INTEGER SafeTimeOut;
|
LARGE_INTEGER SafeTimeOut;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
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)
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
{
|
}
|
||||||
_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))
|
/* Start by getting the signal object*/
|
||||||
{
|
Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
|
||||||
return Status;
|
0,
|
||||||
}
|
NULL,
|
||||||
}
|
PreviousMode,
|
||||||
|
&SignalObj,
|
||||||
|
&HandleInfo);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
|
/* Now get the wait object */
|
||||||
0,
|
Status = ObReferenceObjectByHandle(WaitableObjectHandle,
|
||||||
NULL,
|
SYNCHRONIZE,
|
||||||
PreviousMode,
|
NULL,
|
||||||
&SignalObj,
|
PreviousMode,
|
||||||
NULL);
|
&WaitObj,
|
||||||
if (!NT_SUCCESS(Status))
|
NULL);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
return Status;
|
{
|
||||||
}
|
ObDereferenceObject(SignalObj);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(WaitableObjectHandle,
|
/* FIXME: Use DefaultObject from ObjectHeader */
|
||||||
SYNCHRONIZE,
|
Header = (PDISPATCHER_HEADER)SignalObj;
|
||||||
NULL,
|
|
||||||
PreviousMode,
|
/* Check dispatcher type */
|
||||||
&WaitObj,
|
/* FIXME: Check Object Type instead! */
|
||||||
NULL);
|
switch (Header->Type)
|
||||||
if (!NT_SUCCESS(Status))
|
{
|
||||||
{
|
case EventNotificationObject:
|
||||||
ObDereferenceObject(SignalObj);
|
case EventSynchronizationObject:
|
||||||
return Status;
|
/* Set the Event */
|
||||||
}
|
/* FIXME: Check permissions */
|
||||||
|
KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
hdr = (DISPATCHER_HEADER *)SignalObj;
|
case MutantObject:
|
||||||
switch (hdr->Type)
|
/* Release the Mutant. This can raise an exception*/
|
||||||
{
|
_SEH_TRY
|
||||||
case EventNotificationObject:
|
{
|
||||||
case EventSynchronizationObject:
|
KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE);
|
||||||
KeSetEvent(SignalObj,
|
}
|
||||||
EVENT_INCREMENT,
|
_SEH_HANDLE
|
||||||
TRUE);
|
{
|
||||||
break;
|
Status = _SEH_GetExceptionCode();
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
break;
|
||||||
|
|
||||||
case MutantObject:
|
case SemaphoreObject:
|
||||||
KeReleaseMutex(SignalObj,
|
/* Release the Semaphore. This can raise an exception*/
|
||||||
TRUE);
|
/* FIXME: Check permissions */
|
||||||
break;
|
_SEH_TRY
|
||||||
|
{
|
||||||
|
KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE);
|
||||||
|
}
|
||||||
|
_SEH_HANDLE
|
||||||
|
{
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
break;
|
||||||
|
|
||||||
case SemaphoreObject:
|
default:
|
||||||
KeReleaseSemaphore(SignalObj,
|
Status = STATUS_OBJECT_TYPE_MISMATCH;
|
||||||
SEMAPHORE_INCREMENT,
|
goto Quickie;
|
||||||
1,
|
}
|
||||||
TRUE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
/* Now wait. Also SEH this since it can also raise an exception */
|
||||||
ObDereferenceObject(SignalObj);
|
_SEH_TRY
|
||||||
ObDereferenceObject(WaitObj);
|
{
|
||||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
Status = KeWaitForSingleObject(WaitObj,
|
||||||
}
|
UserRequest,
|
||||||
|
PreviousMode,
|
||||||
|
Alertable,
|
||||||
|
TimeOut);
|
||||||
|
}
|
||||||
|
_SEH_HANDLE
|
||||||
|
{
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
|
||||||
Status = KeWaitForSingleObject(WaitObj,
|
/* We're done here */
|
||||||
UserRequest,
|
Quickie:
|
||||||
PreviousMode,
|
ObDereferenceObject(SignalObj);
|
||||||
Alertable,
|
ObDereferenceObject(WaitObj);
|
||||||
TimeOut);
|
return Status;
|
||||||
|
|
||||||
ObDereferenceObject(SignalObj);
|
|
||||||
ObDereferenceObject(WaitObj);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue