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,29 +196,30 @@ 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;
OBJECT_HANDLE_INFORMATION HandleInfo;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PreviousMode = ExGetPreviousMode(); /* Capture timeout */
if(!TimeOut && PreviousMode != KernelMode)
if(TimeOut != NULL && PreviousMode != KernelMode)
{ {
_SEH_TRY _SEH_TRY
{ {
ProbeForRead(TimeOut, ProbeForRead(TimeOut,
sizeof(LARGE_INTEGER), sizeof(LARGE_INTEGER),
sizeof(ULONG)); sizeof(ULONG));
/* make a copy on the stack */ /* Make a copy on the stack */
SafeTimeOut = *TimeOut; SafeTimeOut = *TimeOut;
TimeOut = &SafeTimeOut; TimeOut = &SafeTimeOut;
} }
@ -228,23 +229,22 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
} }
_SEH_END; _SEH_END;
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status)) return Status;
{
return Status;
}
} }
/* Start by getting the signal object*/
Status = ObReferenceObjectByHandle(ObjectHandleToSignal, Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
0, 0,
NULL, NULL,
PreviousMode, PreviousMode,
&SignalObj, &SignalObj,
NULL); &HandleInfo);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return Status;
} }
/* Now get the wait object */
Status = ObReferenceObjectByHandle(WaitableObjectHandle, Status = ObReferenceObjectByHandle(WaitableObjectHandle,
SYNCHRONIZE, SYNCHRONIZE,
NULL, NULL,
@ -257,43 +257,73 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
return Status; return Status;
} }
hdr = (DISPATCHER_HEADER *)SignalObj; /* FIXME: Use DefaultObject from ObjectHeader */
switch (hdr->Type) Header = (PDISPATCHER_HEADER)SignalObj;
/* Check dispatcher type */
/* FIXME: Check Object Type instead! */
switch (Header->Type)
{ {
case EventNotificationObject: case EventNotificationObject:
case EventSynchronizationObject: case EventSynchronizationObject:
KeSetEvent(SignalObj, /* Set the Event */
EVENT_INCREMENT, /* FIXME: Check permissions */
TRUE); KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE);
break; break;
case MutantObject: case MutantObject:
KeReleaseMutex(SignalObj, /* Release the Mutant. This can raise an exception*/
TRUE); _SEH_TRY
{
KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
goto Quickie;
}
_SEH_END;
break; break;
case SemaphoreObject: case SemaphoreObject:
KeReleaseSemaphore(SignalObj, /* Release the Semaphore. This can raise an exception*/
SEMAPHORE_INCREMENT, /* FIXME: Check permissions */
1, _SEH_TRY
TRUE); {
KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
goto Quickie;
}
_SEH_END;
break; break;
default: default:
ObDereferenceObject(SignalObj); Status = STATUS_OBJECT_TYPE_MISMATCH;
ObDereferenceObject(WaitObj); goto Quickie;
return STATUS_OBJECT_TYPE_MISMATCH;
} }
/* Now wait. Also SEH this since it can also raise an exception */
_SEH_TRY
{
Status = KeWaitForSingleObject(WaitObj, Status = KeWaitForSingleObject(WaitObj,
UserRequest, UserRequest,
PreviousMode, PreviousMode,
Alertable, Alertable,
TimeOut); TimeOut);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* We're done here */
Quickie:
ObDereferenceObject(SignalObj); ObDereferenceObject(SignalObj);
ObDereferenceObject(WaitObj); ObDereferenceObject(WaitObj);
return Status; return Status;
} }