- 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
--- 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);
--- 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); }
--- 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); }
--- 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); }
--- 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;
--- 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
--- 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>
--- 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); /*
--- 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
--- 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 *****************************************************************/
--- 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,
--- 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);