- 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);