- 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. Modified: trunk/reactos/ntoskrnl/ex/callback.c Modified: trunk/reactos/ntoskrnl/ex/event.c Modified: trunk/reactos/ntoskrnl/ex/mutant.c Modified: trunk/reactos/ntoskrnl/ex/profile.c Modified: trunk/reactos/ntoskrnl/ex/win32k.c Modified: trunk/reactos/ntoskrnl/include/internal/ex.h Modified: trunk/reactos/ntoskrnl/include/ntoskrnl.h Modified: trunk/reactos/ntoskrnl/io/iomgr.c Modified: trunk/reactos/ntoskrnl/ke/wait.c Modified: trunk/reactos/ntoskrnl/ob/handle.c Modified: trunk/reactos/ntoskrnl/ob/wait.c Modified: trunk/reactos/ntoskrnl/ps/psmgr.c _____
Modified: trunk/reactos/ntoskrnl/ex/callback.c --- trunk/reactos/ntoskrnl/ex/callback.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ex/callback.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -91,7 +91,6 @@
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CALLBACK_OBJECT); ObjectTypeInitializer.GenericMapping = ExpCallbackMapping; ObjectTypeInitializer.PoolType = NonPagedPool; - ObjectTypeInitializer.UseDefaultObject = TRUE;
Status = ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExCallbackObjectType);
_____
Modified: trunk/reactos/ntoskrnl/ex/event.c --- trunk/reactos/ntoskrnl/ex/event.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ex/event.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -50,7 +50,6 @@
ObjectTypeInitializer.GenericMapping = ExpEventMapping; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS; - ObjectTypeInitializer.UseDefaultObject = TRUE; ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExEventObjectType); }
_____
Modified: trunk/reactos/ntoskrnl/ex/mutant.c --- trunk/reactos/ntoskrnl/ex/mutant.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ex/mutant.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -68,7 +68,6 @@
ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant; ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS; - ObjectTypeInitializer.UseDefaultObject = TRUE; ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExMutantObjectType); }
_____
Modified: trunk/reactos/ntoskrnl/ex/profile.c --- trunk/reactos/ntoskrnl/ex/profile.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ex/profile.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -94,7 +94,6 @@
ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.DeleteProcedure = ExpDeleteProfile; ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_ALL; - ObjectTypeInitializer.UseDefaultObject = TRUE; ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExProfileObjectType); }
_____
Modified: trunk/reactos/ntoskrnl/ex/win32k.c --- trunk/reactos/ntoskrnl/ex/win32k.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ex/win32k.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -133,7 +133,6 @@
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.GenericMapping = ExpWindowStationMapping; ObjectTypeInitializer.PoolType = NonPagedPool; - ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.OpenProcedure = ExpWinStaObjectOpen; ObjectTypeInitializer.DeleteProcedure = ExpWinStaObjectDelete; ObjectTypeInitializer.ParseProcedure = ExpWinStaObjectParse; _____
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h --- trunk/reactos/ntoskrnl/include/internal/ex.h 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/include/internal/ex.h 2005-08-07 21:29:51 UTC (rev 17179) @@ -8,6 +8,13 @@
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 _____
Modified: trunk/reactos/ntoskrnl/include/ntoskrnl.h --- trunk/reactos/ntoskrnl/include/ntoskrnl.h 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/include/ntoskrnl.h 2005-08-07 21:29:51 UTC (rev 17179) @@ -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> _____
Modified: trunk/reactos/ntoskrnl/io/iomgr.c --- trunk/reactos/ntoskrnl/io/iomgr.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/io/iomgr.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -217,6 +217,7 @@
ObjectTypeInitializer.DeleteProcedure = IopDeleteFile; ObjectTypeInitializer.SecurityProcedure = IopSecurityFile; ObjectTypeInitializer.QueryNameProcedure = IopQueryNameFile; + ObjectTypeInitializer.UseDefaultObject = FALSE; ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoFileObjectType);
/* _____
Modified: trunk/reactos/ntoskrnl/ke/wait.c --- trunk/reactos/ntoskrnl/ke/wait.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ke/wait.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -225,22 +225,6 @@
/* 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 @@ /* 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 @@ 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 _____
Modified: trunk/reactos/ntoskrnl/ob/handle.c --- trunk/reactos/ntoskrnl/ob/handle.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ob/handle.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -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 *****************************************************************/ _____
Modified: trunk/reactos/ntoskrnl/ob/wait.c --- trunk/reactos/ntoskrnl/ob/wait.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ob/wait.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -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 @@ 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 @@ return Status; }
- /* FIXME: Use DefaultObject from ObjectHeader */ - Header = (PDISPATCHER_HEADER)SignalObj; + /* Get the real waitable object */ + WaitableObject = BODY_TO_HEADER(WaitObj)->Type->DefaultObject; + + /* Handle internal offset */ + if ((LONG_PTR)WaitableObject >= 0) + { + /* Get real pointer */ + WaitableObject = (PVOID)((ULONG_PTR)WaitObj + + (ULONG_PTR)WaitableObject); + }
- /* Check dispatcher type */ - /* FIXME: Check Object Type instead! */ - switch (Header->Type) + /* Check Signal Object Type */ + Type = BODY_TO_HEADER(WaitObj)->Type; + if (Type == ExEventObjectType) { - 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; + /* 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, _____
Modified: trunk/reactos/ntoskrnl/ps/psmgr.c --- trunk/reactos/ntoskrnl/ps/psmgr.c 2005-08-07 20:33:11 UTC (rev 17178) +++ trunk/reactos/ntoskrnl/ps/psmgr.c 2005-08-07 21:29:51 UTC (rev 17179) @@ -97,7 +97,6 @@
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 @@ ObjectTypeInitializer.GenericMapping = PiProcessMapping; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS; - ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.DeleteProcedure = PspDeleteProcess; ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &PsProcessType);