mirror of
https://github.com/reactos/reactos.git
synced 2025-04-18 03:34:11 +00:00
- Completely reimplement NtWaitForMultipleObjects:
- Check for invalid Objectcount and wait type - Don't use 2.6KB of stack space (kernel threads only get 4...) - Don't call ObReferenceObjectByHandle since it does a lot of superflous checks, continous locking/unlocking and makes us extremly slow for a large wait and also doesn't give us the full flexibility we need. - Detect if a Waitall is being done with the same object duplicated. - Protect wait with SEH. - General fixes for all NtWaitXXX: - Use DefaultObject from Object Header and remove all previous associated hacks, including the IO_TYPE hack. The DefaultObject will either be NULL, an offset to an internal Object Event, or a pointer to a default event. We handle all three. - Guard the KeWaitXXX call with SEH since it can raise exceptions. - Fix all object type intiailizers regarding DefaultObject. svn path=/trunk/; revision=17179
This commit is contained in:
parent
a6b3bd07b6
commit
4c1eb86320
12 changed files with 350 additions and 271 deletions
|
@ -91,7 +91,6 @@ ExpInitializeCallbacks(VOID)
|
|||
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CALLBACK_OBJECT);
|
||||
ObjectTypeInitializer.GenericMapping = ExpCallbackMapping;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
|
||||
Status = ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExCallbackObjectType);
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@ ExpInitializeEventImplementation(VOID)
|
|||
ObjectTypeInitializer.GenericMapping = ExpEventMapping;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExEventObjectType);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ ExpInitializeMutantImplementation(VOID)
|
|||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant;
|
||||
ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExMutantObjectType);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ ExpInitializeProfileImplementation(VOID)
|
|||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.DeleteProcedure = ExpDeleteProfile;
|
||||
ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_ALL;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExProfileObjectType);
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,6 @@ ExpWin32kInit(VOID)
|
|||
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
||||
ObjectTypeInitializer.GenericMapping = ExpWindowStationMapping;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObjectTypeInitializer.OpenProcedure = ExpWinStaObjectOpen;
|
||||
ObjectTypeInitializer.DeleteProcedure = ExpWinStaObjectDelete;
|
||||
ObjectTypeInitializer.ParseProcedure = ExpWinStaObjectParse;
|
||||
|
|
|
@ -8,6 +8,13 @@ extern LARGE_INTEGER ExpTimeZoneBias;
|
|||
extern ULONG ExpTimeZoneId;
|
||||
extern POBJECT_TYPE ExEventPairObjectType;
|
||||
|
||||
#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
|
||||
~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE)))
|
||||
#define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->u1.Object) & \
|
||||
~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE)))
|
||||
|
||||
/* INITIALIZATION FUNCTIONS *************************************************/
|
||||
|
||||
VOID
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#include <ndk/ntndk.h>
|
||||
#include <ndk/sysguid.h>
|
||||
#include <ndk/asm.h>
|
||||
#undef IO_TYPE_FILE
|
||||
#define IO_TYPE_FILE 0x0F5L /* Temp Hack */
|
||||
|
||||
/* FIXME: Temporary until CC Ros is gone */
|
||||
#include <ccros.h>
|
||||
|
|
|
@ -217,6 +217,7 @@ IoInit (VOID)
|
|||
ObjectTypeInitializer.DeleteProcedure = IopDeleteFile;
|
||||
ObjectTypeInitializer.SecurityProcedure = IopSecurityFile;
|
||||
ObjectTypeInitializer.QueryNameProcedure = IopQueryNameFile;
|
||||
ObjectTypeInitializer.UseDefaultObject = FALSE;
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoFileObjectType);
|
||||
|
||||
/*
|
||||
|
|
|
@ -225,22 +225,6 @@ KeWaitForSingleObject(PVOID Object,
|
|||
/* Get the Current Object */
|
||||
CurrentObject = (PDISPATCHER_HEADER)Object;
|
||||
|
||||
/* FIXME:
|
||||
* Temporary hack until my Object Manager re-write. Basically some objects, like
|
||||
* the File Object, but also LPCs and others, are actually waitable on their event.
|
||||
* The Object Manager sets this up in The ObjectTypeInformation->DefaultObject member,
|
||||
* by using pretty much the same kind of hack as us. Normal objects point to themselves
|
||||
* in that pointer. Then, NtWaitForXXX will populate the WaitList that gets sent to us by
|
||||
* using ->DefaultObject, so the proper actual objects will be sent to us. Until then however,
|
||||
* I will keep this hack here, since there's no need to make an interim hack until the rewrite
|
||||
* -- Alex Ionescu 24/02/05
|
||||
*/
|
||||
if (CurrentObject->Type == IO_TYPE_FILE) {
|
||||
|
||||
DPRINT1("Hack used: %x\n", &((PFILE_OBJECT)CurrentObject)->Event);
|
||||
CurrentObject = (PDISPATCHER_HEADER)(&((PFILE_OBJECT)CurrentObject)->Event);
|
||||
}
|
||||
|
||||
/* Check if the Object is Signaled */
|
||||
if (KiIsObjectSignaled(CurrentObject, CurrentThread)) {
|
||||
|
||||
|
@ -441,21 +425,6 @@ KeWaitForMultipleObjects(ULONG Count,
|
|||
/* Get the Current Object */
|
||||
CurrentObject = (PDISPATCHER_HEADER)Object[WaitIndex];
|
||||
|
||||
/* FIXME:
|
||||
* Temporary hack until my Object Manager re-write. Basically some objects, like
|
||||
* the File Object, but also LPCs and others, are actually waitable on their event.
|
||||
* The Object Manager sets this up in The ObjectTypeInformation->DefaultObject member,
|
||||
* by using pretty much the same kind of hack as us. Normal objects point to themselves
|
||||
* in that pointer. Then, NtWaitForXXX will populate the WaitList that gets sent to us by
|
||||
* using ->DefaultObject, so the proper actual objects will be sent to us. Until then however,
|
||||
* I will keep this hack here, since there's no need to make an interim hack until the rewrite
|
||||
* -- Alex Ionescu 24/02/05
|
||||
*/
|
||||
if (CurrentObject->Type == IO_TYPE_FILE) {
|
||||
|
||||
CurrentObject = (PDISPATCHER_HEADER)(&((PFILE_OBJECT)CurrentObject)->Event);
|
||||
}
|
||||
|
||||
/* Check if the Object is Signaled */
|
||||
if (KiIsObjectSignaled(CurrentObject, CurrentThread)) {
|
||||
|
||||
|
@ -807,31 +776,6 @@ KiIsObjectSignaled(PDISPATCHER_HEADER Object,
|
|||
return (!Object->SignalState <= 0);
|
||||
}
|
||||
|
||||
BOOL
|
||||
inline
|
||||
FASTCALL
|
||||
KiIsObjectWaitable(PVOID Object)
|
||||
{
|
||||
POBJECT_HEADER Header;
|
||||
Header = BODY_TO_HEADER(Object);
|
||||
|
||||
if (Header->Type == ExEventObjectType ||
|
||||
Header->Type == IoCompletionType ||
|
||||
Header->Type == ExMutantObjectType ||
|
||||
Header->Type == ExSemaphoreObjectType ||
|
||||
Header->Type == ExTimerType ||
|
||||
Header->Type == PsProcessType ||
|
||||
Header->Type == PsThreadType ||
|
||||
Header->Type == IoFileObjectType) {
|
||||
|
||||
return TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
inline
|
||||
FASTCALL
|
||||
|
|
|
@ -33,13 +33,6 @@
|
|||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
|
||||
~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE)))
|
||||
#define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->u1.Object) & \
|
||||
~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE)))
|
||||
|
||||
#define GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
|
||||
|
||||
/* GLOBALS *****************************************************************/
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* FILE: ntoskrnl/ob/wait.c
|
||||
* PURPOSE: Handles Waiting on Objects
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created file
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
* David Welch (welch@mcmail.com)
|
||||
*/
|
||||
|
||||
|
@ -14,188 +14,322 @@
|
|||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#define TAG_WAIT TAG('W', 'a', 'i', 't')
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOL inline FASTCALL KiIsObjectWaitable(PVOID Object);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtWaitForMultipleObjects(IN ULONG ObjectCount,
|
||||
IN PHANDLE ObjectsArray,
|
||||
IN WAIT_TYPE WaitType,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
IN PHANDLE HandleArray,
|
||||
IN WAIT_TYPE WaitType,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
{
|
||||
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
|
||||
HANDLE SafeObjectsArray[MAXIMUM_WAIT_OBJECTS];
|
||||
PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
|
||||
ULONG i, j;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PKWAIT_BLOCK WaitBlockArray = NULL;
|
||||
HANDLE Handles[MAXIMUM_WAIT_OBJECTS];
|
||||
PVOID Objects[MAXIMUM_WAIT_OBJECTS];
|
||||
PVOID WaitObjects[MAXIMUM_WAIT_OBJECTS];
|
||||
ULONG i = 0, ReferencedObjects = 0, j;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
BOOLEAN LockInUse;
|
||||
PHANDLE_TABLE_ENTRY HandleEntry;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
PHANDLE_TABLE HandleTable;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
LONG ExHandle;
|
||||
PVOID DefaultObject;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
|
||||
"TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
|
||||
DPRINT("NtWaitForMultipleObjects(ObjectCount %lu HandleArray[] %x, Alertable %d, "
|
||||
"TimeOut %x)\n", ObjectCount, HandleArray, Alertable, TimeOut);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
/* Enter a critical region since we'll play with handles */
|
||||
LockInUse = TRUE;
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
if (0 == ObjectCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
/* Check for valid Object Count */
|
||||
if ((ObjectCount > MAXIMUM_WAIT_OBJECTS) || !ObjectCount)
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER_1;
|
||||
DPRINT1("No object count, or too many objects\n");
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
if(PreviousMode != KernelMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForRead(ObjectsArray,
|
||||
ObjectCount * sizeof(ObjectsArray[0]),
|
||||
sizeof(ULONG));
|
||||
/* make a copy so we don't have to guard with SEH later and keep track of
|
||||
what objects we referenced in case dereferencing pointers suddenly fails */
|
||||
RtlCopyMemory(SafeObjectsArray, ObjectsArray, ObjectCount * sizeof(ObjectsArray[0]));
|
||||
ObjectsArray = SafeObjectsArray;
|
||||
/* Check for valid Wait Type */
|
||||
if ((WaitType != WaitAll) && (WaitType != WaitAny))
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER_3;
|
||||
DPRINT1("Invalid wait type\n");
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
if(TimeOut != NULL)
|
||||
{
|
||||
ProbeForRead(TimeOut,
|
||||
sizeof(LARGE_INTEGER),
|
||||
sizeof(ULONG));
|
||||
/* make a local copy of the timeout on the stack */
|
||||
SafeTimeOut = *TimeOut;
|
||||
TimeOut = &SafeTimeOut;
|
||||
}
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
/* Capture arguments */
|
||||
_SEH_TRY
|
||||
{
|
||||
if(PreviousMode != KernelMode)
|
||||
{
|
||||
ProbeForRead(HandleArray,
|
||||
ObjectCount * sizeof(HANDLE),
|
||||
sizeof(HANDLE));
|
||||
|
||||
if(TimeOut)
|
||||
{
|
||||
ProbeForRead(TimeOut,
|
||||
sizeof(LARGE_INTEGER),
|
||||
sizeof(ULONG));
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
/* Make a local copy of the timeout on the stack */
|
||||
SafeTimeOut = *TimeOut;
|
||||
TimeOut = &SafeTimeOut;
|
||||
}
|
||||
}
|
||||
|
||||
/* reference all objects */
|
||||
for (i = 0; i < ObjectCount; i++)
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(ObjectsArray[i],
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
&ObjectPtrArray[i],
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i]))
|
||||
{
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Waiting for object type '%wZ' is not supported\n",
|
||||
&BODY_TO_HEADER(ObjectPtrArray[i])->Type->Name);
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
i++;
|
||||
}
|
||||
/* dereference all referenced objects */
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
ObDereferenceObject(ObjectPtrArray[j]);
|
||||
}
|
||||
/*
|
||||
* Make a copy so we don't have to guard with SEH later and keep
|
||||
* track of what objects we referenced if dereferencing pointers
|
||||
* suddenly fails
|
||||
*/
|
||||
RtlCopyMemory(Handles,
|
||||
HandleArray,
|
||||
ObjectCount * sizeof(HANDLE));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
if(!NT_SUCCESS(Status)) goto Quickie;
|
||||
|
||||
Status = KeWaitForMultipleObjects(ObjectCount,
|
||||
ObjectPtrArray,
|
||||
WaitType,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
TimeOut,
|
||||
WaitBlockArray);
|
||||
/* Check if we can use the internal Wait Array */
|
||||
if (ObjectCount > THREAD_WAIT_OBJECTS)
|
||||
{
|
||||
/* Allocate from Pool */
|
||||
WaitBlockArray = ExAllocatePoolWithTag(NonPagedPool,
|
||||
ObjectCount * sizeof(KWAIT_BLOCK),
|
||||
TAG_WAIT);
|
||||
}
|
||||
|
||||
/* dereference all objects */
|
||||
for (i = 0; i < ObjectCount; i++)
|
||||
{
|
||||
ObDereferenceObject(ObjectPtrArray[i]);
|
||||
}
|
||||
/* Start the loop */
|
||||
do
|
||||
{
|
||||
/* Use the right Executive Handle */
|
||||
if(ObIsKernelHandle(Handles[i], PreviousMode))
|
||||
{
|
||||
/* Use the System Handle Table and decode */
|
||||
HandleTable = ObpKernelHandleTable;
|
||||
ExHandle = HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handles[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the Process' Handle table and get the Ex Handle */
|
||||
HandleTable = PsGetCurrentProcess()->ObjectTable;
|
||||
ExHandle = HANDLE_TO_EX_HANDLE(Handles[i]);
|
||||
}
|
||||
|
||||
return(Status);
|
||||
/* Get a pointer to it */
|
||||
if (!(HandleEntry = ExMapHandleToPointer(HandleTable, ExHandle)))
|
||||
{
|
||||
DPRINT1("Invalid handle\n");
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Check for synchronize access */
|
||||
GrantedAccess = HandleEntry->u2.GrantedAccess;
|
||||
if ((PreviousMode != KernelMode) && (!(GrantedAccess & SYNCHRONIZE)))
|
||||
{
|
||||
/* Unlock the entry and fail */
|
||||
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
DPRINT1("Handle doesn't have SYNCH access\n");
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Get the Object Header */
|
||||
ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
|
||||
|
||||
/* Get default Object */
|
||||
DefaultObject = ObjectHeader->Type->DefaultObject;
|
||||
|
||||
/* Check if it's the internal offset */
|
||||
if ((LONG_PTR)DefaultObject >= 0)
|
||||
{
|
||||
/* Increase reference count */
|
||||
InterlockedIncrement(&ObjectHeader->PointerCount);
|
||||
ReferencedObjects++;
|
||||
|
||||
/* Save the Object and Wait Object, this is a relative offset */
|
||||
Objects[i] = &ObjectHeader->Body;
|
||||
WaitObjects[i] = (PVOID)((ULONG_PTR)&ObjectHeader->Body +
|
||||
(ULONG_PTR)DefaultObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is our internal Object */
|
||||
ReferencedObjects++;
|
||||
Objects[i] = NULL;
|
||||
WaitObjects[i] = DefaultObject;
|
||||
}
|
||||
|
||||
/* Unlock the Handle Table Entry */
|
||||
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
||||
|
||||
/* Keep looping */
|
||||
i++;
|
||||
} while (i < ObjectCount);
|
||||
|
||||
/* For a Waitall, we can't have the same object more then once */
|
||||
if (WaitType == WaitAll)
|
||||
{
|
||||
/* Start the loop */
|
||||
do
|
||||
{
|
||||
/* Check the current and forward object */
|
||||
for (i = 0, j = i + 1; j < ObjectCount; j++)
|
||||
{
|
||||
/* Make sure they don't match */
|
||||
if (WaitObjects[i] == WaitObjects[j])
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_INVALID_PARAMETER_MIX;
|
||||
DPRINT1("Objects duplicated with WaitAll\n");
|
||||
goto Quickie;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep looping */
|
||||
i++;
|
||||
} while (i < ObjectCount);
|
||||
}
|
||||
|
||||
/* Now we can finally wait. Use SEH since it can raise an exception */
|
||||
_SEH_TRY
|
||||
{
|
||||
/* We're done playing with handles */
|
||||
LockInUse = FALSE;
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Do the kernel wait */
|
||||
Status = KeWaitForMultipleObjects(ObjectCount,
|
||||
WaitObjects,
|
||||
WaitType,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
TimeOut,
|
||||
WaitBlockArray);
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
Quickie:
|
||||
/* First derefence */
|
||||
while (ReferencedObjects)
|
||||
{
|
||||
ReferencedObjects--;
|
||||
if (Objects[ReferencedObjects])
|
||||
{
|
||||
ObDereferenceObject(Objects[ReferencedObjects]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free wait block array */
|
||||
if (WaitBlockArray) ExFreePool(WaitBlockArray);
|
||||
|
||||
/* Re-enable APCs if needed */
|
||||
if (LockInUse) KeLeaveCriticalRegion();
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtWaitForSingleObject(IN HANDLE ObjectHandle,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
{
|
||||
PVOID ObjectPtr;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PVOID Object, WaitableObject;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
|
||||
ObjectHandle,Alertable,TimeOut);
|
||||
DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
|
||||
ObjectHandle,Alertable,TimeOut);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* Get the Object */
|
||||
Status = ObReferenceObjectByHandle(ObjectHandle,
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
&Object,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Get the Waitable Object */
|
||||
WaitableObject = BODY_TO_HEADER(Object)->Type->DefaultObject;
|
||||
|
||||
Status = ObReferenceObjectByHandle(ObjectHandle,
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
&ObjectPtr,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
if (!KiIsObjectWaitable(ObjectPtr))
|
||||
{
|
||||
DPRINT1("Waiting for object type '%wZ' is not supported\n",
|
||||
&BODY_TO_HEADER(ObjectPtr)->Type->Name);
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = KeWaitForSingleObject(ObjectPtr,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
TimeOut);
|
||||
}
|
||||
/* Is it an offset for internal objects? */
|
||||
if ((LONG_PTR)WaitableObject >= 0)
|
||||
{
|
||||
/* Turn it into a pointer */
|
||||
WaitableObject = (PVOID)((ULONG_PTR)Object +
|
||||
(ULONG_PTR)WaitableObject);
|
||||
}
|
||||
|
||||
ObDereferenceObject(ObjectPtr);
|
||||
/* Now wait. Also SEH this since it can also raise an exception */
|
||||
_SEH_TRY
|
||||
{
|
||||
Status = KeWaitForSingleObject(WaitableObject,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
TimeOut);
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
return(Status);
|
||||
/* Dereference the Object */
|
||||
ObDereferenceObject(Object);
|
||||
}
|
||||
|
||||
/* Return the status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
|
||||
|
@ -204,15 +338,17 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
|
|||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
PDISPATCHER_HEADER Header;
|
||||
POBJECT_TYPE Type;
|
||||
PVOID SignalObj;
|
||||
PVOID WaitObj;
|
||||
PVOID WaitableObject;
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
OBJECT_HANDLE_INFORMATION HandleInfo;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
/* Capture timeout */
|
||||
if(!TimeOut && PreviousMode != KernelMode)
|
||||
DPRINT("NtSignalAndWaitForSingleObject\n");
|
||||
if(TimeOut && PreviousMode != KernelMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
|
@ -257,58 +393,65 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* FIXME: Use DefaultObject from ObjectHeader */
|
||||
Header = (PDISPATCHER_HEADER)SignalObj;
|
||||
|
||||
/* Check dispatcher type */
|
||||
/* FIXME: Check Object Type instead! */
|
||||
switch (Header->Type)
|
||||
/* Get the real waitable object */
|
||||
WaitableObject = BODY_TO_HEADER(WaitObj)->Type->DefaultObject;
|
||||
|
||||
/* Handle internal offset */
|
||||
if ((LONG_PTR)WaitableObject >= 0)
|
||||
{
|
||||
case EventNotificationObject:
|
||||
case EventSynchronizationObject:
|
||||
/* Set the Event */
|
||||
/* FIXME: Check permissions */
|
||||
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 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;
|
||||
|
||||
default:
|
||||
Status = STATUS_OBJECT_TYPE_MISMATCH;
|
||||
/* Get real pointer */
|
||||
WaitableObject = (PVOID)((ULONG_PTR)WaitObj +
|
||||
(ULONG_PTR)WaitableObject);
|
||||
}
|
||||
|
||||
/* Check Signal Object Type */
|
||||
Type = BODY_TO_HEADER(WaitObj)->Type;
|
||||
if (Type == ExEventObjectType)
|
||||
{
|
||||
/* Set the Event */
|
||||
/* FIXME: Check permissions */
|
||||
KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE);
|
||||
}
|
||||
else if (Type == ExMutantObjectType)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
else if (Type == ExSemaphoreObjectType)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_OBJECT_TYPE_MISMATCH;
|
||||
DPRINT1("Waiting on invalid object type\n");
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Now wait. Also SEH this since it can also raise an exception */
|
||||
_SEH_TRY
|
||||
{
|
||||
Status = KeWaitForSingleObject(WaitObj,
|
||||
Status = KeWaitForSingleObject(WaitableObject,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
|
|
|
@ -97,7 +97,6 @@ PsInitThreadManagment(VOID)
|
|||
ObjectTypeInitializer.GenericMapping = PiThreadMapping;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObjectTypeInitializer.DeleteProcedure = PspDeleteThread;
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &PsThreadType);
|
||||
|
||||
|
@ -138,7 +137,6 @@ PsInitProcessManagment(VOID)
|
|||
ObjectTypeInitializer.GenericMapping = PiProcessMapping;
|
||||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS;
|
||||
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
||||
ObjectTypeInitializer.DeleteProcedure = PspDeleteProcess;
|
||||
ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &PsProcessType);
|
||||
|
||||
|
|
Loading…
Reference in a new issue