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:
Alex Ionescu 2005-08-07 09:40:00 +00:00
parent 09e2e1a5cb
commit 1479011f30
2 changed files with 120 additions and 87 deletions

View file

@ -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)

View file

@ -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,
&WaitObj,
NULL);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(SignalObj);
return Status;
}
hdr = (DISPATCHER_HEADER *)SignalObj; /* Check dispatcher type */
switch (hdr->Type) /* FIXME: Check Object Type instead! */
{ switch (Header->Type)
case EventNotificationObject: {
case EventSynchronizationObject: case EventNotificationObject:
KeSetEvent(SignalObj, case EventSynchronizationObject:
EVENT_INCREMENT, /* Set the Event */
TRUE); /* FIXME: Check permissions */
break; KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE);
break;
case MutantObject: case MutantObject:
KeReleaseMutex(SignalObj, /* Release the Mutant. This can raise an exception*/
TRUE); _SEH_TRY
break; {
KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
goto Quickie;
}
_SEH_END;
break;
case SemaphoreObject: case SemaphoreObject:
KeReleaseSemaphore(SignalObj, /* Release the Semaphore. This can raise an exception*/
SEMAPHORE_INCREMENT, /* FIXME: Check permissions */
1, _SEH_TRY
TRUE); {
break; KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
goto Quickie;
}
_SEH_END;
break;
default: default:
ObDereferenceObject(SignalObj); Status = STATUS_OBJECT_TYPE_MISMATCH;
ObDereferenceObject(WaitObj); goto Quickie;
return STATUS_OBJECT_TYPE_MISMATCH; }
}
Status = KeWaitForSingleObject(WaitObj, /* Now wait. Also SEH this since it can also raise an exception */
UserRequest, _SEH_TRY
PreviousMode, {
Alertable, Status = KeWaitForSingleObject(WaitObj,
TimeOut); UserRequest,
PreviousMode,
Alertable,
TimeOut);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
ObDereferenceObject(SignalObj); /* We're done here */
ObDereferenceObject(WaitObj); Quickie:
ObDereferenceObject(SignalObj);
return Status; ObDereferenceObject(WaitObj);
return Status;
} }
/* EOF */ /* EOF */