- 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(a)relsoft.net) - Created file
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
* David Welch (welch(a)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);