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