Reverting to 13775. Sorry for the mess. This is dedicated to Jane! 19934415.
authorAlex Ionescu <aionescu@gmail.com>
Mon, 28 Feb 2005 17:40:15 +0000 (17:40 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 28 Feb 2005 17:40:15 +0000 (17:40 +0000)
svn path=/trunk/; revision=13777

56 files changed:
reactos/config
reactos/drivers/storage/floppy/floppy.c
reactos/include/ddk/extypes.h
reactos/include/ddk/iotypes.h
reactos/include/ddk/ketypes.h
reactos/include/ntos/zwtypes.h
reactos/lib/ntdll/def/ntdll.def
reactos/ntoskrnl/Makefile
reactos/ntoskrnl/cm/registry.c
reactos/ntoskrnl/ex/error.c [deleted file]
reactos/ntoskrnl/ex/event.c
reactos/ntoskrnl/ex/evtpair.c
reactos/ntoskrnl/ex/init.c
reactos/ntoskrnl/ex/mutant.c
reactos/ntoskrnl/ex/rundown.c
reactos/ntoskrnl/ex/sem.c
reactos/ntoskrnl/ex/sysinfo.c
reactos/ntoskrnl/ex/timer.c
reactos/ntoskrnl/ex/work.c
reactos/ntoskrnl/include/internal/ex.h
reactos/ntoskrnl/include/internal/id.h
reactos/ntoskrnl/include/internal/io.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/include/internal/nls.h
reactos/ntoskrnl/include/internal/ntoskrnl.h
reactos/ntoskrnl/include/internal/ps.h
reactos/ntoskrnl/io/bootlog.c
reactos/ntoskrnl/io/create.c
reactos/ntoskrnl/io/driver.c
reactos/ntoskrnl/io/iocomp.c
reactos/ntoskrnl/io/iomgr.c
reactos/ntoskrnl/io/wmi.c
reactos/ntoskrnl/ke/alert.c [new file with mode: 0644]
reactos/ntoskrnl/ke/apc.c
reactos/ntoskrnl/ke/bug.c
reactos/ntoskrnl/ke/catch.c
reactos/ntoskrnl/ke/critical.c [new file with mode: 0644]
reactos/ntoskrnl/ke/dpc.c
reactos/ntoskrnl/ke/error.c [new file with mode: 0644]
reactos/ntoskrnl/ke/event.c
reactos/ntoskrnl/ke/i386/tskswitch.S
reactos/ntoskrnl/ke/kthread.c
reactos/ntoskrnl/ke/main.c
reactos/ntoskrnl/ke/mutex.c
reactos/ntoskrnl/ke/queue.c
reactos/ntoskrnl/ke/sem.c
reactos/ntoskrnl/ke/timer.c
reactos/ntoskrnl/ke/wait.c
reactos/ntoskrnl/ntoskrnl.def
reactos/ntoskrnl/ntoskrnl.mc
reactos/ntoskrnl/ob/wait.c [deleted file]
reactos/ntoskrnl/ps/kill.c
reactos/ntoskrnl/ps/process.c
reactos/ntoskrnl/ps/thread.c
reactos/ntoskrnl/rtl/nls.c
reactos/tools/nci/sysfuncs.lst

index 9a6cdff..5a8c1f6 100644 (file)
@@ -15,7 +15,7 @@ ARCH := i386
 # be optimze for. 
 #
 
-OARCH := pentium2
+OARCH := i486
 
 #
 # Whether to compile in the kernel debugger
@@ -30,7 +30,7 @@ DBG := 0
 #
 # Whether to compile with optimizations
 #
-OPTIMIZED := 1
+OPTIMIZED := 0
 
 #
 # Whether to compile a multiprocessor or single processor version
index 3447930..987eb2f 100644 (file)
@@ -58,7 +58,7 @@ static ULONG gNumberOfControllers = 0;
 
 /* Queue thread management */
 static KEVENT QueueThreadTerminate;
-static PVOID QueueThreadObject;
+static PVOID ThreadObject;
 
 \f
 static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
@@ -378,8 +378,8 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
   KdPrint(("floppy: unloading\n"));
 
   KeSetEvent(&QueueThreadTerminate, 0, FALSE);
-  KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0);
-  ObDereferenceObject(QueueThreadObject);
+  KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0);
+  ObDereferenceObject(ThreadObject);
 
   for(i = 0; i < gNumberOfControllers; i++)
     {
@@ -1152,7 +1152,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject,
       return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-  if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
+  if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ThreadObject, NULL) != STATUS_SUCCESS)
     {
       KdPrint(("floppy: Unable to reference returned thread handle; failing init\n"));
       return STATUS_UNSUCCESSFUL;
index 2c438f6..4db6f6d 100644 (file)
@@ -30,23 +30,6 @@ typedef enum _WORK_QUEUE_TYPE {
     MaximumWorkQueue
 } WORK_QUEUE_TYPE;
 
-typedef struct _EX_QUEUE_WORKER_INFO {
-    UCHAR QueueDisabled:1;
-    UCHAR MakeThreadsAsNecessary:1;
-    UCHAR WaitMode:1;
-    ULONG WorkerCount:29;
-} EX_QUEUE_WORKER_INFO, *PEX_QUEUE_WORKER_INFO;
-
-typedef struct _EX_WORK_QUEUE {
-    KQUEUE WorkerQueue;
-    ULONG DynamicThreadCount;
-    ULONG WorkItemsProcessed;
-    ULONG WorkItemsProcessedLastPass;
-    ULONG QueueDepthLastPass;
-    EX_QUEUE_WORKER_INFO Info;    
-} EX_WORK_QUEUE, *PEX_WORK_QUEUE;
-
-
 typedef ULONG_PTR ERESOURCE_THREAD, *PERESOURCE_THREAD;
 
 typedef struct _OWNER_ENTRY
@@ -257,10 +240,6 @@ typedef VOID STDCALL_FUNC
                      PVOID Argument1,
                      PVOID Argument2);
 
-extern struct _OBJECT_TYPE EXPORTED *ExMutantObjectType;
-extern struct _OBJECT_TYPE EXPORTED *ExSemaphoreObjectType;
-extern struct _OBJECT_TYPE EXPORTED *ExTimerType;
-
 #endif /* __INCLUDE_DDK_EXTYPES_H */
 
 /* EOF */
index 379cfc8..bca0769 100644 (file)
@@ -886,8 +886,6 @@ struct _FAST_IO_DISPATCH_TABLE
 #endif
 
 #define IO_TYPE_DRIVER 4L
-#define IO_TYPE_FILE 0x0F5L
-
 #define DRVO_UNLOAD_INVOKED 0x1L
 #define DRVO_LEGACY_DRIVER  0x2L
 #define DRVO_BUILTIN_DRIVER 0x4L
index b938fc6..ce77b02 100644 (file)
@@ -36,34 +36,23 @@ typedef VOID STDCALL_FUNC
 
 struct _DISPATCHER_HEADER;
 
-typedef enum _KOBJECTS {
-   EventNotificationObject = 0,
-   EventSynchronizationObject = 1,
-   MutantObject = 2,
-   ProcessObject = 3,
-   QueueObject = 4,
-   SemaphoreObject = 5,
-   ThreadObject = 6,
-   GateObject = 7,
-   TimerNotificationObject = 8,
-   TimerSynchronizationObject = 9,
-   Spare2Object = 10,
-   Spare3Object = 11,
-   Spare4Object = 12,
-   Spare5Object = 13,
-   Spare6Object = 14,
-   Spare7Object = 15,
-   Spare8Object = 16,
-   Spare9Object = 17,
-   ApcObject = 18,
-   DpcObject = 19,
-   DeviceQueueObject = 20,
-   EventPairObject = 21,
-   InterruptObject = 22,
-   ProfileObject = 23,
-   ThreadedDpcObject = 24,
-   MaximumKernelObject = 25
-} KOBJECTS;
+typedef enum _KERNEL_OBJECTS {
+       KNotificationEvent = 0,
+       KSynchronizationEvent = 1,
+       KMutant = 2,
+       KProcess = 3,
+       KQueue = 4,
+       KSemaphore = 5,
+       KThread = 6,
+       KNotificationTimer = 8,
+       KSynchronizationTimer = 9,
+       KApc = 18,
+       KDpc = 19,
+       KDeviceQueue = 20,
+       KEventPair = 21,
+       KInterrupt = 22,
+       KProfile = 23
+} KERNEL_OBJECTS;
 
 #include <pshpack1.h>
 
index 78f6d1e..37ba0b1 100755 (executable)
@@ -1262,9 +1262,9 @@ typedef enum _MUTANT_INFORMATION_CLASS
 
 typedef struct _MUTANT_BASIC_INFORMATION
 {
-  LONG CurrentCount;
-  BOOLEAN OwnedByCaller;
-  BOOLEAN AbandonedState;
+  LONG Count;
+  BOOLEAN Owned;
+  BOOLEAN Abandoned;
 } MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
 
 
index 66e909c..f9101ba 100644 (file)
@@ -225,6 +225,7 @@ NtSetEaFile@16
 NtSetEvent@8
 NtSetHighEventPair@4
 NtSetHighWaitLowEventPair@4
+NtSetHighWaitLowThread@0
 NtSetInformationFile@20
 NtSetInformationJobObject@16
 NtSetInformationKey@16
@@ -237,6 +238,7 @@ NtSetIoCompletion@20
 NtSetLdtEntries@24
 NtSetLowEventPair@4
 NtSetLowWaitHighEventPair@4
+NtSetLowWaitHighThread@0
 NtSetSecurityObject@12
 NtSetSystemEnvironmentValue@8
 NtSetSystemInformation@12
@@ -847,6 +849,7 @@ ZwSetEaFile@16
 ZwSetEvent@8
 ZwSetHighEventPair@4
 ZwSetHighWaitLowEventPair@4
+ZwSetHighWaitLowThread@0
 ZwSetInformationFile@20
 ZwSetInformationKey@16
 ZwSetInformationObject@16
@@ -858,6 +861,7 @@ ZwSetIoCompletion@20
 ZwSetLdtEntries@24
 ZwSetLowEventPair@4
 ZwSetLowWaitHighEventPair@4
+ZwSetLowWaitHighThread@0
 ZwSetSecurityObject@12
 ZwSetSystemEnvironmentValue@8
 ZwSetSystemInformation@12
index ca48237..9dc41bf 100644 (file)
@@ -101,8 +101,10 @@ OBJECTS_KE = \
        ke/bug.o \
        ke/catch.o \
        ke/clock.o \
+       ke/critical.o \
        ke/dpc.o \
        ke/device.o \
+       ke/error.o \
        ke/event.o \
        ke/kqueue.o \
        ke/kthread.o \
@@ -116,6 +118,7 @@ OBJECTS_KE = \
        ke/spinlock.o \
        ke/timer.o \
        ke/wait.o \
+       ke/alert.o
 
 # Memory Manager (Mm)
 OBJECTS_MM = \
@@ -216,8 +219,7 @@ OBJECTS_OB = \
        ob/object.o \
        ob/sdcache.o \
        ob/security.o \
-       ob/symlink.o \
-       ob/wait.o
+       ob/symlink.o
 
 # Process Manager (Ps)
 OBJECTS_PS = \
@@ -240,7 +242,6 @@ OBJECTS_PS = \
 OBJECTS_EX = \
        ex/btree.o \
        ex/callback.o \
-       ex/error.o \
        ex/event.o \
        ex/evtpair.o \
        ex/fmutex.o \
index 919c307..304192c 100644 (file)
@@ -241,29 +241,6 @@ CmiCheckRegistry(BOOLEAN Verbose)
   CmiCheckByName(Verbose, L"User");
 }
 
-VOID
-INIT_FUNCTION
-STDCALL
-CmInitHives(BOOLEAN SetupBoot)
-{
-    PCHAR BaseAddress;
-    
-    /* Load Registry Hives */
-    BaseAddress = (PCHAR)CachedModules[SystemRegistry]->ModStart;
-    CmImportSystemHive(BaseAddress,
-                       CachedModules[SystemRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
-    
-    BaseAddress = (PCHAR)CachedModules[HardwareRegistry]->ModStart;
-    CmImportHardwareHive(BaseAddress,
-                         CachedModules[HardwareRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
-    
-
-    /* Create dummy keys if no hardware hive was found */
-    CmImportHardwareHive (NULL, 0);
-
-    /* Initialize volatile registry settings */
-    if (SetupBoot == FALSE) CmInit2((PCHAR)KeLoaderBlock.CommandLine);
-}   
 
 VOID INIT_FUNCTION
 CmInitializeRegistry(VOID)
diff --git a/reactos/ntoskrnl/ex/error.c b/reactos/ntoskrnl/ex/error.c
deleted file mode 100644 (file)
index d1d99a5..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/ex/error.c
- * PURPOSE:         Error Functions and Status/Exception Dispatching/Raising
- *
- * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net) - Created File
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* GLOBALS ****************************************************************/
-
-BOOLEAN ExReadyForErrors = FALSE;
-PEPORT ExpDefaultErrorPort = NULL;
-PEPROCESS ExpDefaultErrorPortProcess = NULL;
-
-/* FUNCTIONS ****************************************************************/
-
-/*
- * @implemented
- */
-VOID 
-STDCALL
-ExRaiseAccessViolation(VOID)
-{
-    /* Raise the Right Status */
-    ExRaiseStatus (STATUS_ACCESS_VIOLATION);
-}
-
-/*
- * @implemented
- */
-VOID
-STDCALL
-ExRaiseDatatypeMisalignment (VOID)
-{
-    /* Raise the Right Status */
-    ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
-}
-
-/*
- * @implemented
- */
-VOID 
-STDCALL
-ExRaiseStatus(IN NTSTATUS Status)
-{
-    EXCEPTION_RECORD ExceptionRecord;
-
-    DPRINT("ExRaiseStatus(%x)\n", Status);
-
-    /* Set up an Exception Record */
-    ExceptionRecord.ExceptionRecord = NULL;
-    ExceptionRecord.NumberParameters = 0;
-    ExceptionRecord.ExceptionCode = Status;
-    ExceptionRecord.ExceptionFlags = 0;
-    
-    /* Call the Rtl Function */
-    RtlRaiseException(&ExceptionRecord);
-}
-
-/*
- * @implemented
- */
-VOID
-STDCALL
-ExRaiseException (PEXCEPTION_RECORD ExceptionRecord)
-{
-    /* Call the Rtl function */
-    RtlRaiseException(ExceptionRecord);
-}
-
-/*
- * @implemented
- */
-BOOLEAN
-STDCALL
-ExSystemExceptionFilter(VOID)
-{
-    return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
-}
-
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-ExRaiseHardError(IN NTSTATUS ErrorStatus,
-                 IN ULONG NumberOfParameters, 
-                 IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
-                 IN PVOID *Parameters, 
-                 IN HARDERROR_RESPONSE_OPTION ResponseOption, 
-                 OUT PHARDERROR_RESPONSE Response)
-{
-    UNIMPLEMENTED;
-}
-
-NTSTATUS 
-STDCALL 
-NtRaiseHardError(IN NTSTATUS ErrorStatus,
-                 IN ULONG NumberOfParameters,
-                 IN PUNICODE_STRING UnicodeStringParameterMask  OPTIONAL,
-                 IN PVOID *Parameters,
-                 IN HARDERROR_RESPONSE_OPTION ResponseOption,
-                 OUT PHARDERROR_RESPONSE Response)
-{
-    DPRINT1("Hard error %x\n", ErrorStatus);
-  
-    /* Call the Executive Function (WE SHOULD PUT SEH HERE/CAPTURE!) */
-    ExRaiseHardError(ErrorStatus,
-                     NumberOfParameters,
-                     UnicodeStringParameterMask,
-                     Parameters,
-                     ResponseOption,
-                     Response);
-  
-    /* Return Success */
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS 
-STDCALL 
-NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
-{
-    
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_UNSUCCESSFUL;
-  
-    /* Check if we have the Privilege */
-    if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) {
-        
-        DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
-        return STATUS_PRIVILEGE_NOT_HELD;
-    }
-  
-    /* Only called once during bootup, make sure we weren't called yet */
-    if(!ExReadyForErrors) {
-        
-        Status = ObReferenceObjectByHandle(PortHandle,
-                                           0,
-                                           LpcPortObjectType,
-                                           PreviousMode,
-                                           (PVOID*)&ExpDefaultErrorPort,
-                                           NULL);
-        
-        /* Check for Success */
-        if(NT_SUCCESS(Status)) {
-            
-            /* Save the data */
-            ExpDefaultErrorPortProcess = PsGetCurrentProcess();
-            ExReadyForErrors = TRUE;
-        }
-    }
-  
-    return Status;
-}
-
-/* EOF */
index c05fedb..4db20f5 100644 (file)
 POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
 
 static GENERIC_MAPPING ExpEventMapping = {
-    STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
-    STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
-    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
-    EVENT_ALL_ACCESS};
-
-static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
-    
-    /* EventBasicInformation */
-    ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
+       STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
+       STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
+       STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
+       EVENT_ALL_ACCESS};
+
+static const INFORMATION_CLASS_INFO ExEventInfoClass[] =
+{
+  ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* EventBasicInformation */
 };
 
 /* FUNCTIONS *****************************************************************/
 
-VOID 
-INIT_FUNCTION
+NTSTATUS STDCALL
+NtpCreateEvent(PVOID ObjectBody,
+              PVOID Parent,
+              PWSTR RemainingPath,
+              POBJECT_ATTRIBUTES ObjectAttributes)
+{
+  DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+        ObjectBody, Parent, RemainingPath);
+
+  if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
+    {
+      return(STATUS_UNSUCCESSFUL);
+    }
+
+  return(STATUS_SUCCESS);
+}
+
+
+VOID INIT_FUNCTION
 ExpInitializeEventImplementation(VOID)
 {
-    /* Create the Event Object Type */
-    ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-    RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
-    ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
-    ExEventObjectType->PeakObjects = 0;
-    ExEventObjectType->PeakHandles = 0;
-    ExEventObjectType->TotalObjects = 0;
-    ExEventObjectType->TotalHandles = 0;
-    ExEventObjectType->PagedPoolCharge = 0;
-    ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
-    ExEventObjectType->Mapping = &ExpEventMapping;
-    ExEventObjectType->Dump = NULL;
-    ExEventObjectType->Open = NULL;
-    ExEventObjectType->Close = NULL;
-    ExEventObjectType->Delete = NULL;
-    ExEventObjectType->Parse = NULL;
-    ExEventObjectType->Security = NULL;
-    ExEventObjectType->QueryName = NULL;
-    ExEventObjectType->OkayToClose = NULL;
-    ExEventObjectType->Create = NULL;
-    ExEventObjectType->DuplicationNotify = NULL;
-    ObpCreateTypeObject(ExEventObjectType);
+   ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
+   
+   RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
+   
+   ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
+   ExEventObjectType->PeakObjects = 0;
+   ExEventObjectType->PeakHandles = 0;
+   ExEventObjectType->TotalObjects = 0;
+   ExEventObjectType->TotalHandles = 0;
+   ExEventObjectType->PagedPoolCharge = 0;
+   ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
+   ExEventObjectType->Mapping = &ExpEventMapping;
+   ExEventObjectType->Dump = NULL;
+   ExEventObjectType->Open = NULL;
+   ExEventObjectType->Close = NULL;
+   ExEventObjectType->Delete = NULL;
+   ExEventObjectType->Parse = NULL;
+   ExEventObjectType->Security = NULL;
+   ExEventObjectType->QueryName = NULL;
+   ExEventObjectType->OkayToClose = NULL;
+   ExEventObjectType->Create = NtpCreateEvent;
+   ExEventObjectType->DuplicationNotify = NULL;
+
+   ObpCreateTypeObject(ExEventObjectType);
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtClearEvent(IN HANDLE EventHandle)
 {
-    PKEVENT Event;
-    NTSTATUS Status;
-    
-    PAGED_CODE();
+   PKEVENT Event;
+   NTSTATUS Status;
    
-    /* Reference the Object */
-   Status = ObReferenceObjectByHandle(EventHandle,
-                                      EVENT_MODIFY_STATE,
-                                      ExEventObjectType,
-                                      ExGetPreviousMode(),
-                                      (PVOID*)&Event,
-                                      NULL);
+   PAGED_CODE();
    
-   /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Clear the Event and Dereference */
-        KeClearEvent(Event);
-        ObDereferenceObject(Event);
-    }
+   Status = ObReferenceObjectByHandle(EventHandle,
+                                     EVENT_MODIFY_STATE,
+                                     ExEventObjectType,
+                                     ExGetPreviousMode(),
+                                     (PVOID*)&Event,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     KeClearEvent(Event);
+     ObDereferenceObject(Event);
+   }
    
-    /* Return Status */
-    return Status;
+   return Status;
 }
 
 
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtCreateEvent(OUT PHANDLE EventHandle,
-              IN ACCESS_MASK DesiredAccess,
-              IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
-              IN EVENT_TYPE EventType,
-              IN BOOLEAN InitialState)
+             IN ACCESS_MASK DesiredAccess,
+             IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
+             IN EVENT_TYPE EventType,
+             IN BOOLEAN InitialState)
 {
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    PKEVENT Event;
-    HANDLE hEvent;
-    NTSTATUS Status = STATUS_SUCCESS;
+   KPROCESSOR_MODE PreviousMode;
+   PKEVENT Event;
+   HANDLE hEvent;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
+   PAGED_CODE();
  
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(EventHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
+   PreviousMode = ExGetPreviousMode();
+   if(PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(EventHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
      
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Create the Object */
-    Status = ObCreateObject(PreviousMode,
-                            ExEventObjectType,
-                            ObjectAttributes,
-                            PreviousMode,
-                            NULL,
-                            sizeof(KEVENT),
-                            0,
-                            0,
-                            (PVOID*)&Event);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Initalize the Event */
-        KeInitializeEvent(Event,
-                          EventType,
-                          InitialState);
-        
-        /* Insert it */
-        Status = ObInsertObject((PVOID)Event,
-                                 NULL,
-                                 DesiredAccess,
-                                 0,
-                                 NULL,
-                                 &hEvent);
-        ObDereferenceObject(Event);
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
  
-        /* Check for success and return handle */
-        if(NT_SUCCESS(Status)) {
-            
-            _SEH_TRY {
-                
-                *EventHandle = hEvent;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-                
-            } _SEH_END;
-        }
-    }
-
-    /* Return Status */
-    return Status;
+   Status = ObCreateObject(PreviousMode,
+                           ExEventObjectType,
+                           ObjectAttributes,
+                           PreviousMode,
+                           NULL,
+                           sizeof(KEVENT),
+                           0,
+                           0,
+                           (PVOID*)&Event);
+   if(NT_SUCCESS(Status))
+   {
+     KeInitializeEvent(Event,
+                       EventType,
+                       InitialState);
+     Status = ObInsertObject((PVOID)Event,
+                             NULL,
+                             DesiredAccess,
+                             0,
+                             NULL,
+                             &hEvent);
+     ObDereferenceObject(Event);
+     if(NT_SUCCESS(Status))
+     {
+       _SEH_TRY
+       {
+         *EventHandle = hEvent;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
+   }
+   return Status;
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtOpenEvent(OUT PHANDLE EventHandle,
-            IN ACCESS_MASK DesiredAccess,
-            IN POBJECT_ATTRIBUTES ObjectAttributes)
+           IN ACCESS_MASK DesiredAccess,
+           IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-    HANDLE hEvent;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   HANDLE hEvent;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-    DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
-
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(EventHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
+   PAGED_CODE();
+   
+   DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
+
+   PreviousMode = ExGetPreviousMode();
+   
+   if(PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(EventHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
      
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Open the Object */
-    Status = ObOpenObjectByName(ObjectAttributes,
-                                ExEventObjectType,
-                                NULL,
-                                PreviousMode,
-                                DesiredAccess,
-                                NULL,
-                                &hEvent);
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObOpenObjectByName(ObjectAttributes,
+                              ExEventObjectType,
+                              NULL,
+                              PreviousMode,
+                              DesiredAccess,
+                              NULL,
+                              &hEvent);
              
-    /* Check for success and return handle */
-    if(NT_SUCCESS(Status)) {
-            
-        _SEH_TRY {
-            
-            *EventHandle = hEvent;
-                
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-    }
+   if(NT_SUCCESS(Status))
+   {
+     _SEH_TRY
+     {
+       *EventHandle = hEvent;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
    
-    /* Return status */
-    return Status;
+   return Status;
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtPulseEvent(IN HANDLE EventHandle,
-             OUT PLONG PreviousState OPTIONAL)
+            OUT PLONG PreviousState  OPTIONAL)
 {
-    PKEVENT Event;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   PKEVENT Event;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-    DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
-            EventHandle, PreviousState);
-
-    /* Check buffer validity */
-    if(PreviousState && PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(PreviousState,
-                          sizeof(LONG),
-                          sizeof(ULONG));
-         } _SEH_HANDLE {
-             
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
+   PAGED_CODE();
 
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventHandle,
-                                       EVENT_MODIFY_STATE,
-                                       ExEventObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Event,
-                                       NULL);
-    
-    /* Check for success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Pulse the Event */
-        LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
-        ObDereferenceObject(Event);
+   DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
+         EventHandle, PreviousState);
+
+   PreviousMode = ExGetPreviousMode();
+   
+   if(PreviousState != NULL && PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(PreviousState,
+                     sizeof(LONG),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
      
-        /* Return it */        
-        if(PreviousState) {
-            
-            _SEH_TRY {
-                
-                *PreviousState = Prev;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-            
-            } _SEH_END;
-        }
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObReferenceObjectByHandle(EventHandle,
+                                     EVENT_MODIFY_STATE,
+                                     ExEventObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Event,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
+     ObDereferenceObject(Event);
+     
+     if(PreviousState != NULL)
+     {
+       _SEH_TRY
+       {
+         *PreviousState = Prev;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
    }
 
-   /* Return Status */
    return Status;
 }
 
@@ -306,202 +320,230 @@ NtPulseEvent(IN HANDLE EventHandle,
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtQueryEvent(IN HANDLE EventHandle,
-             IN EVENT_INFORMATION_CLASS EventInformationClass,
-             OUT PVOID EventInformation,
-             IN ULONG EventInformationLength,
-             OUT PULONG ReturnLength  OPTIONAL)
+            IN EVENT_INFORMATION_CLASS EventInformationClass,
+            OUT PVOID EventInformation,
+            IN ULONG EventInformationLength,
+            OUT PULONG ReturnLength  OPTIONAL)
 {
-    PKEVENT Event;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
-    PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
-    
-    /* Check buffers and class validity */
-    DefaultQueryInfoBufferCheck(EventInformationClass,
-                                ExEventInfoClass,
-                                EventInformation,
-                                EventInformationLength,
-                                ReturnLength,
-                                PreviousMode,
-                                &Status);
-    if(!NT_SUCCESS(Status)) {
-        
-        /* Invalid buffers */
-        DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
-        return Status;
-    }
+   PKEVENT Event;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    /* Get the Object */
-    Status = ObReferenceObjectByHandle(EventHandle,
-                                       EVENT_QUERY_STATE,
-                                       ExEventObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Event,
-                                       NULL);
-    
-    /* Check for success */
-    if(NT_SUCCESS(Status)) {
-
-        _SEH_TRY {
-            
-            /* Return Event Type and State */
-            BasicInfo->EventType = Event->Header.Type;
-            BasicInfo->EventState = KeReadStateEvent(Event);
-
-            /* Return length */
-            if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
-            
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-     
-        /* Dereference the Object */
-        ObDereferenceObject(Event);
+   PAGED_CODE();
+
+   PreviousMode = ExGetPreviousMode();
+   
+   DefaultQueryInfoBufferCheck(EventInformationClass,
+                               ExEventInfoClass,
+                               EventInformation,
+                               EventInformationLength,
+                               ReturnLength,
+                               PreviousMode,
+                               &Status);
+   if(!NT_SUCCESS(Status))
+   {
+     DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status);
+     return Status;
+   }
+
+   Status = ObReferenceObjectByHandle(EventHandle,
+                                     EVENT_QUERY_STATE,
+                                     ExEventObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Event,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     switch(EventInformationClass)
+     {
+       case EventBasicInformation:
+       {
+         PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
+         
+         _SEH_TRY
+         {
+           if (Event->Header.Type == InternalNotificationEvent)
+             BasicInfo->EventType = NotificationEvent;
+           else
+             BasicInfo->EventType = SynchronizationEvent;
+           BasicInfo->EventState = KeReadStateEvent(Event);
+
+           if(ReturnLength != NULL)
+           {
+             *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
+           }
+         }
+         _SEH_HANDLE
+         {
+           Status = _SEH_GetExceptionCode();
+         }
+         _SEH_END;
+         break;
+       }
+
+       default:
+         Status = STATUS_NOT_IMPLEMENTED;
+         break;
+     }
+
+     ObDereferenceObject(Event);
    }
 
-   /* Return status */
    return Status;
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtResetEvent(IN HANDLE EventHandle,
-             OUT PLONG PreviousState OPTIONAL)
+            OUT PLONG PreviousState  OPTIONAL)
 {
-    PKEVENT Event;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   PKEVENT Event;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-
-    DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
-            EventHandle, PreviousState);
-
-    /* Check buffer validity */
-    if(PreviousState && PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(PreviousState,
-                          sizeof(LONG),
-                          sizeof(ULONG));
-         } _SEH_HANDLE {
-             
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-
-        if(!NT_SUCCESS(Status)) return Status;
-    }
+   PAGED_CODE();
+
+   DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
+         EventHandle, PreviousState);
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousState != NULL && PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(PreviousState,
+                     sizeof(LONG),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
 
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventHandle,
-                                       EVENT_MODIFY_STATE,
-                                       ExEventObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Event,
-                                       NULL);
-    
-    /* Check for success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Reset the Event */
-        LONG Prev = KeResetEvent(Event);
-        ObDereferenceObject(Event);
+   Status = ObReferenceObjectByHandle(EventHandle,
+                                     EVENT_MODIFY_STATE,
+                                     ExEventObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Event,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     LONG Prev = KeResetEvent(Event);
+     ObDereferenceObject(Event);
      
-        /* Return it */        
-        if(PreviousState) {
-            
-            _SEH_TRY {
-                
-                *PreviousState = Prev;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-            
-            } _SEH_END;
-        }
+     if(PreviousState != NULL)
+     {
+       _SEH_TRY
+       {
+         *PreviousState = Prev;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
    }
 
-   /* Return Status */
    return Status;
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtSetEvent(IN HANDLE EventHandle,
-           OUT PLONG PreviousState  OPTIONAL)
+          OUT PLONG PreviousState  OPTIONAL)
 {
-    PKEVENT Event;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   PKEVENT Event;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-
-    DPRINT1("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
-            EventHandle, PreviousState);
-
-    /* Check buffer validity */
-    if(PreviousState != NULL && PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(PreviousState,
-                          sizeof(LONG),
-                          sizeof(ULONG));
-         } _SEH_HANDLE {
-             
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-
-        if(!NT_SUCCESS(Status)) return Status;
-    }
+   PAGED_CODE();
+
+   DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
+         EventHandle, PreviousState);
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousState != NULL && PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(PreviousState,
+                     sizeof(LONG),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
 
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventHandle,
-                                       EVENT_MODIFY_STATE,
-                                       ExEventObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Event,
-                                       NULL);
-    
-    /* Check for success */
-    if(NT_SUCCESS(Status)) {
-
-        /* Set the Event */
-        LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
-        ObDereferenceObject(Event);
-
-        /* Return it */        
-        if(PreviousState) {
-            
-            _SEH_TRY {
-                
-                *PreviousState = Prev;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-            
-            } _SEH_END;
-        }
+   Status = ObReferenceObjectByHandle(EventHandle,
+                                     EVENT_MODIFY_STATE,
+                                     ExEventObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Event,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
+     ObDereferenceObject(Event);
+
+     if(PreviousState != NULL)
+     {
+       _SEH_TRY
+       {
+         *PreviousState = Prev;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
    }
 
-   /* Return Status */
    return Status;
 }
 
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+NtTraceEvent(
+       IN ULONG TraceHandle,
+       IN ULONG Flags,
+       IN ULONG TraceHeaderLength,
+       IN struct _EVENT_TRACE_HEADER* TraceHeader
+       )
+{
+       UNIMPLEMENTED;
+       return STATUS_NOT_IMPLEMENTED;
+}
+
+
 /* EOF */
index 05876a7..15b05e6 100644 (file)
@@ -1,11 +1,11 @@
-/*
+/* $Id: evtpair.c 12779 2005-01-04 04:45:00Z gdalsnes $
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ex/evtpair.c
  * PURPOSE:         Support for event pairs
  *
- * PROGRAMMERS:     Alex Ionescu (Commented, reorganized, removed Thread Pair, used KeInitializeEventPair, added SEH)
- *                  David Welch (welch@mcmail.com)
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
  *                  Skywing (skywing@valhallalegends.com)
  */
 
 #define NDEBUG
 #include <internal/debug.h>
 
+#ifndef NTSYSAPI
+#define NTSYSAPI
+#endif
+
+#ifndef NTAPI
+#define NTAPI STDCALL
+#endif
+
+
 /* GLOBALS *******************************************************************/
 
 POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
 
 static GENERIC_MAPPING ExEventPairMapping = {
-    STANDARD_RIGHTS_READ,
-    STANDARD_RIGHTS_WRITE,
-    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
-    EVENT_PAIR_ALL_ACCESS};
+       STANDARD_RIGHTS_READ,
+       STANDARD_RIGHTS_WRITE,
+       STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
+       EVENT_PAIR_ALL_ACCESS};
 
+static KSPIN_LOCK ExThreadEventPairSpinLock;
 
 /* FUNCTIONS *****************************************************************/
 
-VOID
-INIT_FUNCTION
+NTSTATUS STDCALL
+ExpCreateEventPair(PVOID ObjectBody,
+                  PVOID Parent,
+                  PWSTR RemainingPath,
+                  POBJECT_ATTRIBUTES ObjectAttributes)
+{
+  DPRINT("ExpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+        ObjectBody, Parent, RemainingPath);
+
+  if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
+    {
+      return(STATUS_UNSUCCESSFUL);
+    }
+  
+  return(STATUS_SUCCESS);
+}
+
+VOID INIT_FUNCTION
 ExpInitializeEventPairImplementation(VOID)
 {
-    /* Create the Event Pair Object Type */
-    ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-    RtlpCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair", NonPagedPool);
-    ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a');
-    ExEventPairObjectType->PeakObjects = 0;
-    ExEventPairObjectType->PeakHandles = 0;
-    ExEventPairObjectType->TotalObjects = 0;
-    ExEventPairObjectType->TotalHandles = 0;
-    ExEventPairObjectType->PagedPoolCharge = 0;
-    ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR);
-    ExEventPairObjectType->Mapping = &ExEventPairMapping;
-    ExEventPairObjectType->Dump = NULL;
-    ExEventPairObjectType->Open = NULL;
-    ExEventPairObjectType->Close = NULL;
-    ExEventPairObjectType->Delete = NULL;
-    ExEventPairObjectType->Parse = NULL;
-    ExEventPairObjectType->Security = NULL;
-    ExEventPairObjectType->QueryName = NULL;
-    ExEventPairObjectType->OkayToClose = NULL;
-    ExEventPairObjectType->Create = NULL;
-    ExEventPairObjectType->DuplicationNotify = NULL;
-    ObpCreateTypeObject(ExEventPairObjectType);
+   ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
+   
+   RtlpCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair", NonPagedPool);
+   ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a');
+   ExEventPairObjectType->PeakObjects = 0;
+   ExEventPairObjectType->PeakHandles = 0;
+   ExEventPairObjectType->TotalObjects = 0;
+   ExEventPairObjectType->TotalHandles = 0;
+   ExEventPairObjectType->PagedPoolCharge = 0;
+   ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR);
+   ExEventPairObjectType->Mapping = &ExEventPairMapping;
+   ExEventPairObjectType->Dump = NULL;
+   ExEventPairObjectType->Open = NULL;
+   ExEventPairObjectType->Close = NULL;
+   ExEventPairObjectType->Delete = NULL;
+   ExEventPairObjectType->Parse = NULL;
+   ExEventPairObjectType->Security = NULL;
+   ExEventPairObjectType->QueryName = NULL;
+   ExEventPairObjectType->OkayToClose = NULL;
+   ExEventPairObjectType->Create = ExpCreateEventPair;
+   ExEventPairObjectType->DuplicationNotify = NULL;
+
+   KeInitializeSpinLock(&ExThreadEventPairSpinLock);
+   ObpCreateTypeObject(ExEventPairObjectType);
 }
 
-NTSTATUS
-STDCALL
+
+NTSTATUS STDCALL
 NtCreateEventPair(OUT PHANDLE EventPairHandle,
-                  IN ACCESS_MASK DesiredAccess,
-                  IN POBJECT_ATTRIBUTES ObjectAttributes)
+                 IN ACCESS_MASK DesiredAccess,
+                 IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-    PKEVENT_PAIR EventPair;
-    HANDLE hEventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
-    
-    DPRINT1("NtCreateEventPair: %x\n", EventPairHandle);
+   PKEVENT_PAIR EventPair;
+   HANDLE hEventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+   
+   PAGED_CODE();
    
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(EventPairHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(EventPairHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
      
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Create the Object */
-    DPRINT1("Creating EventPair\n");
-    Status = ObCreateObject(PreviousMode,
-                            ExEventPairObjectType,
-                            ObjectAttributes,
-                            PreviousMode,
-                            NULL,
-                            sizeof(KEVENT_PAIR),
-                            0,
-                            0,
-                            (PVOID*)&EventPair);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Initalize the Event */
-        DPRINT1("Initializing EventPair\n");
-        KeInitializeEventPair(EventPair);
-        
-        /* Insert it */
-        Status = ObInsertObject((PVOID)EventPair,
-                                 NULL,
-                                 DesiredAccess,
-                                 0,
-                                 NULL,
-                                 &hEventPair);
-        ObDereferenceObject(EventPair);
-        /* Check for success and return handle */
-        if(NT_SUCCESS(Status)) {
-            
-            _SEH_TRY {
-                
-                *EventPairHandle = hEventPair;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-                
-            } _SEH_END;
-        }
-    }
-
-    /* Return Status */
-    return Status;
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObCreateObject(PreviousMode,
+                          ExEventPairObjectType,
+                          ObjectAttributes,
+                          PreviousMode,
+                          NULL,
+                          sizeof(KEVENT_PAIR),
+                          0,
+                          0,
+                          (PVOID*)&EventPair);
+   if(NT_SUCCESS(Status))
+   {
+     KeInitializeEvent(&EventPair->LowEvent,
+                      SynchronizationEvent,
+                      FALSE);
+     KeInitializeEvent(&EventPair->HighEvent,
+                      SynchronizationEvent,
+                      FALSE);
+
+     Status = ObInsertObject ((PVOID)EventPair,
+                             NULL,
+                             DesiredAccess,
+                             0,
+                             NULL,
+                             &hEventPair);
+     ObDereferenceObject(EventPair);
+     
+     if(NT_SUCCESS(Status))
+     {
+       _SEH_TRY
+       {
+         *EventPairHandle = hEventPair;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
+   }
+   return Status;
 }
 
 
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtOpenEventPair(OUT PHANDLE EventPairHandle,
-                IN ACCESS_MASK DesiredAccess,
-                IN POBJECT_ATTRIBUTES ObjectAttributes)
+               IN ACCESS_MASK DesiredAccess,
+               IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-    HANDLE hEventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   HANDLE hEventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(EventPairHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
+   PAGED_CODE();
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(EventPairHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
      
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Open the Object */
-    Status = ObOpenObjectByName(ObjectAttributes,
-                                ExEventPairObjectType,
-                                NULL,
-                                PreviousMode,
-                                DesiredAccess,
-                                NULL,
-                                &hEventPair);
-             
-    /* Check for success and return handle */
-    if(NT_SUCCESS(Status)) {
-            
-        _SEH_TRY {
-            
-            *EventPairHandle = hEventPair;
-                
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-    }
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObOpenObjectByName(ObjectAttributes,
+                              ExEventPairObjectType,
+                              NULL,
+                              PreviousMode,
+                              DesiredAccess,
+                              NULL,
+                              &hEventPair);
+   if(NT_SUCCESS(Status))
+   {
+     _SEH_TRY
+     {
+       *EventPairHandle = hEventPair;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
    
-    /* Return status */
-    return Status;
+   return Status;
 }
 
 
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
 NtSetHighEventPair(IN HANDLE EventPairHandle)
 {
-    PKEVENT_PAIR EventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status;
+   PKEVENT_PAIR EventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status;
+   
+   PAGED_CODE();
+
+   DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
+         EventPairHandle);
 
-    DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
+   PreviousMode = ExGetPreviousMode();
    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventPairHandle,
-                                       SYNCHRONIZE,
-                                       ExEventPairObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&EventPair,
-                                       NULL);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Set the Event */
-        KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
-
-        /* Dereference Object */
-        ObDereferenceObject(EventPair);
-    }
+   Status = ObReferenceObjectByHandle(EventPairHandle,
+                                     SYNCHRONIZE,
+                                     ExEventPairObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&EventPair,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     KeSetEvent(&EventPair->HighEvent,
+               EVENT_INCREMENT,
+               FALSE);
+
+     ObDereferenceObject(EventPair);
+   }
    
-    /* Return status */
-    return Status;
+   return Status;
 }
 
 
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
 {
-    PKEVENT_PAIR EventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status;
-
-    DPRINT1("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
-    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventPairHandle,
-                                       SYNCHRONIZE,
-                                       ExEventPairObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&EventPair,
-                                       NULL);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Set the Event */
-        KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
-        
-        /* Wait for the Other one */
-        KeWaitForSingleObject(&EventPair->LowEvent,
-                              WrEventPair,
-                              PreviousMode,
-                              FALSE,
-                              NULL);
-
-        /* Dereference Object */
-        ObDereferenceObject(EventPair);
-    }
+   PKEVENT_PAIR EventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status;
    
-    /* Return status */
-    return Status;
+   PAGED_CODE();
+
+   DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n",
+         EventPairHandle);
+
+   PreviousMode = ExGetPreviousMode();
+   
+   Status = ObReferenceObjectByHandle(EventPairHandle,
+                                     SYNCHRONIZE,
+                                     ExEventPairObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&EventPair,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     KeSetEvent(&EventPair->HighEvent,
+               EVENT_INCREMENT,
+               TRUE);
+
+     KeWaitForSingleObject(&EventPair->LowEvent,
+                          WrEventPair,
+                          PreviousMode,
+                          FALSE,
+                          NULL);
+
+     ObDereferenceObject(EventPair);
+   }
+   
+   return Status;
 }
 
-NTSTATUS 
-STDCALL
+
+NTSTATUS STDCALL
 NtSetLowEventPair(IN HANDLE EventPairHandle)
 {
-    PKEVENT_PAIR EventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status;
+   PKEVENT_PAIR EventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status;
+   
+   PAGED_CODE();
 
-    DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
+   DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
+         EventPairHandle);
+
+   PreviousMode = ExGetPreviousMode();
    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventPairHandle,
-                                       SYNCHRONIZE,
-                                       ExEventPairObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&EventPair,
-                                       NULL);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Set the Event */
-        KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
-
-        /* Dereference Object */
-        ObDereferenceObject(EventPair);
-    }
-    
-    /* Return status */
-    return Status;
+   Status = ObReferenceObjectByHandle(EventPairHandle,
+                                     SYNCHRONIZE,
+                                     ExEventPairObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&EventPair,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     KeSetEvent(&EventPair->LowEvent,
+               EVENT_INCREMENT,
+               FALSE);
+
+     ObDereferenceObject(EventPair);
+   }
+   
+   return Status;
 }
 
 
 NTSTATUS STDCALL
 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
 {
-    PKEVENT_PAIR EventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status;
-
-    DPRINT1("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
-    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventPairHandle,
-                                       SYNCHRONIZE,
-                                       ExEventPairObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&EventPair,
-                                       NULL);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Set the Event */
-        KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
-        
-        /* Wait for the Other one */
-        KeWaitForSingleObject(&EventPair->HighEvent,
-                              WrEventPair,
-                              PreviousMode,
-                              FALSE,
-                              NULL);
-
-        /* Dereference Object */
-        ObDereferenceObject(EventPair);
-    }
+   PKEVENT_PAIR EventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status;
+   
+   PAGED_CODE();
+
+   DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
+         EventPairHandle);
+
+   PreviousMode = ExGetPreviousMode();
    
-    /* Return status */
-    return Status;
+   Status = ObReferenceObjectByHandle(EventPairHandle,
+                                     SYNCHRONIZE,
+                                     ExEventPairObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&EventPair,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     KeSetEvent(&EventPair->LowEvent,
+               EVENT_INCREMENT,
+               TRUE);
+
+     KeWaitForSingleObject(&EventPair->HighEvent,
+                          WrEventPair,
+                          PreviousMode,
+                          FALSE,
+                          NULL);
+
+     ObDereferenceObject(EventPair);
+   }
+   
+   return Status;
 }
 
 
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtWaitLowEventPair(IN HANDLE EventPairHandle)
 {
-    PKEVENT_PAIR EventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status;
-
-    DPRINT1("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
-    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventPairHandle,
-                                       SYNCHRONIZE,
-                                       ExEventPairObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&EventPair,
-                                       NULL);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-               
-        /* Wait for the Event */
-        KeWaitForSingleObject(&EventPair->LowEvent,
-                              WrEventPair,
-                              PreviousMode,
-                              FALSE,
-                              NULL);
-
-        /* Dereference Object */
-        ObDereferenceObject(EventPair);
-    }
+   PKEVENT_PAIR EventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status;
+   
+   PAGED_CODE();
+
+   DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
+         EventPairHandle);
+
+   PreviousMode = ExGetPreviousMode();
    
-    /* Return status */
-    return Status;
+   Status = ObReferenceObjectByHandle(EventPairHandle,
+                                     SYNCHRONIZE,
+                                     ExEventPairObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&EventPair,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     KeWaitForSingleObject(&EventPair->LowEvent,
+                          WrEventPair,
+                          PreviousMode,
+                          FALSE,
+                          NULL);
+
+     ObDereferenceObject(EventPair);
+   }
+   
+   return Status;
 }
 
-NTSTATUS 
-STDCALL
+
+NTSTATUS STDCALL
 NtWaitHighEventPair(IN HANDLE EventPairHandle)
 {
-    PKEVENT_PAIR EventPair;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status;
-
-    DPRINT1("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
-    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(EventPairHandle,
-                                       SYNCHRONIZE,
-                                       ExEventPairObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&EventPair,
-                                       NULL);
-    
-    /* Check for Success */
-    if(NT_SUCCESS(Status)) {
-               
-        /* Wait for the Event */
-        KeWaitForSingleObject(&EventPair->HighEvent,
-                              WrEventPair,
-                              PreviousMode,
-                              FALSE,
-                              NULL);
-
-        /* Dereference Object */
-        ObDereferenceObject(EventPair);
-    }
+   PKEVENT_PAIR EventPair;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status;
+   
+   PAGED_CODE();
+
+   DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
+         EventPairHandle);
+
+   PreviousMode = ExGetPreviousMode();
    
-    /* Return status */
-    return Status;
+   Status = ObReferenceObjectByHandle(EventPairHandle,
+                                     SYNCHRONIZE,
+                                     ExEventPairObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&EventPair,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     KeWaitForSingleObject(&EventPair->HighEvent,
+                          WrEventPair,
+                          PreviousMode,
+                          FALSE,
+                          NULL);
+
+     ObDereferenceObject(EventPair);
+   }
+
+   return Status;
+}
+
+#ifdef _ENABLE_THRDEVTPAIR
+
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when setting the thread
+ * eventpair via NtSetInformationThread.
+ * @implemented
+ */
+NTSTATUS
+NTSYSAPI
+NTAPI
+NtSetLowWaitHighThread(
+       VOID
+       )
+{
+       PETHREAD Thread;
+       PKEVENT_PAIR EventPair;
+       NTSTATUS Status;
+       KIRQL Irql;
+       
+       PAGED_CODE();
+       
+       PreviousMode = ExGetPreviousMode();
+
+       if(!Thread->EventPair)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+       EventPair = Thread->EventPair;
+
+       if(EventPair)
+               ObReferenceObjectByPointer(EventPair,
+                                          EVENT_PAIR_ALL_ACCESS,
+                                          ExEventPairObjectType,
+                                          UserMode);
+       
+       KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+
+       if(EventPair == NULL)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeSetEvent(&EventPair->LowEvent,
+               EVENT_INCREMENT,
+               TRUE);
+
+       Status = KeWaitForSingleObject(&EventPair->HighEvent,
+                                      WrEventPair,
+                                      UserMode,
+                                      FALSE,
+                                      NULL);
+
+       ObDereferenceObject(EventPair);
+
+       return Status;
 }
 
+
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when setting the thread
+ * eventpair via NtSetInformationThread.
+ * @implemented
+ */
+NTSTATUS
+NTSYSAPI
+NTAPI
+NtSetHighWaitLowThread(
+       VOID
+       )
+{
+       PETHREAD Thread;
+       PKEVENT_PAIR EventPair;
+       NTSTATUS Status;
+       KIRQL Irql;
+       
+       PAGED_CODE();
+
+       Thread = PsGetCurrentThread();
+
+       if(!Thread->EventPair)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+       EventPair = PsGetCurrentThread()->EventPair;
+
+       if(EventPair)
+               ObReferenceObjectByPointer(EventPair,
+                                          EVENT_PAIR_ALL_ACCESS,
+                                          ExEventPairObjectType,
+                                          UserMode);
+       
+       KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+
+       if(EventPair == NULL)
+               return STATUS_NO_EVENT_PAIR;
+
+       KeSetEvent(&EventPair->HighEvent,
+               EVENT_INCREMENT,
+               TRUE);
+
+       Status = KeWaitForSingleObject(&EventPair->LowEvent,
+                                      WrEventPair,
+                                      UserMode,
+                                      FALSE,
+                                      NULL);
+
+       ObDereferenceObject(EventPair);
+
+       return Status;
+}
+
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when waiting on the
+ * eventpair via NtSetLow/HighWaitHigh/LowThread.  Additionally, when
+ * deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
+ * be called to release any preexisting eventpair object associated with
+ * the thread.  The Microsoft name for this function is not known.
+ */
+VOID
+ExpSwapThreadEventPair(
+       IN PETHREAD Thread,
+       IN PKEVENT_PAIR EventPair
+       )
+{
+       PKEVENT_PAIR OriginalEventPair;
+       KIRQL Irql;
+
+       KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+       OriginalEventPair = Thread->EventPair;
+       Thread->EventPair = EventPair;
+
+       if(OriginalEventPair)
+               ObDereferenceObject(OriginalEventPair);
+
+       KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+}
+
+#else /* !_ENABLE_THRDEVTPAIR */
+
+NTSTATUS
+NTSYSAPI
+NTAPI
+NtSetLowWaitHighThread(
+       VOID
+       )
+{
+        DPRINT1("NtSetLowWaitHighThread() not supported anymore (NT4 only)!\n");
+        return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTSYSAPI
+NTAPI
+NtSetHighWaitLowThread(
+       VOID
+       )
+{
+        DPRINT1("NtSetHighWaitLowThread() not supported anymore (NT4 only)!\n");
+        return STATUS_NOT_IMPLEMENTED;
+}
+
+#endif /* _ENABLE_THRDEVTPAIR */
+
 /* EOF */
index 878be04..03951a8 100644 (file)
-/*
+/* $Id$
+ * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ex/init.c
  * PURPOSE:         Executive initalization
  * 
- * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
- *                                                    and optimized/cleaned it.
- *                  Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * PROGRAMMERS:     Eric Kohl (ekohl@abo.rhein-zeitung.de)
  */
 
 #include <ntoskrnl.h>
-#include <ntos/bootvid.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 /* DATA **********************************************************************/
 
-extern ULONG MmCoreDumpType;
-extern CHAR KiTimerSystemAuditing;
-extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
-extern ADDRESS_RANGE KeMemoryMap[64];
-extern ULONG KeMemoryMapRangeCount;
-extern ULONG_PTR FirstKrnlPhysAddr;
-extern ULONG_PTR LastKrnlPhysAddr;
-extern ULONG_PTR LastKernelAddress;
-extern LOADER_MODULE KeLoaderModules[64];
-
 /* FUNCTIONS ****************************************************************/
 
-static 
-VOID 
-INIT_FUNCTION
-InitSystemSharedUserPage (PCSZ ParameterLine)
-{
-    UNICODE_STRING ArcDeviceName;
-    UNICODE_STRING ArcName;
-    UNICODE_STRING BootPath;
-    UNICODE_STRING DriveDeviceName;
-    UNICODE_STRING DriveName;
-    WCHAR DriveNameBuffer[20];
-    PCHAR ParamBuffer;
-    PWCHAR ArcNameBuffer;
-    PCHAR p;
-    NTSTATUS Status;
-    ULONG Length;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    HANDLE Handle;
-    ULONG i;
-    BOOLEAN BootDriveFound = FALSE;
-
-   /*
-    * NOTE:
-    *   The shared user page has been zeroed-out right after creation.
-    *   There is NO need to do this again.
-    */
-    Ki386SetProcessorFeatures();
-    
-    /* Set the Version Data */
-    SharedUserData->NtProductType = NtProductWinNt;
-    SharedUserData->ProductTypeIsValid = TRUE;
-    SharedUserData->NtMajorVersion = 5;
-    SharedUserData->NtMinorVersion = 0;
-   
-    /*
-     * Retrieve the current dos system path
-     * (e.g.: C:\reactos) from the given arc path
-     * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
-     * Format: "<arc_name>\<path> [options...]"
-     */
-
-    /* Create local parameter line copy */
-    ParamBuffer = ExAllocatePool(PagedPool, 256);
-    strcpy (ParamBuffer, (char *)ParameterLine);
-    DPRINT("%s\n", ParamBuffer);
-
-    /* Cut options off */
-    p = strchr (ParamBuffer, ' ');
-    if (p) *p = 0;
-    DPRINT("%s\n", ParamBuffer);
-
-    /* Extract path */
-    p = strchr (ParamBuffer, '\\');
-    if (p) {
-        
-        DPRINT("Boot path: %s\n", p);
-        RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
-        *p = 0;
-    
-    } else {
-        
-        DPRINT("Boot path: %s\n", "\\");
-        RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
-    }
-    DPRINT("Arc name: %s\n", ParamBuffer);
-   
-    /* Only ARC Name left - Build full ARC Name */
-    ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-    swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
-    RtlInitUnicodeString (&ArcName, ArcNameBuffer);
-    DPRINT("Arc name: %wZ\n", &ArcName);
-
-    /* Free ParamBuffer */
-    ExFreePool (ParamBuffer);
-
-    /* Allocate ARC Device Name string */
-    ArcDeviceName.Length = 0;
-    ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
-    ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-
-    /* Open the Symbolic Link */
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &ArcName,
-                               OBJ_OPENLINK,
-                               NULL,
-                               NULL);
-    Status = NtOpenSymbolicLinkObject(&Handle,
-                                      SYMBOLIC_LINK_ALL_ACCESS,
-                                      &ObjectAttributes);
-    
-    /* Free the String */
-    RtlFreeUnicodeString (&ArcName);
-    
-    /* Check for Success */
-    if (!NT_SUCCESS(Status)) {
-        
-        /* Free the Strings */
-        RtlFreeUnicodeString(&BootPath);
-        RtlFreeUnicodeString(&ArcDeviceName);
-        CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
-        KEBUGCHECK(0);
-    }
-    
-    /* Query the Link */
-    Status = NtQuerySymbolicLinkObject(Handle,
-                                       &ArcDeviceName,
-                                       &Length);
-    NtClose (Handle);
-    
-    /* Check for Success */
-    if (!NT_SUCCESS(Status)) {
-        
-        /* Free the Strings */
-        RtlFreeUnicodeString(&BootPath);
-        RtlFreeUnicodeString(&ArcDeviceName);
-        CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
-        KEBUGCHECK(0);
-    }
-    DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
-
-    /* Allocate Device Name string */
-    DriveDeviceName.Length = 0;
-    DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
-    DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-
-    /* Loop Drives */
-    for (i = 0; i < 26; i++)  {
-        
-        /* Setup the String */
-        swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
-        RtlInitUnicodeString(&DriveName,
-                             DriveNameBuffer);
-        
-        /* Open the Symbolic Link */
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   &DriveName,
-                                   OBJ_OPENLINK,
-                                   NULL,
-                                   NULL);
-        Status = NtOpenSymbolicLinkObject(&Handle,
-                                          SYMBOLIC_LINK_ALL_ACCESS,
-                                          &ObjectAttributes);
-        
-        /* If it failed, skip to the next drive */
-        if (!NT_SUCCESS(Status)) {
-            DPRINT("Failed to open link %wZ\n", &DriveName);
-            continue;
-        }
-        
-        /* Query it */
-        Status = NtQuerySymbolicLinkObject(Handle,
-                                           &DriveDeviceName,
-                                           &Length);
-        
-        /* If it failed, skip to the next drive */
-        if (!NT_SUCCESS(Status)) {
-            DPRINT("Failed to query link %wZ\n", &DriveName);
-            continue;
-        }
-        DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
-
-        /* See if we've found the boot drive */
-        if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
-            
-            DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
-            swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
-            BootDriveFound = TRUE;
-        }
-
-        /* Close this Link */
-        NtClose (Handle);
-    }
-    
-    /* Free all the Strings we have in memory */
-    RtlFreeUnicodeString (&BootPath);
-    RtlFreeUnicodeString (&DriveDeviceName);
-    RtlFreeUnicodeString (&ArcDeviceName);
-
-    /* Make sure we found the Boot Drive */
-    if (BootDriveFound == FALSE) {
-        
-        DbgPrint("No system drive found!\n");
-        KEBUGCHECK (NO_BOOT_DEVICE);
-    }
-}
-
-inline
-VOID
-STDCALL
-ExecuteRuntimeAsserts(VOID)
-{
-    /*
-     * Fail at runtime if someone has changed various structures without
-     * updating the offsets used for the assembler code.
-     */
-    ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
-    ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
-    ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
-    ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
-    ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
-    ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
-    ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
-    ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
-    ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
-    ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
-    ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
-    ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
-    ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
-    ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
-    ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
-    ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
-    ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
-    ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
-    ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);  
-    ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
-    ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
-    ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
-    ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
-    ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
-}
-
-inline
-VOID
-STDCALL
-ParseAndCacheLoadedModules(PBOOLEAN SetupBoot)
-{
-    ULONG i;
-    PCHAR Name;
-    
-    /* Loop the Module List and get the modules we want */
-    for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
-       
-        /* Get the Name of this Module */
-        if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
-      
-            /* Save the name */
-            Name = (PCHAR)KeLoaderModules[i].String;
-          
-        } else {
-      
-            /* No name, skip */
-            Name++;
-        }
-      
-        /* Now check for any of the modules we will need later */
-        if (!_stricmp(Name, "ansi.nls")) {
-          
-            CachedModules[AnsiCodepage] = &KeLoaderModules[i];
-      
-        } else if (!_stricmp(Name, "oem.nls")) {
-          
-            CachedModules[OemCodepage] = &KeLoaderModules[i];
-      
-        } else if (!_stricmp(Name, "casemap.nls")) {
-      
-            CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
-      
-        } else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
-      
-            CachedModules[SystemRegistry] = &KeLoaderModules[i];
-            *SetupBoot = FALSE;
-      
-        } else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
-      
-            CachedModules[HardwareRegistry] = &KeLoaderModules[i];
-        }
-    }    
-}
-
-inline
-VOID
-STDCALL
-ParseCommandLine(PULONG MaxMem, PBOOLEAN NoGuiBoot, PBOOLEAN BootLog)
-{
-    PCHAR p1, p2; 
-    
-    p1 = (PCHAR)KeLoaderBlock.CommandLine;
-    while(*p1 && (p2 = strchr(p1, '/'))) {
-        
-        p2++;
-        if (!_strnicmp(p2, "MAXMEM", 6)) {
-            
-            p2 += 6;
-            while (isspace(*p2)) p2++;
-            
-            if (*p2 == '=') {
-                
-                p2++;
-                
-                while(isspace(*p2)) p2++;
-                
-                if (isdigit(*p2)) {
-                    while (isdigit(*p2)) {
-                        *MaxMem = *MaxMem * 10 + *p2 - '0';
-                        p2++;
-                    }                
-                    break;
-                }
-            }
-        } else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
-            
-            p2 += 9;
-            *NoGuiBoot = TRUE;
-            
-        } else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
-            
-            p2 += 9;
-            if (*p2 == ':') {
-                
-                p2++;
-                if (!_strnicmp(p2, "FULL", 4)) {
-                    
-                    MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
-                    
-                } else {
-                    
-                    MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
-                }
-            }
-        } else if (!_strnicmp(p2, "BOOTLOG", 7)) {
-            
-            p2 += 7;
-            *BootLog = TRUE;
-        }
-        
-        p1 = p2;
-    }
-}
-
-VOID 
-INIT_FUNCTION
-STDCALL
-ExpInitializeExecutive(VOID)
-{
-    CHAR str[50];
-    UNICODE_STRING EventName;
-    HANDLE InitDoneEventHandle;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    BOOLEAN NoGuiBoot = FALSE;
-    BOOLEAN BootLog = FALSE;
-    ULONG MaxMem = 0;
-    BOOLEAN SetupBoot = TRUE;
-    LARGE_INTEGER Timeout;
-    HANDLE ProcessHandle;
-    HANDLE ThreadHandle;
-    NTSTATUS Status;
-
-    /* Check if the structures match the ASM offset constants */
-    ExecuteRuntimeAsserts();
-    
-    /* Sets up the Text Sections of the Kernel and HAL for debugging */
-    LdrInit1();
-    
-    /* Lower the IRQL to Dispatch Level */
-    KeLowerIrql(DISPATCH_LEVEL);
-    
-    /* Sets up the VDM Data */
-    NtEarlyInitVdm();
-
-    /* Parse Command Line Settings */
-    ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog);
-    
-    /* Initialize Kernel Memory Address Space */
-    MmInit1(FirstKrnlPhysAddr,
-            LastKrnlPhysAddr,
-            LastKernelAddress,
-            (PADDRESS_RANGE)&KeMemoryMap,
-            KeMemoryMapRangeCount,
-            MaxMem > 8 ? MaxMem : 4096);
-
-    /* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
-    ParseAndCacheLoadedModules(&SetupBoot);
-    
-    /* Initialize the kernel debugger */
-    KdInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
-    /* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
-    KeInit2();
-
-    /* Bring back the IRQL to Passive */
-    KeLowerIrql(PASSIVE_LEVEL);
-    
-    /* Load basic Security for other Managers */
-    if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
-
-    /* Create the Basic Object Manager Types to allow new Object Types */
-    ObInit();
-    
-    /* Initialize Lookaside Lists */
-    ExInit2();
-    
-    /* Set up Region Maps, Sections and the Paging File */
-    MmInit2();
-
-    /* Initialize Tokens now that the Object Manager is ready */
-    if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
-
-    /* Set 1 CPU for now, we'll increment this later */
-    KeNumberProcessors = 1;
-    
-    /* Initalize the Process Manager */
-    PiInitProcessManager();
-
-    /* Break into the Debugger if requested */
-    if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
-
-    /* Initialize all processors */
-    while (!HalAllProcessorsStarted()) {
-        
-        PVOID ProcessorStack;
-
-        /* Set up the Kernel and Process Manager for this CPU */
-        KePrepareForApplicationProcessorInit(KeNumberProcessors);
-        PsPrepareForApplicationProcessorInit(KeNumberProcessors);
-
-        /* Allocate a stack for use when booting the processor */
-        ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
-
-        /* Tell HAL a new CPU is being started */
-        HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
-        KeNumberProcessors++;
-    }
-
-    /* Do Phase 1 HAL Initalization */
-    HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-    
-    /* Initialize Basic System Objects and Worker Threads */
-    ExInit3();
-    
-    /* Initialize the GDB Stub and break */
-    KdInit1();
-  
-    /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
-    IoInit();
-    
-    /* TBD */
-    PoInit();
-  
-    /* Initialize the Registry (Hives are NOT yet loaded!) */
-    CmInitializeRegistry();
-  
-    /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
-    MmInit3();
-  
-    /* Initialize Cache Views */
-    CcInit();
-  
-    /* Hook System Interrupt for the Debugger */
-    KdInit2();
-    
-    /* Initialize File Locking */
-    FsRtlpInitFileLockingImplementation();
-
-    /* Report all resources used by hal */
-    HalReportResourceUsage();  
-
-    /* Clear the screen to blue */
-    HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
-    /* Display version number and copyright/warranty message */
-    HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
-                     KERNEL_VERSION_BUILD_STR")\n");
-    HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
-    HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
-                     "Public License, and you\n");
-    HalDisplayString("are welcome to change it and/or distribute copies of it "
-                     "under certain\n"); 
-    HalDisplayString("conditions. There is absolutely no warranty for "
-                      "ReactOS.\n\n");
-
-    /* Display number of Processors */
-    sprintf(str,
-            "Found %d system processor(s). [%lu MB Memory]\n",
-            KeNumberProcessors,
-            (KeLoaderBlock.MemHigher + 1088)/ 1024);
-    HalDisplayString(str);
-
-    /* Print which Debugger is being used */
-    KdInit3();
-
-    /* Import and create NLS Data and Sections */
-    RtlpInitNls();
-
-    /* Import and Load Registry Hives */
-    CmInitHives(SetupBoot);
-    
-    /* Initialize the time zone information from the registry */
-    ExpInitTimeZoneInfo();
-   
-  /* Enter the kernel debugger before starting up the boot drivers */
-#ifdef KDBG
-    KdbEnter();
-#endif /* KDBG */
-
-    /* Setup Drivers and Root Device Node */
-    IoInit2(BootLog);
-
-    /* Display the boot screen image if not disabled */
-    if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
-    
-    /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
-    IoInit3();
-       
-    /* Initialize the Default Locale */
-    PiInitDefaultLocale();
-    
-    /* Initialize shared user page. Set dos system path, dos device map, etc. */
-    InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
-
-    /* Create 'ReactOSInitDone' event */
-    RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &EventName,
-                               0,
-                               NULL,
-                               NULL);
-    Status = ZwCreateEvent(&InitDoneEventHandle,
-                           EVENT_ALL_ACCESS,
-                           &ObjectAttributes,
-                           SynchronizationEvent,
-                           FALSE);
-    
-    /* Check for Success */
-    if (!NT_SUCCESS(Status)) {
-        
-        DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
-        InitDoneEventHandle = INVALID_HANDLE_VALUE;
-    }
-
-    /* Launch initial process */
-    Status = LdrLoadInitialProcess(&ProcessHandle,
-                                   &ThreadHandle);
-    
-    /* Check for success, Bugcheck if we failed */
-    if (!NT_SUCCESS(Status)) {
-        
-        KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
-    }
-
-    /* Wait on the Completion Event */
-    if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
-
-        HANDLE Handles[2]; /* Init event, Initial process */
-
-        /* Setup the Handles to wait on */
-        Handles[0] = InitDoneEventHandle;
-        Handles[1] = ProcessHandle;
-
-        /* Wait for the system to be initialized */
-        Timeout.QuadPart = (LONGLONG)-1200000000;  /* 120 second timeout */
-        Status = ZwWaitForMultipleObjects(2,
-                                          Handles,
-                                          WaitAny,
-                                          FALSE,
-                                          &Timeout);
-        if (!NT_SUCCESS(Status)) {
-            
-            DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
-        
-        } else if (Status == STATUS_TIMEOUT) {
-            
-            DPRINT1("WARNING: System not initialized after 120 seconds.\n");
-        
-        } else if (Status == STATUS_WAIT_0 + 1) {
-            
-            /* Crash the system if the initial process was terminated. */
-            KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
-        }
-
-        /* Disable the Boot Logo */
-        if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
-
-        /* Signal the Event and close the handle */
-        ZwSetEvent(InitDoneEventHandle, NULL);
-        ZwClose(InitDoneEventHandle);
-    
-    } else {
-        
-        /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
-        if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
-
-        /* Crash the system if the initial process terminates within 5 seconds. */
-        Timeout.QuadPart = (LONGLONG)-50000000;  /* 5 second timeout */
-        Status = ZwWaitForSingleObject(ProcessHandle,
-                                       FALSE,
-                                       &Timeout);
-        
-        /* Check for timeout, crash if the initial process didn't initalize */
-        if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
-    }
-    
-    /* Enable the Clock, close remaining handles */
-    KiTimerSystemAuditing = 1;
-    ZwClose(ThreadHandle);
-    ZwClose(ProcessHandle);
-}
-
 VOID INIT_FUNCTION
 ExInit2(VOID)
 {
@@ -634,7 +25,7 @@ ExInit2(VOID)
 VOID INIT_FUNCTION
 ExInit3 (VOID)
 {
-  ExpInitializeWorkerThreads();
+  ExInitializeWorkerThreads();
   ExpInitializeEventImplementation();
   ExpInitializeEventPairImplementation();
   ExpInitializeMutantImplementation();
@@ -644,7 +35,28 @@ ExInit3 (VOID)
   ExpInitializeProfileImplementation();
   ExpWin32kInit();
   ExpInitUuids();
-  ExpInitializeCallbacks();
+}
+
+
+/*
+ * @implemented
+ */
+BOOLEAN STDCALL
+ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
+{
+  if (ProcessorFeature >= PROCESSOR_FEATURE_MAX)
+    return(FALSE);
+
+  return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
+}
+
+
+VOID STDCALL
+ExPostSystemEvent (ULONG       Unknown1,
+                  ULONG        Unknown2,
+                  ULONG        Unknown3)
+{
+  /* doesn't do anything */
 }
 
 /* EOF */
index 8c125e2..f6a2d4b 100644 (file)
@@ -1,13 +1,11 @@
-/* 
+/* $Id:$
+ * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ex/mutant.c
- * PURPOSE:         Executive Management of Mutants
+ * PURPOSE:         Synchronization primitives
  * 
- * PROGRAMMERS:     
- *                  Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and
- *                                 add more debug output.
- *                  David Welch (welch@cwcom.net)
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 POBJECT_TYPE ExMutantObjectType = NULL;
 
 static GENERIC_MAPPING ExpMutantMapping = {
-    STANDARD_RIGHTS_READ    | SYNCHRONIZE | MUTANT_QUERY_STATE,
-    STANDARD_RIGHTS_WRITE   | SYNCHRONIZE,
-    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
-    MUTANT_ALL_ACCESS};
+       STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
+       STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
+       STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
+       MUTANT_ALL_ACCESS};
 
-static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = {
-    
-     /* MutantBasicInformation */
-    ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
+{
+  ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */
 };
 
 /* FUNCTIONS *****************************************************************/
 
-VOID 
-STDCALL
-ExpDeleteMutant(PVOID ObjectBody)
+
+NTSTATUS STDCALL
+ExpCreateMutant(PVOID ObjectBody,
+               PVOID Parent,
+               PWSTR RemainingPath,
+               POBJECT_ATTRIBUTES ObjectAttributes)
 {
+  DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+        ObjectBody, Parent, RemainingPath);
 
-    DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody);
+  if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
+    {
+      return(STATUS_UNSUCCESSFUL);
+    }
 
-    /* Make sure to release the Mutant */
-    KeReleaseMutant((PKMUTANT)ObjectBody,
-                    MUTANT_INCREMENT,
-                    TRUE,
-                    FALSE);
+  return(STATUS_SUCCESS);
 }
 
-VOID 
-INIT_FUNCTION
-ExpInitializeMutantImplementation(VOID)
+
+VOID STDCALL
+ExpDeleteMutant(PVOID ObjectBody)
 {
+  DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
 
-    /* Allocate the Object Type */
-    ExMutantObjectType = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), TAG('M', 't', 'n', 't'));
-
-    /* Create the Object Type */
-    RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
-    ExMutantObjectType->Tag = TAG('M', 't', 'n', 't');
-    ExMutantObjectType->PeakObjects = 0;
-    ExMutantObjectType->PeakHandles = 0;
-    ExMutantObjectType->TotalObjects = 0;
-    ExMutantObjectType->TotalHandles = 0;
-    ExMutantObjectType->PagedPoolCharge = 0;
-    ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
-    ExMutantObjectType->Mapping = &ExpMutantMapping;
-    ExMutantObjectType->Dump = NULL;
-    ExMutantObjectType->Open = NULL;
-    ExMutantObjectType->Close = NULL;
-    ExMutantObjectType->Delete = ExpDeleteMutant;
-    ExMutantObjectType->Parse = NULL;
-    ExMutantObjectType->Security = NULL;
-    ExMutantObjectType->QueryName = NULL;
-    ExMutantObjectType->OkayToClose = NULL;
-    ExMutantObjectType->Create = NULL;
-    ExMutantObjectType->DuplicationNotify = NULL;
-    ObpCreateTypeObject(ExMutantObjectType);
+  KeReleaseMutant((PKMUTANT)ObjectBody,
+                 MUTANT_INCREMENT,
+                 TRUE,
+                 FALSE);
 }
 
+
+VOID INIT_FUNCTION
+ExpInitializeMutantImplementation(VOID)
+{
+  ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
+
+  RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
+
+  ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T');
+  ExMutantObjectType->PeakObjects = 0;
+  ExMutantObjectType->PeakHandles = 0;
+  ExMutantObjectType->TotalObjects = 0;
+  ExMutantObjectType->TotalHandles = 0;
+  ExMutantObjectType->PagedPoolCharge = 0;
+  ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
+  ExMutantObjectType->Mapping = &ExpMutantMapping;
+  ExMutantObjectType->Dump = NULL;
+  ExMutantObjectType->Open = NULL;
+  ExMutantObjectType->Close = NULL;
+  ExMutantObjectType->Delete = ExpDeleteMutant;
+  ExMutantObjectType->Parse = NULL;
+  ExMutantObjectType->Security = NULL;
+  ExMutantObjectType->QueryName = NULL;
+  ExMutantObjectType->OkayToClose = NULL;
+  ExMutantObjectType->Create = ExpCreateMutant;
+  ExMutantObjectType->DuplicationNotify = NULL;
+
+  ObpCreateTypeObject(ExMutantObjectType);
+}
+
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtCreateMutant(OUT PHANDLE MutantHandle,
-               IN ACCESS_MASK DesiredAccess,
-               IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
-               IN BOOLEAN InitialOwner)
+              IN ACCESS_MASK DesiredAccess,
+              IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
+              IN BOOLEAN InitialOwner)
 {
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    HANDLE hMutant;
-    PKMUTANT Mutant;
-    NTSTATUS Status = STATUS_SUCCESS;
-    
-    DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
+  KPROCESSOR_MODE PreviousMode;
+  HANDLE hMutant;
+  PKMUTEX Mutant;
+  NTSTATUS Status = STATUS_SUCCESS;
   
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(MutantHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
-
-        if(!NT_SUCCESS(Status)) return Status;
+  PAGED_CODE();
+  
+  PreviousMode = ExGetPreviousMode();
+
+  if(PreviousMode == UserMode)
+  {
+    _SEH_TRY
+    {
+      ProbeForWrite(MutantHandle,
+                    sizeof(HANDLE),
+                    sizeof(ULONG));
     }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+     
+    if(!NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  }
+
+  Status = ObCreateObject(PreviousMode,
+                         ExMutantObjectType,
+                         ObjectAttributes,
+                         PreviousMode,
+                         NULL,
+                         sizeof(KMUTANT),
+                         0,
+                         0,
+                         (PVOID*)&Mutant);
+  if(NT_SUCCESS(Status))
+  {
+    KeInitializeMutant(Mutant,
+                      InitialOwner);
+
+    Status = ObInsertObject((PVOID)Mutant,
+                           NULL,
+                           DesiredAccess,
+                           0,
+                           NULL,
+                           &hMutant);
+    ObDereferenceObject(Mutant);
     
-    /* Create the Mutant Object*/
-    Status = ObCreateObject(PreviousMode,
-                            ExMutantObjectType,
-                            ObjectAttributes,
-                            PreviousMode,
-                            NULL,
-                            sizeof(KMUTANT),
-                            0,
-                            0,
-                            (PVOID*)&Mutant);
-    
-    /* Check for success */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Initalize the Kernel Mutant */
-        DPRINT("Initializing the Mutant\n");
-        KeInitializeMutant(Mutant, InitialOwner);
-
-        /* Insert the Object */
-        Status = ObInsertObject((PVOID)Mutant,
-                                NULL,
-                                DesiredAccess,
-                                0,
-                                NULL,
-                                &hMutant);
-        ObDereferenceObject(Mutant);
-    
-        /* Check for success and return handle */
-        if(NT_SUCCESS(Status)) {
-            
-            _SEH_TRY {
-                
-                *MutantHandle = hMutant;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-                
-            } _SEH_END;
-        }
+    if(NT_SUCCESS(Status))
+    {
+      _SEH_TRY
+      {
+        *MutantHandle = hMutant;
+      }
+      _SEH_HANDLE
+      {
+        Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
     }
+  }
 
-    /* Return Status */
-    return Status;
+  return Status;
 }
 
 
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtOpenMutant(OUT PHANDLE MutantHandle,
-             IN ACCESS_MASK DesiredAccess,
-             IN POBJECT_ATTRIBUTES ObjectAttributes)
+            IN ACCESS_MASK DesiredAccess,
+            IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-    HANDLE hMutant;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+  HANDLE hMutant;
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status = STATUS_SUCCESS;
   
-   PAGED_CODE();
+  PAGED_CODE();
 
-    DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
-
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(MutantHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
-     
-        if(!NT_SUCCESS(Status)) return Status;
+  DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
+
+  PreviousMode = ExGetPreviousMode();
+
+  if(PreviousMode == UserMode)
+  {
+    _SEH_TRY
+    {
+      ProbeForWrite(MutantHandle,
+                    sizeof(HANDLE),
+                    sizeof(ULONG));
     }
-    
-    /* Open the Object */
-    Status = ObOpenObjectByName(ObjectAttributes,
-                                ExMutantObjectType,
-                                NULL,
-                                PreviousMode,
-                                DesiredAccess,
-                                NULL,
-                                &hMutant);
-
-    /* Check for success and return handle */
-    if(NT_SUCCESS(Status)) {
-            
-        _SEH_TRY {
-            
-            *MutantHandle = hMutant;
-        
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
+    if(!NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  }
+
+  Status = ObOpenObjectByName(ObjectAttributes,
+                             ExMutantObjectType,
+                             NULL,
+                             PreviousMode,
+                             DesiredAccess,
+                             NULL,
+                             &hMutant);
+
+  if(NT_SUCCESS(Status))
+  {
+    _SEH_TRY
+    {
+      *MutantHandle = hMutant;
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
     }
+    _SEH_END;
+  }
 
-    /* Return Status */
-    return Status;
+  return Status;
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtQueryMutant(IN HANDLE MutantHandle,
-              IN MUTANT_INFORMATION_CLASS MutantInformationClass,
-              OUT PVOID MutantInformation,
-              IN ULONG MutantInformationLength,
-              OUT PULONG ResultLength  OPTIONAL)
+             IN MUTANT_INFORMATION_CLASS MutantInformationClass,
+             OUT PVOID MutantInformation,
+             IN ULONG MutantInformationLength,
+             OUT PULONG ResultLength  OPTIONAL)
 {
-    PKMUTANT Mutant;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
-    PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
-    
-    /* Check buffers and parameters */
-    DefaultQueryInfoBufferCheck(MutantInformationClass,
-                                ExMutantInfoClass,
-                                MutantInformation,
-                                MutantInformationLength,
-                                ResultLength,
-                                PreviousMode,
-                                &Status);
-    if(!NT_SUCCESS(Status)) {
-        
-        DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
-        return Status;
-    }
+   PKMUTANT Mutant;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
    PAGED_CODE();
 
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(MutantHandle,
-                                       MUTANT_QUERY_STATE,
-                                       ExMutantObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Mutant,
-                                       NULL);
-    /* Check for Status */
-    if(NT_SUCCESS(Status)) {
-
-         _SEH_TRY {
-             
-            /* Fill out the Basic Information Requested */
-            DPRINT1("Returning Mutant Information\n");
-            BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
-            BasicInfo->OwnedByCaller = (Mutant->OwnerThread == KeGetCurrentThread());
-            BasicInfo->AbandonedState = Mutant->Abandoned;
-
-            /* Return the Result Length if requested */
-           if(ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
-        
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-
-        /* Release the Object */
-        ObDereferenceObject(Mutant);
-    }
-    
-    /* Return Status */
-    return Status;
+   PreviousMode = ExGetPreviousMode();
+
+   DefaultQueryInfoBufferCheck(MutantInformationClass,
+                               ExMutantInfoClass,
+                               MutantInformation,
+                               MutantInformationLength,
+                               ResultLength,
+                               PreviousMode,
+                               &Status);
+   if(!NT_SUCCESS(Status))
+   {
+     DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
+     return Status;
+   }
+
+   Status = ObReferenceObjectByHandle(MutantHandle,
+                                     MUTANT_QUERY_STATE,
+                                     ExMutantObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Mutant,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     switch(MutantInformationClass)
+     {
+       case MutantBasicInformation:
+       {
+         PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
+
+         _SEH_TRY
+         {
+           BasicInfo->Count = KeReadStateMutant(Mutant);
+           BasicInfo->Owned = (Mutant->OwnerThread != NULL);
+           BasicInfo->Abandoned = Mutant->Abandoned;
+
+           if(ResultLength != NULL)
+           {
+             *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
+           }
+         }
+         _SEH_HANDLE
+         {
+           Status = _SEH_GetExceptionCode();
+         }
+         _SEH_END;
+         break;
+       }
+
+       default:
+         Status = STATUS_NOT_IMPLEMENTED;
+         break;
+     }
+
+     ObDereferenceObject(Mutant);
+   }
+
+   return Status;
 }
 
 
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtReleaseMutant(IN HANDLE MutantHandle,
-                IN PLONG PreviousCount  OPTIONAL)
+               IN PLONG PreviousCount  OPTIONAL)
 {
-    PKMUTANT Mutant;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   PKMUTANT Mutant;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-
-    DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n", 
-            MutantHandle, 
-            PreviousCount);
-
-    /* Check Output Safety */
-    if(PreviousMode == UserMode && PreviousCount) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(PreviousCount,
-                          sizeof(LONG),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
-     
-        if(!NT_SUCCESS(Status)) return Status;
-    } 
-
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(MutantHandle,
-                                       MUTANT_QUERY_STATE,
-                                       ExMutantObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Mutant,
-                                       NULL);
-    
-    /* Check for Success and release if such */
-    if(NT_SUCCESS(Status)) {
-        
-        /* Save the Old State */
-        DPRINT1("Releasing Mutant\n");
-        LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, FALSE, FALSE);
-        ObDereferenceObject(Mutant);
-
-        /* Return it */        
-        if(PreviousCount) {
-            
-            _SEH_TRY {
-                
-                *PreviousCount = Prev;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-            
-            } _SEH_END;
-        }
-    }
+   PAGED_CODE();
 
-    /* Return Status */
-    return Status;
+   DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
+         MutantHandle, PreviousCount);
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousCount != NULL && PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(PreviousCount,
+                     sizeof(LONG),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObReferenceObjectByHandle(MutantHandle,
+                                     MUTANT_QUERY_STATE,
+                                     ExMutantObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Mutant,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE);
+     ObDereferenceObject(Mutant);
+
+     if(PreviousCount != NULL)
+     {
+       _SEH_TRY
+       {
+         *PreviousCount = Prev;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
+   }
+
+   return Status;
 }
 
 /* EOF */
index 580d9bb..baf8a38 100644 (file)
@@ -1,10 +1,11 @@
-/*
+/* $Id$
+ * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ex/rundown.c
  * PURPOSE:         Rundown Protection Functions
  * 
- * PROGRAMMERS:     Alex Ionescu & Thomas Weidenmueller - Implementation
+ * PROGRAMMERS:     No programmer listed.
  */
 
 /* INCLUDES *****************************************************************/
index ef9a41c..274ce8a 100644 (file)
@@ -1,11 +1,11 @@
-/*
+/* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ex/sem.c
  * PURPOSE:         Synchronization primitives
  * 
- * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes.
- *                  David Welch (welch@mcmail.com)
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES *****************************************************************/
 POBJECT_TYPE ExSemaphoreObjectType;
 
 static GENERIC_MAPPING ExSemaphoreMapping = {
-    STANDARD_RIGHTS_READ    | SEMAPHORE_QUERY_STATE,
-    STANDARD_RIGHTS_WRITE   | SEMAPHORE_MODIFY_STATE,
-    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
-    SEMAPHORE_ALL_ACCESS};
-
-static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = {
-    
-     /* SemaphoreBasicInformation */
-    ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+       STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
+       STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
+       STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
+       SEMAPHORE_ALL_ACCESS};
+
+static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
+{
+  ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */
 };
 
-VOID 
-INIT_FUNCTION
+/* FUNCTIONS *****************************************************************/
+
+NTSTATUS STDCALL
+ExpCreateSemaphore(PVOID ObjectBody,
+                  PVOID Parent,
+                  PWSTR RemainingPath,
+                  POBJECT_ATTRIBUTES ObjectAttributes)
+{
+  DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+        ObjectBody, Parent, RemainingPath);
+
+  if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
+    {
+      return(STATUS_UNSUCCESSFUL);
+    }
+
+  return(STATUS_SUCCESS);
+}
+
+VOID INIT_FUNCTION
 ExpInitializeSemaphoreImplementation(VOID)
 {
-    
-    /* Create the Semaphore Object */
-    ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
-    RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool);
-    ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
-    ExSemaphoreObjectType->PeakObjects = 0;
-    ExSemaphoreObjectType->PeakHandles = 0;
-    ExSemaphoreObjectType->TotalObjects = 0;
-    ExSemaphoreObjectType->TotalHandles = 0;
-    ExSemaphoreObjectType->PagedPoolCharge = 0;
-    ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE);
-    ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping;
-    ExSemaphoreObjectType->Dump = NULL;
-    ExSemaphoreObjectType->Open = NULL;
-    ExSemaphoreObjectType->Close = NULL;
-    ExSemaphoreObjectType->Delete = NULL;
-    ExSemaphoreObjectType->Parse = NULL;
-    ExSemaphoreObjectType->Security = NULL;
-    ExSemaphoreObjectType->QueryName = NULL;
-    ExSemaphoreObjectType->OkayToClose = NULL;
-    ExSemaphoreObjectType->Create = NULL;
-    ExSemaphoreObjectType->DuplicationNotify = NULL;
-    ObpCreateTypeObject(ExSemaphoreObjectType);
+   ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+   
+   RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool);
+   
+   ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
+   ExSemaphoreObjectType->PeakObjects = 0;
+   ExSemaphoreObjectType->PeakHandles = 0;
+   ExSemaphoreObjectType->TotalObjects = 0;
+   ExSemaphoreObjectType->TotalHandles = 0;
+   ExSemaphoreObjectType->PagedPoolCharge = 0;
+   ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE);
+   ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping;
+   ExSemaphoreObjectType->Dump = NULL;
+   ExSemaphoreObjectType->Open = NULL;
+   ExSemaphoreObjectType->Close = NULL;
+   ExSemaphoreObjectType->Delete = NULL;
+   ExSemaphoreObjectType->Parse = NULL;
+   ExSemaphoreObjectType->Security = NULL;
+   ExSemaphoreObjectType->QueryName = NULL;
+   ExSemaphoreObjectType->OkayToClose = NULL;
+   ExSemaphoreObjectType->Create = ExpCreateSemaphore;
+   ExSemaphoreObjectType->DuplicationNotify = NULL;
+
+   ObpCreateTypeObject(ExSemaphoreObjectType);
 }
 
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
-                  IN ACCESS_MASK DesiredAccess,
-                  IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
-                  IN LONG InitialCount,
-                  IN LONG MaximumCount)
+                 IN ACCESS_MASK DesiredAccess,
+                 IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
+                 IN LONG InitialCount,
+                 IN LONG MaximumCount)
 {
-    PKSEMAPHORE Semaphore;
-    HANDLE hSemaphore;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   PKSEMAPHORE Semaphore;
+   HANDLE hSemaphore;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(SemaphoreHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
-     
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Make sure the counts make sense */
-    if (!MaximumCount || !InitialCount || InitialCount > MaximumCount) {
-    
-        DPRINT("Invalid Count Data!\n");
-        return STATUS_INVALID_PARAMETER;
-    }
+   PAGED_CODE();
 
-    /* Create the Semaphore Object */
-    Status = ObCreateObject(PreviousMode,
-                            ExSemaphoreObjectType,
-                            ObjectAttributes,
-                            PreviousMode,
-                            NULL,
-                            sizeof(KSEMAPHORE),
-                            0,
-                            0,
-                            (PVOID*)&Semaphore);
-    
-    /* Check for Success */
-    if (NT_SUCCESS(Status)) {
-        
-        /* Initialize it */
-        KeInitializeSemaphore(Semaphore,
-                              InitialCount,
-                              MaximumCount);
-        
-        /* Insert it into the Object Tree */
-        Status = ObInsertObject((PVOID)Semaphore,
-                                NULL,
-                                DesiredAccess,
-                                0,
-                                NULL,
-                                &hSemaphore);
-        ObDereferenceObject(Semaphore);
-
-        /* Check for success and return handle */
-        if(NT_SUCCESS(Status)) {
-            
-            _SEH_TRY {
-                
-                *SemaphoreHandle = hSemaphore;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-                
-            } _SEH_END;
-        }
-    }
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(SemaphoreHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObCreateObject(PreviousMode,
+                          ExSemaphoreObjectType,
+                          ObjectAttributes,
+                          PreviousMode,
+                          NULL,
+                          sizeof(KSEMAPHORE),
+                          0,
+                          0,
+                          (PVOID*)&Semaphore);
+   if (NT_SUCCESS(Status))
+   {
+     KeInitializeSemaphore(Semaphore,
+                          InitialCount,
+                          MaximumCount);
+
+     Status = ObInsertObject ((PVOID)Semaphore,
+                             NULL,
+                             DesiredAccess,
+                             0,
+                             NULL,
+                             &hSemaphore);
 
-    /* Return Status */
-    return Status;
+     ObDereferenceObject(Semaphore);
+
+     if(NT_SUCCESS(Status))
+     {
+       _SEH_TRY
+       {
+         *SemaphoreHandle = hSemaphore;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
+   }
+
+   return Status;
 }
 
 
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
-                IN ACCESS_MASK DesiredAccess,
-                IN POBJECT_ATTRIBUTES ObjectAttributes)
+               IN ACCESS_MASK  DesiredAccess,
+               IN POBJECT_ATTRIBUTES ObjectAttributes)
 {
-    HANDLE hSemaphore;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
+   HANDLE hSemaphore;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-
-    /* Check Output Safety */
-    if(PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(SemaphoreHandle,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        
-        } _SEH_END;
-     
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Open the Object */
-    Status = ObOpenObjectByName(ObjectAttributes,
-                                ExSemaphoreObjectType,
-                                NULL,
-                                PreviousMode,
-                                DesiredAccess,
-                                NULL,
-                                &hSemaphore);
-    
-    /* Check for success and return handle */
-    if(NT_SUCCESS(Status)) {
-            
-        _SEH_TRY {
-            
-            *SemaphoreHandle = hSemaphore;
-        
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-    }
+   PAGED_CODE();
 
-    /* Return Status */
-    return Status;
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(SemaphoreHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+   
+   Status = ObOpenObjectByName(ObjectAttributes,
+                              ExSemaphoreObjectType,
+                              NULL,
+                              PreviousMode,
+                              DesiredAccess,
+                              NULL,
+                              &hSemaphore);
+   if(NT_SUCCESS(Status))
+   {
+     _SEH_TRY
+     {
+       *SemaphoreHandle = hSemaphore;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
+   
+   return Status;
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
 NtQuerySemaphore(IN HANDLE SemaphoreHandle,
-                 IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
-                 OUT PVOID SemaphoreInformation,
-                 IN ULONG SemaphoreInformationLength,
-                 OUT PULONG ReturnLength  OPTIONAL)
+                IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
+                OUT PVOID SemaphoreInformation,
+                IN ULONG SemaphoreInformationLength,
+                OUT PULONG ReturnLength  OPTIONAL)
 {
-    PKSEMAPHORE Semaphore;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    PAGED_CODE();
-               
-    /* Check buffers and class validity */
-    DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
-                                ExSemaphoreInfoClass,
-                                SemaphoreInformation,
-                                SemaphoreInformationLength,
-                                ReturnLength,
-                                PreviousMode,
-                                &Status);
-    if(!NT_SUCCESS(Status)) {
-        
-        /* Invalid buffers */
-        DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
-        return Status;
-    }
-   
-    /* Get the Object */
-    Status = ObReferenceObjectByHandle(SemaphoreHandle,
-                                       SEMAPHORE_QUERY_STATE,
-                                       ExSemaphoreObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Semaphore,
-                                       NULL);
-    
-    /* Check for success */
-    if(NT_SUCCESS(Status)) {
+   PKSEMAPHORE Semaphore;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-        _SEH_TRY {
-            
-             /* Return the basic information */             
-            BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
-            BasicInfo->MaximumCount = Semaphore->Limit;
-
-            /* Return length */
-            if(ReturnLength) *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
-            
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-     
-        /* Dereference the Object */
-        ObDereferenceObject(Semaphore);
+   PAGED_CODE();
+
+   PreviousMode = ExGetPreviousMode();
+
+   DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
+                               ExSemaphoreInfoClass,
+                               SemaphoreInformation,
+                               SemaphoreInformationLength,
+                               ReturnLength,
+                               PreviousMode,
+                               &Status);
+   if(!NT_SUCCESS(Status))
+   {
+     DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
+     return Status;
+   }
+
+   Status = ObReferenceObjectByHandle(SemaphoreHandle,
+                                     SEMAPHORE_QUERY_STATE,
+                                     ExSemaphoreObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Semaphore,
+                                     NULL);
+   if(NT_SUCCESS(Status))
+   {
+     switch(SemaphoreInformationClass)
+     {
+       case SemaphoreBasicInformation:
+       {
+         PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
+
+         _SEH_TRY
+         {
+           BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
+           BasicInfo->MaximumCount = Semaphore->Limit;
+
+           if(ReturnLength != NULL)
+           {
+             *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
+           }
+         }
+         _SEH_HANDLE
+         {
+           Status = _SEH_GetExceptionCode();
+         }
+         _SEH_END;
+         break;
+       }
+
+       default:
+         Status = STATUS_NOT_IMPLEMENTED;
+         break;
+     }
+
+     ObDereferenceObject(Semaphore);
    }
 
-   /* Return status */
    return Status;
 }
 
+
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
+NTSTATUS STDCALL
 NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
-                   IN LONG ReleaseCount,
-                   OUT PLONG PreviousCount  OPTIONAL)
+                  IN LONG ReleaseCount,
+                  OUT PLONG PreviousCount  OPTIONAL)
 {
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();;
-    PKSEMAPHORE Semaphore;
-    NTSTATUS Status = STATUS_SUCCESS; 
+   KPROCESSOR_MODE PreviousMode;
+   PKSEMAPHORE Semaphore;
+   NTSTATUS Status = STATUS_SUCCESS;
    
-    PAGED_CODE();
-
-    /* Check buffer validity */
-    if(PreviousCount != NULL && PreviousMode == UserMode) {
-        
-        _SEH_TRY {
-            
-            ProbeForWrite(PreviousCount,
-                          sizeof(LONG),
-                          sizeof(ULONG));
-         } _SEH_HANDLE {
-             
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-
-        if(!NT_SUCCESS(Status)) return Status;
-    }
-    
-    /* Make sure count makes sense */
-    if (!ReleaseCount) {
-    
-        DPRINT("Invalid Release Count\n");
-        return STATUS_INVALID_PARAMETER;
-    }
+   PAGED_CODE();
    
-    /* Get the Object */
-    Status = ObReferenceObjectByHandle(SemaphoreHandle,
-                                       SEMAPHORE_MODIFY_STATE,
-                                       ExSemaphoreObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Semaphore,
-                                       NULL);
-    
-    /* Check for success */
-    if (NT_SUCCESS(Status)) {
-        
-        /* Release the semaphore */
-        LONG PrevCount = KeReleaseSemaphore(Semaphore,
-                                            IO_NO_INCREMENT,
-                                            ReleaseCount,
-                                            FALSE);
-        ObDereferenceObject(Semaphore);
+   PreviousMode = ExGetPreviousMode();
+   
+   if(PreviousCount != NULL && PreviousMode == UserMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(PreviousCount,
+                     sizeof(LONG),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+   
+   Status = ObReferenceObjectByHandle(SemaphoreHandle,
+                                     SEMAPHORE_MODIFY_STATE,
+                                     ExSemaphoreObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&Semaphore,
+                                     NULL);
+   if (NT_SUCCESS(Status))
+   {
+     LONG PrevCount = KeReleaseSemaphore(Semaphore,
+                                         IO_NO_INCREMENT,
+                                         ReleaseCount,
+                                         FALSE);
+     ObDereferenceObject(Semaphore);
      
-        /* Return it */        
-        if(PreviousCount) {
-            
-            _SEH_TRY {
-                
-                *PreviousCount = PrevCount;
-            
-            } _SEH_HANDLE {
-                
-                Status = _SEH_GetExceptionCode();
-            
-            } _SEH_END;
-        }
-    }
+     if(PreviousCount != NULL)
+     {
+       _SEH_TRY
+       {
+         *PreviousCount = PrevCount;
+       }
+       _SEH_HANDLE
+       {
+         Status = _SEH_GetExceptionCode();
+       }
+       _SEH_END;
+     }
+   }
 
-    /* Return Status */
-    return Status;
+   return Status;
 }
 
 /* EOF */
index 352e3a8..2efe729 100644 (file)
@@ -86,20 +86,6 @@ ExGetCurrentProcessorCounts (
        ProcessorNumber = &ProcNumber;
 }
 
-/*
- * @implemented
- */
-BOOLEAN 
-STDCALL
-ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
-{
-    /* Quick check to see if it exists at all */
-    if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
-
-    /* Return our support for it */
-    return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
-}
-
 NTSTATUS STDCALL
 NtQuerySystemEnvironmentValue (IN      PUNICODE_STRING VariableName,
                               OUT      PWCHAR          ValueBuffer,
index c2ecdd5..fa0a254 100644 (file)
@@ -473,7 +473,7 @@ NtQueryTimer(IN HANDLE TimerHandle,
     PreviousMode = ExGetPreviousMode();
 
     DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass);
-
+    
     /* Check Validity */
     DefaultQueryInfoBufferCheck(TimerInformationClass,
                                 ExTimerInfoClass,
@@ -498,23 +498,27 @@ NtQueryTimer(IN HANDLE TimerHandle,
     
     /* Check for Success */
     if(NT_SUCCESS(Status)) {
+        
+        switch(TimerInformationClass) {
+           case TimerBasicInformation: {
+              /* Return the Basic Information */
+               _SEH_TRY {
 
-        /* Return the Basic Information */
-        _SEH_TRY {
-
-            /* FIXME: Interrupt correction based on Interrupt Time */
-            DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
-            BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
-            BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
+                  /* FIXME: Interrupt correction based on Interrupt Time */
+                  DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
+                  BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
+                  BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
 
-            if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
+                  if(ReturnLength != NULL) {
+                      *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
+                  }
 
-        } _SEH_HANDLE {
-            
+              } _SEH_HANDLE {
                   Status = _SEH_GetExceptionCode();
-        } _SEH_END;
+              } _SEH_END;
+           }
+        }
         
-        /* Dereference Object */
         ObDereferenceObject(Timer);
     }
    
index 0a5f82f..8d7bac1 100644 (file)
@@ -1,11 +1,11 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:          See COPYING in the top level directory
  * PROJECT:            ReactOS kernel
  * FILE:               ntoskrnl/ex/work.c
  * PURPOSE:            Manage system work queues
  * 
- * PROGRAMMERS:        Alex Ionescu - Used correct work queue array and added some fixes and checks.
- *                     Gunnar Dalsnes - Implemented
+ * PROGRAMMERS:        David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES ******************************************************************/
 /*
  * PURPOSE: Queue of items waiting to be processed at normal priority
  */
-EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
+KQUEUE EiNormalWorkQueue;
+
+KQUEUE EiCriticalWorkQueue;
+
+KQUEUE EiHyperCriticalWorkQueue;
 
 /* FUNCTIONS ****************************************************************/
 
+//static NTSTATUS STDCALL
+static VOID STDCALL
+ExWorkerThreadEntryPoint(IN PVOID context)
 /*
  * FUNCTION: Entry point for a worker thread
  * ARGUMENTS:
@@ -37,138 +44,138 @@ EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
  * NOTE: To kill a worker thread you must queue an item whose callback
  * calls PsTerminateSystemThread
  */
-static
-VOID 
-STDCALL
-ExpWorkerThreadEntryPoint(IN PVOID Context)
 {
-    PWORK_QUEUE_ITEM WorkItem;
-    PLIST_ENTRY QueueEntry;
-    WORK_QUEUE_TYPE WorkQueueType;
-    PEX_WORK_QUEUE WorkQueue;
+
+   PWORK_QUEUE_ITEM item;
+   PLIST_ENTRY current;
    
-    /* Get Queue Type and Worker Queue */
-    WorkQueueType = (WORK_QUEUE_TYPE)Context;
-    WorkQueue = &ExWorkerQueue[WorkQueueType];
-    
-    /* Loop forever */
-    while (TRUE) {
-        
-        /* Wait for Something to Happen on the Queue */
-        QueueEntry = KeRemoveQueue(&WorkQueue->WorkerQueue, KernelMode, NULL);
+   while (TRUE) 
+   {
+      current = KeRemoveQueue( (PKQUEUE)context, KernelMode, NULL );
       
-        /* Can't happen since we do a KernelMode wait (and we're a system thread) */
-        ASSERT((NTSTATUS)QueueEntry != STATUS_USER_APC);
+      /* can't happend since we do a KernelMode wait (and we're a system thread) */
+      ASSERT((NTSTATUS)current != STATUS_USER_APC);
       
-        /* this should never happen either, since we wait with NULL timeout,
-         * but there's a slight possibility that STATUS_TIMEOUT is returned
-         * at queue rundown in NT (unlikely) -Gunnar
-         */
-        ASSERT((NTSTATUS)QueueEntry != STATUS_TIMEOUT);
-    
-        /* Increment Processed Work Items */
-        InterlockedIncrement(&WorkQueue->WorkItemsProcessed);
-
-        /* Get the Work Item */
-        WorkItem = CONTAINING_RECORD(QueueEntry, WORK_QUEUE_ITEM, List);
-        
-        /* Call the Worker Routine */
-        WorkItem->WorkerRoutine(WorkItem->Parameter);
-    
-        /* Make sure it returned at right IRQL */
-        if (KeGetCurrentIrql() != PASSIVE_LEVEL) {
-        
-            /* FIXME: Make this an Ex */
-            KEBUGCHECK(WORKER_THREAD_RETURNED_AT_BAD_IRQL);
-        }
-    
-        /* Make sure it returned with Impersionation Disabled */
-        if (PsGetCurrentThread()->ActiveImpersonationInfo) {
-            
-            /* FIXME: Make this an Ex */
-            KEBUGCHECK(IMPERSONATING_WORKER_THREAD);
-        }
-    }
+      /* this should never happend either, since we wait with NULL timeout,
+       * but there's a slight possibility that STATUS_TIMEOUT is returned
+       * at queue rundown in NT (unlikely) -Gunnar
+       */
+      ASSERT((NTSTATUS)current != STATUS_TIMEOUT);
+      
+      /* based on INVALID_WORK_QUEUE_ITEM bugcheck desc. */
+      if (current->Flink == NULL || current->Blink == NULL)
+      {
+         KeBugCheck(INVALID_WORK_QUEUE_ITEM);
+      }
+      
+      /* "reinitialize" item (same as done in ExInitializeWorkItem) */
+      current->Flink = NULL;
+      
+      item = CONTAINING_RECORD( current, WORK_QUEUE_ITEM, List);
+      item->WorkerRoutine(item->Parameter);
+      
+      if (KeGetCurrentIrql() != PASSIVE_LEVEL)
+      {
+         KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
+      }
+   }
+   
 }
 
-static 
-VOID 
-STDCALL
-ExpInitializeWorkQueue(WORK_QUEUE_TYPE WorkQueueType,
-                       KPRIORITY Priority)
+static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
+                                 KPRIORITY Priority)
 {
-    ULONG i;
-    PETHREAD Thread;
-    HANDLE hThread;
+   ULONG i;
+   PETHREAD Thread;
+   HANDLE   hThread;
    
-    /* Loop through how many threads we need to create */
-    for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) {
-        
-        /* Create the System Thread */
-        PsCreateSystemThread(&hThread,
-                             THREAD_ALL_ACCESS,
-                             NULL,
-                             NULL,
-                             NULL,
-                             ExpWorkerThreadEntryPoint,
-                             (PVOID)WorkQueueType);
-        
-        /* Get the Thread */
-        ObReferenceObjectByHandle(hThread,
-                                  THREAD_SET_INFORMATION,
-                                  PsThreadType,
-                                  KernelMode,
-                                  (PVOID*)&Thread,
-                                  NULL);
-        
-        /* Set the Priority */
-        KeSetPriorityThread(&Thread->Tcb, Priority);
+   
+   for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
+     {
         
-        /* Dereference and close handle */
-        ObDereferenceObject(Thread);
-        ZwClose(hThread);
-    }
+   PsCreateSystemThread(&hThread,
+                            THREAD_ALL_ACCESS,
+                            NULL,
+                            NULL,
+                            NULL,
+                            ExWorkerThreadEntryPoint,
+              WorkQueue);
+   ObReferenceObjectByHandle(hThread,
+                                 THREAD_ALL_ACCESS,
+                                 PsThreadType,
+                                 KernelMode,
+                                 (PVOID*)&Thread,
+                                 NULL);
+       KeSetPriorityThread(&Thread->Tcb,
+                           Priority);
+       ObDereferenceObject(Thread);
+   ZwClose(hThread);
+     }
 }
 
-VOID 
-INIT_FUNCTION
-ExpInitializeWorkerThreads(VOID)
+VOID INIT_FUNCTION
+ExInitializeWorkerThreads(VOID)
 {
-    ULONG WorkQueueType;
-    
-    /* Initialize the Array */
-    for (WorkQueueType = 0; WorkQueueType < MaximumWorkQueue; WorkQueueType++) {
-    
-        RtlZeroMemory(&ExWorkerQueue[WorkQueueType], sizeof(EX_WORK_QUEUE));
-        KeInitializeQueue(&ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
-    }
-    
-    /* Create the built-in worker threads for each work queue */
-    ExpInitializeWorkQueue(CriticalWorkQueue, LOW_REALTIME_PRIORITY);
-    ExpInitializeWorkQueue(DelayedWorkQueue, LOW_PRIORITY);
-    ExpInitializeWorkQueue(HyperCriticalWorkQueue, HIGH_PRIORITY);
+   KeInitializeQueue( &EiNormalWorkQueue, NUMBER_OF_WORKER_THREADS );
+   KeInitializeQueue( &EiCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
+   KeInitializeQueue( &EiHyperCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
+
+   ExInitializeWorkQueue(&EiNormalWorkQueue,
+                        LOW_PRIORITY);
+   ExInitializeWorkQueue(&EiCriticalWorkQueue,
+                        LOW_REALTIME_PRIORITY);
+   ExInitializeWorkQueue(&EiHyperCriticalWorkQueue,
+                        HIGH_PRIORITY);
 }
 
 /*
  * @implemented
- *
+ */
+VOID STDCALL
+ExQueueWorkItem (PWORK_QUEUE_ITEM      WorkItem,
+                WORK_QUEUE_TYPE                QueueType)
+/*
  * FUNCTION: Inserts a work item in a queue for one of the system worker
  * threads to process
  * ARGUMENTS:
  *        WorkItem = Item to insert
  *        QueueType = Queue to insert it in
  */
-VOID 
-STDCALL
-ExQueueWorkItem(PWORK_QUEUE_ITEM WorkItem,
-                WORK_QUEUE_TYPE QueueType)
 {
     ASSERT(WorkItem!=NULL);
     ASSERT_IRQL(DISPATCH_LEVEL);
     ASSERT(WorkItem->List.Flink == NULL);
-    
-    /* Insert the Queue */
-    KeInsertQueue(&ExWorkerQueue[QueueType].WorkerQueue, &WorkItem->List);
+   /*
+    * Insert the item in the appropiate queue and wake up any thread
+    * waiting for something to do
+    */
+    switch(QueueType)
+    {
+    case DelayedWorkQueue:
+      KeInsertQueue (
+          &EiNormalWorkQueue,
+          &WorkItem->List
+            );
+       break;
+       
+    case CriticalWorkQueue:
+            KeInsertQueue (
+              &EiCriticalWorkQueue,
+              &WorkItem->List
+              );
+           break;
+
+    case HyperCriticalWorkQueue:
+            KeInsertQueue (
+             &EiHyperCriticalWorkQueue,
+             &WorkItem->List
+             );
+               break;
+     
+    default:
+        break;
+
+    }
 }
 
 /* EOF */
index d42decd..3596bfe 100644 (file)
@@ -98,19 +98,24 @@ ExInit3(VOID);
 VOID
 ExpInitTimeZoneInfo(VOID);
 VOID
-ExpInitializeWorkerThreads(VOID);
+ExInitializeWorkerThreads(VOID);
 VOID
 ExpInitLookasideLists(VOID);
 VOID
 ExpInitializeCallbacks(VOID);
 VOID
 ExpInitUuids(VOID);
-VOID
-STDCALL
-ExpInitializeExecutive(VOID);
 
 /* OTHER FUNCTIONS **********************************************************/
 
+#ifdef _ENABLE_THRDEVTPAIR
+VOID
+ExpSwapThreadEventPair(
+       IN struct _ETHREAD* Thread,
+       IN struct _KEVENT_PAIR* EventPair
+       );
+#endif /* _ENABLE_THRDEVTPAIR */
+
 LONGLONG 
 FASTCALL
 ExfpInterlockedExchange64(LONGLONG volatile * Destination,
index 5f86d91..43a2958 100644 (file)
@@ -2,5 +2,18 @@
  * Structure ids
  */
 
+#define InternalBaseType                      (0xcc)
+#define InternalNotificationEvent             (InternalBaseType + 1)
+#define InternalSynchronizationEvent          (InternalBaseType + 2)
+#define InternalSemaphoreType                 (InternalBaseType + 3)
+#define InternalProcessType                   (InternalBaseType + 4)
+#define InternalThreadType                    (InternalBaseType + 5)
+#define InternalFileType                      (InternalBaseType + 6)
+#define InternalDriverType                    (InternalBaseType + 7)
+#define InternalDeviceType                    (InternalBaseType + 8)
+#define InternalMutexType                     (InternalBaseType + 9)
+#define InternalNotificationTimer             (InternalBaseType + 10)
+#define InternalSynchronizationTimer          (InternalBaseType + 11)
+#define InternalQueueType                     (InternalBaseType + 12)
 
 
index 95d129c..823c153 100644 (file)
@@ -412,7 +412,7 @@ IoDestroyDriverList(VOID);
 /* bootlog.c */
 
 VOID
-IopInitBootLog(BOOLEAN StartBootLog);
+IopInitBootLog(VOID);
 
 VOID
 IopStartBootLog(VOID);
index c4f48ea..e9e78f6 100644 (file)
@@ -115,17 +115,6 @@ typedef struct _KPROFILE
   struct _EPROCESS *Process;
 } KPROFILE, *PKPROFILE;
 
-/* Cached modules from the loader block */
-typedef enum _CACHED_MODULE_TYPE {
-    AnsiCodepage,
-    OemCodepage,
-    UnicodeCasemap,
-    SystemRegistry,
-    HardwareRegistry,
-    MaximumCachedModuleType,        
-} CACHED_MODULE_TYPE, *PCACHED_MODULE_TYPE;
-extern PLOADER_MODULE CachedModules[MaximumCachedModuleType];
-
 VOID STDCALL 
 DbgBreakPointNoBugCheck(VOID);
 
@@ -155,42 +144,30 @@ VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
 
 VOID STDCALL KiExpireTimers(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
 
-KIRQL inline FASTCALL KeAcquireDispatcherDatabaseLock(VOID);
-VOID inline FASTCALL KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
-VOID inline FASTCALL KeReleaseDispatcherDatabaseLock(KIRQL Irql);
-VOID inline FASTCALL KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
+KIRQL KeAcquireDispatcherDatabaseLock(VOID);
+VOID KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
+VOID KeReleaseDispatcherDatabaseLock(KIRQL Irql);
+VOID KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
 
 BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment);
 VOID STDCALL KeExpireTimers(PKDPC Apc,
                            PVOID Arg1,
                            PVOID Arg2,
                            PVOID Arg3);
-VOID inline FASTCALL KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
+VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
                                  ULONG Size, ULONG SignalState);
 VOID KeDumpStackFrames(PULONG Frame);
 BOOLEAN KiTestAlert(VOID);
 
-VOID FASTCALL KiAbortWaitThread(struct _KTHREAD* Thread, NTSTATUS WaitStatus);
-
-BOOLEAN STDCALL KiInsertTimer(PKTIMER Timer, LARGE_INTEGER DueTime);
-
-VOID inline FASTCALL KiSatisfyObjectWait(PDISPATCHER_HEADER Object, PKTHREAD Thread);
-
-BOOLEAN inline FASTCALL KiIsObjectSignaled(PDISPATCHER_HEADER Object, PKTHREAD Thread);
-
-VOID inline FASTCALL KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
-
-VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
+BOOLEAN KiAbortWaitThread(struct _KTHREAD* Thread, NTSTATUS WaitStatus);
 
 PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
 VOID KeContextToTrapFrame(PCONTEXT Context, PKTRAP_FRAME TrapFrame);
 VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
                   PVOID Reserved,
                   PKTRAP_FRAME TrapFrame);
-                  
-VOID STDCALL KeInitializeEventPair(PKEVENT_PAIR EventPair);
                  
-VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
+VOID KiInitializeUserApc(IN PVOID Reserved,
                         IN PKTRAP_FRAME TrapFrame,
                         IN PKNORMAL_ROUTINE NormalRoutine,
                         IN PVOID NormalContext,
@@ -206,7 +183,6 @@ STDCALL
 KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
 
 BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
-VOID FASTCALL KiWakeQueue(IN PKQUEUE Queue);
 PLIST_ENTRY STDCALL KeRundownQueue(IN PKQUEUE Queue);
 
 extern LARGE_INTEGER SystemBootTime;
@@ -218,7 +194,7 @@ VOID KeInitInterrupts(VOID);
 VOID KeInitTimer(VOID);
 VOID KeInitDpc(struct _KPCR* Pcr);
 VOID KeInitDispatcher(VOID);
-VOID inline FASTCALL KeInitializeDispatcher(VOID);
+VOID KeInitializeDispatcher(VOID);
 VOID KiInitializeSystemClock(VOID);
 VOID KeInitializeBugCheck(VOID);
 VOID Phase1Initialization(PVOID Context);
index 84787cb..46906e3 100644 (file)
@@ -29,7 +29,6 @@ extern ULONG NlsUnicodeTableOffset;
 extern PUSHORT NlsUnicodeUpcaseTable;
 extern PUSHORT NlsUnicodeLowercaseTable;
 
-VOID STDCALL RtlpInitNls(VOID);
 VOID RtlpImportAnsiCodePage(PUSHORT TableBase, ULONG Size);
 VOID RtlpImportOemCodePage(PUSHORT TableBase, ULONG Size);
 VOID RtlpImportUnicodeCasemap(PUSHORT TableBase, ULONG Size);
index 972b42a..a98537f 100644 (file)
@@ -49,12 +49,10 @@ VOID ExpInitializeProfileImplementation(VOID);
  */
 VOID MmInitSystem(ULONG Phase, PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG LastKernelAddress);
 VOID IoInit(VOID);
-VOID IoInit2(BOOLEAN BootLog);
-VOID STDCALL IoInit3(VOID);
+VOID IoInit2(VOID);
 VOID ObInit(VOID);
 VOID PsInit(VOID);
 VOID CmInitializeRegistry(VOID);
-VOID STDCALL CmInitHives(BOOLEAN SetupBoot);
 VOID CmInit2(PCHAR CommandLine);
 VOID CmShutdownRegistry(VOID);
 BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
index c954fb7..1be0eee 100644 (file)
@@ -498,9 +498,7 @@ VOID STDCALL PsExitSpecialApc(PKAPC Apc,
 
 
 VOID 
-STDCALL
 KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
-
 NTSTATUS KeReleaseThread(PKTHREAD Thread);
 
 VOID
@@ -527,11 +525,8 @@ VOID PsUnfreezeProcessThreads(PEPROCESS Process);
 ULONG PsEnumThreadsByProcess(PEPROCESS Process);
 PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
 VOID
-STDCALL
-PsBlockThread(PNTSTATUS Status, 
-              UCHAR Alertable, 
-              ULONG WaitMode,
-              UCHAR WaitReason);
+PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode, 
+             BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason);
 VOID
 PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment);
 VOID
index 9324dd9..71dc17b 100644 (file)
@@ -27,14 +27,13 @@ static ERESOURCE IopBootLogResource;
 /* FUNCTIONS ****************************************************************/
 
 VOID INIT_FUNCTION
-IopInitBootLog(BOOLEAN StartBootLog)
+IopInitBootLog(VOID)
 {
   ExInitializeResourceLite(&IopBootLogResource);
-  if (StartBootLog) IopStartBootLog();
 }
 
 
-VOID INIT_FUNCTION
+VOID
 IopStartBootLog(VOID)
 {
   IopBootLogCreate = TRUE;
index 6a2919e..b507fc5 100644 (file)
@@ -176,7 +176,7 @@ IopCreateFile(PVOID                 ObjectBody,
         FileObject,
         DeviceObject);
   FileObject->Vpb = DeviceObject->Vpb;
-  FileObject->Type = IO_TYPE_FILE;
+  FileObject->Type = InternalFileType;
 
   return(STATUS_SUCCESS);
 }
@@ -240,7 +240,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject,
 
   CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
   CreatedFileObject->Vpb = DeviceObject->Vpb;
-  CreatedFileObject->Type = IO_TYPE_FILE;
+  CreatedFileObject->Type = InternalFileType;
   CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
 
   // shouldn't we initialize the lock event, and several other things here too?
index 9e29e1c..7cab4e6 100644 (file)
@@ -160,7 +160,7 @@ IopCreateDriver(
 
    RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
 
-   Object->Type = IO_TYPE_DRIVER;
+   Object->Type = InternalDriverType;
 
    for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
       Object->MajorFunction[i] = IopInvalidDeviceRequest;
index d52fcc4..de412e5 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id$
+ * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/io/iocomp.c
 
 POBJECT_TYPE ExIoCompletionType;
 
-NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
+NPAGED_LOOKASIDE_LIST  IoCompletionPacketLookaside;
 
 static GENERIC_MAPPING ExIoCompletionMapping = 
 {
-    STANDARD_RIGHTS_READ    | IO_COMPLETION_QUERY_STATE,
-    STANDARD_RIGHTS_WRITE   | IO_COMPLETION_MODIFY_STATE,
-    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
-    IO_COMPLETION_ALL_ACCESS
+   STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
+   STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
+   STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
+   IO_COMPLETION_ALL_ACCESS
 };
 
 /* FUNCTIONS *****************************************************************/
 
-VOID 
+NTSTATUS 
 STDCALL
+IopCreateIoCompletion(
+   PVOID                ObjectBody,
+   PVOID                Parent,
+   PWSTR                RemainingPath,
+   POBJECT_ATTRIBUTES   ObjectAttributes
+   )
+{
+   DPRINT("IopCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+      ObjectBody, Parent, RemainingPath);
+
+   if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
+   {
+      return STATUS_UNSUCCESSFUL;
+   }
+
+   return STATUS_SUCCESS;
+}
+
+VOID STDCALL
 IopDeleteIoCompletion(PVOID ObjectBody)
 {
-    PKQUEUE Queue = ObjectBody;
-    PLIST_ENTRY FirstEntry;
-    PLIST_ENTRY CurrentEntry;
-    PIO_COMPLETION_PACKET Packet;
-
-    DPRINT("IopDeleteIoCompletion()\n");
-
-    /* Rundown the Queue */
-    FirstEntry = KeRundownQueue(Queue);
-    
-    /* Clean up the IRPs */
-    if (FirstEntry) {
-    
-        CurrentEntry = FirstEntry;
-        do {
-        
-            /* Get the Packet */
-            Packet = CONTAINING_RECORD(CurrentEntry, IO_COMPLETION_PACKET, ListEntry);
-            
-            /* Go to next Entry */
-            CurrentEntry = CurrentEntry->Flink;
-            
-            /* Free it */
-            ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
-        } while (FirstEntry != CurrentEntry);
-    }
+   PKQUEUE Queue = ObjectBody;
+
+   DPRINT("IopDeleteIoCompletion()\n");
+
+   KeRundownQueue(Queue);
 }
 
+
 /*
- * @implemented
+ * @unimplemented
  */
 NTSTATUS
 STDCALL
-IoSetIoCompletion(IN PVOID IoCompletion,
-                  IN PVOID KeyContext,
-                  IN PVOID ApcContext,
-                  IN NTSTATUS IoStatus,
-                  IN ULONG_PTR IoStatusInformation,
-                  IN BOOLEAN Quota)
+IoSetCompletionRoutineEx(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_COMPLETION_ROUTINE CompletionRoutine,
+    IN PVOID Context,
+    IN BOOLEAN InvokeOnSuccess,
+    IN BOOLEAN InvokeOnError,
+    IN BOOLEAN InvokeOnCancel
+    )
 {
-    PKQUEUE Queue = (PKQUEUE)IoCompletion;
-    PIO_COMPLETION_PACKET Packet;
-
-    /* Allocate the Packet */
-    Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
-    if (NULL == Packet) return STATUS_NO_MEMORY;
-    
-    /* Set up the Packet */
-    Packet->Key = KeyContext;
-    Packet->Context = ApcContext;
-    Packet->IoStatus.Status = IoStatus;
-    Packet->IoStatus.Information = IoStatusInformation;
-    
-    /* Insert the Queue */
-    KeInsertQueue(Queue, &Packet->ListEntry);
-
-    /* Return Success */
-    return STATUS_SUCCESS;
+       UNIMPLEMENTED;
+       return STATUS_NOT_IMPLEMENTED;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 NTSTATUS
 STDCALL
-IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject,
-                         IN PIRP Irp,
-                         IN PIO_COMPLETION_ROUTINE CompletionRoutine,
-                         IN PVOID Context,
-                         IN BOOLEAN InvokeOnSuccess,
-                         IN BOOLEAN InvokeOnError,
-                         IN BOOLEAN InvokeOnCancel)
+IoSetIoCompletion (
+       IN PVOID IoCompletion,
+       IN PVOID KeyContext,
+       IN PVOID ApcContext,
+       IN NTSTATUS IoStatus,
+       IN ULONG_PTR IoStatusInformation,
+       IN BOOLEAN Quota
+       )
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+   PKQUEUE Queue = (PKQUEUE) IoCompletion;
+   PIO_COMPLETION_PACKET   Packet;
+
+   Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
+   if (NULL == Packet)
+   {
+     return STATUS_NO_MEMORY;
+   }
+
+   Packet->Key = KeyContext;
+   Packet->Context = ApcContext;
+   Packet->IoStatus.Status = IoStatus;
+   Packet->IoStatus.Information = IoStatusInformation;
+   
+   KeInsertQueue(Queue, &Packet->ListEntry);
+
+   return STATUS_SUCCESS;
 }
 
 VOID
 FASTCALL
 IopInitIoCompletionImplementation(VOID)
 {
-    /* Create the IO Completion Type */
-    ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));   
-    RtlpCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion", NonPagedPool);
-    ExIoCompletionType->Tag = IOC_TAG;
-    ExIoCompletionType->PeakObjects = 0;
-    ExIoCompletionType->PeakHandles = 0;
-    ExIoCompletionType->TotalObjects = 0;
-    ExIoCompletionType->TotalHandles = 0;
-    ExIoCompletionType->PagedPoolCharge = 0;
-    ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
-    ExIoCompletionType->Mapping = &ExIoCompletionMapping;
-    ExIoCompletionType->Dump = NULL;
-    ExIoCompletionType->Open = NULL;
-    ExIoCompletionType->Close = NULL;
-    ExIoCompletionType->Delete = IopDeleteIoCompletion;
-    ExIoCompletionType->Parse = NULL;
-    ExIoCompletionType->Security = NULL;
-    ExIoCompletionType->QueryName = NULL;
-    ExIoCompletionType->OkayToClose = NULL;
-    ExIoCompletionType->Create = NULL;
-    ExIoCompletionType->DuplicationNotify = NULL;
-
-    /* Initialize the Lookaside List we'll use for packets */
-    ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
-                                    NULL,
-                                    NULL,
-                                    0,
-                                    sizeof(IO_COMPLETION_PACKET),
-                                    IOC_TAG,
-                                    0);
+   ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+   
+   RtlpCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion", NonPagedPool);
+   
+   ExIoCompletionType->Tag = IOC_TAG;
+   ExIoCompletionType->PeakObjects = 0;
+   ExIoCompletionType->PeakHandles = 0;
+   ExIoCompletionType->TotalObjects = 0;
+   ExIoCompletionType->TotalHandles = 0;
+   ExIoCompletionType->PagedPoolCharge = 0;
+   ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
+   ExIoCompletionType->Mapping = &ExIoCompletionMapping;
+   ExIoCompletionType->Dump = NULL;
+   ExIoCompletionType->Open = NULL;
+   ExIoCompletionType->Close = NULL;
+   ExIoCompletionType->Delete = IopDeleteIoCompletion;
+   ExIoCompletionType->Parse = NULL;
+   ExIoCompletionType->Security = NULL;
+   ExIoCompletionType->QueryName = NULL;
+   ExIoCompletionType->OkayToClose = NULL;
+   ExIoCompletionType->Create = IopCreateIoCompletion;
+   ExIoCompletionType->DuplicationNotify = NULL;
+
+   ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
+                                   NULL,
+                                   NULL,
+                                   0,
+                                   sizeof(IO_COMPLETION_PACKET),
+                                   IOC_TAG,
+                                   0);
 }
 
+
 NTSTATUS
 STDCALL
-NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
-                     IN  ACCESS_MASK DesiredAccess,
-                     IN  POBJECT_ATTRIBUTES ObjectAttributes,
-                     IN  ULONG NumberOfConcurrentThreads)
+NtCreateIoCompletion(
+   OUT PHANDLE             IoCompletionHandle,
+   IN  ACCESS_MASK         DesiredAccess,
+   IN  POBJECT_ATTRIBUTES  ObjectAttributes,
+   IN  ULONG               NumberOfConcurrentThreads
+   )
 {
-    PKQUEUE Queue;
-    NTSTATUS Status;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-
-    /* Create the Object */
-    Status = ObCreateObject(PreviousMode,
-                            ExIoCompletionType,
-                            ObjectAttributes,
-                            PreviousMode,
-                            NULL,
-                            sizeof(KQUEUE),
-                            0,
-                            0,
-                            (PVOID*)&Queue);
-    
-    /* Check for success */
-    if (!NT_SUCCESS(Status)) {
-   
-        /* Initialize the Queue */
-        KeInitializeQueue(Queue, NumberOfConcurrentThreads);
-
-        /* Insert it */
-        Status = ObInsertObject(Queue,
-                                NULL,
-                                DesiredAccess,
-                                0,
-                                NULL,
-                                IoCompletionHandle);   
-        ObDereferenceObject(Queue);
+   PKQUEUE     Queue;
+   NTSTATUS    Status;
+
+   Status = ObCreateObject(ExGetPreviousMode(),
+                           ExIoCompletionType,
+                           ObjectAttributes,
+                           ExGetPreviousMode(),
+                           NULL,
+                           sizeof(KQUEUE),
+                           0,
+                           0,
+                           (PVOID*)&Queue);
+   if (!NT_SUCCESS(Status))
+   {
+     return Status;
    }
-   
-   /* Return Status */
+
+   Status = ObInsertObject ((PVOID)Queue,
+                           NULL,
+                           DesiredAccess,
+                           0,
+                           NULL,
+                           IoCompletionHandle);
+   if (!NT_SUCCESS(Status))
+   {
+     ObDereferenceObject(Queue);
+     return Status;
+   }
+
+   KeInitializeQueue(Queue, NumberOfConcurrentThreads);
+   ObDereferenceObject(Queue);
+
    return STATUS_SUCCESS;
+   /*
+
+  CompletionPort = NULL OR ExistingCompletionPort
+
+  */
+
 }
 
+/*
+DesiredAccess:
+ZERO
+IO_COMPLETION_QUERY_STATE Query access
+IO_COMPLETION_MODIFY_STATE Modify access
+IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL
+
+ObjectAttributes
+OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes
+
+Return Value
+STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or
+STATUS_OBJECT_NAME_NOT_FOUND.
+*/
 NTSTATUS
 STDCALL
-NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
-                   IN ACCESS_MASK DesiredAccess,
-                   IN POBJECT_ATTRIBUTES ObjectAttributes)
+NtOpenIoCompletion(
+   OUT PHANDLE             IoCompletionHandle,
+   IN  ACCESS_MASK         DesiredAccess,
+   IN  POBJECT_ATTRIBUTES  ObjectAttributes
+   )
 {
-    NTSTATUS Status;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    
-    /* Open the Object */
-    Status = ObOpenObjectByName(ObjectAttributes,
-                                ExIoCompletionType,
-                                NULL,
-                                PreviousMode,
-                                DesiredAccess,
-                                NULL,
-                                IoCompletionHandle);
-    /* Return Status */  
-    return Status;
+   NTSTATUS Status;
+   
+   Status = ObOpenObjectByName(ObjectAttributes,
+                               ExIoCompletionType,
+                               NULL,
+                               UserMode,
+                               DesiredAccess,
+                               NULL,
+                               IoCompletionHandle);  //<- ???
+   
+   return Status;
 }
 
+
 NTSTATUS
 STDCALL
-NtQueryIoCompletion(IN  HANDLE IoCompletionHandle,
-                    IN  IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
-                    OUT PVOID IoCompletionInformation,
-                    IN  ULONG IoCompletionInformationLength,
-                    OUT PULONG ResultLength OPTIONAL)
+NtQueryIoCompletion(
+   IN  HANDLE                          IoCompletionHandle,
+   IN  IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
+   OUT PVOID                           IoCompletionInformation,
+   IN  ULONG                           IoCompletionInformationLength,
+   OUT PULONG                          ResultLength OPTIONAL
+   )
 {
-    PKQUEUE Queue;
-    NTSTATUS Status;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+   PKQUEUE  Queue;
+   NTSTATUS Status;
 
-    /* Get the Object */
-    Status = ObReferenceObjectByHandle(IoCompletionHandle,
+   if (IoCompletionInformationClass != IoCompletionBasicInformation)
+   {
+      return STATUS_INVALID_INFO_CLASS;
+   }
+   if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION))
+   {
+      return STATUS_INFO_LENGTH_MISMATCH;
+   }
+
+   Status = ObReferenceObjectByHandle( IoCompletionHandle,
                                        IO_COMPLETION_QUERY_STATE,
                                        ExIoCompletionType,
-                                       PreviousMode,
+                                       UserMode,
                                        (PVOID*)&Queue,
                                        NULL);
-    
-    /* Check for Success */
-   if (NT_SUCCESS(Status)) {
-      
-        /* Return Info */
-        ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = KeReadStateQueue(Queue);
-        ObDereferenceObject(Queue);
+   if (NT_SUCCESS(Status))
+   {
+      ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = 
+         Queue->Header.SignalState;
 
-        /* Return Result Length if needed */
-        if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
-    }
+      ObDereferenceObject(Queue);
 
-    /* Return Status */
-    return Status;
+      if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
+   }
+
+   return Status;
 }
 
+
 /*
  * Dequeues an I/O completion message from an I/O completion object
  */
 NTSTATUS
 STDCALL
-NtRemoveIoCompletion(IN  HANDLE IoCompletionHandle,
-                     OUT PVOID *CompletionKey,
-                     OUT PVOID *CompletionContext,
-                     OUT PIO_STATUS_BLOCK IoStatusBlock,
-                     IN  PLARGE_INTEGER Timeout OPTIONAL)
+NtRemoveIoCompletion(
+   IN  HANDLE           IoCompletionHandle,
+   OUT PVOID            *CompletionKey,
+   OUT PVOID            *CompletionContext,
+   OUT PIO_STATUS_BLOCK IoStatusBlock,
+   IN  PLARGE_INTEGER   Timeout OPTIONAL
+   )
 {
-    PKQUEUE Queue;
-    NTSTATUS Status;
-    PIO_COMPLETION_PACKET Packet;
-    PLIST_ENTRY ListEntry;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    
-    /* Open the Object */
-    Status = ObReferenceObjectByHandle(IoCompletionHandle,
+   PKQUEUE  Queue;
+   NTSTATUS Status;
+   PIO_COMPLETION_PACKET   Packet;
+   PLIST_ENTRY             ListEntry;
+
+   Status = ObReferenceObjectByHandle( IoCompletionHandle,
                                        IO_COMPLETION_MODIFY_STATE,
                                        ExIoCompletionType,
-                                       PreviousMode,
+                                       UserMode,
                                        (PVOID*)&Queue,
                                        NULL);
-    
-    /* Check for success */
-    if (NT_SUCCESS(Status)) {
-
-        /* Remove queue */
-        ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout);
-
-        /* If we got a timeout or user_apc back, return the status */
-        if ((NTSTATUS)ListEntry == STATUS_TIMEOUT || (NTSTATUS)ListEntry == STATUS_USER_APC) {
-            
-            Status = (NTSTATUS)ListEntry; 
-            
-        } else {
-            
-            /* Get the Packet Data */
-            Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
-            
-            /* Return it */
-           if (CompletionKey) *CompletionKey = Packet->Key;
-           if (CompletionContext) *CompletionContext = Packet->Context;
-           if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
-           
-           /* Free packet */
-           ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
-        }
+   if (!NT_SUCCESS(Status))
+   {
+      return Status;
+   }
+
+   /*
+   Try 2 remove packet from queue. Wait (optionaly) if
+   no packet in queue or max num of threads allready running.
+   */
+      
+   do {
+      
+      ListEntry = KeRemoveQueue(Queue, UserMode, Timeout );
+
+      /* Nebbets book says nothing about NtRemoveIoCompletion returning STATUS_USER_APC,
+      and the umode equivalent GetQueuedCompletionStatus says nothing about this either,
+      so my guess it we should restart the operation. Need further investigation. -Gunnar
+      */
+
+   } while((NTSTATUS)ListEntry == STATUS_USER_APC);
+
+   ObDereferenceObject(Queue);
+   
+   if ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
+   {
+      return STATUS_TIMEOUT;
+   }
+   
+   ASSERT(ListEntry);
    
-        /* Dereference the Object */
-        ObDereferenceObject(Queue);
-    }
-    
-    /* Return status */
-    return Status;
+   Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
+
+   if (CompletionKey) *CompletionKey = Packet->Key;
+   if (CompletionContext) *CompletionContext = Packet->Context;
+   if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
+
+   ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
+
+   return STATUS_SUCCESS;
 }
 
+
+/*
+ASSOSIERT MED FOB's IoCompletionContext
+
+typedef struct _IO_COMPLETION_CONTEXT {
+        PVOID Port; 
+        ULONG Key; 
+} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
+
+*/
+
+
 /*
  * Queues an I/O completion message to an I/O completion object
  */
 NTSTATUS
 STDCALL
-NtSetIoCompletion(IN HANDLE IoCompletionPortHandle,
-                  IN PVOID CompletionKey,
-                  IN PVOID CompletionContext,
-                  IN NTSTATUS CompletionStatus,
-                  IN ULONG CompletionInformation)
+NtSetIoCompletion(
+   IN HANDLE   IoCompletionPortHandle,
+   IN PVOID    CompletionKey,
+   IN PVOID    CompletionContext,
+   IN NTSTATUS CompletionStatus,
+   IN ULONG    CompletionInformation
+   )
 {
-    NTSTATUS Status;
-    PKQUEUE Queue;
-    
-    /* Get the Object */
-    Status = ObReferenceObjectByHandle(IoCompletionPortHandle,
+   NTSTATUS                Status;
+   PKQUEUE                 Queue;
+
+   Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
                                        IO_COMPLETION_MODIFY_STATE,
                                        ExIoCompletionType,
-                                       ExGetPreviousMode(),
+                                       UserMode,
                                        (PVOID*)&Queue,
                                        NULL);
-    
-    /* Check for Success */
-    if (NT_SUCCESS(Status)) {
-        
-        /* Set the Completion */
-        Status = IoSetIoCompletion(Queue, 
-                                   CompletionKey, 
-                                   CompletionContext,
-                                   CompletionStatus, 
-                                   CompletionInformation, 
-                                   TRUE);
-        ObDereferenceObject(Queue);
-    }
-    
-    /* Return status */
-    return Status;
+   if (NT_SUCCESS(Status))
+   {
+      Status = IoSetIoCompletion(Queue, CompletionKey, CompletionContext,
+                                 CompletionStatus, CompletionInformation, TRUE);
+      ObDereferenceObject(Queue);
+   }
+
+   return Status;
 }
index 4cc4d60..81852d2 100644 (file)
@@ -553,17 +553,14 @@ IoInit (VOID)
 }
 
 
-VOID 
-INIT_FUNCTION
-IoInit2(BOOLEAN BootLog)
+VOID INIT_FUNCTION
+IoInit2(VOID)
 {
   PDEVICE_NODE DeviceNode;
   PDRIVER_OBJECT DriverObject;
   MODULE_OBJECT ModuleObject;
   NTSTATUS Status;
 
-  IoCreateDriverList();
-          
   KeInitializeSpinLock (&IoStatisticsLock);
 
   /* Initialize raw filesystem driver */
@@ -608,56 +605,6 @@ IoInit2(BOOLEAN BootLog)
   IopInvalidateDeviceRelations(
     IopRootDeviceNode,
     BusRelations);
-  
-     /* Start boot logging */
-    IopInitBootLog(BootLog);
-  
-    /* Load boot start drivers */
-    IopInitializeBootDrivers();
-}
-
-VOID
-STDCALL
-INIT_FUNCTION
-IoInit3(VOID)
-{
-    NTSTATUS Status;
-    
-    /* Create ARC names for boot devices */
-    IoCreateArcNames();
-
-    /* Create the SystemRoot symbolic link */
-    CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
-    Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
-    if (!NT_SUCCESS(Status)) {
-        DbgPrint("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
-        DbgPrintErrorMessage (Status);
-        KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
-    }
-
-    /* Start Profiling on a Debug Build */
-#if defined(KDBG) || defined(DBG)
-    KdbInitProfiling2();
-#endif /* KDBG */
-
-    /* I/O is now setup for disk access, so start the debugging logger thread. */
-    if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_BOOTLOG)) DebugLogInit2();
-
-    /* Load services for devices found by PnP manager */
-    IopInitializePnpServices(IopRootDeviceNode, FALSE);
-
-    /* Load system start drivers */
-    IopInitializeSystemDrivers();
-    IoDestroyDriverList();
-
-    /* Stop boot logging */
-    IopStopBootLog();
-
-    /* Assign drive letters */
-    IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
-                         NULL,
-                         NULL,
-                         NULL);    
 }
 
 /*
index 9d01c6b..8b90882 100644 (file)
@@ -249,18 +249,4 @@ IoWMIDeviceObjectToInstanceName(
        return STATUS_NOT_IMPLEMENTED;
 }
 
-/*
- * @unimplemented
- */
-NTSTATUS
-STDCALL
-NtTraceEvent(IN ULONG TraceHandle,
-             IN ULONG Flags,
-             IN ULONG TraceHeaderLength,
-             IN struct _EVENT_TRACE_HEADER* TraceHeader)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
 /*Eof*/
diff --git a/reactos/ntoskrnl/ke/alert.c b/reactos/ntoskrnl/ke/alert.c
new file mode 100644 (file)
index 0000000..99084a8
--- /dev/null
@@ -0,0 +1,150 @@
+/* $Id:$
+ * 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ke/alert.c
+ * PURPOSE:         Alerts
+ * 
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* GLOBALS *******************************************************************/
+
+
+/* FUNCTIONS *****************************************************************/
+
+
+BOOLEAN
+STDCALL
+KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
+/*
+ * FUNCTION: Tests whether there are any pending APCs for the current thread
+ * and if so the APCs will be delivered on exit from kernel mode
+ */
+{
+   KIRQL OldIrql;
+   PKTHREAD Thread = KeGetCurrentThread();
+   BOOLEAN OldState;
+   
+   ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+   
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   KiAcquireSpinLock(&Thread->ApcQueueLock);
+   
+   OldState = Thread->Alerted[AlertMode];
+   
+   /* If the Thread is Alerted, Clear it */
+   if (OldState) {
+      Thread->Alerted[AlertMode] = FALSE;
+   } else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) {
+      /* If the mode is User and the Queue isn't empty, set Pending */
+      Thread->ApcState.UserApcPending = TRUE;
+   }
+   
+   KiReleaseSpinLock(&Thread->ApcQueueLock);
+   KeReleaseDispatcherDatabaseLock(OldIrql);
+   return OldState;
+}
+
+
+VOID
+KeAlertThread(PKTHREAD Thread, KPROCESSOR_MODE AlertMode)
+{
+   KIRQL oldIrql;
+
+   
+   oldIrql = KeAcquireDispatcherDatabaseLock();
+      
+
+   /* Return if thread is already alerted. */
+   if (Thread->Alerted[AlertMode] == FALSE)
+   {
+      if (Thread->State == THREAD_STATE_BLOCKED &&
+          (AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
+          Thread->Alertable)
+      {
+         KiAbortWaitThread(Thread, STATUS_ALERTED);
+      }
+      else
+      {
+         Thread->Alerted[AlertMode] = TRUE;
+      }
+   }
+   
+   KeReleaseDispatcherDatabaseLock(oldIrql);
+}
+
+
+/* 
+ *
+ * NOT EXPORTED
+ */
+NTSTATUS STDCALL
+NtAlertResumeThread(IN  HANDLE ThreadHandle,
+          OUT PULONG SuspendCount)
+{
+   UNIMPLEMENTED;
+   return(STATUS_NOT_IMPLEMENTED);
+
+}
+
+/* 
+ * @implemented
+ *
+ * EXPORTED
+ */
+NTSTATUS STDCALL
+NtAlertThread (IN HANDLE ThreadHandle)
+{
+   KPROCESSOR_MODE PreviousMode;
+   PETHREAD Thread;
+   NTSTATUS Status;
+   
+   PreviousMode = ExGetPreviousMode();
+
+   Status = ObReferenceObjectByHandle(ThreadHandle,
+                  THREAD_SUSPEND_RESUME,
+                  PsThreadType,
+                  PreviousMode,
+                  (PVOID*)&Thread,
+                  NULL);
+   if (!NT_SUCCESS(Status))
+     {
+   return(Status);
+     }
+
+   /* do an alert depending on the processor mode. If some kmode code wants to
+      enforce a umode alert it should call KeAlertThread() directly. If kmode
+      code wants to do a kmode alert it's sufficient to call it with Zw or just
+      use KeAlertThread() directly */
+
+   KeAlertThread(&Thread->Tcb, PreviousMode);
+   
+   ObDereferenceObject(Thread);
+   return(STATUS_SUCCESS);
+}
+
+
+/* 
+ * NOT EXPORTED
+ */
+NTSTATUS
+STDCALL
+NtTestAlert(VOID)
+{
+   KPROCESSOR_MODE PreviousMode;
+   
+   PreviousMode = ExGetPreviousMode();
+   
+   /* Check and Alert Thread if needed */
+   
+   return KeTestAlertThread(PreviousMode) ? STATUS_ALERTED : STATUS_SUCCESS;
+}
+
index 04d9786..5b47908 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/apc.c
 
 VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
 
-/* FUNCTIONS *****************************************************************/
+#define TAG_KAPC     TAG('K', 'A', 'P', 'C')
 
-/*++
- * KeEnterCriticalRegion 
- * @implemented NT4
- *
- *     The KeEnterCriticalRegion routine temporarily disables the delivery of 
- *      normal kernel APCs; special kernel-mode APCs are still delivered.
- *
- * Params:
- *     None.
- *
- * Returns:
- *     None.
- *
- * Remarks:
- *     Highest-level drivers can call this routine while running in the context
- *     of the thread that requested the current I/O operation. Any caller of 
- *     this routine should call KeLeaveCriticalRegion as quickly as possible.
- *
- *     Callers of KeEnterCriticalRegion must be running at IRQL <= APC_LEVEL.
- *
- *--*/
-VOID 
-STDCALL 
-KeEnterCriticalRegion(VOID)
-{
-    /* Disable Kernel APCs */
-    PKTHREAD Thread = KeGetCurrentThread();
-    if (Thread) Thread->KernelApcDisable--;
-}
+/* FUNCTIONS *****************************************************************/
 
-/*++
- * KeInitializeApc 
- * @implemented NT4
- *
- *     The The KeInitializeApc routine initializes an APC object, and registers
- *     the Kernel, Rundown and Normal routines for that object.
- *
- * Params:
- *     Apc - Pointer to a KAPC structure that represents the APC object to 
- *           initialize. The caller must allocate storage for the structure
- *           from resident memory.
- *
- *     Thread - Thread to which to deliver the APC.
- *
- *     TargetEnvironment - APC Environment to be used.
- *
- *     KernelRoutine - Points to the KernelRoutine to associate with the APC.
- *                     This routine is executed for all APCs.
- *
- *     RundownRoutine - Points to the RundownRoutine to associate with the APC.
- *                      This routine is executed when the Thread exists with
- *                      the APC executing.
- *
- *     NormalRoutine - Points to the NormalRoutine to associate with the APC.
- *                     This routine is executed at PASSIVE_LEVEL. If this is
- *                     not specifed, the APC becomes a Special APC and the
- *                     Mode and Context parameters are ignored.
- *
- *     Mode - Specifies the processor mode at which to run the Normal Routine.
- *
- *     Context - Specifices the value to pass as Context parameter to the 
- *               registered routines.
- *
- * Returns:
- *     None.
- *
- * Remarks:
- *     The caller can queue an initialized APC with KeInsertQueueApc.
- *
- *     Storage for the APC object must be resident, such as nonpaged pool 
- *     allocated by the caller.
- *
- *     Callers of this routine must be running at IRQL = PASSIVE_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
 VOID
 STDCALL
-KeInitializeApc(IN PKAPC Apc,
-                IN PKTHREAD Thread,
-                IN KAPC_ENVIRONMENT TargetEnvironment,
-                IN PKKERNEL_ROUTINE KernelRoutine,
-                IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
-                IN PKNORMAL_ROUTINE NormalRoutine,
-                IN KPROCESSOR_MODE Mode,
-                IN PVOID Context)
+KeInitializeApc(
+       IN PKAPC  Apc,
+       IN PKTHREAD  Thread,
+       IN KAPC_ENVIRONMENT  TargetEnvironment,
+       IN PKKERNEL_ROUTINE  KernelRoutine,
+       IN PKRUNDOWN_ROUTINE  RundownRoutine OPTIONAL,
+       IN PKNORMAL_ROUTINE  NormalRoutine,
+       IN KPROCESSOR_MODE  Mode,
+       IN PVOID  Context)
+/*
+ * FUNCTION: Initialize an APC object
+ * ARGUMENTS:
+ *       Apc = Pointer to the APC object to initialized
+ *       Thread = Thread the APC is to be delivered to
+ *       TargetEnvironment = APC environment to use
+ *       KernelRoutine = Routine to be called for a kernel-mode APC
+ *       RundownRoutine = Routine to be called if the thread has exited with
+ *                        the APC being executed
+ *       NormalRoutine = Routine to be called for a user-mode APC
+ *       Mode = APC mode
+ *       Context = Parameter to be passed to the APC routine
+ */
 {
-    DPRINT("KeInitializeApc(Apc %x, Thread %x, Environment %d, "
-           "KernelRoutine %x, RundownRoutine %x, NormalRoutine %x, Mode %d, "
-           "Context %x)\n",Apc,Thread,TargetEnvironment,KernelRoutine,RundownRoutine,
-            NormalRoutine,Mode,Context);
-
-    /* Set up the basic APC Structure Data */
-    RtlZeroMemory(Apc, sizeof(KAPC));
-    Apc->Type = ApcObject;
-    Apc->Size = sizeof(KAPC);
-    
-    /* Set the Environment */
-    if (TargetEnvironment == CurrentApcEnvironment) {
-        
-        Apc->ApcStateIndex = Thread->ApcStateIndex;
-        
-    } else {
-        
-        Apc->ApcStateIndex = TargetEnvironment;
-    }
-    
-    /* Set the Thread and Routines */
-    Apc->Thread = Thread;
-    Apc->KernelRoutine = KernelRoutine;
-    Apc->RundownRoutine = RundownRoutine;
-    Apc->NormalRoutine = NormalRoutine;
+       DPRINT ("KeInitializeApc(Apc %x, Thread %x, Environment %d, "
+               "KernelRoutine %x, RundownRoutine %x, NormalRoutine %x, Mode %d, "
+               "Context %x)\n",Apc,Thread,TargetEnvironment,KernelRoutine,RundownRoutine,
+               NormalRoutine,Mode,Context);
+
+       /* Set up the basic APC Structure Data */
+       RtlZeroMemory(Apc, sizeof(KAPC));
+       Apc->Type = KApc;
+       Apc->Size = sizeof(KAPC);
+       
+       /* Set the Environment */
+       if (TargetEnvironment == CurrentApcEnvironment) {
+               Apc->ApcStateIndex = Thread->ApcStateIndex;
+       } else {
+               Apc->ApcStateIndex = TargetEnvironment;
+       }
+       
+       /* Set the Thread and Routines */
+       Apc->Thread = Thread;
+       Apc->KernelRoutine = KernelRoutine;
+       Apc->RundownRoutine = RundownRoutine;
+       Apc->NormalRoutine = NormalRoutine;
    
-    /* Check if this is a Special APC, in which case we use KernelMode and no Context */
-    if (ARGUMENT_PRESENT(NormalRoutine)) {
-        
-        Apc->ApcMode = Mode;
-        Apc->NormalContext = Context;
-        
-    } else {
-        
-        Apc->ApcMode = KernelMode;
-    }  
+       /* Check if this is a Special APC, in which case we use KernelMode and no Context */
+       if (ARGUMENT_PRESENT(NormalRoutine)) {
+               Apc->ApcMode = Mode;
+               Apc->NormalContext = Context;
+       } else {
+               Apc->ApcMode = KernelMode;
+       }  
 }
 
-/*++
- * KeInsertQueueApc 
- * @implemented NT4
- *
- *     The KeInsertQueueApc routine queues a APC for execution when the right
- *     scheduler environment exists.
- *
- * Params:
- *     Apc - Pointer to an initialized control object of type DPC for which the
- *           caller provides the storage. 
- *
- *     SystemArgument[1,2] - Pointer to a set of two parameters that contain
- *                           untyped data.
- *
- *     PriorityBoost - Priority Boost to apply to the Thread.
- *
- * Returns:
- *     If the APC is already inserted or APC queueing is disabled, FALSE.
- *     Otherwise, TRUE.
- *
- * Remarks:
- *     The APC will execute at APC_LEVEL for the KernelRoutine registered, and
- *     at PASSIVE_LEVEL for the NormalRoutine registered.
- *
- *     Callers of this routine must be running at IRQL = PASSIVE_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
 BOOLEAN
 STDCALL
-KeInsertQueueApc(PKAPC Apc,
-                 PVOID SystemArgument1,
-                 PVOID SystemArgument2,
-                 KPRIORITY PriorityBoost)
-
+KeInsertQueueApc (PKAPC        Apc,
+                 PVOID SystemArgument1,
+                 PVOID SystemArgument2,
+                 KPRIORITY PriorityBoost)
+/*
+ * FUNCTION: Queues an APC for execution
+ * ARGUMENTS:
+ *         Apc = APC to be queued
+ *         SystemArgument[1-2] = Arguments we ignore and simply pass on.
+ *         PriorityBoost = Priority Boost to give to the Thread
+ */
 {
-    KIRQL OldIrql;
-    PKTHREAD Thread;
-    PLIST_ENTRY ApcListEntry;
-    PKAPC QueuedApc;
+       KIRQL OldIrql;
+       PKTHREAD Thread;
+       PLIST_ENTRY ApcListEntry;
+       PKAPC QueuedApc;
    
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-    DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
-           "SystemArgument2 %x)\n",Apc,SystemArgument1,
-            SystemArgument2);
-
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Get the Thread specified in the APC */
-    Thread = Apc->Thread;
-       
-    /* Make sure the thread allows APC Queues.
+   ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+       DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
+               "SystemArgument2 %x)\n",Apc,SystemArgument1,
+               SystemArgument2);
+
+       OldIrql = KeAcquireDispatcherDatabaseLock();
+       
+       /* Get the Thread specified in the APC */
+       Thread = Apc->Thread;
+          
+       /* Make sure the thread allows APC Queues.
     * The thread is not apc queueable, for instance, when it's (about to be) terminated.
     */
-    if (Thread->ApcQueueable == FALSE) {
-        DPRINT("Thread doesn't allow APC Queues\n");
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        return FALSE;
-    }
-    
-    /* Set the System Arguments */
-    Apc->SystemArgument1 = SystemArgument1;
-    Apc->SystemArgument2 = SystemArgument2;
-
-    /* Don't do anything if the APC is already inserted */
-    if (Apc->Inserted) {
-        
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        return FALSE;
-    }
-    
-    /* Three scenarios: 
-       1) Kernel APC with Normal Routine or User APC = Put it at the end of the List
-       2) User APC which is PsExitSpecialApc = Put it at the front of the List
-       3) Kernel APC without Normal Routine = Put it at the end of the No-Normal Routine Kernel APC list
-    */
-    if ((Apc->ApcMode != KernelMode) && (Apc->KernelRoutine == (PKKERNEL_ROUTINE)PsExitSpecialApc)) {
-        
-        DPRINT ("Inserting the Process Exit APC into the Queue\n");
-        Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = TRUE;
-        InsertHeadList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
-                       &Apc->ApcListEntry);
-        
-    } else if (Apc->NormalRoutine == NULL) {
-        
-        DPRINT ("Inserting Special APC %x into the Queue\n", Apc);
-        
-        for (ApcListEntry = Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode].Flink;
-             ApcListEntry != &Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode];
-             ApcListEntry = ApcListEntry->Flink) {
-
-            QueuedApc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
-            if (Apc->NormalRoutine != NULL) break;
-        }
-        
-        /* We found the first "Normal" APC, so write right before it */
-        ApcListEntry = ApcListEntry->Blink;
-        InsertHeadList(ApcListEntry, &Apc->ApcListEntry);
-        
-    } else {
-        
-        DPRINT ("Inserting Normal APC %x into the %x Queue\n", Apc, Apc->ApcMode);
-        InsertTailList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
-                   &Apc->ApcListEntry);
-    }
-    
-    /* Confirm Insertion */    
-    Apc->Inserted = TRUE;
-
-    /*
-     * Three possibilites here again:
-     *  1) Kernel APC, The thread is Running: Request an Interrupt
-     *  2) Kernel APC, The Thread is Waiting at PASSIVE_LEVEL and APCs are enabled and not in progress: Unwait the Thread
-     *  3) User APC, Unwait the Thread if it is alertable
-     */ 
-    if (Apc->ApcMode == KernelMode) { 
-        
-        /* Set Kernel APC pending */
-        Thread->ApcState.KernelApcPending = TRUE;
-        
-        /* Check the Thread State */
-        if (Thread->State == THREAD_STATE_RUNNING) { 
-            
-            /* FIXME: Use IPI */
-            DPRINT ("Requesting APC Interrupt for Running Thread \n");
-            HalRequestSoftwareInterrupt(APC_LEVEL);
-            
-        } else if ((Thread->State == THREAD_STATE_BLOCKED) && 
+       if (Thread->ApcQueueable == FALSE) {
+               DPRINT("Thread doesn't allow APC Queues\n");
+               KeReleaseDispatcherDatabaseLock(OldIrql);
+               return FALSE;
+       }
+       
+       /* Set the System Arguments */
+       Apc->SystemArgument1 = SystemArgument1;
+       Apc->SystemArgument2 = SystemArgument2;
+
+       /* Don't do anything if the APC is already inserted */
+       if (Apc->Inserted) {
+               KeReleaseDispatcherDatabaseLock(OldIrql);
+               return FALSE;
+       }
+       
+       /* Three scenarios: 
+          1) Kernel APC with Normal Routine or User APC = Put it at the end of the List
+          2) User APC which is PsExitSpecialApc = Put it at the front of the List
+          3) Kernel APC without Normal Routine = Put it at the end of the No-Normal Routine Kernel APC list
+       */
+       if ((Apc->ApcMode != KernelMode) && (Apc->KernelRoutine == (PKKERNEL_ROUTINE)PsExitSpecialApc)) {
+               DPRINT ("Inserting the Process Exit APC into the Queue\n");
+               Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = TRUE;
+               InsertHeadList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
+                              &Apc->ApcListEntry);
+       } else if (Apc->NormalRoutine == NULL) {
+               DPRINT ("Inserting Special APC %x into the Queue\n", Apc);
+               for (ApcListEntry = Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode].Flink;
+                    ApcListEntry != &Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode];
+                    ApcListEntry = ApcListEntry->Flink) {
+
+                       QueuedApc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
+                       if (Apc->NormalRoutine != NULL) break;
+               }
+               
+               /* We found the first "Normal" APC, so write right before it */
+               ApcListEntry = ApcListEntry->Blink;
+               InsertHeadList(ApcListEntry, &Apc->ApcListEntry);
+       } else {
+               DPRINT ("Inserting Normal APC %x into the %x Queue\n", Apc, Apc->ApcMode);
+               InsertTailList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
+                              &Apc->ApcListEntry);
+       }
+       
+       /* Confirm Insertion */ 
+       Apc->Inserted = TRUE;
+
+       /* Three possibilites here again:
+          1) Kernel APC, The thread is Running: Request an Interrupt
+          2) Kernel APC, The Thread is Waiting at PASSIVE_LEVEL and APCs are enabled and not in progress: Unwait the Thread
+          3) User APC, Unwait the Thread if it is alertable
+       */ 
+       if (Apc->ApcMode == KernelMode) { 
+               Thread->ApcState.KernelApcPending = TRUE;
+               if (Thread->State == THREAD_STATE_RUNNING) { 
+                       /* FIXME: Use IPI */
+                       DPRINT ("Requesting APC Interrupt for Running Thread \n");
+                       HalRequestSoftwareInterrupt(APC_LEVEL);
+      } else if ((Thread->State == THREAD_STATE_BLOCKED) && 
                  (Thread->WaitIrql < APC_LEVEL) && 
-                 (Apc->NormalRoutine == NULL)) {
-          
-            DPRINT("Waking up Thread for Kernel-Mode APC Delivery \n");
-            KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
-        }
-        
+                 (Apc->NormalRoutine == NULL)) 
+      {
+                       DPRINT ("Waking up Thread for Kernel-Mode APC Delivery \n");
+                       KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
+               }
    } else if ((Thread->State == THREAD_STATE_BLOCKED) && 
               (Thread->WaitMode == UserMode) && 
-              (Thread->Alertable)) {
-       
-        DPRINT("Waking up Thread for User-Mode APC Delivery \n");
-        Thread->ApcState.UserApcPending = TRUE;
-        KiAbortWaitThread(Thread, STATUS_USER_APC);
-    }
-
-    /* Return Sucess if we are here */
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return TRUE;
+              (Thread->Alertable)) 
+   {
+               DPRINT ("Waking up Thread for User-Mode APC Delivery \n");
+               Thread->ApcState.UserApcPending = TRUE;
+      KiAbortWaitThread(Thread, STATUS_USER_APC);
+       }
+
+       /* Return Sucess if we are here */
+       KeReleaseDispatcherDatabaseLock(OldIrql);
+       return TRUE;
 }
 
-/*++
- * KeLeaveCriticalRegion 
- * @implemented NT4
- *
- *     The KeLeaveCriticalRegion routine reenables the delivery of normal 
- *     kernel-mode APCs that were disabled by a call to KeEnterCriticalRegion.
- *
- * Params:
- *     None.
- *
- * Returns:
- *     None.
- *
- * Remarks:
- *     Highest-level drivers can call this routine while running in the context
- *     of the thread that requested the current I/O operation. 
- *
- *     Callers of KeLeaveCriticalRegion must be running at IRQL <= DISPATCH_LEVEL.
- *
- *--*/
-VOID 
-STDCALL 
-KeLeaveCriticalRegion (VOID)
+BOOLEAN STDCALL
+KeRemoveQueueApc (PKAPC Apc)
+/*
+ * FUNCTION: Removes APC object from the apc queue
+ * ARGUMENTS:
+ *          Apc = APC to remove
+ * RETURNS: TRUE if the APC was in the queue
+ *          FALSE otherwise
+ * NOTE: This function is not exported.
+ */
 {
-    PKTHREAD Thread = KeGetCurrentThread(); 
-
-    /* Check if Kernel APCs are now enabled */
-    if((Thread) && (++Thread->KernelApcDisable == 0)) { 
-        
-        /* Check if we need to request an APC Delivery */
-        if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) { 
-            
-            /* Set APC Pending */
-            Thread->ApcState.KernelApcPending = TRUE; 
-            HalRequestSoftwareInterrupt(APC_LEVEL); 
-        } 
-    } 
+       KIRQL OldIrql;
+       PKTHREAD Thread = Apc->Thread;
+
+   ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+       DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
+       
+       OldIrql = KeAcquireDispatcherDatabaseLock();
+       KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+       
+       /* Remove it from the Queue if it's inserted */
+       if (!Apc->Inserted == FALSE) {
+               RemoveEntryList(&Apc->ApcListEntry);
+               Apc->Inserted = FALSE;
+               
+               /* If the Queue is completely empty, then no more APCs are pending */
+               if (IsListEmpty(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode])) {
+                       if (Apc->ApcMode == KernelMode) {
+                               Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->KernelApcPending = FALSE;
+                       } else {
+                               Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = FALSE;
+                       }
+               }
+       } else {
+               KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+               KeReleaseDispatcherDatabaseLock(OldIrql);
+               return(FALSE);
+       }
+       
+       /* Restore IRQL and Return */
+       KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+       KeReleaseDispatcherDatabaseLock(OldIrql);
+       return(TRUE);
 }
 
-/*++
- * KeRemoveQueueApc 
- *
- *     The KeRemoveQueueApc routine removes a given APC object from the system 
- *     APC queue.
- *
- * Params:
- *     APC - Pointer to an initialized APC object that was queued by calling
- *           KeInsertQueueApc.
- *
- * Returns:
- *     TRUE if the APC Object is in the APC Queue. If it isn't, no operation is
- *     performed and FALSE is returned.
- *
- * Remarks:
- *     If the given APC Object is currently queued, it is removed from the queue
- *     and any calls to the registered routines are cancelled.
- *
- *     Callers of KeLeaveCriticalRegion can be running at any IRQL.
- *
- *--*/
-BOOLEAN 
-STDCALL
-KeRemoveQueueApc(PKAPC Apc)
-{
-    KIRQL OldIrql;
-    PKTHREAD Thread = Apc->Thread;
-
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-    DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
-    
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
-    
-    /* Check if it's inserted */
-    if (Apc->Inserted) {
-        
-        /* Remove it from the Queue*/
-        RemoveEntryList(&Apc->ApcListEntry);
-        Apc->Inserted = FALSE;
-        
-        /* If the Queue is completely empty, then no more APCs are pending */
-        if (IsListEmpty(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode])) {
-            
-            /* Set the correct State based on the Apc Mode */
-            if (Apc->ApcMode == KernelMode) {
-                
-                Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->KernelApcPending = FALSE;
-                
-            } else {
-                
-                Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = FALSE;
-            }
-        }
-        
-    } else {
-        
-        /* It's not inserted, fail */
-        KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        return(FALSE);
-    }
-    
-    /* Restore IRQL and Return */
-    KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return(TRUE);
-}
 
-/*++
- * KiDeliverApc 
- * @implemented @NT4
- *    
- *     The KiDeliverApc routine is called from IRQL switching code if the
- *     thread is returning from an IRQL >= APC_LEVEL and Kernel-Mode APCs are
- *     pending. 
- *
- * Params:
- *     DeliveryMode - Specifies the current processor mode.
- *
- *     Reserved - Pointer to the Exception Frame on non-i386 builds.
- *
- *     TrapFrame - Pointer to the Trap Frame.
- *
- * Returns:
- *     None.
- *
- * Remarks:
- *     First, Special APCs are delivered, followed by Kernel-Mode APCs and
- *     User-Mode APCs. Note that the TrapFrame is only valid if the previous
- *     mode is User.
- *
- *     Upon entry, this routine executes at APC_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
 VOID 
 STDCALL
 KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
              PVOID Reserved,
              PKTRAP_FRAME TrapFrame)
+/*
+ * FUNCTION: Deliver an APC to the current thread.
+ * NOTES: This is called from the IRQL switching code if the current thread
+ * is returning from an IRQL greater than or equal to APC_LEVEL to 
+ * PASSIVE_LEVEL and there are kernel-mode APCs pending. This means any
+ * pending APCs will be delivered after a thread gets a new quantum and
+ * after it wakes from a wait. Note that the TrapFrame is only valid if
+ * the previous mode is User.
+ */
 {
-    PKTHREAD Thread = KeGetCurrentThread();
-    PLIST_ENTRY ApcListEntry;
-    PKAPC Apc;
-    KIRQL OldIrql;
-    PKKERNEL_ROUTINE KernelRoutine;
-    PVOID NormalContext;
-    PKNORMAL_ROUTINE NormalRoutine;
-    PVOID SystemArgument1;
-    PVOID SystemArgument2;
+       PKTHREAD Thread = KeGetCurrentThread();
+       PLIST_ENTRY ApcListEntry;
+       PKAPC Apc;
+       KIRQL OldIrql;
+       PKKERNEL_ROUTINE KernelRoutine;
+       PVOID NormalContext;
+       PKNORMAL_ROUTINE NormalRoutine;
+       PVOID SystemArgument1;
+       PVOID SystemArgument2;
    
-    ASSERT_IRQL_EQUAL(APC_LEVEL);
-
-    /* Lock the APC Queue and Raise IRQL to Synch */
-    KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
-
-    /* Clear APC Pending */
-    Thread->ApcState.KernelApcPending = FALSE;
-    
-    /* Do the Kernel APCs first */
-    while (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) {
-    
-        /* Get the next Entry */
-        ApcListEntry = Thread->ApcState.ApcListHead[KernelMode].Flink;
-        Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
-        
-        /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
-        NormalRoutine   = Apc->NormalRoutine;
-        KernelRoutine   = Apc->KernelRoutine;
-        NormalContext   = Apc->NormalContext;
-        SystemArgument1 = Apc->SystemArgument1;
-        SystemArgument2 = Apc->SystemArgument2;
+   ASSERT_IRQL_EQUAL(APC_LEVEL);
+
+       /* Lock the APC Queue and Raise IRQL to Synch */
+       KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+
+       /* Clear APC Pending */
+       Thread->ApcState.KernelApcPending = FALSE;
+       
+       /* Do the Kernel APCs first */
+       while (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) {
+       
+               /* Get the next Entry */
+               ApcListEntry = Thread->ApcState.ApcListHead[KernelMode].Flink;
+               Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
+               
+               /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
+               NormalRoutine   = Apc->NormalRoutine;
+               KernelRoutine   = Apc->KernelRoutine;
+               NormalContext   = Apc->NormalContext;
+               SystemArgument1 = Apc->SystemArgument1;
+               SystemArgument2 = Apc->SystemArgument2;
        
-        /* Special APC */
-       if (NormalRoutine == NULL) {
-           
-            /* Remove the APC from the list */
-            Apc->Inserted = FALSE;
-            RemoveEntryList(ApcListEntry);
-            
-            /* Go back to APC_LEVEL */
-            KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-            
-            /* Call the Special APC */
-            DPRINT("Delivering a Special APC: %x\n", Apc);
-            KernelRoutine(Apc,
-                      &NormalRoutine,
-                      &NormalContext,
-                      &SystemArgument1,
-                      &SystemArgument2);
-
-            /* Raise IRQL and Lock again */
-            KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+               /* Special APC */
+       if (NormalRoutine == NULL) {
+                       /* Remove the APC from the list */
+                       Apc->Inserted = FALSE;
+                       RemoveEntryList(ApcListEntry);
+                       
+                       /* Go back to APC_LEVEL */
+                       KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+                       
+                       /* Call the Special APC */
+                       DPRINT("Delivering a Special APC: %x\n", Apc);
+                       KernelRoutine(Apc,
+                                     &NormalRoutine,
+                                     &NormalContext,
+                                     &SystemArgument1,
+                                     &SystemArgument2);
+
+                       /* Raise IRQL and Lock again */
+                       KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+               } else {
+                        /* Normal Kernel APC */
+                       if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
             
-        } else {
-            
-             /* Normal Kernel APC */
-            if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
-            
-                /*
-                 * DeliveryMode must be KernelMode in this case, since one may not
-                 * return to umode while being inside a critical section or while 
-                 * a regular kmode apc is running (the latter should be impossible btw).
-                 * -Gunnar
-                 */
-                ASSERT(DeliveryMode == KernelMode);
-
-                KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-                return;
-            }
-            
-            /* Dequeue the APC */
-            RemoveEntryList(ApcListEntry);
-            Apc->Inserted = FALSE;
-            
-            /* Go back to APC_LEVEL */
-            KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-            
-            /* Call the Kernel APC */
-            DPRINT("Delivering a Normal APC: %x\n", Apc);
-            KernelRoutine(Apc,
-                      &NormalRoutine,
-                      &NormalContext,
-                      &SystemArgument1,
-                      &SystemArgument2);
-            
-            /* If There still is a Normal Routine, then we need to call this at PASSIVE_LEVEL */
-            if (NormalRoutine != NULL) {
-                
-                /* At Passive Level, this APC can be prempted by a Special APC */
-                Thread->ApcState.KernelApcInProgress = TRUE;
-                KeLowerIrql(PASSIVE_LEVEL);
-                
-                /* Call and Raise IRQ back to APC_LEVEL */
-                DPRINT("Calling the Normal Routine for a Normal APC: %x\n", Apc);
-                NormalRoutine(&NormalContext, &SystemArgument1, &SystemArgument2);
-                KeRaiseIrql(APC_LEVEL, &OldIrql);
-            }
-
-            /* Raise IRQL and Lock again */
-            KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
-            Thread->ApcState.KernelApcInProgress = FALSE;
-        }
-    }
-    
-    /* Now we do the User APCs */
-    if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
-        (DeliveryMode == UserMode) && (Thread->ApcState.UserApcPending == TRUE)) {
-             
-        /* It's not pending anymore */
-        Thread->ApcState.UserApcPending = FALSE;
-
-        /* Get the APC Object */
-        ApcListEntry = Thread->ApcState.ApcListHead[UserMode].Flink;
-        Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
-        
-        /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
-        NormalRoutine   = Apc->NormalRoutine;
-        KernelRoutine   = Apc->KernelRoutine;
-        NormalContext   = Apc->NormalContext;
-        SystemArgument1 = Apc->SystemArgument1;
-        SystemArgument2 = Apc->SystemArgument2; 
-        
-        /* Remove the APC from Queue, restore IRQL and call the APC */
-        RemoveEntryList(ApcListEntry);
-        Apc->Inserted = FALSE;
+            /*
+             * DeliveryMode must be KernelMode in this case, since one may not
+             * return to umode while being inside a critical section or while 
+             * a regular kmode apc is running (the latter should be impossible btw).
+             * -Gunnar
+             */
+            ASSERT(DeliveryMode == KernelMode);
+
+                               KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+                               return;
+                       }
+                       
+                       /* Dequeue the APC */
+                       RemoveEntryList(ApcListEntry);
+                       Apc->Inserted = FALSE;
+                       
+                       /* Go back to APC_LEVEL */
+                       KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+                       
+                       /* Call the Kernel APC */
+                       DPRINT("Delivering a Normal APC: %x\n", Apc);
+                       KernelRoutine(Apc,
+                                     &NormalRoutine,
+                                     &NormalContext,
+                                     &SystemArgument1,
+                                     &SystemArgument2);
+                       
+                       /* If There still is a Normal Routine, then we need to call this at PASSIVE_LEVEL */
+                       if (NormalRoutine != NULL) {
+                               /* At Passive Level, this APC can be prempted by a Special APC */
+                               Thread->ApcState.KernelApcInProgress = TRUE;
+                               KeLowerIrql(PASSIVE_LEVEL);
+                               
+                               /* Call and Raise IRQ back to APC_LEVEL */
+                               DPRINT("Calling the Normal Routine for a Normal APC: %x\n", Apc);
+                               NormalRoutine(&NormalContext, &SystemArgument1, &SystemArgument2);
+                               KeRaiseIrql(APC_LEVEL, &OldIrql);
+                       }
+
+                       /* Raise IRQL and Lock again */
+                       KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+                       Thread->ApcState.KernelApcInProgress = FALSE;
+               }
+       }
+       
+       /* Now we do the User APCs */
+       if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
+          (DeliveryMode == UserMode) &&
+                        (Thread->ApcState.UserApcPending == TRUE)) {
+                        
+               /* It's not pending anymore */
+               Thread->ApcState.UserApcPending = FALSE;
+
+               /* Get the APC Object */
+               ApcListEntry = Thread->ApcState.ApcListHead[UserMode].Flink;
+               Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
+               
+               /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
+               NormalRoutine   = Apc->NormalRoutine;
+               KernelRoutine   = Apc->KernelRoutine;
+               NormalContext   = Apc->NormalContext;
+               SystemArgument1 = Apc->SystemArgument1;
+               SystemArgument2 = Apc->SystemArgument2; 
+               
+               /* Remove the APC from Queue, restore IRQL and call the APC */
+               RemoveEntryList(ApcListEntry);
+      Apc->Inserted = FALSE;
       
-        KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-        DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
-        KernelRoutine(Apc,
-                  &NormalRoutine,
-                  &NormalContext,
-                  &SystemArgument1,
-                  &SystemArgument2);
-
-        if (NormalRoutine == NULL) {
-            
-            /* Check if more User APCs are Pending */
-            KeTestAlertThread(UserMode);
-            
-        } else {
-            
-            /* Set up the Trap Frame and prepare for Execution in NTDLL.DLL */
-            DPRINT("Delivering a User APC: %x\n", Apc);
-            KiInitializeUserApc(Reserved, 
-                        TrapFrame,
-                        NormalRoutine,
-                        NormalContext,
-                        SystemArgument1,
-                        SystemArgument2);
-        }
-        
-    } else {
-        
-        /* Go back to APC_LEVEL */
-        KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-    }
+               KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+               DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
+               KernelRoutine(Apc,
+                             &NormalRoutine,
+                             &NormalContext,
+                             &SystemArgument1,
+                             &SystemArgument2);
+
+               if (NormalRoutine == NULL) {
+                       /* Check if more User APCs are Pending */
+                       KeTestAlertThread(UserMode);
+               } else {
+                       /* Set up the Trap Frame and prepare for Execution in NTDLL.DLL */
+                       DPRINT("Delivering a User APC: %x\n", Apc);
+                       KiInitializeUserApc(Reserved, 
+                                           TrapFrame,
+                                           NormalRoutine,
+                                           NormalContext,
+                                           SystemArgument1,
+                                           SystemArgument2);
+               }
+       } else {
+               /* Go back to APC_LEVEL */
+               KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+       }
 }
 
 VOID 
 STDCALL
 KiFreeApcRoutine(PKAPC Apc,
-                 PKNORMAL_ROUTINE* NormalRoutine,
-                 PVOID* NormalContext,
-                 PVOID* SystemArgument1,
-                 PVOID* SystemArgument2)
+                PKNORMAL_ROUTINE* NormalRoutine,
+                PVOID* NormalContext,
+                PVOID* SystemArgument1,
+                PVOID* SystemArgument2)
 {
-    /* Free the APC and do nothing else */
-    ExFreePool(Apc);
+       /* Free the APC and do nothing else */
+       ExFreePool(Apc);
 }
 
-/*++
- * KiInitializeUserApc 
- *    
- *     Prepares the Context for a User-Mode APC called through NTDLL.DLL
- *
- * Params:
- *     Reserved - Pointer to the Exception Frame on non-i386 builds.
- *
- *     TrapFrame - Pointer to the Trap Frame.
- *
- *     NormalRoutine - Pointer to the NormalRoutine to call.
- *
- *     NormalContext - Pointer to the context to send to the Normal Routine.
- *
- *     SystemArgument[1-2] - Pointer to a set of two parameters that contain
- *                           untyped data.
- *
- * Returns:
- *     None.
- *
- * Remarks:
- *     None.
- *
- *--*/
-VOID
-STDCALL
+VOID 
 KiInitializeUserApc(IN PVOID Reserved,
-                    IN PKTRAP_FRAME TrapFrame,
-                    IN PKNORMAL_ROUTINE NormalRoutine,
-                    IN PVOID NormalContext,
-                    IN PVOID SystemArgument1,
-                    IN PVOID SystemArgument2)  
+                   IN PKTRAP_FRAME TrapFrame,
+                   IN PKNORMAL_ROUTINE NormalRoutine,
+                   IN PVOID NormalContext,
+                   IN PVOID SystemArgument1,
+                   IN PVOID SystemArgument2)  
+/*
+ * FUNCTION: Prepares the Context for a user mode APC through ntdll.dll
+ */
 {
-    PCONTEXT Context;
-    PULONG Esp;
+       PCONTEXT Context;
+       PULONG Esp;
 
-    DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame, KeGetCurrentThread()->TrapFrame);
+       DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame, KeGetCurrentThread()->TrapFrame);
    
-    /*
-     * Save the thread's current context (in other words the registers
-     * that will be restored when it returns to user mode) so the
-     * APC dispatcher can restore them later
-     */
-    Context = (PCONTEXT)(((PUCHAR)TrapFrame->Esp) - sizeof(CONTEXT));
-    RtlZeroMemory(Context, sizeof(CONTEXT));
-    Context->ContextFlags = CONTEXT_FULL;
-    Context->SegGs = TrapFrame->Gs;
-    Context->SegFs = TrapFrame->Fs;
-    Context->SegEs = TrapFrame->Es;
-    Context->SegDs = TrapFrame->Ds;
-    Context->Edi = TrapFrame->Edi;
-    Context->Esi = TrapFrame->Esi;
-    Context->Ebx = TrapFrame->Ebx;
-    Context->Edx = TrapFrame->Edx;
-    Context->Ecx = TrapFrame->Ecx;
-    Context->Eax = TrapFrame->Eax;
-    Context->Ebp = TrapFrame->Ebp;
-    Context->Eip = TrapFrame->Eip;
-    Context->SegCs = TrapFrame->Cs;
-    Context->EFlags = TrapFrame->Eflags;
-    Context->Esp = TrapFrame->Esp;
-    Context->SegSs = TrapFrame->Ss;
+       /*
+        * Save the thread's current context (in other words the registers
+        * that will be restored when it returns to user mode) so the
+        * APC dispatcher can restore them later
+        */
+       Context = (PCONTEXT)(((PUCHAR)TrapFrame->Esp) - sizeof(CONTEXT));
+       RtlZeroMemory(Context, sizeof(CONTEXT));
+       Context->ContextFlags = CONTEXT_FULL;
+       Context->SegGs = TrapFrame->Gs;
+       Context->SegFs = TrapFrame->Fs;
+       Context->SegEs = TrapFrame->Es;
+       Context->SegDs = TrapFrame->Ds;
+       Context->Edi = TrapFrame->Edi;
+       Context->Esi = TrapFrame->Esi;
+       Context->Ebx = TrapFrame->Ebx;
+       Context->Edx = TrapFrame->Edx;
+       Context->Ecx = TrapFrame->Ecx;
+       Context->Eax = TrapFrame->Eax;
+       Context->Ebp = TrapFrame->Ebp;
+       Context->Eip = TrapFrame->Eip;
+       Context->SegCs = TrapFrame->Cs;
+       Context->EFlags = TrapFrame->Eflags;
+       Context->Esp = TrapFrame->Esp;
+       Context->SegSs = TrapFrame->Ss;
        
-    /*
-     * Setup the trap frame so the thread will start executing at the
-     * APC Dispatcher when it returns to user-mode
-     */
-    Esp = (PULONG)(((PUCHAR)TrapFrame->Esp) - (sizeof(CONTEXT) + (6 * sizeof(ULONG))));
-    Esp[0] = 0xdeadbeef;
-    Esp[1] = (ULONG)NormalRoutine;
-    Esp[2] = (ULONG)NormalContext;
-    Esp[3] = (ULONG)SystemArgument1;
-    Esp[4] = (ULONG)SystemArgument2;
-    Esp[5] = (ULONG)Context;
-    TrapFrame->Eip = (ULONG)LdrpGetSystemDllApcDispatcher();
-    TrapFrame->Esp = (ULONG)Esp;
+       /*
+        * Setup the trap frame so the thread will start executing at the
+        * APC Dispatcher when it returns to user-mode
+        */
+       Esp = (PULONG)(((PUCHAR)TrapFrame->Esp) - (sizeof(CONTEXT) + (6 * sizeof(ULONG))));
+       Esp[0] = 0xdeadbeef;
+       Esp[1] = (ULONG)NormalRoutine;
+       Esp[2] = (ULONG)NormalContext;
+       Esp[3] = (ULONG)SystemArgument1;
+       Esp[4] = (ULONG)SystemArgument2;
+       Esp[5] = (ULONG)Context;
+       TrapFrame->Eip = (ULONG)LdrpGetSystemDllApcDispatcher();
+       TrapFrame->Esp = (ULONG)Esp;
 }
 
-/*++
- * KeAreApcsDisabled 
- * @implemented NT4
- *    
- *     Prepares the Context for a User-Mode APC called through NTDLL.DLL
- *
- * Params:
- *     None.
- *
- * Returns:
- *     KeAreApcsDisabled returns TRUE if the thread is within a critical region
- *     or a guarded region, and FALSE otherwise.
- *
- * Remarks:
- *     A thread running at IRQL = PASSIVE_LEVEL can use KeAreApcsDisabled to 
- *     determine if normal kernel APCs are disabled. A thread that is inside a 
- *     critical region has both user APCs and normal kernel APCs disabled, but 
- *     not special kernel APCs. A thread that is inside a guarded region has 
- *     all APCs disabled, including special kernel APCs.
- *
- *     Callers of this routine must be running at IRQL <= APC_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
 BOOLEAN
 STDCALL
-KeAreApcsDisabled(VOID)
+KeAreApcsDisabled(
+       VOID
+       )
 {
-    /* Return the Kernel APC State */
-    return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
+       return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
 }
 
-/*++
- * NtQueueApcThread 
- * NT4
- *    
- *    This routine is used to queue an APC from user-mode for the specified 
- *    thread.
- *
- * Params:
- *     Thread Handle - Handle to the Thread. This handle must have THREAD_SET_CONTEXT privileges.
- *
- *     ApcRoutine - Pointer to the APC Routine to call when the APC executes.
- *
- *     NormalContext - Pointer to the context to send to the Normal Routine.
- *
- *     SystemArgument[1-2] - Pointer to a set of two parameters that contain
- *                           untyped data.
- *
- * Returns:
- *     STATUS_SUCCESS or failure cute from associated calls.
- *
- * Remarks:
- *      The thread must enter an alertable wait before the APC will be 
- *      delivered.
- *
- *--*/
 NTSTATUS 
 STDCALL
-NtQueueApcThread(HANDLE ThreadHandle,
-         PKNORMAL_ROUTINE ApcRoutine,
-         PVOID NormalContext,
-         PVOID SystemArgument1,
-         PVOID SystemArgument2)
+NtQueueApcThread(HANDLE                        ThreadHandle,
+                PKNORMAL_ROUTINE       ApcRoutine,
+                PVOID                  NormalContext,
+                PVOID                  SystemArgument1,
+                PVOID                  SystemArgument2)
+/*
+ * FUNCTION: 
+ *           This function is used to queue an APC from user-mode for the specified thread.
+ *           The thread must enter an alertable wait before the APC will be delivered.
+ *
+ * ARGUMENTS:
+ *           Thread Handle - Handle to the Thread. This handle must have THREAD_SET_CONTEXT privileges.
+ *           ApcRoutine - Pointer to the APC Routine to call when the APC executes.
+ *           NormalContext - User-defined value to pass to the APC Routine
+ *           SystemArgument1 - User-defined value to pass to the APC Routine
+ *           SystemArgument2 - User-defined value to pass to the APC Routine
+ *
+ * RETURNS:  NTSTATUS SUCCESS or Failure Code from included calls.
+ */
 {
-    PKAPC Apc;
-    PETHREAD Thread;
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status;
-
-    /* Get ETHREAD from Handle */
-    Status = ObReferenceObjectByHandle(ThreadHandle,
-                       THREAD_SET_CONTEXT,
-                       PsThreadType,
-                       PreviousMode,
-                       (PVOID)&Thread,
-                       NULL);
-    
-    /* Fail if the Handle is invalid for some reason */
-    if (!NT_SUCCESS(Status)) {
-        
-        return(Status);
-    }
-    
-    /* If this is a Kernel or System Thread, then fail */
-    if (Thread->Tcb.Teb == NULL) {
-        
-        ObDereferenceObject(Thread);
-        return STATUS_INVALID_HANDLE;
-    }
+
+       PKAPC Apc;
+       PETHREAD Thread;
+       KPROCESSOR_MODE PreviousMode;
+       NTSTATUS Status;
+       
+       PreviousMode = ExGetPreviousMode();
+
+       /* Get ETHREAD from Handle */
+       Status = ObReferenceObjectByHandle(ThreadHandle,
+                                          THREAD_SET_CONTEXT,
+                                          PsThreadType,
+                                          PreviousMode,
+                                          (PVOID)&Thread,
+                                          NULL);
+       
+       /* Fail if the Handle is invalid for some reason */
+       if (!NT_SUCCESS(Status)) {
+               return(Status);
+       }
+       
+       /* If this is a Kernel or System Thread, then fail */
+       if (Thread->Tcb.Teb == NULL) {
+               ObDereferenceObject(Thread);
+               return STATUS_INVALID_HANDLE;
+       }
    
-    /* Allocate an APC */
-    Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG('P', 's', 'a', 'p'));
-    if (Apc == NULL) {
-        
-        ObDereferenceObject(Thread);
-        return(STATUS_NO_MEMORY);
-    }
+       /* Allocate an APC */
+       Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
+       if (Apc == NULL) {
+               ObDereferenceObject(Thread);
+               return(STATUS_NO_MEMORY);
+       }
    
-    /* Initialize and Queue a user mode apc (always!) */
-    KeInitializeApc(Apc,
-                    &Thread->Tcb,
-                    OriginalApcEnvironment,
-                    KiFreeApcRoutine,
-                    NULL,
-                    ApcRoutine,
-                    UserMode,
-                    NormalContext);
-    
-    if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) {
-        
-        Status = STATUS_UNSUCCESSFUL;
-        
-    } else {
-        
-        Status = STATUS_SUCCESS;
-    }
+       /* Initialize and Queue a user mode apc (always!) */
+       KeInitializeApc(Apc,
+                       &Thread->Tcb,
+                       OriginalApcEnvironment,
+                       KiFreeApcRoutine,
+                       NULL,
+                       ApcRoutine,
+                       UserMode,
+                       NormalContext);
+       if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) {
+               Status = STATUS_UNSUCCESSFUL;
+       } else {
+               Status = STATUS_SUCCESS;
+       }
    
-    /* Dereference Thread and Return */
-    ObDereferenceObject(Thread);
-    return Status;
+       /* Dereference Thread and Return */
+       ObDereferenceObject(Thread);
+       return Status;
 }
 
-static inline 
-VOID RepairList(PLIST_ENTRY Original, 
-                PLIST_ENTRY Copy,
-                KPROCESSOR_MODE Mode)
+
+static inline VOID RepairList(PLIST_ENTRY Original, 
+                             PLIST_ENTRY Copy,
+                             KPROCESSOR_MODE Mode)
 {
-    /* Copy Source to Desination */
-    if (IsListEmpty(&Original[(int)Mode])) {
-        
-        InitializeListHead(&Copy[(int)Mode]);
-        
-    } else {
-        
-        Copy[(int)Mode].Flink = Original[(int)Mode].Flink; 
-        Copy[(int)Mode].Blink = Original[(int)Mode].Blink;
-        Original[(int)Mode].Flink->Blink = &Copy[(int)Mode];
-        Original[(int)Mode].Blink->Flink = &Copy[(int)Mode];
-    }
+       /* Copy Source to Desination */
+       if (IsListEmpty(&Original[(int)Mode])) {
+               InitializeListHead(&Copy[(int)Mode]);
+       } else {
+               Copy[(int)Mode].Flink = Original[(int)Mode].Flink; 
+               Copy[(int)Mode].Blink = Original[(int)Mode].Blink;
+               Original[(int)Mode].Flink->Blink = &Copy[(int)Mode];
+               Original[(int)Mode].Blink->Flink = &Copy[(int)Mode];
+       }
 }
 
 VOID
 STDCALL
-KiMoveApcState(PKAPC_STATE OldState,
-               PKAPC_STATE NewState)
+KiMoveApcState (PKAPC_STATE OldState,
+               PKAPC_STATE NewState)
 {
-    /* Restore backup of Original Environment */
-    *NewState = *OldState;
+       /* Restore backup of Original Environment */
+       *NewState = *OldState;
     
-    /* Repair Lists */
-    RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
-    RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
+       /* Repair Lists */
+       RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
+       RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
 }
 
index fd2f58c..2af3e26 100644 (file)
@@ -47,17 +47,6 @@ KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
        return FALSE;
 }
 
-/*
- * @unimplemented
- */
-BOOLEAN
-STDCALL
-KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
-{
-    UNIMPLEMENTED;
-    return FALSE;
-}
-
 /*
  * @implemented
  */
@@ -85,20 +74,6 @@ KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
        return(FALSE);
 }
 
-/*
- * @unimplemented
- */
-BOOLEAN
-STDCALL
-KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
-                                 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
-                                 IN KBUGCHECK_CALLBACK_REASON Reason,
-                                 IN PUCHAR Component)
-{
-    UNIMPLEMENTED;
-    return FALSE;
-}
-
 VOID STDCALL
 KeBugCheckWithTf(ULONG BugCheckCode,        
                 ULONG BugCheckParameter1,
index 1657b5f..1d4ca92 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/catch.c
@@ -20,206 +21,282 @@ ULONG
 RtlpDispatchException(IN PEXCEPTION_RECORD  ExceptionRecord,
        IN PCONTEXT  Context);
 
-/*
- * @unimplemented
- */
 VOID
-STDCALL
-KiCoprocessorError(VOID)
+KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
+                   PCONTEXT Context,
+                   PKTRAP_FRAME Tf,
+                   KPROCESSOR_MODE PreviousMode,
+                   BOOLEAN SearchFrames)
 {
-    UNIMPLEMENTED;
-}
+  EXCEPTION_DISPOSITION Value;
+  CONTEXT TContext;
+  KD_CONTINUE_TYPE Action = kdHandleException;
 
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-KiUnexpectedInterrupt(VOID)
-{
-    UNIMPLEMENTED;
-}
+  DPRINT("KiDispatchException() called\n");
 
-VOID
-KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
-                    PCONTEXT Context,
-                    PKTRAP_FRAME Tf,
-                    KPROCESSOR_MODE PreviousMode,
-                    BOOLEAN SearchFrames)
-{
-    EXCEPTION_DISPOSITION Value;
-    CONTEXT TContext;
-    KD_CONTINUE_TYPE Action = kdHandleException;
-
-    DPRINT("KiDispatchException() called\n");
-
-    /* Increase number of Exception Dispatches */
-    KeGetCurrentKPCR()->PrcbData.KeExceptionDispatchCount++;
-
-    if (!Context) {
-        
-        /* Assume Full context */
-        TContext.ContextFlags = CONTEXT_FULL;
-        
-        /* Check the mode */
-        if (PreviousMode == UserMode) {
-            
-            /* Add Debugger Registers if this is User Mode */
-            TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
-        }
+
+  /* PCR->KeExceptionDispatchCount++; */
+
+  if (Context == NULL)
+    {
+      TContext.ContextFlags = CONTEXT_FULL;
+      if (PreviousMode == UserMode)
+       {
+         TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
+       }
   
-        /* Convert the Trapframe into a Context */
-        KeTrapFrameToContext(Tf, &TContext);
+      KeTrapFrameToContext(Tf, &TContext);
 
-        /* Use local stack context */
-        Context = &TContext;
+      Context = &TContext;
     }
 
-#if 0 /* FIXME: Isn't this right? With a break after? */
-    if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
-        Context->Eip--;
+#if 0
+  if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) 
+    {
+      Context->Eip--;
     }
 #endif
+      
+  if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
+    {
+      Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
+    }
 
-    /* Check if a Debugger is enabled */
-    if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) {
-    
-        /* Break into it */
-        Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
+  if (Action == kdContinue)
+    {
+      return;
     }
-    
-    /* If the debugger said continue, then continue */
-    if (Action == kdContinue) return;
-    
-    /* If the Debugger couldn't handle it... */
-    if (Action != kdDoNotHandleException) {
-        
-        /* See what kind of Exception this is */
-        if (PreviousMode == UserMode) {
-            
-            /* User mode exception, search the frames if we have to */
-            if (SearchFrames) {
-
-                PULONG Stack;
-                ULONG CDest;
-                char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
-                PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
-                NTSTATUS StatusOfCopy;
+
+  if (Action != kdDoNotHandleException)
+    {
+      if (PreviousMode == UserMode)
+       {
+         if (SearchFrames)
+           {
+             PULONG Stack;
+             ULONG CDest;
+             char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
+             PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
+             NTSTATUS StatusOfCopy;
 
 #ifdef KDBG
-                /* Enter KDB if available */
-                Action = KdbEnterDebuggerException(ExceptionRecord, 
-                                                   PreviousMode,
-                                                   Context, 
-                                                   Tf, 
-                                                   FALSE);
-
-                /* Exit if we're continuing */
-                if (Action == kdContinue) return;
+             Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+                                                 Context, Tf, FALSE);
+              if (Action == kdContinue)
+                {
+                  return;
+                }
 #endif
 
-            /* FIXME: Forward exception to user mode debugger */
-
-            /* FIXME: Check user mode stack for enough space */
-    
-            /* Let usermode try and handle the exception. Setup Stack */
-            Stack = (PULONG)temp_space;
-            CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
-            /* Return Address */
-            Stack[0] = 0;
-            /* Pointer to EXCEPTION_RECORD structure */
-            Stack[1] = (ULONG)&pNewUserStack[3];
-            /* Pointer to CONTEXT structure */
-            Stack[2] = (ULONG)&pNewUserStack[CDest];
-            memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
-            memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
-            
-            /* Copy Stack */
-            StatusOfCopy = MmCopyToCaller(pNewUserStack,
-                                          temp_space,
-                                          (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
-            
-            /* Check for success */
-            if (NT_SUCCESS(StatusOfCopy)) {
-                
-                /* Set new Stack Pointer */
-                Tf->Esp = (ULONG)pNewUserStack;
-                
-            } else {
-                
-                /*
-                 * Now it really hit the ventilation device. Sorry,
-                 * can do nothing but kill the sucker.
-                 */
-                ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
-                DPRINT1("User-mode stack was invalid. Terminating target thread\n");
-            }
-            
-            /* Set EIP to the User-mode Dispathcer */
-            Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
-            return;
-        }
+             /* FIXME: Forward exception to user mode debugger */
+
+             /* FIXME: Check user mode stack for enough space */
+         
+             /*
+              * Let usermode try and handle the exception
+              */
+             Stack = (PULONG)temp_space;
+             CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
+             /* Return address */
+             Stack[0] = 0;    
+             /* Pointer to EXCEPTION_RECORD structure */
+             Stack[1] = (ULONG)&pNewUserStack[3];
+             /* Pointer to CONTEXT structure */
+             Stack[2] = (ULONG)&pNewUserStack[CDest];
+             memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
+             memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
 
-        /* FIXME: Forward the exception to the debugger */
+             StatusOfCopy = MmCopyToCaller(pNewUserStack,
+                                           temp_space,
+                                           (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
+             if (NT_SUCCESS(StatusOfCopy))
+               {
+                 Tf->Esp = (ULONG)pNewUserStack;
+               }
+             else
+               {
+                 /* Now it really hit the ventilation device. Sorry,
+                  * can do nothing but kill the sucker.
+                  */
+                 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
+                 DPRINT1("User-mode stack was invalid. Terminating target thread\n");
+               }
+             Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
+             return;
+           }
 
-        /* FIXME: Forward the exception to the process exception port */
+         /* FIXME: Forward the exception to the debugger */
+
+         /* FIXME: Forward the exception to the process exception port */
 
-                  
 #ifdef KDBG
-        /* Enter KDB if available */
-        Action = KdbEnterDebuggerException(ExceptionRecord, 
-                                            PreviousMode,
-                                            Context, 
-                                            Tf, 
-                                            TRUE);
-
-        /* Exit if we're continuing */
-        if (Action == kdContinue) return;
+         Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+                                             Context, Tf, TRUE);
+          if (Action == kdContinue)
+            {
+              return;
+            }
 #endif
 
-        /* Terminate the offending thread */
-        DPRINT1("Unhandled UserMode exception, terminating thread\n");
-        ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
-        
-        } else {
-
-            /* This is Kernel Mode */            
+         /* Terminate the offending thread */
+         DPRINT1("Unhandled UserMode exception, terminating thread\n");
+         ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
+       }
+      else
+       {
+         /* PreviousMode == KernelMode */
 #ifdef KDBG
-            /* Enter KDB if available */
-            Action = KdbEnterDebuggerException(ExceptionRecord, 
-                                                PreviousMode,
-                                                Context, 
-                                                Tf, 
-                                                FALSE);
-
-            /* Exit if we're continuing */
-            if (Action == kdContinue) return;
+         Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+                                             Context, Tf, FALSE);
+          if (Action == kdContinue)
+            {
+              return;
+            }
 #endif
 
-            /* Dispatch the Exception */
-            Value = RtlpDispatchException (ExceptionRecord, Context);
-            DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
-        
-            /* If RtlpDispatchException() did not handle the exception then bugcheck */
-            if (Value != ExceptionContinueExecution ||
-                0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)) {
-            
-                DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n", ExceptionRecord->ExceptionAddress);
+         Value = RtlpDispatchException (ExceptionRecord, Context);
+         
+         DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
+         /* 
+          * If RtlpDispatchException() does not handle the exception then 
+          * bugcheck 
+          */
+         if (Value != ExceptionContinueExecution ||
+             0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
+           {
+             DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
+                    ExceptionRecord->ExceptionAddress );
 #ifdef KDBG
-                /* Enter KDB if available */
-                Action = KdbEnterDebuggerException(ExceptionRecord, 
-                                                   PreviousMode,
-                                                   Context, 
-                                                   Tf, 
-                                                   TRUE);
-
-                /* Exit if we're continuing */
-                if (Action == kdContinue) return;
+              Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+                                                  Context, Tf, TRUE);
+              if (Action == kdContinue)
+                {
+                  return;
+                }
 #endif
-                KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
-            }
-        }
+             KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
+           }
+       }
     }
 }
 
+/*
+ * @implemented
+ */
+VOID STDCALL
+ExRaiseAccessViolation (VOID)
+{
+  ExRaiseStatus (STATUS_ACCESS_VIOLATION);
+}
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+ExRaiseDatatypeMisalignment (VOID)
+{
+  ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
+}
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+ExRaiseStatus (IN NTSTATUS Status)
+{
+  EXCEPTION_RECORD ExceptionRecord;
+
+  DPRINT("ExRaiseStatus(%x)\n", Status);
+
+  ExceptionRecord.ExceptionRecord = NULL;
+  ExceptionRecord.NumberParameters = 0;
+  ExceptionRecord.ExceptionCode = Status;
+  ExceptionRecord.ExceptionFlags = 0;
+
+  RtlRaiseException(&ExceptionRecord);
+}
+
+
+
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+ExRaiseException (
+       PEXCEPTION_RECORD ExceptionRecord
+       )
+{
+    RtlRaiseException(ExceptionRecord);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+STDCALL
+ExSystemExceptionFilter(VOID)
+{
+  return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+ExRaiseHardError (
+       IN NTSTATUS ErrorStatus,
+       IN ULONG NumberOfParameters, 
+       IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
+       IN PVOID *Parameters, 
+       IN HARDERROR_RESPONSE_OPTION ResponseOption, 
+       OUT PHARDERROR_RESPONSE Response 
+       )
+{
+       UNIMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+BOOLEAN
+STDCALL
+KeDeregisterBugCheckReasonCallback(
+    IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
+    )
+{
+       UNIMPLEMENTED;
+       return FALSE;
+}
+
+/*
+ * @unimplemented
+ */
+ULONG
+STDCALL
+KeGetRecommendedSharedDataAlignment(
+       VOID
+       )
+{
+       UNIMPLEMENTED;
+       return 0;
+}
+
+/*
+ * @unimplemented
+ */
+BOOLEAN
+STDCALL
+KeRegisterBugCheckReasonCallback(
+    IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
+    IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
+    IN KBUGCHECK_CALLBACK_REASON Reason,
+    IN PUCHAR Component
+    )
+{
+       UNIMPLEMENTED;
+       return FALSE;
+}
+
 /* EOF */
diff --git a/reactos/ntoskrnl/ke/critical.c b/reactos/ntoskrnl/ke/critical.c
new file mode 100644 (file)
index 0000000..e242854
--- /dev/null
@@ -0,0 +1,56 @@
+/* $Id$
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ke/critical.c
+ * PURPOSE:         Implement critical regions
+ * 
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+VOID STDCALL KeEnterCriticalRegion (VOID)
+{
+   PKTHREAD Thread = KeGetCurrentThread(); 
+   
+   DPRINT("KeEnterCriticalRegion()\n");
+   
+   if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
+
+   Thread->KernelApcDisable--;
+}
+
+/*
+ * @implemented
+ */
+VOID STDCALL KeLeaveCriticalRegion (VOID)
+{
+  PKTHREAD Thread = KeGetCurrentThread(); 
+
+  DPRINT("KeLeaveCriticalRegion()\n");
+  
+  if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
+
+  /* Reference: http://www.ntfsd.org/archive/ntfsd0104/msg0203.html */
+  if(++Thread->KernelApcDisable == 0) 
+  { 
+    if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) 
+    { 
+      Thread->ApcState.KernelApcPending = TRUE; 
+      HalRequestSoftwareInterrupt(APC_LEVEL); 
+    } 
+  } 
+
+}
+
+/* EOF */
index 0d68ce6..2aee866 100644 (file)
 /* TYPES *******************************************************************/
 
 #define MAX_QUANTUM 0x7F
+/* GLOBALS ******************************************************************/
 
 /* FUNCTIONS ****************************************************************/
 
+VOID INIT_FUNCTION
+KeInitDpc(PKPCR Pcr)
 /*
  * FUNCTION: Initialize DPC handling
  */
-VOID
-INIT_FUNCTION
-KeInitDpc(PKPCR Pcr)
 {
    InitializeListHead(&Pcr->PrcbData.DpcData[0].DpcListHead);
    KeInitializeEvent(Pcr->PrcbData.DpcEvent, 0, 0);
@@ -47,9 +47,9 @@ KeInitDpc(PKPCR Pcr)
  */
 VOID
 STDCALL
-KeInitializeThreadedDpc(PKDPC Dpc,
-                        PKDEFERRED_ROUTINE DeferredRoutine,
-                        PVOID DeferredContext)
+KeInitializeThreadedDpc(PKDPC                  Dpc,
+                       PKDEFERRED_ROUTINE      DeferredRoutine,
+                       PVOID                   DeferredContext)
 /*
  * FUNCTION: 
  *          Initalizes a Threaded DPC and registers the DeferredRoutine for it.
@@ -60,18 +60,24 @@ KeInitializeThreadedDpc(PKDPC Dpc,
  * NOTE: Callers can be running at any IRQL.
  */
 {
-    DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
-    Dpc->Type = ThreadedDpcObject;
-    Dpc->Number= 0;
-    Dpc->Importance= MediumImportance;
-    Dpc->DeferredRoutine = DeferredRoutine;
-    Dpc->DeferredContext = DeferredContext;
-    Dpc->DpcData = NULL;
+       DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
+       //Dpc->Type = KThreadedDpc;
+       Dpc->Number= 0;
+       Dpc->Importance= MediumImportance;
+       Dpc->DeferredRoutine = DeferredRoutine;
+       Dpc->DeferredContext = DeferredContext;
+       Dpc->DpcData = NULL;
 }
 
 /*
  * @implemented
- *
+ */
+VOID
+STDCALL
+KeInitializeDpc (PKDPC                 Dpc,
+                PKDEFERRED_ROUTINE     DeferredRoutine,
+                PVOID                  DeferredContext)
+/*
  * FUNCTION: 
  *          Initalizes a DPC and registers the DeferredRoutine for it.
  * ARGUMENTS:
@@ -80,24 +86,24 @@ KeInitializeThreadedDpc(PKDPC Dpc,
  *          DeferredContext = Parameter to be passed to the callback routine.
  * NOTE: Callers can be running at any IRQL.
  */
-VOID
-STDCALL
-KeInitializeDpc(PKDPC Dpc,
-                PKDEFERRED_ROUTINE DeferredRoutine,
-                PVOID DeferredContext)
 {
-    DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
-    Dpc->Type = DpcObject;
-    Dpc->Number= 0;
-    Dpc->Importance= MediumImportance;
-    Dpc->DeferredRoutine = DeferredRoutine;
-    Dpc->DeferredContext = DeferredContext;
-    Dpc->DpcData = NULL;
+       DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
+       Dpc->Type = KDpc;
+       Dpc->Number= 0;
+       Dpc->Importance= MediumImportance;
+       Dpc->DeferredRoutine = DeferredRoutine;
+       Dpc->DeferredContext = DeferredContext;
+       Dpc->DpcData = NULL;
 }
 
 /*
  * @implemented
- *
+ */
+BOOLEAN STDCALL
+KeInsertQueueDpc (PKDPC        Dpc,
+                 PVOID SystemArgument1,
+                 PVOID SystemArgument2)
+/*
  * FUNCTION: 
  *          Queues a DPC for execution when the IRQL of a processor
  *          drops below DISPATCH_LEVEL
@@ -149,141 +155,124 @@ KeInitializeDpc(PKDPC Dpc,
  * is greater that the target depth or the minimum DPC rate is less than the
  * target rate.
  */
-BOOLEAN 
-STDCALL
-KeInsertQueueDpc(PKDPC Dpc,
-                 PVOID SystemArgument1,
-                 PVOID SystemArgument2)
 {
-    KIRQL OldIrql;
-    PKPCR Pcr;
-
-    DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
-        Dpc, SystemArgument1, SystemArgument2);
-
-    /* Check IRQL and Raise it to HIGH_LEVEL */
-    ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
-    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-    
-    /* Check if this is a Thread DPC, which we don't support (yet) */
-    if (Dpc->Type == ThreadedDpcObject) {
-        return FALSE;
-        KeLowerIrql(OldIrql);
-    }
+       KIRQL OldIrql;
+       PKPCR Pcr;
+
+       DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
+               Dpc, SystemArgument1, SystemArgument2);
+
+       /* Check IRQL and Raise it to HIGH_LEVEL */
+       ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
+       KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+       
+       /* Check if this is a Thread DPC, which we don't support (yet) */
+       //if (Dpc->Type == KThreadedDpc) {
+       //      return FALSE;
+       //      KeLowerIrql(OldIrql);
+       //}
 
 #ifdef CONFIG_SMP
-    /* Get the right PCR for this CPU */
-    if (Dpc->Number >= MAXIMUM_PROCESSORS) {
-    
-        ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
-        Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE);
-        
-    } else {
-        
-        ASSERT (Dpc->Number < KeNumberProcessors);
-        Pcr = KeGetCurrentKPCR();
-        Dpc->Number = KeGetCurrentProcessorNumber();
-    }
-    
-    KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+       /* Get the right PCR for this CPU */
+       if (Dpc->Number >= MAXIMUM_PROCESSORS) {
+               ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
+               Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE);
+       } else {
+               ASSERT (Dpc->Number < KeNumberProcessors);
+               Pcr = KeGetCurrentKPCR();
+               Dpc->Number = KeGetCurrentProcessorNumber();
+       }
+       KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
 #else
-    Pcr = (PKPCR)KPCR_BASE;
+       Pcr = (PKPCR)KPCR_BASE;
 #endif
 
-    /* Get the DPC Data */
-    if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
-    
-        DPRINT("DPC Already Inserted");
+       /* Get the DPC Data */
+       if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
+               DPRINT("DPC Already Inserted");
 #ifdef CONFIG_SMP
-        KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+               KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
 #endif
-        KeLowerIrql(OldIrql);
-        return(FALSE);
-    }
-    
-    /* Make sure the lists are free if the Queue is 0 */
-    if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
-        
-        ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
-    } else {
-        
-        ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));    
-    }
-
-    /* Now we can play with the DPC safely */
-    Dpc->SystemArgument1=SystemArgument1;
-    Dpc->SystemArgument2=SystemArgument2;
-    Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
-    Pcr->PrcbData.DpcData[0].DpcCount++;
-    
-    /* Insert the DPC into the list. HighImportance DPCs go at the beginning  */
-    if (Dpc->Importance == HighImportance) {
-        
-        InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
-    } else { 
-        
-        InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
-    }
-    DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
+               KeLowerIrql(OldIrql);
+               return(FALSE);
+       }
+       
+       /* Make sure the lists are free if the Queue is 0 */
+       if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
+               ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
+       } else {
+               ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));    
+       }
+
+       /* Now we can play with the DPC safely */
+       Dpc->SystemArgument1=SystemArgument1;
+       Dpc->SystemArgument2=SystemArgument2;
+       Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
+       Pcr->PrcbData.DpcData[0].DpcCount++;
+       
+       /* Insert the DPC into the list. HighImportance DPCs go at the beginning  */
+       if (Dpc->Importance == HighImportance) {
+               InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
+       } else { 
+               InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
+       }
+       DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
    
-    /* Make sure a DPC isn't executing already and respect rules outlined above. */
-    if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
-        
-#ifdef CONFIG_SMP    
-        /* Check if this is the same CPU */
-        if (Pcr != KeGetCurrentKPCR()) {
-    
-            /* Send IPI if High Importance */
-            if ((Dpc->Importance == HighImportance) ||
-                (Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
-                
-                if (Dpc->Number >= MAXIMUM_PROCESSORS) {
-                    
-                    KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
-                } else {
-                    
-                    KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
-                }
-
-            }
-        } else {
-            
-            /* Request an Interrupt only if the DPC isn't low priority */
-            if ((Dpc->Importance != LowImportance) || 
-                 (Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
-                (Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
-            
-                /* Request Interrupt */
-                HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
-                Pcr->PrcbData.DpcInterruptRequested = TRUE;
-            }
-        }
+       /* Make sure a DPC isn't executing already and respect rules outlined above. */
+       if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
+               
+#ifdef CONFIG_SMP      
+               /* Check if this is the same CPU */
+               if (Pcr != KeGetCurrentKPCR()) {
+                       /* Send IPI if High Importance */
+                       if ((Dpc->Importance == HighImportance) ||
+                           (Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
+                               if (Dpc->Number >= MAXIMUM_PROCESSORS) {
+                                   KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
+                               } else {
+                                   KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
+                               }
+
+                       }
+               } else {
+                       /* Request an Interrupt only if the DPC isn't low priority */
+                       if ((Dpc->Importance != LowImportance) || 
+                            (Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
+                               (Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
+                       
+                               /* Request Interrupt */
+                               HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+                               Pcr->PrcbData.DpcInterruptRequested = TRUE;
+                       }
+               }
 #else
-        DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
-        
-        /* Request an Interrupt only if the DPC isn't low priority */
-        if ((Dpc->Importance != LowImportance) || 
-            (Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
-            (Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
-            
-            /* Request Interrupt */
-            DPRINT("Requesting Interrupt\n");
-            HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
-            Pcr->PrcbData.DpcInterruptRequested = TRUE;
-        }
+               DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
+               /* Request an Interrupt only if the DPC isn't low priority */
+               if ((Dpc->Importance != LowImportance) || 
+                    (Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
+                       (Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
+                       
+                       /* Request Interrupt */
+                       DPRINT("Requesting Interrupt\n");
+                       HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+                       Pcr->PrcbData.DpcInterruptRequested = TRUE;
+               }
 #endif
-    }
+       }
 #ifdef CONFIG_SMP
-    KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+       KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
 #endif
-    /* Lower IRQL */    
-    KeLowerIrql(OldIrql);
-    return(TRUE);
+       /* Lower IRQL */        
+       KeLowerIrql(OldIrql);
+       return(TRUE);
 }
 
 /*
  * @implemented
- *
+ */
+BOOLEAN STDCALL
+KeRemoveQueueDpc (PKDPC        Dpc)
+/*
  * FUNCTION: 
  *          Removes DPC object from the system dpc queue
  * ARGUMENTS:
@@ -292,36 +281,33 @@ KeInsertQueueDpc(PKDPC Dpc,
  *          TRUE if the DPC was in the queue
  *          FALSE otherwise
  */
-BOOLEAN 
-STDCALL
-KeRemoveQueueDpc(PKDPC Dpc)
 {
-    BOOLEAN WasInQueue;
-    KIRQL OldIrql;
-    
-    /* Raise IRQL */
-    DPRINT("Removing DPC: %x\n", Dpc);
-    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+       BOOLEAN WasInQueue;
+       KIRQL OldIrql;
+       
+       /* Raise IRQL */
+       DPRINT("Removing DPC: %x\n", Dpc);
+       KeRaiseIrql(HIGH_LEVEL, &OldIrql);
 #ifdef CONFIG_SMP
-    KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
+       KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
 #endif
-    
-    /* First make sure the DPC lock isn't being held */
-    WasInQueue = Dpc->DpcData ? TRUE : FALSE;
-    if (Dpc->DpcData) {    
-        
-        /* Remove the DPC */
-        ((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
-        RemoveEntryList(&Dpc->DpcListEntry);
-
-    }
+       
+       /* First make sure the DPC lock isn't being held */
+       WasInQueue = Dpc->DpcData ? TRUE : FALSE;
+       if (Dpc->DpcData) {     
+               
+               /* Remove the DPC */
+               ((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
+               RemoveEntryList(&Dpc->DpcListEntry);
+
+       }
 #ifdef CONFIG_SMP
         KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
 #endif
 
-    /* Return if the DPC was in the queue or not */
-    KeLowerIrql(OldIrql);
-    return WasInQueue;
+       /* Return if the DPC was in the queue or not */
+       KeLowerIrql(OldIrql);
+       return WasInQueue;
 }
 
 /*
@@ -337,8 +323,7 @@ KeFlushQueuedDpcs(VOID)
  *          Called when deleting a Driver.
  */
 {
-    /* Request an interrupt if needed */
-    if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+       if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
 }
 
 /*
@@ -347,11 +332,10 @@ KeFlushQueuedDpcs(VOID)
 BOOLEAN 
 STDCALL
 KeIsExecutingDpc(
-    VOID
+       VOID
 )
 {
-    /* Return if the Dpc Routine is active */
-    return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
+       return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
 }
 
 /*
@@ -365,41 +349,39 @@ KeIsExecutingDpc(
  */
 VOID 
 STDCALL
-KeSetImportanceDpc (IN PKDPC Dpc,
-            IN KDPC_IMPORTANCE Importance)
+KeSetImportanceDpc (IN PKDPC           Dpc,
+                   IN  KDPC_IMPORTANCE Importance)
 {
-    /* Set the DPC Importance */
-    Dpc->Importance = Importance;
+       Dpc->Importance = Importance;
 }
 
 /*
- * @implemented
- *
  * FUNCTION: Specifies on which processor the DPC will run
  * ARGUMENTS:
  *          Dpc = Initalizes DPC
  *          Number = Processor number
  * RETURNS: None
+ *
+ * @implemented
  */
-VOID 
-STDCALL
-KeSetTargetProcessorDpc(IN PKDPC Dpc,
-                        IN CCHAR Number)
+VOID STDCALL
+KeSetTargetProcessorDpc (IN    PKDPC   Dpc,
+                        IN     CCHAR   Number)
 {
-    /* Check how many CPUs are on the system */
-    if (Number >= MAXIMUM_PROCESSORS) {
-        
-        /* No CPU Number */
-        Dpc->Number = 0;
-        
-    } else {
-       
-        /* Set the Number Specified */
-        ASSERT(Number < KeNumberProcessors);
-        Dpc->Number = Number + MAXIMUM_PROCESSORS;
-    }
+   if (Number >= MAXIMUM_PROCESSORS)
+   {
+      Dpc->Number = 0;
+   }
+   else
+   {
+      ASSERT(Number < KeNumberProcessors);
+      Dpc->Number = Number + MAXIMUM_PROCESSORS;
+   }
 }
 
+VOID
+STDCALL
+KiQuantumEnd(VOID)
 /*
  * FUNCTION: 
  *          Called when a quantum end occurs to check if priority should be changed
@@ -407,173 +389,152 @@ KeSetTargetProcessorDpc(IN PKDPC Dpc,
  * NOTES:
  *          Called when deleting a Driver.
  */
-VOID
-STDCALL
-KiQuantumEnd(VOID)
 {
-    PKPRCB Prcb;
-    PKTHREAD CurrentThread;
-    KIRQL OldIrql;
-    PKPROCESS Process;
-    KPRIORITY OldPriority;
-    KPRIORITY NewPriority;
-    
-    /* Lock dispatcher, get current thread */
-    Prcb = &KeGetCurrentKPCR()->PrcbData;
-    CurrentThread = KeGetCurrentThread();
-    OldIrql = KeRaiseIrqlToSynchLevel();
-    
-    /* Get the Thread's Process */
-    Process = CurrentThread->ApcState.Process;
-    
-    /* Set DPC Event if requested */
-    if (Prcb->DpcSetEventRequest) {
-        KeSetEvent(Prcb->DpcEvent, 0, 0);
-    }
-    
-    /* Check if Quantum expired */
-    if (CurrentThread->Quantum <= 0) {
-        /* Set the new Quantum */
-        CurrentThread->Quantum = Process->ThreadQuantum;
-        
-        /* Calculate new priority */
-        OldPriority = CurrentThread->Priority;
-        if (OldPriority < LOW_REALTIME_PRIORITY) {
-            
-            /* Set the New Priority and add the Priority Decrement */
-            NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
-            
-            /* Don't go out of bounds */
-            if (NewPriority < CurrentThread->BasePriority) NewPriority = CurrentThread->BasePriority;
-            
-            /* Reset the priority decrement */
-            CurrentThread->PriorityDecrement = 0;
-            
-            /* Set a new priority if needed */
-            if (OldPriority != NewPriority) {
-                
-                /* Set new Priority */
-                CurrentThread->Priority = NewPriority;
-            
-            } else {
-                
-                /* Queue new thread if none is already */
-                if (Prcb->NextThread == NULL) {
-                    
-                    /* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
-                               
-                } else {
-                           
-                    /* Make the current thread non-premeptive if a new thread is queued */
-                    CurrentThread->Preempted = FALSE;
-                }
-            }
-
-            
-        } else {
-            /* Set the Quantum back to Maximum */
-            //if (CurrentThread->DisableQuantum) {
-            //    CurrentThread->Quantum = MAX_QUANTUM;
-            //}
-        }
-    }
-
-    /* Dispatch the Thread */
-    KeLowerIrql(DISPATCH_LEVEL);
-    PsDispatchThread(THREAD_STATE_READY);
-}    
+       PKPRCB Prcb;
+       PKTHREAD CurrentThread;
+       KIRQL OldIrql;
+       PKPROCESS Process;
+       KPRIORITY OldPriority;
+       KPRIORITY NewPriority;
+       
+       /* Lock dispatcher, get current thread */
+       Prcb = &KeGetCurrentKPCR()->PrcbData;
+       CurrentThread = KeGetCurrentThread();
+       OldIrql = KeRaiseIrqlToSynchLevel();
+       
+       /* Get the Thread's Process */
+       Process = CurrentThread->ApcState.Process;
+       
+       /* Set DPC Event if requested */
+       if (Prcb->DpcSetEventRequest) {
+               KeSetEvent(Prcb->DpcEvent, 0, 0);
+       }
+       
+       /* Check if Quantum expired */
+       if (CurrentThread->Quantum <= 0) {
+               /* Set the new Quantum */
+               CurrentThread->Quantum = Process->ThreadQuantum;
+               
+               /* Calculate new priority */
+               OldPriority = CurrentThread->Priority;
+               if (OldPriority < LOW_REALTIME_PRIORITY) {
+                       NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
+                       if (NewPriority < CurrentThread->BasePriority) {
+                               NewPriority = CurrentThread->BasePriority;
+                       }
+                       CurrentThread->PriorityDecrement = 0;
+                       if (OldPriority != NewPriority) {
+                               /* Set new Priority */
+                               CurrentThread->Priority = NewPriority;
+                       } else {
+                               /* Queue new thread if none is already */
+                               if (Prcb->NextThread == NULL) {
+                                       /* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
+                               } else {
+                                       /* Make the current thread non-premeptive if a new thread is queued */
+                                       CurrentThread->Preempted = FALSE;
+                               }
+                       }
+               } else {
+                       /* Set the Quantum back to Maximum */
+                       //if (CurrentThread->DisableQuantum) {
+                       //      CurrentThread->Quantum = MAX_QUANTUM;
+                       //}
+               }
+       }
+       /* Dispatch the Thread */
+       KeLowerIrql(DISPATCH_LEVEL);
+       PsDispatchThread(THREAD_STATE_READY);
+}      
 
 /*
  * @implemented
- *
- * FUNCTION: 
- *          Called whenever a system interrupt is generated at DISPATCH_LEVEL.
- *          It delivers queued DPCs and dispatches a new thread if need be.
  */
 VOID
 STDCALL
 KiDispatchInterrupt(VOID)
+/*
+ * FUNCTION: 
+ *          Called whenever a system interrupt is generated at DISPATCH_LEVEL.
+ *          It delivers queued DPCs and dispatches a new thread if need be.
+ */
 {
-    PLIST_ENTRY DpcEntry;
-    PKDPC Dpc;
-    KIRQL OldIrql;
-    PKPCR Pcr;
-
-    DPRINT("Dispatching Interrupts\n");
-    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-
-    /* Set DPC Deliver to Active */
-    Pcr = KeGetCurrentKPCR();
-
-    if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
-        /* Raise IRQL */
-        KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-#ifdef CONFIG_SMP        
-        KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+       PLIST_ENTRY DpcEntry;
+       PKDPC Dpc;
+       KIRQL OldIrql;
+       PKPCR Pcr;
+
+       DPRINT("Dispatching Interrupts\n");
+       ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+       /* Set DPC Deliver to Active */
+       Pcr = KeGetCurrentKPCR();
+
+       if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
+               /* Raise IRQL */
+               KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+#ifdef CONFIG_SMP              
+               KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
 #endif
-            Pcr->PrcbData.DpcRoutineActive = TRUE;
-
-        DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
-        /* Loop while we have entries */
-        while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
-            
-            ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
-            DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
-            
-            /* Get the DPC call it */
-            DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
-            Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
-            DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
-            Dpc->DpcData = NULL;
-            Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
+               Pcr->PrcbData.DpcRoutineActive = TRUE;
+
+               DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
+               /* Loop while we have entries */
+               while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
+                       ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
+                       DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
+                       
+                       /* Get the DPC call it */
+                       DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
+                       Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
+                       DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
+                       Dpc->DpcData = NULL;
+                       Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
 #ifdef CONFIG_SMP
-            KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+                       KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
 #endif
-            /* Disable/Enabled Interrupts and Call the DPC */
-            KeLowerIrql(OldIrql);
-            DPRINT("Calling DPC: %x\n", Dpc);
-            Dpc->DeferredRoutine(Dpc,
-                         Dpc->DeferredContext,
-                         Dpc->SystemArgument1,
-                         Dpc->SystemArgument2);
-            KeRaiseIrql(HIGH_LEVEL, &OldIrql);
-            
+                       /* Disable/Enabled Interrupts and Call the DPC */
+                       KeLowerIrql(OldIrql);
+                       DPRINT("Calling DPC: %x\n", Dpc);
+                       Dpc->DeferredRoutine(Dpc,
+                                            Dpc->DeferredContext,
+                                            Dpc->SystemArgument1,
+                                            Dpc->SystemArgument2);
+                       KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+                       
 #ifdef CONFIG_SMP
-            KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
-            /* 
-             * If the dpc routine drops the irql below DISPATCH_LEVEL,
-             * a thread switch can occur and after the next thread switch 
-             * the execution may start on an other processor.
-             */
-            if (Pcr != KeGetCurrentKPCR()) {
-                
-                Pcr->PrcbData.DpcRoutineActive = FALSE;
-                KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
-                Pcr = KeGetCurrentKPCR();
-                KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
-                Pcr->PrcbData.DpcRoutineActive = TRUE;
-            }
+                       KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+                       /* 
+                        * If the dpc routine drops the irql below DISPATCH_LEVEL,
+                        * a thread switch can occur and after the next thread switch 
+                        * the execution may start on an other processor.
+                        */
+                       if (Pcr != KeGetCurrentKPCR()) {
+                               Pcr->PrcbData.DpcRoutineActive = FALSE;
+                               KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+                               Pcr = KeGetCurrentKPCR();
+                               KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+                               Pcr->PrcbData.DpcRoutineActive = TRUE;
+                       }
 #endif
-        }
-        /* Clear DPC Flags */
-        Pcr->PrcbData.DpcRoutineActive = FALSE;
-        Pcr->PrcbData.DpcInterruptRequested = FALSE;
+               }
+               /* Clear DPC Flags */
+               Pcr->PrcbData.DpcRoutineActive = FALSE;
+               Pcr->PrcbData.DpcInterruptRequested = FALSE;
 #ifdef CONFIG_SMP
-        KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
+               KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
 #endif
-        
-        /* DPC Dispatching Ended, re-enable interrupts */
-        KeLowerIrql(OldIrql);
-    }
-    
-    DPRINT("Checking for Quantum End\n");
-    
-    /* If we have Quantum End, call the function */
-    if (Pcr->PrcbData.QuantumEnd) {
-        
-        Pcr->PrcbData.QuantumEnd = FALSE;
-        KiQuantumEnd();
-    }
+               
+               /* DPC Dispatching Ended, re-enable interrupts */
+               KeLowerIrql(OldIrql);
+       }
+       
+       DPRINT("Checking for Quantum End\n");
+       /* If we have Quantum End, call the function */
+       if (Pcr->PrcbData.QuantumEnd) {
+               Pcr->PrcbData.QuantumEnd = FALSE;
+               KiQuantumEnd();
+       }
 }
 
 /* EOF */
diff --git a/reactos/ntoskrnl/ke/error.c b/reactos/ntoskrnl/ke/error.c
new file mode 100644 (file)
index 0000000..d6172aa
--- /dev/null
@@ -0,0 +1,98 @@
+/* $Id$
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ke/error.c
+ * PURPOSE:         Error reason setting/getting
+ *
+ * PROGRAMMERS:     David Welch
+ */
+
+/* INCLUDE *****************************************************************/
+
+#include <ntoskrnl.h>
+#include <internal/debug.h>
+
+/* FUNCTIONS ***************************************************************/
+
+BOOLEAN ExReadyForErrors = FALSE;
+PEPORT ExpDefaultErrorPort = NULL;
+PEPROCESS ExpDefaultErrorPortProcess = NULL;
+
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+KiCoprocessorError(
+    VOID
+)
+{
+       UNIMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+KiUnexpectedInterrupt(
+    VOID
+)
+{
+       UNIMPLEMENTED;
+}
+
+NTSTATUS STDCALL 
+NtRaiseHardError(IN NTSTATUS ErrorStatus,
+                 IN ULONG NumberOfParameters,
+                 IN PUNICODE_STRING UnicodeStringParameterMask  OPTIONAL,
+                 IN PVOID *Parameters,
+                 IN HARDERROR_RESPONSE_OPTION ResponseOption,
+                 OUT PHARDERROR_RESPONSE Response)
+{
+  DPRINT1("Hard error %x\n", ErrorStatus);
+  return(STATUS_SUCCESS);
+}
+
+NTSTATUS STDCALL 
+NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
+{
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status;
+  
+  PreviousMode = ExGetPreviousMode();
+  
+  if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
+                             PreviousMode))
+  {
+    DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
+    return STATUS_PRIVILEGE_NOT_HELD;
+  }
+  
+  /* serialization shouldn't be required here as it usually is just called once
+     during startup */
+  
+  if(!ExReadyForErrors)
+  {
+    Status = ObReferenceObjectByHandle(PortHandle,
+                                       0,
+                                       LpcPortObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&ExpDefaultErrorPort,
+                                       NULL);
+    if(NT_SUCCESS(Status))
+    {
+      ExpDefaultErrorPortProcess = PsGetCurrentProcess();
+      ExReadyForErrors = TRUE;
+    }
+  }
+  else
+  {
+    Status = STATUS_UNSUCCESSFUL;
+  }
+  
+  return Status;
+}
+
+/* EOF */
index 7683afa..5ef0e62 100644 (file)
 /*
  * @implemented
  */
-VOID 
-STDCALL 
-KeClearEvent(PKEVENT Event)
+VOID STDCALL KeClearEvent (PKEVENT Event)
 {
-    DPRINT("KeClearEvent(Event %x)\n", Event);
-    
-    /* Reset Signal State */
-    Event->Header.SignalState = FALSE;
+   DPRINT("KeClearEvent(Event %x)\n", Event);
+   Event->Header.SignalState = FALSE;
 }
 
 /*
  * @implemented
  */
-VOID 
-STDCALL 
-KeInitializeEvent(PKEVENT Event,
-                  EVENT_TYPE Type,
-                  BOOLEAN State)
+VOID STDCALL KeInitializeEvent (PKEVENT                Event,
+                               EVENT_TYPE      Type,
+                               BOOLEAN         State)
 {
-    DPRINT("KeInitializeEvent(Event %x)\n", Event);
-    
-    /* Initialize the Dispatcher Header */
-    KeInitializeDispatcherHeader(&Event->Header,
-                                 Type,
-                                 sizeof(Event) / sizeof(ULONG),
-                                 State);
+   ULONG IType;
+   
+   if (Type == NotificationEvent)
+     {
+       IType = InternalNotificationEvent;
+     }
+   else if (Type == SynchronizationEvent)
+     {
+       IType = InternalSynchronizationEvent;
+     }
+   else
+     {
+       ASSERT(FALSE);
+       return;
+     }
+   
+   KeInitializeDispatcherHeader(&(Event->Header),
+                               IType,
+                               sizeof(Event)/sizeof(ULONG),State);
+   InitializeListHead(&(Event->Header.WaitListHead));
 }
 
 /*
  * @implemented
  */
-VOID 
-STDCALL 
-KeInitializeEventPair(PKEVENT_PAIR EventPair)
+LONG STDCALL KeReadStateEvent (PKEVENT Event)
 {
-    DPRINT("KeInitializeEventPair(Event %x)\n", EventPair);
-    
-    /* Initialize the Event Pair Type and Size */
-    EventPair->Type = EventPairObject;
-    EventPair->Size = sizeof(KEVENT_PAIR);
-    
-    /* Initialize the two Events */
-    KeInitializeEvent(&EventPair->LowEvent, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&EventPair->HighEvent, SynchronizationEvent, FALSE);
+   return(Event->Header.SignalState);
 }
 
 /*
  * @implemented
  */
-LONG STDCALL
-KePulseEvent(IN PKEVENT Event,
-             IN KPRIORITY Increment,
-             IN BOOLEAN Wait)
+LONG STDCALL KeResetEvent (PKEVENT Event)
 {
-    KIRQL OldIrql;
-    LONG PreviousState;
-
-    DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
-    
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Save the Old State */
-    PreviousState = Event->Header.SignalState;
-    
-    /* Check if we are non-signaled and we have stuff in the Wait Queue */
-    if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead)) {
-        
-        /* Set the Event to Signaled */
-        Event->Header.SignalState = 1;
-    
-        /* Wake the Event */
-        KiWaitTest(&Event->Header, Increment);
-    }
-    
-    /* Unsignal it */
-    Event->Header.SignalState = 0;
-    
-    /* Check what wait state was requested */
-    if (Wait == FALSE) {
-    
-        /* Wait not requested, release Dispatcher Database and return */    
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        
-    } else {
-        
-        /* Return Locked and with a Wait */
-        KTHREAD *Thread = KeGetCurrentThread();
-        Thread->WaitNext = TRUE;
-        Thread->WaitIrql = OldIrql;
-    }
-
-    /* Return the previous State */
-    return PreviousState;
+  /* FIXME: must use interlocked func. everywhere! (wait.c)
+   * or use dispather lock instead
+   * -Gunnar */
+   return(InterlockedExchange(&(Event->Header.SignalState),0));
 }
 
 /*
  * @implemented
  */
-LONG 
-STDCALL 
-KeReadStateEvent(PKEVENT Event)
+LONG STDCALL KeSetEvent (PKEVENT               Event,
+                        KPRIORITY      Increment,
+                        BOOLEAN                Wait)
 {
-    /* Return the Signal State */
-    return Event->Header.SignalState;
-}
+  KIRQL OldIrql;
+  int ret;
 
-/*
- * @implemented
- */
-LONG 
-STDCALL 
-KeResetEvent(PKEVENT Event)
-{
-    KIRQL OldIrql;
-    LONG PreviousState;
-    
-    DPRINT("KeResetEvent(Event %x)\n",Event);
-    
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Save the Previous State */
-    PreviousState = Event->Header.SignalState;
-    
-    /* Set it to zero */
-    Event->Header.SignalState = 0;
-    
-    /* Release Dispatcher Database and return previous state */    
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return PreviousState;
+  DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
+
+  OldIrql = KeAcquireDispatcherDatabaseLock();
+
+  ret = InterlockedExchange(&Event->Header.SignalState,1);
+
+  KiDispatcherObjectWake(&Event->Header, Increment);
+
+  if (Wait == FALSE)
+    {
+      KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+  else
+    {
+      KTHREAD *Thread = KeGetCurrentThread();
+      Thread->WaitNext = TRUE;
+      Thread->WaitIrql = OldIrql;
+    }
+
+  return(ret);
 }
 
 /*
  * @implemented
  */
-LONG
-STDCALL 
-KeSetEvent(PKEVENT Event,
-           KPRIORITY Increment,
-           BOOLEAN Wait)
+LONG STDCALL
+KePulseEvent (IN PKEVENT       Event,
+              IN KPRIORITY     Increment,
+              IN BOOLEAN       Wait)
 {
-    KIRQL OldIrql;
-    LONG PreviousState;
-    PKWAIT_BLOCK WaitBlock;
-
-    DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
-
-    /* Lock the Dispathcer Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Save the Previous State */
-    PreviousState = Event->Header.SignalState;
-    
-    /* Check if we have stuff in the Wait Queue */
-    if (IsListEmpty(&Event->Header.WaitListHead)) {
-        
-        /* Set the Event to Signaled */
-        DPRINT("Empty Wait Queue, Signal the Event\n");
-        Event->Header.SignalState = 1;
-        
-    } else {
-    
-        /* Get the Wait Block */
-        WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
-                                      KWAIT_BLOCK,
-                                      WaitListEntry);
-        
-        
-        /* Check the type of event */
-        if (Event->Header.Type == NotificationEvent || WaitBlock->WaitType == WaitAll) {
-            
-            if (PreviousState == 0) {
-                
-                /* We must do a full wait satisfaction */
-                DPRINT("Notification Event or WaitAll, Wait on the Event and Signal\n");
-                Event->Header.SignalState = 1;
-                KiWaitTest(&Event->Header, Increment);
-            }
-                
-        } else {
-        
-            /* We can satisfy wait simply by waking the thread, since our signal state is 0 now */        
-            DPRINT("WaitAny or Sync Event, just unwait the thread\n");
-            KiAbortWaitThread(WaitBlock->Thread, WaitBlock->WaitKey);
-        }
+   KIRQL OldIrql;
+   LONG Ret;
+
+   DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   Ret = InterlockedExchange(&Event->Header.SignalState,1);
+   KiDispatcherObjectWake(&Event->Header, Increment);
+   InterlockedExchange(&(Event->Header.SignalState),0);
+
+  if (Wait == FALSE)
+    {
+      KeReleaseDispatcherDatabaseLock(OldIrql);
     }
-    
-    /* Check what wait state was requested */
-    if (Wait == FALSE) {
-    
-        /* Wait not requested, release Dispatcher Database and return */    
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        
-    } else {
-        
-        /* Return Locked and with a Wait */
-        KTHREAD *Thread = KeGetCurrentThread();
-        Thread->WaitNext = TRUE;
-        Thread->WaitIrql = OldIrql;
+  else
+    {
+      KTHREAD *Thread = KeGetCurrentThread();
+      Thread->WaitNext = TRUE;
+      Thread->WaitIrql = OldIrql;
     }
 
-    /* Return the previous State */
-    DPRINT("Done: %d\n", PreviousState);
-    return PreviousState;
+   return Ret;
 }
 
 /*
@@ -231,39 +141,27 @@ KeSetEvent(PKEVENT Event,
  */
 VOID
 STDCALL
-KeSetEventBoostPriority(IN PKEVENT Event,
-                        IN PKTHREAD *Thread OPTIONAL)
+KeSetEventBoostPriority(
+       IN PKEVENT Event,
+       IN PKTHREAD *Thread OPTIONAL
+)
 {
-    PKTHREAD WaitingThread;
-    KIRQL OldIrql;
-
-    DPRINT("KeSetEventBoostPriority(Event %x, Thread %x)\n",Event,Thread);
-    
-    /* Acquire Dispatcher Database Lock */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* If our wait list is empty, then signal the event and return */
-    if (IsListEmpty(&Event->Header.WaitListHead)) {
-    
-        Event->Header.SignalState = 1;
-    
-    } else {
-        
-        /* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
-        WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, 
-                                          KWAIT_BLOCK, 
-                                          WaitListEntry)->Thread;
-
-        /* Return it to caller if requested */
-        if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
-
-        /* Reset the Quantum and Unwait the Thread */
-        WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
-        KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
-    }
+       PKTHREAD WaitingThread;
+   KIRQL OldIrql;
+       
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   
+       /* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
+       WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
+       
+       /* Return it to caller if requested */
+       if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
+       
+       /* Reset the Quantum and Unwait the Thread */
+       WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
+       KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
    
-    /* Release the Dispatcher Database Lock */
-    KeReleaseDispatcherDatabaseLock(OldIrql);
+   KeReleaseDispatcherDatabaseLock(OldIrql);
 }
 
 /* EOF */
index 6d5038a..a97577f 100644 (file)
@@ -200,7 +200,7 @@ _Ki386ContextSwitch:
         */
        sti
 
-       call    @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
+       call    _KeReleaseDispatcherDatabaseLockFromDpcLevel
 
        cmpl    $0, _PiNrThreadsAwaitingReaping
        je      5f
index de1fd0b..40b352f 100644 (file)
@@ -1,11 +1,11 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/kthread.c
  * PURPOSE:         Microkernel thread support
  * 
- * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net) - Commented, reorganized some stuff, fixed/implemented some functions.
- *                  David Welch (welch@cwcom.net)
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 
 /* FUNCTIONS *****************************************************************/
 
-ULONG
-STDCALL
-KeAlertResumeThread(IN PKTHREAD Thread)
+VOID
+KiServiceCheck (VOID)
 {
-    ULONG PreviousCount;
-    KIRQL OldIrql;
-
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-   
-    /* Lock the Dispatcher Database and the APC Queue */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    KiAcquireSpinLock(&Thread->ApcQueueLock);
-
-    /* Return if Thread is already alerted. */
-    if (Thread->Alerted[KernelMode] == FALSE) {
-       
-        /* If it's Blocked, unblock if it we should */
-        if (Thread->State == THREAD_STATE_BLOCKED &&  Thread->Alertable) {
-            
-            DPRINT("Aborting Wait\n");
-            KiAbortWaitThread(Thread, STATUS_ALERTED);
-       
-        } else {
-           
-            /* If not, simply Alert it */
-            Thread->Alerted[KernelMode] = TRUE;
-        }
-    }
-    
-    /* Save the old Suspend Count */
-    PreviousCount = Thread->SuspendCount;    
-    
-    /* If the thread is suspended, decrease one of the suspend counts */
-    if (PreviousCount) {
-            
-        /* Decrease count. If we are now zero, unwait it completely */
-        if (--Thread->SuspendCount) {
-            
-            /* Signal and satisfy */
-            Thread->SuspendSemaphore.Header.SignalState++;
-            KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
-        }
-    }
+  PETHREAD Thread;
 
-    /* Release Locks and return the Old State */
-    KiReleaseSpinLock(&Thread->ApcQueueLock);
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return PreviousCount;
-}
+  Thread = PsGetCurrentThread();
 
-BOOLEAN
-STDCALL
-KeAlertThread(PKTHREAD Thread, 
-              KPROCESSOR_MODE AlertMode)
-{
-    KIRQL OldIrql;
-    BOOLEAN PreviousState;
+  if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow)
+    {
+      PsInitWin32Thread (Thread);
 
-    /* Acquire the Dispatcher Database Lock */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-   
-    /* Save the Previous State */
-    PreviousState = Thread->Alerted[AlertMode];
-      
-    /* Return if Thread is already alerted. */
-    if (PreviousState == FALSE) {
-       
-        /* If it's Blocked, unblock if it we should */
-        if (Thread->State == THREAD_STATE_BLOCKED && 
-            (AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
-            Thread->Alertable) {
-            
-            DPRINT("Aborting Wait\n");
-            KiAbortWaitThread(Thread, STATUS_ALERTED);
-       
-        } else {
-           
-            /* If not, simply Alert it */
-            Thread->Alerted[AlertMode] = TRUE;
-        }
+      Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
     }
-    
-    /* Release the Dispatcher Lock */
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    
-    /* Return the old state */
-    return PreviousState;
 }
 
 /*
@@ -110,231 +36,28 @@ KeAlertThread(PKTHREAD Thread,
  */
 VOID
 STDCALL
-KeCapturePersistentThreadState(IN PVOID CurrentThread,
-                               IN ULONG Setting1,
-                               IN ULONG Setting2,
-                               IN ULONG Setting3,
-                               IN ULONG Setting4,
-                               IN ULONG Setting5,
-                               IN PVOID ThreadState)
+KeCapturePersistentThreadState(
+       IN PVOID        CurrentThread,
+       IN ULONG        Setting1,
+       IN ULONG        Setting2,
+       IN ULONG        Setting3,
+       IN ULONG        Setting4,
+       IN ULONG        Setting5,
+       IN PVOID        ThreadState
+)
 {
-    UNIMPLEMENTED;
+       UNIMPLEMENTED;
 }
 
-/*
- * FUNCTION: Initialize the microkernel state of the thread
- */
 VOID
-STDCALL
-KeInitializeThread(PKPROCESS Process, 
-                   PKTHREAD Thread, 
-                   BOOLEAN First)
+KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, 
+               PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
 {
-    PVOID KernelStack;
-    NTSTATUS Status;
-    extern unsigned int init_stack_top;
-    extern unsigned int init_stack;
-    PMEMORY_AREA StackArea;
-    ULONG i;
-    PHYSICAL_ADDRESS BoundaryAddressMultiple;
-  
-    /* Initialize the Boundary Address */
-    BoundaryAddressMultiple.QuadPart = 0;
-  
-    /* Initalize the Dispatcher Header */
-    KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
-                                 ThreadObject,
-                                 sizeof(KTHREAD),
-                                 FALSE);
-    InitializeListHead(&Thread->MutantListHead);
-    
-    /* If this is isn't the first thread, allocate the Kernel Stack */
-    if (!First) {
-        
-        PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
-        KernelStack = NULL;
-      
-        MmLockAddressSpace(MmGetKernelAddressSpace());
-        Status = MmCreateMemoryArea(NULL,
-                                    MmGetKernelAddressSpace(),
-                                    MEMORY_AREA_KERNEL_STACK,
-                                    &KernelStack,
-                                    MM_STACK_SIZE,
-                                    0,
-                                    &StackArea,
-                                    FALSE,
-                                    FALSE,
-                                    BoundaryAddressMultiple);
-        MmUnlockAddressSpace(MmGetKernelAddressSpace());
-      
-        /* Check for Success */
-        if (!NT_SUCCESS(Status)) {
-            
-            DPRINT1("Failed to create thread stack\n");
-            KEBUGCHECK(0);
-        }
-        
-        /* Mark the Stack */
-        for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) {
-
-            Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
-            
-            /* Check for success */
-            if (!NT_SUCCESS(Status)) {
-                
-                KEBUGCHECK(0);
-            }
-        }
-        
-        /* Create a Virtual Mapping for it */
-        Status = MmCreateVirtualMapping(NULL,
-                                        KernelStack,
-                                        PAGE_READWRITE,
-                                        Page,
-                                        MM_STACK_SIZE / PAGE_SIZE);
-        
-        /* Check for success */
-        if (!NT_SUCCESS(Status)) {
-            
-            KEBUGCHECK(0);
-        }
-        
-        /* Set the Kernel Stack */
-        Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
-        Thread->StackBase    = (PCHAR)KernelStack + MM_STACK_SIZE;
-        Thread->StackLimit   = (ULONG_PTR)KernelStack;
-        Thread->KernelStack  = (PCHAR)KernelStack + MM_STACK_SIZE;
-        
-    } else {
-        
-        /* Use the Initial Stack */
-        Thread->InitialStack = (PCHAR)init_stack_top;
-        Thread->StackBase = (PCHAR)init_stack_top;
-        Thread->StackLimit = (ULONG_PTR)init_stack;
-        Thread->KernelStack = (PCHAR)init_stack_top;
+  ASSERT(SwapEntry == 0);
+  if (Page != 0)
+    {
+      MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
     }
-
-    /* 
-     * Establish the pde's for the new stack and the thread structure within the 
-     * address space of the new process. They are accessed while taskswitching or
-     * while handling page faults. At this point it isn't possible to call the 
-     * page fault handler for the missing pde's. 
-     */
-    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
-    MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
-
-    /* Set the Thread to initalized */
-    Thread->State = THREAD_STATE_INITIALIZED;
-    
-    /* The Native API function will initialize the TEB field later */
-    Thread->Teb = NULL;
-    
-    /* Initialize stuff to zero */
-    Thread->TlsArray = NULL;
-    Thread->DebugActive = 0;
-    Thread->Alerted[0] = 0;
-    Thread->Alerted[1] = 0;
-    Thread->Iopl = 0;
-    
-    /* FIXME: Think how this might work */
-    Thread->NpxState = 0;
-    Thread->NpxIrql = 0;
-   
-    /* Setup APC Fields */
-    InitializeListHead(&Thread->ApcState.ApcListHead[0]);
-    InitializeListHead(&Thread->ApcState.ApcListHead[1]);
-    Thread->ApcState.Process = Process;
-    Thread->ApcState.KernelApcInProgress = 0;
-    Thread->ApcState.KernelApcPending = 0;
-    Thread->ApcState.UserApcPending = 0;
-    Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
-    Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
-    Thread->ApcStateIndex = OriginalApcEnvironment;
-    Thread->ApcQueueable = TRUE;
-    memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
-    KeInitializeSpinLock(&Thread->ApcQueueLock);
-    
-    /* Setup Wait Fields */
-    Thread->WaitStatus = STATUS_SUCCESS;
-    Thread->WaitIrql = PASSIVE_LEVEL;
-    Thread->WaitMode = 0;
-    Thread->WaitNext = FALSE;
-    Thread->WaitListEntry.Flink = NULL;
-    Thread->WaitListEntry.Blink = NULL;
-    Thread->WaitTime = 0;
-    Thread->WaitBlockList = NULL;
-    memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK) * 4);
-    memset(&Thread->Timer, 0, sizeof(KTIMER));
-    KeInitializeTimer(&Thread->Timer);
-    
-    /* Setup scheduler Fields */
-    Thread->BasePriority = Process->BasePriority;
-    Thread->DecrementCount = 0;
-    Thread->PriorityDecrement = 0;
-    Thread->Quantum = Process->ThreadQuantum;
-    Thread->Saturation = 0;
-    Thread->Priority = Process->BasePriority; 
-    Thread->UserAffinity = Process->Affinity;
-    Thread->SystemAffinityActive = 0;
-    Thread->Affinity = Process->Affinity;
-    Thread->Preempted = 0;
-    Thread->ProcessReadyQueue = 0;
-    Thread->KernelStackResident = 1;
-    Thread->NextProcessor = 0;
-    Thread->ContextSwitches = 0;
-    
-    /* Setup Queue Fields */
-    Thread->Queue = NULL;
-    Thread->QueueListEntry.Flink = NULL;
-    Thread->QueueListEntry.Blink = NULL;
-
-    /* Setup Misc Fields */
-    Thread->LegoData = 0; 
-    Thread->PowerState = 0;
-    Thread->ServiceTable = KeServiceDescriptorTable;
-    Thread->CallbackStack = NULL;
-    Thread->Win32Thread = NULL;
-    Thread->TrapFrame = NULL;
-    Thread->EnableStackSwap = 0;
-    Thread->LargeStack = 0;
-    Thread->ResourceIndex = 0;
-    Thread->PreviousMode = KernelMode;
-    Thread->KernelTime = 0;
-    Thread->UserTime = 0;
-    Thread->AutoAlignment = Process->AutoAlignment;
-   
-  /* FIXME OPTIMIZATION OF DOOM. DO NOT ENABLE FIXME */
-#if 0
-  Thread->WaitBlock[3].Object = (PVOID)&Thread->Timer;
-  Thread->WaitBlock[3].Thread = Thread;
-  Thread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
-  Thread->WaitBlock[3].WaitType = WaitAny;
-  Thread->WaitBlock[3].NextWaitBlock = NULL;
-  InsertTailList(&Thread->Timer.Header.WaitListHead,
-                 &Thread->WaitBlock[3].WaitListEntry);
-#endif
-
-    /* Initialize the Suspend APC */  
-    KeInitializeApc(&Thread->SuspendApc,
-                    Thread,
-                    OriginalApcEnvironment,
-                    PiSuspendThreadKernelRoutine,
-                    PiSuspendThreadRundownRoutine,
-                    PiSuspendThreadNormalRoutine,
-                    KernelMode,
-                    NULL);
-     
-    /* Initialize the Suspend Semaphore */
-    KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
-    
-    /* Insert the Thread into the Process's Thread List */
-    InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
-  
-    /* Set up the Suspend Counts */
-    Thread->FreezeCount = 0;
-    Thread->SuspendCount = 0;
-   
-    /* Do x86 specific part */
 }
 
 /*
@@ -342,9 +65,11 @@ KeInitializeThread(PKPROCESS Process,
  */
 KPRIORITY
 STDCALL
-KeQueryPriorityThread (IN PKTHREAD Thread)
+KeQueryPriorityThread (
+    IN PKTHREAD Thread
+    )
 {
-    return Thread->Priority;
+       return Thread->Priority;
 }
 
 /*
@@ -352,29 +77,19 @@ KeQueryPriorityThread (IN PKTHREAD Thread)
  */
 ULONG
 STDCALL
-KeQueryRuntimeThread(IN PKTHREAD Thread,
-                     OUT PULONG UserTime)
-{
-    /* Return the User Time */
-    *UserTime = Thread->UserTime;
-    
-    /* Return the Kernel Time */
-    return Thread->KernelTime;
-}
-
-VOID
-KeFreeStackPage(PVOID Context, 
-                MEMORY_AREA* MemoryArea, 
-                PVOID Address, 
-                PFN_TYPE Page, 
-                SWAPENTRY SwapEntry, 
-                BOOLEAN Dirty)
+KeQueryRuntimeThread(
+       IN PKTHREAD Thread,
+       OUT PULONG UserTime
+       )
 {
-    ASSERT(SwapEntry == 0);
-    if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
+       /* Return the User Time */
+       *UserTime = Thread->UserTime;
+       
+       /* Return the Kernel Time */
+       return Thread->KernelTime;
 }
 
-NTSTATUS
+NTSTATUS 
 KeReleaseThread(PKTHREAD Thread)
 /*
  * FUNCTION: Releases the resource allocated for a thread by
@@ -408,329 +123,344 @@ KeReleaseThread(PKTHREAD Thread)
  */
 BOOLEAN
 STDCALL
-KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
+KeSetKernelStackSwapEnable(
+       IN BOOLEAN Enable
+       )
 {
-    PKTHREAD Thread = KeGetCurrentThread();
-    BOOLEAN PreviousState;
-    KIRQL OldIrql;
-     /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-
-    /* Save Old State */
-    PreviousState = Thread->EnableStackSwap;
-
-    /* Set New State */
-    Thread->EnableStackSwap = Enable;
-
-    /* No, Release Lock */
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-        
-    /* Return Old State */
-    return PreviousState;
+       PKTHREAD Thread;
+       BOOLEAN PreviousState;
+       
+       Thread = KeGetCurrentThread();
+       
+       /* Save Old State */
+       PreviousState = Thread->EnableStackSwap;
+       
+       /* Set New State */
+       Thread->EnableStackSwap = Enable;
+
+       /* Return Old State */
+       return PreviousState;
 }
 
+VOID
+KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
 /*
- * @implemented
+ * FUNCTION: Initialize the microkernel state of the thread
  */
-VOID
-STDCALL
-KeRevertToUserAffinityThread(VOID)
 {
-    PKTHREAD CurrentThread = KeGetCurrentThread();
-    KIRQL OldIrql;
-
-    ASSERT(CurrentThread->SystemAffinityActive != FALSE);
-        
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-
-    /* Return to User Affinity */
-    CurrentThread->Affinity = CurrentThread->UserAffinity;
-
-    /* Disable System Affinity */
-    CurrentThread->SystemAffinityActive = FALSE;
-    
-    /* Check if we need to Dispatch a New thread */
-    if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber())) {
-        
-        /* No, just release */
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-    
-    } else {
-        
-        /* We need to dispatch a new thread */
-        CurrentThread->WaitIrql = OldIrql;
-        PsDispatchThreadNoLock(THREAD_STATE_READY);
-        KeLowerIrql(OldIrql);
+  PVOID KernelStack;
+  NTSTATUS Status;
+  extern unsigned int init_stack_top;
+  extern unsigned int init_stack;
+  PMEMORY_AREA StackArea;
+  ULONG i;
+  PHYSICAL_ADDRESS BoundaryAddressMultiple;
+  
+  BoundaryAddressMultiple.QuadPart = 0;
+  
+  KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
+                              InternalThreadType,
+                              sizeof(ETHREAD),
+                              FALSE);
+  InitializeListHead(&Thread->MutantListHead);
+  if (!First)
+    {
+      PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
+      KernelStack = NULL;
+      
+      MmLockAddressSpace(MmGetKernelAddressSpace());
+      Status = MmCreateMemoryArea(NULL,
+                                 MmGetKernelAddressSpace(),
+                                 MEMORY_AREA_KERNEL_STACK,
+                                 &KernelStack,
+                                 MM_STACK_SIZE,
+                                 0,
+                                 &StackArea,
+                                 FALSE,
+                                 FALSE,
+                                 BoundaryAddressMultiple);
+      MmUnlockAddressSpace(MmGetKernelAddressSpace());
+      
+      if (!NT_SUCCESS(Status))
+       {
+         DPRINT1("Failed to create thread stack\n");
+         KEBUGCHECK(0);
+       }
+      for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
+       {
+         Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
+         if (!NT_SUCCESS(Status))
+           {
+             KEBUGCHECK(0);
+           }
+       }
+      Status = MmCreateVirtualMapping(NULL,
+                                     KernelStack,
+                                     PAGE_READWRITE,
+                                     Page,
+                                     MM_STACK_SIZE / PAGE_SIZE);
+      if (!NT_SUCCESS(Status))
+        {
+          KEBUGCHECK(0);
+       }
+      Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
+      Thread->StackBase    = (PCHAR)KernelStack + MM_STACK_SIZE;
+      Thread->StackLimit   = (ULONG_PTR)KernelStack;
+      Thread->KernelStack  = (PCHAR)KernelStack + MM_STACK_SIZE;
+    }
+  else
+    {
+      Thread->InitialStack = (PCHAR)init_stack_top;
+      Thread->StackBase = (PCHAR)init_stack_top;
+      Thread->StackLimit = (ULONG_PTR)init_stack;
+      Thread->KernelStack = (PCHAR)init_stack_top;
     }
+
+  /* 
+   * Establish the pde's for the new stack and the thread structure within the 
+   * address space of the new process. They are accessed while taskswitching or
+   * while handling page faults. At this point it isn't possible to call the 
+   * page fault handler for the missing pde's. 
+   */
+  
+  MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
+  MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
+
+  /* 
+   * The Native API function will initialize the TEB field later 
+   */
+  Thread->Teb = NULL;
+  Thread->TlsArray = NULL;
+  Thread->DebugActive = 0;
+  Thread->State = THREAD_STATE_INITIALIZED;
+  Thread->Alerted[0] = 0;
+  Thread->Alerted[1] = 0;
+  Thread->Iopl = 0;
+  /*
+   * FIXME: Think how this might work
+   */
+  Thread->NpxState = 0;
+  
+  Thread->Saturation = 0;
+  Thread->Priority = Process->BasePriority; 
+  InitializeListHead(&Thread->ApcState.ApcListHead[0]);
+  InitializeListHead(&Thread->ApcState.ApcListHead[1]);
+  Thread->ApcState.Process = Process;
+  Thread->ApcState.KernelApcInProgress = 0;
+  Thread->ApcState.KernelApcPending = 0;
+  Thread->ApcState.UserApcPending = 0;
+  Thread->ContextSwitches = 0;
+  Thread->WaitStatus = STATUS_SUCCESS;
+  Thread->WaitIrql = PASSIVE_LEVEL;
+  Thread->WaitMode = 0;
+  Thread->WaitNext = FALSE;
+  Thread->WaitBlockList = NULL;
+  Thread->WaitListEntry.Flink = NULL;
+  Thread->WaitListEntry.Blink = NULL;
+  Thread->WaitTime = 0;
+  Thread->BasePriority = Process->BasePriority;
+  Thread->DecrementCount = 0;
+  Thread->PriorityDecrement = 0;
+  Thread->Quantum = Process->ThreadQuantum;
+  memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK)*4);
+  Thread->LegoData = 0; 
+  Thread->UserAffinity = Process->Affinity;
+  Thread->SystemAffinityActive = 0;
+  Thread->PowerState = 0;
+  Thread->NpxIrql = 0;
+  Thread->ServiceTable = KeServiceDescriptorTable;
+  Thread->Queue = NULL;
+  KeInitializeSpinLock(&Thread->ApcQueueLock);
+  memset(&Thread->Timer, 0, sizeof(KTIMER));
+  KeInitializeTimer(&Thread->Timer);
+  Thread->QueueListEntry.Flink = NULL;
+  Thread->QueueListEntry.Blink = NULL;
+  Thread->Affinity = Process->Affinity;
+  Thread->Preempted = 0;
+  Thread->ProcessReadyQueue = 0;
+  Thread->KernelStackResident = 1;
+  Thread->NextProcessor = 0;
+  Thread->CallbackStack = NULL;
+  Thread->Win32Thread = NULL;
+  Thread->TrapFrame = NULL;
+  Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
+  Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
+  Thread->EnableStackSwap = 0;
+  Thread->LargeStack = 0;
+  Thread->ResourceIndex = 0;
+  Thread->PreviousMode = KernelMode;
+  Thread->KernelTime = 0;
+  Thread->UserTime = 0;
+  memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
+   
+  Thread->ApcStateIndex = OriginalApcEnvironment;
+  Thread->ApcQueueable = TRUE;
+  Thread->AutoAlignment = Process->AutoAlignment;
+  
+  KeInitializeApc(&Thread->SuspendApc,
+                 Thread,
+                 OriginalApcEnvironment,
+                 PiSuspendThreadKernelRoutine,
+                 PiSuspendThreadRundownRoutine,
+                 PiSuspendThreadNormalRoutine,
+                 KernelMode,
+                 NULL);
+  KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
+  
+  InsertTailList(&Process->ThreadListHead,
+                 &Thread->ThreadListEntry);
+  Thread->FreezeCount = 0;
+  Thread->SuspendCount = 0;
+   
+   /*
+    * Do x86 specific part
+    */
 }
 
 /*
  * @implemented
  */
-CCHAR
+VOID
 STDCALL
-KeSetIdealProcessorThread(IN PKTHREAD Thread,
-                          IN CCHAR Processor)
+KeRevertToUserAffinityThread(VOID)
 {
-    CCHAR PreviousIdealProcessor;
-    KIRQL OldIrql;
-    
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-
-    /* Save Old Ideal Processor */
-    PreviousIdealProcessor = Thread->IdealProcessor;
-
-    /* Set New Ideal Processor */
-    Thread->IdealProcessor = Processor;
-    
-    /* Release Lock */
-    KeReleaseDispatcherDatabaseLock(OldIrql);   
-    
-    /* Return Old Ideal Processor */
-    return PreviousIdealProcessor;
+#ifdef CONFIG_SMP
+       PKTHREAD CurrentThread;
+       KIRQL oldIrql;
+
+        oldIrql = KeAcquireDispatcherDatabaseLock();
+
+       CurrentThread = KeGetCurrentThread();
+
+       ASSERT(CurrentThread->SystemAffinityActive != FALSE);
+
+       /* Return to User Affinity */
+       CurrentThread->Affinity = CurrentThread->UserAffinity;
+       
+       /* Disable System Affinity */
+       CurrentThread->SystemAffinityActive = FALSE;
+
+       if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber()))
+       {
+          KeReleaseDispatcherDatabaseLock(oldIrql);
+       }
+       else
+       {
+          CurrentThread->WaitIrql = oldIrql;
+           PsDispatchThreadNoLock(THREAD_STATE_READY);
+           KeLowerIrql(oldIrql);
+       }
+#endif
 }
 
 /*
  * @implemented
  */
-VOID
+CCHAR
 STDCALL
-KeSetSystemAffinityThread(IN KAFFINITY Affinity)
+KeSetIdealProcessorThread (
+       IN PKTHREAD Thread,
+       IN CCHAR Processor)
 {
-    PKTHREAD CurrentThread = KeGetCurrentThread();
-    KIRQL OldIrql;
-
-    ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
-        
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-
-    /* Set the System Affinity Specified */
-    CurrentThread->Affinity = Affinity;
-
-    /* Enable System Affinity */
-    CurrentThread->SystemAffinityActive = TRUE;
-    
-    /* Check if we need to Dispatch a New thread */
-    if (Affinity & (1 << KeGetCurrentProcessorNumber())) {
-        
-        /* No, just release */
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-    
-    } else {
-        
-        /* We need to dispatch a new thread */
-        CurrentThread->WaitIrql = OldIrql;
-        PsDispatchThreadNoLock(THREAD_STATE_READY);
-        KeLowerIrql(OldIrql);
-    }
+       CCHAR PreviousIdealProcessor;
+
+       /* Save Old Ideal Processor */
+       PreviousIdealProcessor = Thread->IdealProcessor;
+       
+       /* Set New Ideal Processor */
+       Thread->IdealProcessor = Processor;
+       
+       /* Return Old Ideal Processor */
+       return PreviousIdealProcessor;
 }
 
 /*
  * @implemented
  */
- /* The Increment Argument seems to be ignored by NT and always 0 when called */
 VOID
 STDCALL
-KeTerminateThread(IN KPRIORITY Increment)
+KeSetSystemAffinityThread(IN KAFFINITY Affinity)
 {
-    /* Call our own internal routine */
-    PsTerminateCurrentThread(0);
+#ifdef CONFIG_SMP
+       PKTHREAD CurrentThread;
+       KIRQL oldIrql;
+
+        oldIrql = KeAcquireDispatcherDatabaseLock();
+
+       CurrentThread = KeGetCurrentThread();
+
+       ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
+       
+        /* Set the System Affinity Specified */
+       CurrentThread->Affinity = Affinity;
+       
+       /* Enable System Affinity */
+       CurrentThread->SystemAffinityActive = TRUE;
+
+       if (Affinity & (1 << KeGetCurrentProcessorNumber()))
+       {
+          KeReleaseDispatcherDatabaseLock(oldIrql);
+       }
+       else
+       {
+          CurrentThread->WaitIrql = oldIrql;
+           PsDispatchThreadNoLock(THREAD_STATE_READY);
+           KeLowerIrql(oldIrql);
+       }
+#endif
 }
 
 /*
- * FUNCTION: Tests whether there are any pending APCs for the current thread
- * and if so the APCs will be delivered on exit from kernel mode
+ * @implemented
  */
-BOOLEAN
-STDCALL
-KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
-{
-    KIRQL OldIrql;
-    PKTHREAD Thread = KeGetCurrentThread();
-    BOOLEAN OldState;
-   
-    ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-   
-    /* Lock the Dispatcher Database and the APC Queue */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    KiAcquireSpinLock(&Thread->ApcQueueLock);
-   
-    /* Save the old State */
-    OldState = Thread->Alerted[AlertMode];
-   
-    /* If the Thread is Alerted, Clear it */
-    if (OldState) {
-            
-        Thread->Alerted[AlertMode] = FALSE;
-        
-    } else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) {
-        
-        /* If the mode is User and the Queue isn't empty, set Pending */
-        Thread->ApcState.UserApcPending = TRUE;
-    }
-   
-    /* Release Locks and return the Old State */
-    KiReleaseSpinLock(&Thread->ApcQueueLock);
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return OldState;
-}
-
 VOID
-KiServiceCheck (VOID)
-{
-    PKTHREAD Thread = KeGetCurrentThread();
-    
-    /* Check if we need to inialize Win32 for this Thread */
-    if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
-    
-        /* We do. Initialize it and save the new table */  
-        PsInitWin32Thread((PETHREAD)Thread);
-        Thread->ServiceTable = KeServiceDescriptorTableShadow;
-    }
-}
-
-/* 
- *
- * NOT EXPORTED
- */
-NTSTATUS 
 STDCALL
-NtAlertResumeThread(IN  HANDLE ThreadHandle,
-                    OUT PULONG SuspendCount)
+KeTerminateThread(IN KPRIORITY Increment)
 {
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    PETHREAD Thread;
-    NTSTATUS Status;
-    ULONG PreviousState;
-
-    /* Check if parameters are valid */
-    if(PreviousMode != KernelMode) {
-     
-        _SEH_TRY {
-            
-            ProbeForWrite(SuspendCount,
-                          sizeof(HANDLE),
-                          sizeof(ULONG));
-       
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-            
-        } _SEH_END;
-    }
-   
-    /* Reference the Object */
-    Status = ObReferenceObjectByHandle(ThreadHandle,
-                                       THREAD_SUSPEND_RESUME,
-                                       PsThreadType,
-                                       PreviousMode,
-                                       (PVOID*)&Thread,
-                                       NULL);
-   
-    /* Check for Success */ 
-    if (NT_SUCCESS(Status)) {
-   
-        /* Call the Kernel Function */
-        PreviousState = KeAlertResumeThread(&Thread->Tcb);
-   
-        /* Dereference Object */
-        ObDereferenceObject(Thread);
-        
-        if (SuspendCount) {
-        
-            _SEH_TRY {
-        
-                *SuspendCount = PreviousState;
-            
-            } _SEH_HANDLE {
-            
-                Status = _SEH_GetExceptionCode();
-            
-            } _SEH_END;
-        }
-    }
-    
-    /* Return status */
-    return Status;
+       /* The Increment Argument seems to be ignored by NT and always 0 when called */
+       
+       /* Call our own internal routine */
+       PsTerminateCurrentThread(0);
 }
 
-/* 
- * @implemented
- *
- * EXPORTED
- */
-NTSTATUS 
-STDCALL
-NtAlertThread (IN HANDLE ThreadHandle)
-{
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    PETHREAD Thread;
-    NTSTATUS Status;
-
-    /* Reference the Object */
-    Status = ObReferenceObjectByHandle(ThreadHandle,
-                                       THREAD_SUSPEND_RESUME,
-                                       PsThreadType,
-                                       PreviousMode,
-                                       (PVOID*)&Thread,
-                                       NULL);
-   
-    /* Check for Success */ 
-    if (NT_SUCCESS(Status)) {
-   
-        /* 
-         * Do an alert depending on the processor mode. If some kmode code wants to
-         * enforce a umode alert it should call KeAlertThread() directly. If kmode
-         * code wants to do a kmode alert it's sufficient to call it with Zw or just
-         * use KeAlertThread() directly 
-         */
-        KeAlertThread(&Thread->Tcb, PreviousMode);
-   
-        /* Dereference Object */
-        ObDereferenceObject(Thread);
-    }
-    
-    /* Return status */
-    return Status;
-}
 
 NTSTATUS 
 STDCALL
 NtDelayExecution(IN BOOLEAN Alertable,
                  IN PLARGE_INTEGER DelayInterval)
 {
-    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    LARGE_INTEGER SafeInterval;
-    NTSTATUS Status;
+   KPROCESSOR_MODE PreviousMode;
+   LARGE_INTEGER SafeInterval;
    
-    /* Check if parameters are valid */
-    if(PreviousMode != KernelMode) {
+   PreviousMode = ExGetPreviousMode();
+   
+   if(PreviousMode != KernelMode)
+   {
+     NTSTATUS Status = STATUS_SUCCESS;
+     
+     _SEH_TRY
+     {
+       ProbeForRead(DelayInterval,
+                    sizeof(LARGE_INTEGER),
+                    sizeof(ULONG));
+       /* make a copy on the kernel stack and let DelayInterval point to it so
+          we don't need to wrap KeDelayExecutionThread in SEH! */
+       SafeInterval = *DelayInterval;
+       DelayInterval = &SafeInterval;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
      
-        _SEH_TRY {
-            
-            ProbeForRead(DelayInterval,
-                         sizeof(LARGE_INTEGER),
-                         sizeof(ULONG));
-            
-            /* make a copy on the kernel stack and let DelayInterval point to it so
-               we don't need to wrap KeDelayExecutionThread in SEH! */
-            SafeInterval = *DelayInterval;
-       
-        } _SEH_HANDLE {
-            
-            Status = _SEH_GetExceptionCode();
-        } _SEH_END;
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
    }
 
-   /* Call the Kernel Function */
-   Status = KeDelayExecutionThread(PreviousMode,
-                                   Alertable,
-                                   &SafeInterval);
-   
-   /* Return Status */
-   return Status;
+   return KeDelayExecutionThread(PreviousMode,
+                                 Alertable,
+                                 DelayInterval);
 }
index 71021da..eef694b 100644 (file)
@@ -1,24 +1,37 @@
-/*
+/* $Id$
+ * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/main.c
  * PURPOSE:         Initalizes the kernel
  *
- * PROGRAMMERS:     Alex Ionescu (cleaned up code, moved Executiv stuff to ex/init.c)
- *                  David Welch (welch@cwcom.net)
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
+#include "../dbg/kdb.h"
+#include <ntos/bootvid.h>
+#include <napi/core.h>
+
+#ifdef HALDBG
+#include <internal/ntosdbg.h>
+#else
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+#define ps
+#else
+#define ps(args...)
+#endif /* HALDBG */
+
+#endif
+
 #define NDEBUG
 #include <internal/debug.h>
 
 /* GLOBALS *******************************************************************/
 
 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
-
-
 ULONG NtMajorVersion = 4;
 ULONG NtMinorVersion = 0;
 ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(6, 0);
@@ -45,17 +58,19 @@ EXPORTED ULONG KiDmaIoCoherency = 0; /* RISC Architectures only */
 EXPORTED ULONG InitSafeBootMode = 0; /* KB83764 */
 #endif /* __GNUC__ */
 
-LOADER_MODULE KeLoaderModules[64];
+static LOADER_MODULE KeLoaderModules[64];
 static CHAR KeLoaderModuleStrings[64][256];
 static CHAR KeLoaderCommandLine[256];
-ADDRESS_RANGE KeMemoryMap[64];
-ULONG KeMemoryMapRangeCount;
-ULONG_PTR FirstKrnlPhysAddr;
-ULONG_PTR LastKrnlPhysAddr;
-ULONG_PTR LastKernelAddress;
+static ADDRESS_RANGE KeMemoryMap[64];
+static ULONG KeMemoryMapRangeCount;
+static ULONG_PTR FirstKrnlPhysAddr;
+static ULONG_PTR LastKrnlPhysAddr;
+static ULONG_PTR LastKernelAddress;
 volatile BOOLEAN Initialized = FALSE;
+extern ULONG MmCoreDumpType;
+extern CHAR KiTimerSystemAuditing;
 
-ULONG KeLargestCacheLine = 0x40; /* FIXME: Arch-specific */
+extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
 
 /* We allocate 4 pages, but we only use 3. The 4th is to guarantee page alignment */
 ULONG kernel_stack[4096];
@@ -67,59 +82,793 @@ ULONG init_stack_top;
 ULONG trap_stack;
 ULONG trap_stack_top;
 
-/* Cached modules from the loader block */
-PLOADER_MODULE CachedModules[MaximumCachedModuleType];
-
 /* FUNCTIONS ****************************************************************/
 
+static VOID INIT_FUNCTION
+InitSystemSharedUserPage (PCSZ ParameterLine)
+{
+   UNICODE_STRING ArcDeviceName;
+   UNICODE_STRING ArcName;
+   UNICODE_STRING BootPath;
+   UNICODE_STRING DriveDeviceName;
+   UNICODE_STRING DriveName;
+   WCHAR DriveNameBuffer[20];
+   PCHAR ParamBuffer;
+   PWCHAR ArcNameBuffer;
+   PCHAR p;
+   NTSTATUS Status;
+   ULONG Length;
+   OBJECT_ATTRIBUTES ObjectAttributes;
+   HANDLE Handle;
+   ULONG i;
+   BOOLEAN BootDriveFound;
+
+   /*
+    * NOTE:
+    *   The shared user page has been zeroed-out right after creation.
+    *   There is NO need to do this again.
+    */
+
+   Ki386SetProcessorFeatures();
+
+   SharedUserData->NtProductType = NtProductWinNt;
+   SharedUserData->ProductTypeIsValid = TRUE;
+   SharedUserData->NtMajorVersion = 5;
+   SharedUserData->NtMinorVersion = 0;
+
+   BootDriveFound = FALSE;
+
+   /*
+    * Retrieve the current dos system path
+    * (e.g.: C:\reactos) from the given arc path
+    * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
+    * Format: "<arc_name>\<path> [options...]"
+    */
+
+   /* create local parameter line copy */
+   ParamBuffer = ExAllocatePool (PagedPool, 256);
+   strcpy (ParamBuffer, (char *)ParameterLine);
+   DPRINT("%s\n", ParamBuffer);
+
+   /* cut options off */
+   p = strchr (ParamBuffer, ' ');
+   if (p)
+     {
+       *p = 0;
+     }
+   DPRINT("%s\n", ParamBuffer);
+
+   /* extract path */
+   p = strchr (ParamBuffer, '\\');
+   if (p)
+     {
+       DPRINT("Boot path: %s\n", p);
+       RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
+       *p = 0;
+     }
+   else
+     {
+       DPRINT("Boot path: %s\n", "\\");
+       RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
+     }
+   DPRINT("Arc name: %s\n", ParamBuffer);
+   
+   /* Only arc name left - build full arc name */
+   ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
+   swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
+   RtlInitUnicodeString (&ArcName, ArcNameBuffer);
+   DPRINT("Arc name: %wZ\n", &ArcName);
+
+   /* free ParamBuffer */
+   ExFreePool (ParamBuffer);
+
+   /* allocate arc device name string */
+   ArcDeviceName.Length = 0;
+   ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
+   ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
+
+   InitializeObjectAttributes (&ObjectAttributes,
+                              &ArcName,
+                              OBJ_OPENLINK,
+                              NULL,
+                              NULL);
+
+   Status = NtOpenSymbolicLinkObject (&Handle,
+                                     SYMBOLIC_LINK_ALL_ACCESS,
+                                     &ObjectAttributes);
+   RtlFreeUnicodeString (&ArcName);
+   if (!NT_SUCCESS(Status))
+     {
+       RtlFreeUnicodeString (&BootPath);
+       RtlFreeUnicodeString (&ArcDeviceName);
+       CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
+                Status);
+
+       KEBUGCHECK (0x0);
+     }
+
+   Status = NtQuerySymbolicLinkObject (Handle,
+                                      &ArcDeviceName,
+                                      &Length);
+   NtClose (Handle);
+   if (!NT_SUCCESS(Status))
+     {
+       RtlFreeUnicodeString (&BootPath);
+       RtlFreeUnicodeString (&ArcDeviceName);
+       CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
+                Status);
+
+       KEBUGCHECK (0x0);
+     }
+   DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
+
+
+   /* allocate device name string */
+   DriveDeviceName.Length = 0;
+   DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
+   DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
+
+   for (i = 0; i < 26; i++)
+     {
+       swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
+       RtlInitUnicodeString (&DriveName,
+                             DriveNameBuffer);
+
+       InitializeObjectAttributes (&ObjectAttributes,
+                                   &DriveName,
+                                   OBJ_OPENLINK,
+                                   NULL,
+                                   NULL);
+
+       Status = NtOpenSymbolicLinkObject (&Handle,
+                                          SYMBOLIC_LINK_ALL_ACCESS,
+                                          &ObjectAttributes);
+       if (!NT_SUCCESS(Status))
+         {
+            DPRINT("Failed to open link %wZ\n",
+                   &DriveName);
+            continue;
+         }
+
+       Status = NtQuerySymbolicLinkObject (Handle,
+                                           &DriveDeviceName,
+                                           &Length);
+       if (!NT_SUCCESS(Status))
+         {
+            DPRINT("Failed query open link %wZ\n",
+                   &DriveName);
+            continue;
+         }
+       DPRINT("Opened link: %wZ ==> %wZ\n",
+              &DriveName, &DriveDeviceName);
+
+       if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
+         {
+            DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
+            swprintf(SharedUserData->NtSystemRoot,
+                     L"%C:%wZ", 'A' + i, &BootPath);
+            
+            BootDriveFound = TRUE;
+         }
+
+       NtClose (Handle);
+     }
+
+   RtlFreeUnicodeString (&BootPath);
+   RtlFreeUnicodeString (&DriveDeviceName);
+   RtlFreeUnicodeString (&ArcDeviceName);
+
+   if (BootDriveFound == FALSE)
+     {
+       DbgPrint("No system drive found!\n");
+       KEBUGCHECK (NO_BOOT_DEVICE);
+     }
+}
+
+VOID INIT_FUNCTION
+ExpInitializeExecutive(VOID)
+{
+  LARGE_INTEGER Timeout;
+  HANDLE ProcessHandle;
+  HANDLE ThreadHandle;
+  ULONG i;
+  ULONG start;
+  ULONG length;
+  PCHAR name;
+  CHAR str[50];
+  NTSTATUS Status;
+  BOOLEAN SetupBoot;
+  PCHAR p1, p2;
+  ULONG MaxMem;
+  BOOLEAN NoGuiBoot = FALSE;
+  UNICODE_STRING Name;
+  HANDLE InitDoneEventHandle;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+
+  /*
+   * Fail at runtime if someone has changed various structures without
+   * updating the offsets used for the assembler code.
+   */
+  ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
+  ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
+  ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
+  ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
+  ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
+  ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
+  ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
+  ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
+  ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
+  ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == 
+        KPROCESS_DIRECTORY_TABLE_BASE);
+  ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
+  ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
+  ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
+  ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
+  ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
+  ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
+
+  ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
+  ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
+  ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);  
+  ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
+
+  ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
+  ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
+  ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
+
+  ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
+
+  LdrInit1();
+
+  KeLowerIrql(DISPATCH_LEVEL);
+  
+  NtEarlyInitVdm();
+
+  p1 = (PCHAR)KeLoaderBlock.CommandLine;
+
+  MaxMem = 0;
+  while(*p1 && (p2 = strchr(p1, '/')))
+  {
+     p2++;
+     if (!_strnicmp(p2, "MAXMEM", 6))
+     {
+        p2 += 6;
+        while (isspace(*p2)) p2++;
+       if (*p2 == '=')
+       {
+          p2++;
+          while(isspace(*p2)) p2++;
+          if (isdigit(*p2))
+          {
+             while (isdigit(*p2))
+             {
+                MaxMem = MaxMem * 10 + *p2 - '0';
+                p2++;
+             }
+             break;
+          }
+       }
+     }
+     else if (!_strnicmp(p2, "NOGUIBOOT", 9))
+     {
+       p2 += 9;
+       NoGuiBoot = TRUE;
+     }
+     else if (!_strnicmp(p2, "CRASHDUMP", 9))
+     {
+       p2 += 9;
+       if (*p2 == ':')
+        {
+          p2++;
+          if (!_strnicmp(p2, "FULL", 4))
+            {
+              MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
+            }
+          else
+            {
+              MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
+            }
+        }
+     }
+     p1 = p2;
+  }
+
+  MmInit1(FirstKrnlPhysAddr,
+         LastKrnlPhysAddr,
+         LastKernelAddress,
+         (PADDRESS_RANGE)&KeMemoryMap,
+         KeMemoryMapRangeCount,
+         MaxMem > 8 ? MaxMem : 4096);
+
+  /* Import ANSI code page table */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
+
+      if (!_stricmp (name, "ansi.nls"))
+       {
+         RtlpImportAnsiCodePage((PUSHORT)start, length);
+       }
+    }
+
+  /* Import OEM code page table */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
+
+      if (!_stricmp (name, "oem.nls"))
+       {
+         RtlpImportOemCodePage((PUSHORT)start, length);
+       }
+    }
+
+  /* Import Unicode casemap table */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
+
+      if (!_stricmp (name, "casemap.nls"))
+       {
+         RtlpImportUnicodeCasemap((PUSHORT)start, length);
+       }
+    }
+
+  /* Create initial NLS tables */
+  RtlpCreateInitialNlsTables();
+
+  /*
+   * Initialize the kernel debugger
+   */
+  KdInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  KeInit2();
+  
+#if 0
+  if (KeMemoryMapRangeCount > 0)
+    {
+      DPRINT1("MemoryMap:\n");
+      for (i = 0; i < KeMemoryMapRangeCount; i++)
+        {
+          switch(KeMemoryMap[i].Type)
+            {
+              case 1:
+               strcpy(str, "(usable)");
+               break;
+             case 2:
+               strcpy(str, "(reserved)");
+               break;
+             case 3:
+               strcpy(str, "(ACPI data)");
+               break;
+             case 4:
+               strcpy(str, "(ACPI NVS)");
+               break;
+             default:
+               sprintf(str, "type %lu", KeMemoryMap[i].Type);
+            }
+          DPRINT1("%08x - %08x %s\n", KeMemoryMap[i].BaseAddrLow, KeMemoryMap[i].BaseAddrLow + KeMemoryMap[i].LengthLow, str);
+       }
+    }
+#endif
+
+  KeLowerIrql(PASSIVE_LEVEL);
+
+  if (!SeInit1())
+    KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
+
+  ObInit();
+  ExInit2();
+  MmInit2();
+
+  if (!SeInit2())
+    KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
+
+  KeNumberProcessors = 1;
+
+  PiInitProcessManager();
+
+  if (KdPollBreakIn ())
+    {
+      DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
+    }
+
+  /* Initialize all processors */
+  while (!HalAllProcessorsStarted())
+    {
+      PVOID ProcessorStack;
+
+      KePrepareForApplicationProcessorInit(KeNumberProcessors);
+      PsPrepareForApplicationProcessorInit(KeNumberProcessors);
+
+      /* Allocate a stack for use when booting the processor */
+      ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
+
+      HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
+      KeNumberProcessors++;
+    }
+
+  /*
+   * Initialize various critical subsystems
+   */
+  HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  ExInit3();
+  KdInit1();
+  IoInit();
+  PoInit();
+  CmInitializeRegistry();
+  MmInit3();
+  CcInit();
+  KdInit2();
+  FsRtlpInitFileLockingImplementation();
+
+  /* Report all resources used by hal */
+  HalReportResourceUsage();  
+
+  /*
+   * Clear the screen to blue
+   */
+  HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  /*
+   * Display version number and copyright/warranty message
+   */
+  HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
+                  KERNEL_VERSION_BUILD_STR")\n");
+  HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
+  HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
+                  "Public License, and you\n");
+  HalDisplayString("are welcome to change it and/or distribute copies of it "
+                  "under certain\n"); 
+  HalDisplayString("conditions. There is absolutely no warranty for "
+                  "ReactOS.\n\n");
+
+  if (KeNumberProcessors > 1)
+    {
+      sprintf(str,
+             "Found %d system processors. [%lu MB Memory]\n",
+             KeNumberProcessors,
+             (KeLoaderBlock.MemHigher + 1088)/ 1024);
+    }
+  else
+    {
+      sprintf(str,
+             "Found 1 system processor. [%lu MB Memory]\n",
+             (KeLoaderBlock.MemHigher + 1088)/ 1024);
+    }
+  HalDisplayString(str);
+
+  KdInit3();
+
+
+  /* Create the NLS section */
+  RtlpCreateNlsSection();
+
+  /*
+   * Initalize services loaded at boot time
+   */
+  DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
+  for (i=0; i < KeLoaderBlock.ModsCount; i++)
+    {
+      CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
+       KeLoaderModules[i].String,
+       KeLoaderModules[i].ModStart,
+       KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
+    }
+
+  /* Pass 1: import system hive registry chunk */
+  SetupBoot = TRUE;
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
+
+      if (!_stricmp (name, "system") ||
+         !_stricmp (name, "system.hiv"))
+       {
+         CPRINT("Process system hive registry chunk at %08lx\n", start);
+         SetupBoot = FALSE;
+         CmImportSystemHive((PCHAR)start, length);
+       }
+    }
+
+  /* Pass 2: import hardware hive registry chunk */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+      name = (PCHAR)KeLoaderModules[i].String;
+      if (!_stricmp (name, "hardware") ||
+         !_stricmp (name, "hardware.hiv"))
+       {
+         CPRINT("Process hardware hive registry chunk at %08lx\n", start);
+         CmImportHardwareHive((PCHAR)start, length);
+       }
+    }
+
+  /* Create dummy keys if no hardware hive was found */
+  CmImportHardwareHive (NULL, 0);
+
+  /* Initialize volatile registry settings */
+  if (SetupBoot == FALSE)
+    {
+      CmInit2((PCHAR)KeLoaderBlock.CommandLine);
+    }
+
+  /* Initialize the time zone information from the registry */
+  ExpInitTimeZoneInfo();
+
+  /*
+   * Enter the kernel debugger before starting up the boot drivers
+   */
+#ifdef KDBG
+  KdbEnter();
+#endif /* KDBG */
+
+  IoCreateDriverList();
+
+  IoInit2();
+
+  /* Initialize Callbacks before drivers */
+  ExpInitializeCallbacks();
+
+  /* Start boot logging */
+  IopInitBootLog();
+  p1 = (PCHAR)KeLoaderBlock.CommandLine;
+  while (*p1 && (p2 = strchr(p1, '/')))
+  {
+    p2++;
+    if (!_strnicmp(p2, "BOOTLOG", 7))
+    {
+      p2 += 7;
+      IopStartBootLog();
+    }
+
+    p1 = p2;
+  }
+
+  /*
+   * Load boot start drivers
+   */
+  IopInitializeBootDrivers();
+
+  /* Display the boot screen image if not disabled */
+  if (!NoGuiBoot)
+    {
+      InbvEnableBootDriver(TRUE);
+    }
+
+  /* Create ARC names for boot devices */
+  IoCreateArcNames();
+
+  /* Create the SystemRoot symbolic link */
+  CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
+  DPRINT1("MmSystemRangeStart: 0x%x PageDir: 0x%x\n", MmSystemRangeStart, KeLoaderBlock.PageDirectoryStart);
+  Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
+  if (!NT_SUCCESS(Status))
+  {
+    DbgPrint ( "IoCreateSystemRootLink FAILED: (0x%x) - ", Status );
+    DbgPrintErrorMessage ( Status );
+    KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
+  }
+
+#if defined(KDBG) || defined(DBG)
+  KdbInitProfiling2();
+#endif /* KDBG */
+
+  /* On the assumption that we can now access disks start up the debug
+   * logger thread */
+  if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_BOOTLOG))
+    {
+      DebugLogInit2();
+    }
+
+  PiInitDefaultLocale();
+
+  /*
+   * Load services for devices found by PnP manager
+   */
+  IopInitializePnpServices(IopRootDeviceNode, FALSE);
+
+  /*
+   * Load system start drivers
+   */
+  IopInitializeSystemDrivers();
+
+  IoDestroyDriverList();
+
+  /* Stop boot logging */
+  IopStopBootLog();
+
+  /*
+   * Assign drive letters
+   */
+  IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
+                       NULL,
+                       NULL,
+                       NULL);
+
+  /*
+   * Initialize shared user page:
+   *  - set dos system path, dos device map, etc.
+   */
+  InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
+
+  /* Create 'ReactOSInitDone' event */
+  RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
+  InitializeObjectAttributes(&ObjectAttributes,
+    &Name,
+    0,
+    NULL,
+    NULL);
+  Status = ZwCreateEvent(&InitDoneEventHandle,
+    EVENT_ALL_ACCESS,
+    &ObjectAttributes,
+    SynchronizationEvent,
+    FALSE);             /* Not signalled */
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
+      InitDoneEventHandle = INVALID_HANDLE_VALUE;
+    }
+
+  /*
+   *  Launch initial process
+   */
+  Status = LdrLoadInitialProcess(&ProcessHandle,
+                                &ThreadHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+  if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
+    {
+      HANDLE Handles[2]; /* Init event, Initial process */
+
+      Handles[0] = InitDoneEventHandle;
+      Handles[1] = ProcessHandle;
+
+      /* Wait for the system to be initialized */
+      Timeout.QuadPart = (LONGLONG)-1200000000;  /* 120 second timeout */
+      Status = ZwWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
+        Handles,
+        WaitAny,
+        FALSE,    /* Non-alertable */
+        &Timeout);
+      if (!NT_SUCCESS(Status))
+        {
+          DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
+        }
+      else if (Status == STATUS_TIMEOUT)
+        {
+          DPRINT1("WARNING: System not initialized after 120 seconds.\n");
+        }
+      else if (Status == STATUS_WAIT_0 + 1)
+        {
+          /*
+           * Crash the system if the initial process was terminated.
+           */
+          KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
+        }
+
+      if (!NoGuiBoot)
+        {
+          InbvEnableBootDriver(FALSE);
+        }
+
+      ZwSetEvent(InitDoneEventHandle, NULL);
+
+      ZwClose(InitDoneEventHandle);
+    }
+  else
+    {
+      /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
+      if (!NoGuiBoot)
+        {
+          InbvEnableBootDriver(FALSE);
+        }
+
+      /*
+       * Crash the system if the initial process terminates within 5 seconds.
+       */
+      Timeout.QuadPart = (LONGLONG)-50000000;  /* 5 second timeout */
+      Status = ZwWaitForSingleObject(ProcessHandle,
+                                FALSE,
+                                &Timeout);
+      if (Status != STATUS_TIMEOUT)
+        {
+          KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
+        }
+    }
 /*
- * @implemented
+ * Tell ke/timer.c it's okay to run.
  */
-ULONG
-STDCALL
-KeGetRecommendedSharedDataAlignment(VOID)
-{
-    return KeLargestCacheLine;
+
+  KiTimerSystemAuditing = 1;
+
+  ZwClose(ThreadHandle);
+  ZwClose(ProcessHandle);
 }
 
-VOID
-__attribute((noinline))
+VOID __attribute((noinline))
 KiSystemStartup(BOOLEAN BootProcessor)
 {
-    DPRINT("KiSystemStartup(%d)\n", BootProcessor);
-    
-    /* Initialize the Application Processor */
-    if (!BootProcessor) KeApplicationProcessorInit();
-    
-    /* Initialize the Processor with HAL */
-    HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
-    /* Load the Kernel if this is the Boot CPU, else inialize the App CPU only */
-    if (BootProcessor) {
-        
-        /* Initialize the Kernel Executive */
-        ExpInitializeExecutive();
-        
-        /* Free Initial Memory */
-        MiFreeInitMemory();
-        
-        /* Never returns */
-        PsTerminateSystemThread(STATUS_SUCCESS);
-    } else {
-        
-        /* Do application processor initialization */
-        PsApplicationProcessorInit();
-        
-        /* Lower IRQL and go to Idle Thread */
-        KeLowerIrql(PASSIVE_LEVEL);
-        PsIdleThreadMain(NULL);
-    }
-    
-    /* Bug Check and loop forever if anything failed */
-    KEBUGCHECK(0);
-    for(;;);
+  DPRINT1("KiSystemStartup(%d)\n", BootProcessor);
+  if (BootProcessor)
+  {
+  }
+  else
+  {
+     KeApplicationProcessorInit();
+  }
+
+  HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  if (BootProcessor)
+  {
+     ExpInitializeExecutive();
+     MiFreeInitMemory();
+     /* Never returns */
+     PsTerminateSystemThread(STATUS_SUCCESS);
+  }
+  else
+  {
+     /* Do application processor initialization */
+     PsApplicationProcessorInit();
+     KeLowerIrql(PASSIVE_LEVEL);
+     PsIdleThreadMain(NULL);
+  }
+  KEBUGCHECK(0);
+  for(;;);
 }
 
+VOID INIT_FUNCTION
+_main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
 /*
  * FUNCTION: Called by the boot loader to start the kernel
  * ARGUMENTS:
@@ -128,158 +877,172 @@ KiSystemStartup(BOOLEAN BootProcessor)
  * NOTE: The boot parameters are stored in low memory which will become
  * invalid after the memory managment is initialized so we make a local copy.
  */
-VOID 
-INIT_FUNCTION
-_main(ULONG MultiBootMagic, 
-      PLOADER_PARAMETER_BLOCK _LoaderBlock)
 {
-    ULONG i;
-    ULONG size;
-    ULONG HalBase;
-    ULONG DriverBase;
-    ULONG DriverSize;
-    PIMAGE_NT_HEADERS NtHeader;
-    PIMAGE_OPTIONAL_HEADER OptHead;
-    CHAR* s;
-
-    /* Set up the Stacks (Initial Kernel Stack and Double Trap Stack)*/
-    trap_stack = PAGE_ROUND_UP(&double_trap_stack);
-    trap_stack_top = trap_stack + 3 * PAGE_SIZE;
-    init_stack = PAGE_ROUND_UP(&kernel_stack);
-    init_stack_top = init_stack + 3 * PAGE_SIZE;
+  ULONG i;
+  ULONG size;
+  ULONG HalBase;
+  ULONG DriverBase;
+  ULONG DriverSize;
+
+  /* Set up the Stacks */
+  trap_stack = PAGE_ROUND_UP(&double_trap_stack);
+  trap_stack_top = trap_stack + 3 * PAGE_SIZE;
+  init_stack = PAGE_ROUND_UP(&kernel_stack);
+  init_stack_top = init_stack + 3 * PAGE_SIZE;
             
-    /* Copy the Loader Block Data locally since Low-Memory will be wiped */
-    memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
-    memcpy(&KeLoaderModules[1], 
-           (PVOID)KeLoaderBlock.ModsAddr,
-           sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
-    KeLoaderBlock.ModsCount++;
-    KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
-
-    /* Save the Base Address */
-    MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
+  /*
+   * Copy the parameters to a local buffer because lowmem will go away
+   */
+  memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+  memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
+        sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
+  KeLoaderBlock.ModsCount++;
+  KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
+
+  /* Save the Base Address */
+  MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
   
-    /* Set the Command Line */
-    strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine);
-    KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
+  /*
+   * Convert a path specification in the grub format to one understood by the
+   * rest of the kernel.
+   */
+  if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
+    {
+      ULONG DiskNumber = 0, PartNumber = 0;
+      PCH p;
+      CHAR Temp[256];
+      PCH options;
+      PCH s1;
+
+      if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
+         ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
+       {
+         DiskNumber = ((PCHAR)_LoaderBlock->CommandLine)[3] - '0';
+         PartNumber = ((PCHAR)_LoaderBlock->CommandLine)[5] - '0';
+       }
+      strcpy(Temp, &((PCHAR)_LoaderBlock->CommandLine)[7]);
+      if ((options = strchr(Temp, ' ')) != NULL)
+       {
+         *options = 0;
+         options++;
+       }
+      else
+       {
+         options = "";
+       }
+      if ((s1 = strrchr(Temp, '/')) != NULL)
+       {
+         *s1 = 0;
+         if ((s1 = strrchr(Temp, '/')) != NULL)
+           {
+             *s1 = 0;
+           }
+       }
+      sprintf(KeLoaderCommandLine, 
+             "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
+             DiskNumber, PartNumber + 1, Temp, options);
+
+      p = KeLoaderCommandLine;
+      while (*p != 0 && *p != ' ')
+       {
+         if ((*p) == '/')
+           {
+             (*p) = '\\';
+           }
+         p++;
+       }
+      DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
+    }
+  else
+    {
+      strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine);
+    }
+  KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
   
-    /* Write the first Module (the Kernel) */
-    strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
-    KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
-    KeLoaderModules[0].ModStart = KERNEL_BASE;
-    
-    /* Read PE Data */
-    NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
-    OptHead = &NtHeader->OptionalHeader;
-    
-    /* Set Kernel Ending */
+  strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
+  KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
+  KeLoaderModules[0].ModStart = KERNEL_BASE;
+  /* Take this value from the PE... */
+    PIMAGE_NT_HEADERS      NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
+    PIMAGE_OPTIONAL_HEADER OptHead  = &NtHeader->OptionalHeader;
     KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
-    
-    /* Create a block for each module */
-    for (i = 1; i < KeLoaderBlock.ModsCount; i++) {      
-        
-        /* Check if we have to copy the path or not */
-        if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0) {
-            
-            strcpy(KeLoaderModuleStrings[i], s + 1);
-            
-        } else {
-            
-            strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
-        }
-    
-        /* Substract the base Address in Physical Memory */    
-        KeLoaderModules[i].ModStart -= 0x200000;
-        
-        /* Add the Kernel Base Address in Virtual Memory */
-        KeLoaderModules[i].ModStart += KERNEL_BASE;
-        
-        /* Substract the base Address in Physical Memory */    
-        KeLoaderModules[i].ModEnd -= 0x200000;
-        
-        /* Add the Kernel Base Address in Virtual Memory */
-        KeLoaderModules[i].ModEnd += KERNEL_BASE;
-        
-        /* Select the proper String */
-        KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {      
+      CHAR* s;
+      if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
+       {
+         strcpy(KeLoaderModuleStrings[i], s + 1);
+       }
+      else
+       {
+         strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
+       }
+      KeLoaderModules[i].ModStart -= 0x200000;
+      KeLoaderModules[i].ModStart += KERNEL_BASE;
+      KeLoaderModules[i].ModEnd -= 0x200000;
+      KeLoaderModules[i].ModEnd += KERNEL_BASE;
+      KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
     }
 
-    /* Choose last module address as the final kernel address */
-    LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
-
-    /* Low level architecture specific initialization */
-    KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
-    
-    /* Select the HAL Base */
-    HalBase = KeLoaderModules[1].ModStart;
-    
-    /* Choose Driver Base */
-    DriverBase = LastKernelAddress;
-    LdrHalBase = (ULONG_PTR)DriverBase;
-    
-    /* Initialize Module Management */
-    LdrInitModuleManagement();
-    
-    /* Load HAL.DLL with the PE Loader */
-    LdrSafePEProcessModule((PVOID)HalBase, 
-                            (PVOID)DriverBase, 
-                            (PVOID)KERNEL_BASE, 
-                            &DriverSize);
-    
-    /* Increase the last kernel address with the size of HAL */
-    LastKernelAddress += PAGE_ROUND_UP(DriverSize);
-
-    /* Load the Kernel with the PE Loader */
-    LdrSafePEProcessModule((PVOID)KERNEL_BASE, 
-                           (PVOID)KERNEL_BASE, 
-                           (PVOID)DriverBase,
-                           &DriverSize);
-
-    /* Now select the final beginning and ending Kernel Addresses */
-    FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
-    LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
-
-    KeMemoryMapRangeCount = 0;
-    if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO) {
-        
-        /* We have a memory map from the nice BIOS */
-        size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
-        i = 0;
-      
-        /* Map it until we run out of size */
-        while (i < KeLoaderBlock.MmapLength) {
-            
-            /* Copy into the Kernel Memory Map */
-            memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
-                    (PVOID)(KeLoaderBlock.MmapAddr + i),
-                    sizeof(ADDRESS_RANGE));
-            
-            /* Increase Memory Map Count */
-            KeMemoryMapRangeCount++;
-          
-            /* Increase Size */
-            i += size;
+  LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
+
+  /* Low level architecture specific initialization */
+  KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
+
+  HalBase = KeLoaderModules[1].ModStart;
+  DriverBase = LastKernelAddress;
+  LdrHalBase = (ULONG_PTR)DriverBase;
+
+  LdrInitModuleManagement();
+
+  /*
+   * Process hal.dll
+   */
+  LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)KERNEL_BASE, &DriverSize);
+
+  LastKernelAddress += PAGE_ROUND_UP(DriverSize);
+
+  /*
+   * Process ntoskrnl.exe
+   */
+  LdrSafePEProcessModule((PVOID)KERNEL_BASE, (PVOID)KERNEL_BASE, (PVOID)DriverBase, &DriverSize);
+
+  /* Now our imports from HAL are fixed. This is the first */
+  /* time in the boot process that we can use HAL          */
+
+  FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
+  LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
+
+  KeMemoryMapRangeCount = 0;
+  if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
+    {
+      /* We have a memory map from the nice BIOS */
+      size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
+      i = 0;
+      while (i < KeLoaderBlock.MmapLength)
+        {
+          memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
+            (PVOID)(KeLoaderBlock.MmapAddr + i),
+                 sizeof(ADDRESS_RANGE));
+          KeMemoryMapRangeCount++;
+          i += size;
         }
-        
-        /* Save data */
-        KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
-        KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
-        
-    } else {
-        
-        /* Nothing from BIOS */
-        KeLoaderBlock.MmapLength = 0;
-        KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
+      KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
+      KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
     }
-    
-    /* Initialize the Debugger */
-    KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-    
-    /* Initialize HAL */
-    HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
-    /* Do general System Startup */
-    KiSystemStartup(1);
+  else
+    {
+      KeLoaderBlock.MmapLength = 0;
+      KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
+    }
+
+  KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+  HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  DPRINT1("_main (%x, %x)\n", MultiBootMagic, _LoaderBlock);
+
+
+  KiSystemStartup(1);
 }
 
 /* EOF */
index 992aa31..3532781 100644 (file)
@@ -3,19 +3,14 @@
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/mutex.c
- * PURPOSE:         Implements Mutexes and Mutants (that silly davec...)
+ * PURPOSE:         Implements mutex
  * 
- * PROGRAMMERS:     
- *                  Alex Ionescu (alex@relsoft.net) - Reorganized/commented some of the code.
- *                                                    Simplified some functions, fixed some return values and
- *                                                    corrected some minor bugs, added debug output.
- *                  David Welch (welch@mcmail.com)
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
-#define NDEBUG
 #include <internal/debug.h>
 
 /* FUNCTIONS *****************************************************************/
 /*
  * @implemented
  */
-VOID 
-STDCALL
-KeInitializeMutant(IN PKMUTANT Mutant,
-                   IN BOOLEAN InitialOwner)
+VOID STDCALL
+KeInitializeMutex(IN PKMUTEX Mutex,
+                 IN ULONG Level)
 {
-    ULONG Signaled = TRUE;
-    PKTHREAD CurrentThread = NULL;
-    KIRQL OldIrql;
-    
-    DPRINT("KeInitializeMutant: %x\n", Mutant);
-    
-    /* Check if we have an initial owner */
-    if (InitialOwner == TRUE) {
-    
-        /* In this case, the object is not signaled */
-        Signaled = FALSE;
-        
-        /* We also need to associate a thread */
-        CurrentThread = KeGetCurrentThread();
-        
-        /* We're about to touch the Thread, so lock the Dispatcher */
-        OldIrql = KeAcquireDispatcherDatabaseLock();
-        
-        /* And insert it into its list */
-        InsertTailList(&CurrentThread->MutantListHead, &Mutant->MutantListEntry);
-        
-        /* Release Dispatcher Lock */
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        DPRINT("Mutant with Initial Owner\n");
-    
-    } else {
-        
-        /* In this case, we don't have an owner yet */
-        Mutant->OwnerThread = NULL;
-    }
-    
-    /* Now we set up the Dispatcher Header */
-    KeInitializeDispatcherHeader(&Mutant->Header,
-                                 MutantObject,
-                                 sizeof(KMUTANT) / sizeof(ULONG),
-                                 Signaled);
-
-    /* Initialize the default data */
-    Mutant->OwnerThread = CurrentThread;
-    Mutant->Abandoned = FALSE;
-    Mutant->ApcDisable = 0;
+  KeInitializeDispatcherHeader(&Mutex->Header,
+                              InternalMutexType,
+                              sizeof(KMUTEX) / sizeof(ULONG),
+                              1);
+  Mutex->MutantListEntry.Flink = NULL;
+  Mutex->MutantListEntry.Blink = NULL;
+  Mutex->OwnerThread = NULL;
+  Mutex->Abandoned = FALSE;
+  Mutex->ApcDisable = 1;
 }
 
 /*
  * @implemented
  */
-VOID 
-STDCALL
-KeInitializeMutex(IN PKMUTEX Mutex,
-                  IN ULONG Level)
+LONG STDCALL
+KeReadStateMutex(IN PKMUTEX Mutex)
 {
-    DPRINT("KeInitializeMutex: %x\n", Mutex);
-        
-        
-    /* Set up the Dispatcher Header */
-    KeInitializeDispatcherHeader(&Mutex->Header,
-                                 MutantObject,
-                                 sizeof(KMUTEX) / sizeof(ULONG),
-                                 1);
-  
-    /* Initialize the default data */
-    Mutex->OwnerThread = NULL;
-    Mutex->Abandoned = FALSE;
-    Mutex->ApcDisable = 1;
-    InitializeListHead(&Mutex->Header.WaitListHead);
+  return(Mutex->Header.SignalState);
 }
 
 /*
  * @implemented
  */
-LONG 
-STDCALL
-KeReadStateMutant(IN PKMUTANT Mutant)
+LONG STDCALL
+KeReleaseMutex(IN PKMUTEX Mutex,
+              IN BOOLEAN Wait)
 {
-    /* Return the Signal State */
-    return(Mutant->Header.SignalState);
+  KIRQL OldIrql;
+
+  OldIrql = KeAcquireDispatcherDatabaseLock();
+  if (Mutex->OwnerThread != KeGetCurrentThread())
+    {
+      DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutex %p\n", Mutex);
+      KEBUGCHECK(THREAD_NOT_MUTEX_OWNER);
+    }
+  Mutex->Header.SignalState++;
+  ASSERT(Mutex->Header.SignalState <= 1);
+  if (Mutex->Header.SignalState == 1)
+    {
+      Mutex->OwnerThread = NULL;
+      if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
+       RemoveEntryList(&Mutex->MutantListEntry);
+      KiDispatcherObjectWake(&Mutex->Header, IO_NO_INCREMENT);
+    }
+
+  if (Wait == FALSE)
+    {
+      KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+  else
+    {
+      KTHREAD *Thread = KeGetCurrentThread();
+      Thread->WaitNext = TRUE;
+      Thread->WaitIrql = OldIrql;
+    }
+
+  return(0);
 }
 
 /*
  * @implemented
  */
-LONG
-STDCALL
-KeReadStateMutex(IN PKMUTEX Mutex)
+NTSTATUS STDCALL
+KeWaitForMutexObject(IN PKMUTEX Mutex,
+                    IN KWAIT_REASON WaitReason,
+                    IN KPROCESSOR_MODE WaitMode,
+                    IN BOOLEAN Alertable,
+                    IN PLARGE_INTEGER Timeout)
 {
-    /* Return the Signal State */
-    return(Mutex->Header.SignalState);
+  return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout));
 }
 
+
 /*
  * @implemented
  */
-LONG 
-STDCALL
-KeReleaseMutant(IN PKMUTANT Mutant,
-                IN KPRIORITY Increment,
-                IN BOOLEAN Abandon,
-                IN BOOLEAN Wait)
+VOID STDCALL
+KeInitializeMutant(IN PKMUTANT Mutant,
+                  IN BOOLEAN InitialOwner)
 {
-    KIRQL OldIrql;
-    LONG PreviousState;
-    PKTHREAD CurrentThread = KeGetCurrentThread();
-    
-    DPRINT("KeReleaseMutant: %x\n", Mutant);
-
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Save the Previous State */
-    PreviousState = Mutant->Header.SignalState;
-    
-    /* Check if it is to be abandonned */
-    if (Abandon == FALSE) {
-
-        /* Make sure that the Owner Thread is the current Thread */
-        if (Mutant->OwnerThread != CurrentThread) {
-            
-            DPRINT1("Trying to touch a Mutant that the caller doesn't own!\n");
-            ExRaiseStatus(STATUS_MUTANT_NOT_OWNED);
-        }
-
-        /* If the thread owns it, then increase the signal state */
-        Mutant->Header.SignalState++;
-    
-    } else  {
-        
-        /* It's going to be abandonned */
-        DPRINT("Abandonning the Mutant\n");
-        Mutant->Header.SignalState = 1;
-        Mutant->Abandoned = TRUE;
-    }
-    
-    /* Check if the signal state is only single */
-    if (Mutant->Header.SignalState == 1) {
-        
-        if (PreviousState <= 0) {
-        
-            DPRINT("Removing Mutant\n");
-            RemoveEntryList(&Mutant->MutantListEntry);
-        }
-        
-        /* Remove the Owning Thread and wake it */
-        Mutant->OwnerThread = NULL;
-        
-        /* Check if the Wait List isn't empty */
-        DPRINT("Checking whether to wake the Mutant\n");
-        if (!IsListEmpty(&Mutant->Header.WaitListHead)) {
-            
-            /* Wake the Mutant */
-            DPRINT("Waking the Mutant\n");
-            KiWaitTest(&Mutant->Header, Increment);
-        }
+  if (InitialOwner == TRUE)
+    {
+      KeInitializeDispatcherHeader(&Mutant->Header,
+                                  InternalMutexType,
+                                  sizeof(KMUTANT) / sizeof(ULONG),
+                                  0);
+      InsertTailList(&KeGetCurrentThread()->MutantListHead,
+                    &Mutant->MutantListEntry);
+      Mutant->OwnerThread = KeGetCurrentThread();
     }
-
-    /* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
-    if (Wait == FALSE) {
-        
-        /* Release the Lock */
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-    
-    } else {
-        
-        /* Set a wait */
-        CurrentThread->WaitNext = TRUE;
-        CurrentThread->WaitIrql = OldIrql;
+  else
+    {
+      KeInitializeDispatcherHeader(&Mutant->Header,
+                                  InternalMutexType,
+                                  sizeof(KMUTANT) / sizeof(ULONG),
+                                  1);
+      Mutant->MutantListEntry.Flink = NULL;
+      Mutant->MutantListEntry.Blink = NULL;
+      Mutant->OwnerThread = NULL;
     }
-
-    /* Return the previous state */
-    return PreviousState;
+  Mutant->Abandoned = FALSE;
+  Mutant->ApcDisable = 0;
 }
 
 /*
  * @implemented
  */
-LONG 
-STDCALL
-KeReleaseMutex(IN PKMUTEX Mutex,
-               IN BOOLEAN Wait)
+LONG STDCALL
+KeReadStateMutant(IN PKMUTANT Mutant)
 {
-
-    /* There's no difference at this level between the two */
-    return KeReleaseMutant(Mutex, IO_NO_INCREMENT, FALSE, Wait);
+  return(Mutant->Header.SignalState);
 }
 
 /*
  * @implemented
  */
-NTSTATUS 
-STDCALL
-KeWaitForMutexObject(IN PKMUTEX Mutex,
-                     IN KWAIT_REASON WaitReason,
-                     IN KPROCESSOR_MODE WaitMode,
-                     IN BOOLEAN Alertable,
-                     IN PLARGE_INTEGER Timeout)
+LONG STDCALL
+KeReleaseMutant(IN PKMUTANT Mutant,
+               IN KPRIORITY Increment,
+               IN BOOLEAN Abandon,
+               IN BOOLEAN Wait)
 {
-    /* This is a simple macro. Export the function here though */
-    return KeWaitForSingleObject(Mutex,
-                                 WaitReason,
-                                 WaitMode,
-                                 Alertable,
-                                 Timeout);
+  KIRQL OldIrql;
+
+  OldIrql = KeAcquireDispatcherDatabaseLock();
+  if (Abandon == FALSE)
+    {
+      if (Mutant->OwnerThread != NULL && Mutant->OwnerThread != KeGetCurrentThread())
+       {
+         DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutant->OwnerThread %p CurrentThread %p\n",
+                  Mutant->OwnerThread,
+                  KeGetCurrentThread());
+         KEBUGCHECK(THREAD_NOT_MUTEX_OWNER);
+       }
+      Mutant->Header.SignalState++;
+      ASSERT(Mutant->Header.SignalState <= 1);
+    }
+  else
+    {
+      if (Mutant->OwnerThread != NULL)
+       {
+         Mutant->Header.SignalState = 1;
+         Mutant->Abandoned = TRUE;
+       }
+    }
+
+  if (Mutant->Header.SignalState == 1)
+    {
+      Mutant->OwnerThread = NULL;
+      if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
+       RemoveEntryList(&Mutant->MutantListEntry);
+      KiDispatcherObjectWake(&Mutant->Header, Increment);
+    }
+
+  if (Wait == FALSE)
+    {
+      KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+  else
+    {
+      KTHREAD *Thread = KeGetCurrentThread();
+      Thread->WaitNext = TRUE;
+      Thread->WaitIrql = OldIrql;
+    }
+
+  return(0);
 }
 
 /* EOF */
index 6a3d63f..9c47870 100644 (file)
 
 /* FUNCTIONS *****************************************************************/
 
-LONG STDCALL KiInsertQueue(IN PKQUEUE Queue, IN PLIST_ENTRY Entry, BOOLEAN Head);
-              
+
 /*
  * @implemented
  */
-VOID 
-STDCALL
+VOID STDCALL
 KeInitializeQueue(IN PKQUEUE Queue,
-                  IN ULONG Count OPTIONAL)
+                 IN ULONG Count OPTIONAL)
 {
-    DPRINT("KeInitializeQueue %x\n", Queue);
-    
-    /* Initialize the Header */
-    KeInitializeDispatcherHeader(&Queue->Header,
-                                 QueueObject,
-                                 sizeof(KQUEUE)/sizeof(ULONG),
-                                 0);
-    
-    /* Initialize the Lists */
-    InitializeListHead(&Queue->EntryListHead);
-    InitializeListHead(&Queue->ThreadListHead);
-    
-    /* Set the Current and Maximum Count */
-    Queue->CurrentCount = 0;
-    Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
+  KeInitializeDispatcherHeader(&Queue->Header,
+                              InternalQueueType,
+                              sizeof(KQUEUE)/sizeof(ULONG),
+                              0);
+  InitializeListHead(&Queue->EntryListHead);
+  InitializeListHead(&Queue->ThreadListHead);
+  Queue->CurrentCount = 0;
+  Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
 }
 
+
 /*
  * @implemented
+ *
+ * Returns number of entries in the queue
  */
-LONG
-STDCALL
-KeInsertHeadQueue(IN PKQUEUE Queue,
-                  IN PLIST_ENTRY Entry)
+LONG STDCALL
+KeReadStateQueue(IN PKQUEUE Queue)
+{
+  return(Queue->Header.SignalState);
+}
+
+/*
+ * Returns the previous number of entries in the queue
+ */
+LONG STDCALL
+KiInsertQueue(
+   IN PKQUEUE Queue,
+   IN PLIST_ENTRY Entry,
+   BOOLEAN Head
+   )
 {
-    LONG PreviousState;
-    KIRQL OldIrql;
-    
-    DPRINT("KeInsertHeadQueue %x\n", Queue);
-    
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Insert the Queue */
-    PreviousState = KiInsertQueue(Queue, Entry, TRUE);
-    
-    /* Release the Dispatcher Lock */
-    KeReleaseDispatcherDatabaseLock(OldIrql);
+   ULONG InitialState;
+  
+   DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
    
-    /* Return previous State */
-    return PreviousState;
+   InitialState = Queue->Header.SignalState;
+
+   if (Head)
+   {
+      InsertHeadList(&Queue->EntryListHead, Entry);
+   }
+   else
+   {
+      InsertTailList(&Queue->EntryListHead, Entry);
+   }
+   
+   //inc. num entries in queue
+   Queue->Header.SignalState++;
+   
+   /* Why the KeGetCurrentThread()->Queue != Queue?
+    * KiInsertQueue might be called from an APC for the current thread. 
+    * -Gunnar
+    */
+   if (Queue->CurrentCount < Queue->MaximumCount &&
+       !IsListEmpty(&Queue->Header.WaitListHead) &&
+       KeGetCurrentThread()->Queue != Queue)
+   {
+      KiDispatcherObjectWake(&Queue->Header, IO_NO_INCREMENT);
+   }
+
+   return InitialState;
 }
 
+
+
 /*
  * @implemented
  */
 LONG STDCALL
-KeInsertQueue(IN PKQUEUE Queue,
-              IN PLIST_ENTRY Entry)
+KeInsertHeadQueue(IN PKQUEUE Queue,
+                 IN PLIST_ENTRY Entry)
 {
-    LONG PreviousState;
-    KIRQL OldIrql;
-    
-    DPRINT("KeInsertQueue %x\n", Queue);
-    
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-    
-    /* Insert the Queue */
-    PreviousState = KiInsertQueue(Queue, Entry, FALSE);
-    
-    /* Release the Dispatcher Lock */
-    KeReleaseDispatcherDatabaseLock(OldIrql);
+   LONG Result;
+   KIRQL OldIrql;
+   
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   Result = KiInsertQueue(Queue,Entry,TRUE);
+   KeReleaseDispatcherDatabaseLock(OldIrql);
    
-    /* Return previous State */
-    return PreviousState;
+   return Result;
 }
 
+
 /*
  * @implemented
- *
- * Returns number of entries in the queue
  */
-LONG
-STDCALL
-KeReadStateQueue(IN PKQUEUE Queue)
+LONG STDCALL
+KeInsertQueue(IN PKQUEUE Queue,
+             IN PLIST_ENTRY Entry)
 {
-    /* Returns the Signal State */
-    return(Queue->Header.SignalState);
+   LONG Result;
+   KIRQL OldIrql;
+   
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   Result = KiInsertQueue(Queue,Entry,FALSE);
+   KeReleaseDispatcherDatabaseLock(OldIrql);
+   
+   return Result;
 }
 
+
 /*
  * @implemented
  */
-PLIST_ENTRY 
-STDCALL
+PLIST_ENTRY STDCALL
 KeRemoveQueue(IN PKQUEUE Queue,
-              IN KPROCESSOR_MODE WaitMode,
-              IN PLARGE_INTEGER Timeout OPTIONAL)
+             IN KPROCESSOR_MODE WaitMode,
+             IN PLARGE_INTEGER Timeout OPTIONAL)
 {
    
-    PLIST_ENTRY ListEntry;
-    NTSTATUS Status;
-    PKTHREAD Thread = KeGetCurrentThread();
-    KIRQL OldIrql;
-    PKQUEUE PreviousQueue;
-    PKWAIT_BLOCK WaitBlock;
-    PKWAIT_BLOCK TimerWaitBlock;
-    PKTIMER Timer;
-
-    DPRINT("KeRemoveQueue %x\n", Queue);
-    
-    /* Check if the Lock is already held */
-    if (Thread->WaitNext) {
-    
-        DPRINT("Lock is already held\n");
-    
-    } else {
-        
-        /* Lock the Dispatcher Database */
-        DPRINT("Lock not held, acquiring\n");
-        OldIrql = KeAcquireDispatcherDatabaseLock();
-        Thread->WaitIrql = OldIrql;
-    }
-
-    /* This is needed so that we can set the new queue right here, before additional processing */
-    PreviousQueue = Thread->Queue;
-    Thread->Queue = Queue;
-
-    /* Check if this is a different queue */    
-    if (Queue != PreviousQueue) {
-        
-        /*
-         * INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
-         * Queue->ThreadListHead when the thread registers with the queue and unlinked when
-         * the thread registers with a new queue. The Thread->Queue already tells us what
-         * queue the thread is registered with.
-         * -Gunnar
-         */
-        DPRINT("Different Queue\n");
-        if (PreviousQueue)  {
-          
-            /* Remove from this list */
-            DPRINT("Removing Old Queue\n");
-            RemoveEntryList(&Thread->QueueListEntry);
-            
-            /* Wake the queue */
-            DPRINT("Activating new thread\n");
-            KiWakeQueue(PreviousQueue);
+   PLIST_ENTRY ListEntry;
+   NTSTATUS Status;
+   PKTHREAD Thread = KeGetCurrentThread();
+   KIRQL OldIrql;
+
+   OldIrql = KeAcquireDispatcherDatabaseLock ();
+
+   if (Thread->Queue != Queue)
+   {
+      /*
+       * INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
+       * Queue->ThreadListHead when the thread registers with the queue and unlinked when
+       * the thread registers with a new queue. The Thread->Queue already tells us what
+       * queue the thread is registered with.
+       * -Gunnar
+       */
+
+      //unregister thread from previous queue (if any)
+      if (Thread->Queue)
+      {
+         RemoveEntryList(&Thread->QueueListEntry);
+         Thread->Queue->CurrentCount--;
+         
+         if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount && 
+             !IsListEmpty(&Thread->Queue->EntryListHead))
+         {
+            KiDispatcherObjectWake(&Thread->Queue->Header, 0);
+         }
       }
 
-        /* Insert in this new Queue */
-        DPRINT("Inserting new Queue!\n");
-        InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
+      // register thread with this queue
+      InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
+      Thread->Queue = Queue;
+   }
+   else /* if (Thread->Queue == Queue) */
+   {
+      //dec. num running threads
+      Queue->CurrentCount--;
+   }
+   
+   
+   
    
-    } else {
-      
-        /* Same queue, decrement waiting threads */
-        DPRINT("Same Queue!\n");
-        Queue->CurrentCount--;
-    }
-    
-    /* Loop until the queue is processed */
-    while (TRUE) {
-      
-        /* Get the Entry */
-        ListEntry = Queue->EntryListHead.Flink;
-        
-        /* Check if the counts are valid and if there is still a queued entry */
-        if ((Queue->CurrentCount < Queue->MaximumCount) && 
-             (ListEntry != &Queue->EntryListHead)) {
-          
-            /* Remove the Entry and Save it */
-            DPRINT("Removing Queue Entry. CurrentCount: %d, Maximum Count: %d\n", 
-                    Queue->CurrentCount, Queue->MaximumCount);
-            ListEntry = RemoveHeadList(&Queue->EntryListHead);
-            
-            /* Decrease the number of entries */
-            Queue->Header.SignalState--;
-            
-            /* Increase numbef of running threads */
-            Queue->CurrentCount++;
-            
-            /* Check if the entry is valid. If not, bugcheck */
-            if (!ListEntry->Flink || !ListEntry->Blink) {
-            
-                KEBUGCHECK(INVALID_WORK_QUEUE_ITEM);
-            }
-            
-            /* Remove the Entry */
-            RemoveEntryList(ListEntry);
-            
-            /* Nothing to wait on */
-            break;
-            
-        } else {
-                       
-            /* Do the wait */
-            DPRINT("Waiting on Queue Entry. CurrentCount: %d, Maximum Count: %d\n", 
-                    Queue->CurrentCount, Queue->MaximumCount);
-            
-            /* Use the Thread's Wait Block, it's big enough */
-            Thread->WaitBlockList = &Thread->WaitBlock[0];
-            
-            /* Fail if there's an APC Pending */
-            if (WaitMode == UserMode && Thread->ApcState.UserApcPending) {
-            
-                /* Return the status and increase the pending threads */
-                ListEntry = (PLIST_ENTRY)STATUS_USER_APC;
-                Queue->CurrentCount++;
-                
-                /* Nothing to wait on */
-                break;
-            }
-            
-            /* Build the Wait Block */
-            WaitBlock = &Thread->WaitBlock[0];
-            WaitBlock->Object = (PVOID)Queue;
-            WaitBlock->WaitKey = STATUS_SUCCESS;
-            WaitBlock->WaitType = WaitAny;
-            WaitBlock->Thread = Thread;
-            WaitBlock->NextWaitBlock = NULL;
-            
-            Thread->WaitStatus = STATUS_SUCCESS;
-            
-            /* We need to wait for the object... check if we have a timeout */
-            if (Timeout) {
-        
-                /* If it's zero, then don't do any waiting */
-                if (!Timeout->QuadPart) {
-            
-                    /* Instant Timeout, return the status and increase the pending threads */
-                    DPRINT("Queue Wait has timed out\n");
-                    ListEntry = (PLIST_ENTRY)STATUS_TIMEOUT;
-                    Queue->CurrentCount++;
-                    
-                    /* Nothing to wait on */
-                    break;
-                }
-                
-                /* 
-                 * Set up the Timer. We'll use the internal function so that we can
-                 * hold on to the dispatcher lock.
-                 */
-                Timer = &Thread->Timer;
-                TimerWaitBlock = &Thread->WaitBlock[1];
-
-                /* Set up the Timer Wait Block */
-                TimerWaitBlock->Object = (PVOID)Timer;
-                TimerWaitBlock->Thread = Thread;
-                TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
-                TimerWaitBlock->WaitType = WaitAny;
-                TimerWaitBlock->NextWaitBlock = NULL;
-            
-                /* Link the timer to this Wait Block */
-                InitializeListHead(&Timer->Header.WaitListHead);
-                InsertTailList(&Timer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
-            
-                /* Create Timer */
-                DPRINT("Creating Timer with timeout %I64d\n", *Timeout);
-                KiInsertTimer(Timer, *Timeout);
-            }
-                            
-            /* Insert the wait block into the Queues's wait list */
-            WaitBlock = Thread->WaitBlockList;
-            InsertTailList(&Queue->Header.WaitListHead, &WaitBlock->WaitListEntry);
-            
-            /* Block the Thread */
-            DPRINT("Blocking the Thread: %x %x!\n", KeGetCurrentThread(), Thread);
-            PsBlockThread(&Status, 
-                          FALSE, 
-                          WaitMode,
-                          WrQueue);
-    
-            /* Reset the wait reason */
-            Thread->WaitReason = 0;
-            
-            /* Check if we were executing an APC */
-            if (Status != STATUS_KERNEL_APC) {
-             
-                /* Done Waiting  */
-                DPRINT("Done waking queue. Thread: %x %x!\n", KeGetCurrentThread(), Thread);
-                return (PLIST_ENTRY)Status;
-            }
-        
-            /* Acquire again the lock */
-            DPRINT("Looping again\n");
-            OldIrql = KeAcquireDispatcherDatabaseLock();
-            
-            /* Save the new IRQL and decrease number of waiting threads */
-            Thread->WaitIrql = OldIrql;
-            Queue->CurrentCount--;
-        }
-    }
-    
-    /* Unlock Database and return */
-    KeReleaseDispatcherDatabaseLock(Thread->WaitIrql);
-    DPRINT("Returning. CurrentCount: %d, Maximum Count: %d\n", 
-            Queue->CurrentCount, Queue->MaximumCount);
-    return ListEntry;
+   while (TRUE)
+   {
+      if (Queue->CurrentCount < Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
+      {
+         ListEntry = RemoveHeadList(&Queue->EntryListHead);
+         //dec. num entries in queue
+         Queue->Header.SignalState--;
+         //inc. num running threads
+         Queue->CurrentCount++;
+         
+         KeReleaseDispatcherDatabaseLock(OldIrql);
+         return ListEntry;
+      }
+      else
+      {
+         //inform KeWaitXxx that we are holding disp. lock
+         Thread->WaitNext = TRUE;
+         Thread->WaitIrql = OldIrql;
+
+         Status = KeWaitForSingleObject(Queue,
+                                        WrQueue,
+                                        WaitMode,
+                                        TRUE, //bAlertable
+                                        Timeout);
+
+         if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
+         {
+            return (PVOID)Status;
+         }
+         
+         OldIrql = KeAcquireDispatcherDatabaseLock ();
+      }
+   }
 }
 
+
 /*
  * @implemented
  */
-PLIST_ENTRY 
-STDCALL
+PLIST_ENTRY STDCALL
 KeRundownQueue(IN PKQUEUE Queue)
 {
-    PLIST_ENTRY EnumEntry;
-    PLIST_ENTRY FirstEntry;
-    PKTHREAD Thread;
-    KIRQL OldIrql;
-
-    DPRINT("KeRundownQueue(Queue %x)\n", Queue);
-
-    /* Get the Dispatcher Lock */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
-
-    /* Get the First Empty Entry */
-    FirstEntry = Queue->EntryListHead.Flink;
-            
-    /* Make sure the list is not empty */
-    if (FirstEntry == &Queue->EntryListHead) {
-    
-        /* It is, so don't return anything */
-        EnumEntry = NULL;
-   
-    } else {
-       
-        /* Remove it */
-        RemoveEntryList(&Queue->EntryListHead);
-    }
-    
-    /* Unlink threads and clear their Thread->Queue */
-    while (!IsListEmpty(&Queue->ThreadListHead)) {
-        
-        /* Get the Entry and Remove it */
-        EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
-        
-        /* Get the Entry's Thread */
-        Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
-        
-        /* Kill its Queue */
-        Thread->Queue = NULL;
-    }
-
-    /* Release the lock and return */
-    KeReleaseDispatcherDatabaseLock(OldIrql);
-    return FirstEntry;
-}
+   PLIST_ENTRY EnumEntry;
+   PKTHREAD Thread;
+   KIRQL OldIrql;
 
-/*
- * Called when a thread which has a queue entry is entering a wait state
- */
-VOID
-FASTCALL
-KiWakeQueue(IN PKQUEUE Queue)
-{
-    PLIST_ENTRY QueueEntry;
-    PLIST_ENTRY WaitEntry;
-    PKWAIT_BLOCK WaitBlock;
-    
-    /* Decrement the number of active threads */
-    DPRINT("KiWakeQueue: %x. Thread: %x\n", Queue, KeGetCurrentThread());
-    Queue->CurrentCount--;
-    
-    /* Make sure the counts are OK */
-    if (Queue->CurrentCount < Queue->MaximumCount) {
-    
-        /* Get the Queue Entry */
-        QueueEntry = Queue->EntryListHead.Flink;
-        
-        /* Get the Wait Entry */
-        WaitEntry = Queue->Header.WaitListHead.Blink;
-        DPRINT("Queue Count is ok, Queue entries: %x, %x\n", QueueEntry, WaitEntry);
-        
-        /* Make sure that the Queue List isn't empty and that this entry is valid */
-        if (!IsListEmpty(&Queue->Header.WaitListHead) && 
-            (QueueEntry != &Queue->EntryListHead)) {
-            
-            /* Remove this entry */
-            DPRINT("Queue in List, removing it\n");
-            RemoveEntryList(QueueEntry);
-            QueueEntry->Flink = NULL;
-            
-            /* Decrease the Signal State */
-            Queue->Header.SignalState--;
-            
-            /* Unwait the Thread */
-            DPRINT("Unwaiting Thread\n");
-            WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
-            KiAbortWaitThread(WaitBlock->Thread, (NTSTATUS)QueueEntry);
-        }
-    }    
-}
+   DPRINT("KeRundownQueue(Queue %x)\n", Queue);
 
-/*
- * Returns the previous number of entries in the queue
- */
-LONG 
-STDCALL
-KiInsertQueue(IN PKQUEUE Queue,
-              IN PLIST_ENTRY Entry,
-              BOOLEAN Head)
-{
-    ULONG InitialState;
-    PKTHREAD Thread = KeGetCurrentThread();
-    PKWAIT_BLOCK WaitBlock;
-    PLIST_ENTRY WaitEntry;
-  
-    DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
-   
-    /* Save the old state */
-    InitialState = Queue->Header.SignalState;
+   /* I'm just guessing how this should work:-/
+    * -Gunnar 
+    */
      
-    /* Get the Entry */
-    WaitEntry = Queue->Header.WaitListHead.Blink;
-    DPRINT("Initial State, WaitEntry: %d, %x\n", InitialState, WaitEntry);
-    
-    /*
-     * Why the KeGetCurrentThread()->Queue != Queue?
-     * KiInsertQueue might be called from an APC for the current thread. 
-     * -Gunnar
-     */
-    if ((Queue->CurrentCount < Queue->MaximumCount) && 
-        (WaitEntry != &Queue->Header.WaitListHead) &&
-        ((Thread->Queue != Queue) || (Thread->WaitReason != WrQueue))) {
-       
-        /* Remove the wait entry */
-        DPRINT("Removing Entry\n");
-        RemoveEntryList(WaitEntry);
-        
-        /* Get the Wait Block and Thread */
-        WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
-        DPRINT("Got wait block: %x\n", WaitBlock);
-        Thread = WaitBlock->Thread;
-        
-        /* Reset the wait reason */
-        Thread->WaitReason = 0;
-        
-        /* Increase the waiting threads */
-        Queue->CurrentCount++;
-        
-        /* Check if there's a Thread Timer */
-        if (Thread->Timer.Header.Inserted) {
-    
-            /* Cancel the Thread Timer with the no-lock fastpath */
-            DPRINT("Removing the Thread's Timer\n");
-            Thread->Timer.Header.Inserted = FALSE;
-            RemoveEntryList(&Thread->Timer.TimerListEntry);
-        }
-        
-        /* Reschedule the Thread */
-        DPRINT("Unblocking the Thread\n");
-        PsUnblockThread((PETHREAD)Thread, (PNTSTATUS)&Entry, 0);
-    
-    } else {
-    
-        /* Increase the Entries */
-        DPRINT("Adding new Queue Entry: %d %d\n", Head, Queue->Header.SignalState);
-        Queue->Header.SignalState++;
-        
-        if (Head) {
-        
-            InsertHeadList(&Queue->EntryListHead, Entry);
-        
-        } else {
-        
-            InsertTailList(&Queue->EntryListHead, Entry);
-        }
-    }
-
-    /* Return the previous state */
-    DPRINT("Returning\n");
-    return InitialState;
+   OldIrql = KeAcquireDispatcherDatabaseLock ();
+
+   //no thread must wait on queue at rundown
+   ASSERT(IsListEmpty(&Queue->Header.WaitListHead));
+   
+   // unlink threads and clear their Thread->Queue
+   while (!IsListEmpty(&Queue->ThreadListHead))
+   {
+      EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
+      Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
+      Thread->Queue = NULL;
+   }
+
+   if (IsListEmpty(&Queue->EntryListHead))
+   {
+      EnumEntry = NULL;
+   }
+   else
+   {
+      EnumEntry = Queue->EntryListHead.Flink;
+   }
+
+   KeReleaseDispatcherDatabaseLock (OldIrql);
+
+   return EnumEntry;
 }
 
 /* EOF */
index f949905..9408e66 100644 (file)
 /*
  * @implemented
  */
-VOID
-STDCALL
-KeInitializeSemaphore(PKSEMAPHORE Semaphore,
-                      LONG Count,
-                      LONG Limit)
+VOID STDCALL
+KeInitializeSemaphore (PKSEMAPHORE     Semaphore,
+                      LONG             Count,
+                      LONG             Limit)
 {
-
-    DPRINT("KeInitializeSemaphore Sem: %x\n", Semaphore);
-    
-    /* Simply Initialize the Header */
-    KeInitializeDispatcherHeader(&Semaphore->Header,
-                                 SemaphoreObject,
-                                 sizeof(KSEMAPHORE)/sizeof(ULONG),
-                                 Count);
-
-    /* Set the Limit */
-    Semaphore->Limit = Limit;  
+   KeInitializeDispatcherHeader(&Semaphore->Header,
+                               InternalSemaphoreType,
+                               sizeof(KSEMAPHORE)/sizeof(ULONG),
+                               Count);
+   Semaphore->Limit=Limit;
 }
 
 /*
  * @implemented
  */
-LONG 
-STDCALL
-KeReadStateSemaphore(PKSEMAPHORE Semaphore)
+LONG STDCALL
+KeReadStateSemaphore (PKSEMAPHORE      Semaphore)
 {
-    /* Just return the Signal State */
-    return(Semaphore->Header.SignalState);
+   return(Semaphore->Header.SignalState);
 }
 
 /*
  * @implemented
- *
+ */
+LONG STDCALL
+KeReleaseSemaphore (PKSEMAPHORE        Semaphore,
+                   KPRIORITY   Increment,
+                   LONG                Adjustment,
+                   BOOLEAN             Wait)
+/*
  * FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
  * routine supplies a runtime priority boost for waiting threads. If this
  * call sets the semaphore to the Signaled state, the semaphore count is
@@ -71,65 +68,40 @@ KeReadStateSemaphore(PKSEMAPHORE Semaphore)
  * RETURNS: If the return value is zero, the previous state of the semaphore
  *          object is Not-Signaled.
  */
-LONG 
-STDCALL
-KeReleaseSemaphore(PKSEMAPHORE Semaphore,
-                   KPRIORITY Increment,
-                   LONG Adjustment,
-                   BOOLEAN Wait)
-
 {
-    ULONG InitialState;
-    KIRQL OldIrql;
-    PKTHREAD CurrentThread;
+  ULONG InitialState;
+  KIRQL OldIrql;
 
-    DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n", 
-            Semaphore, 
-            Increment, 
-            Adjustment, 
-            Wait);
+  DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
+         "Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
 
-    /* Lock the Dispatcher Database */
-    OldIrql = KeAcquireDispatcherDatabaseLock();
+  OldIrql = KeAcquireDispatcherDatabaseLock();
 
-    /* Save the Old State */
-    InitialState = Semaphore->Header.SignalState;
-    
-    /* Check if the Limit was exceeded */
-    if (Semaphore->Limit < (LONG) InitialState + Adjustment || 
-        InitialState > InitialState + Adjustment) {
-        
-        /* Raise an error if it was exceeded */
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-        ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
+  InitialState = Semaphore->Header.SignalState;
+  if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
+      InitialState > InitialState + Adjustment)
+    {
+      ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
     }
 
-    /* Now set the new state */
-    Semaphore->Header.SignalState += Adjustment;
-    
-    /* Check if we should wake it */
-    if (InitialState == 0 && !IsListEmpty(&Semaphore->Header.WaitListHead)) {
-        
-        /* Wake the Semaphore */
-        KiWaitTest(&Semaphore->Header, SEMAPHORE_INCREMENT);
+  Semaphore->Header.SignalState += Adjustment;
+  if (InitialState == 0)
+    {
+      KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT);
     }
 
-    /* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
-    if (Wait == FALSE) {
-        
-        /* Release the Lock */
-        KeReleaseDispatcherDatabaseLock(OldIrql);
-    
-    } else {
-        
-        /* Set a wait */
-        CurrentThread = KeGetCurrentThread();
-        CurrentThread->WaitNext = TRUE;
-        CurrentThread->WaitIrql = OldIrql;
+  if (Wait == FALSE)
+    {
+      KeReleaseDispatcherDatabaseLock(OldIrql);
+    }
+  else
+    {
+      KTHREAD *Thread = KeGetCurrentThread();
+      Thread->WaitNext = TRUE;
+      Thread->WaitIrql = OldIrql;
     }
 
-    /* Return the previous state */
-    return InitialState;
+  return(InitialState);
 }
 
 /* EOF */
index de101af..c46db9d 100644 (file)
@@ -107,11 +107,12 @@ KeInitializeTimerEx (PKTIMER Timer,
     
     /* Initialize the Dispatch Header */
     KeInitializeDispatcherHeader(&Timer->Header,
-                                 TimerNotificationObject + Type,
+                                 InternalNotificationTimer + Type,
                                  sizeof(KTIMER) / sizeof(ULONG),
                                  FALSE);
    
-    /* Initalize the Other data */
+    /* Initalize the List Head and other data */
+    InitializeListHead(&Timer->Header.WaitListHead);
     Timer->DueTime.QuadPart = 0;
     Timer->Period = 0;
 }
@@ -195,6 +196,7 @@ KeSetTimerEx (PKTIMER Timer,
     Timer->Dpc = Dpc;
     Timer->Period = Period;
     Timer->Header.SignalState = FALSE;
+    Timer->Header.Absolute = FALSE;
     
     /* Insert it */
     if (!KiInsertTimer(Timer, DueTime)) {
@@ -294,7 +296,7 @@ KiHandleExpiredTimer(PKTIMER Timer)
     /* Set it as Signaled */
     DPRINT("Setting Timer as Signaled\n");
     Timer->Header.SignalState = TRUE;
-    KiWaitTest(&Timer->Header, 0);   
+    KiDispatcherObjectWake(&Timer->Header, 0);   
 
     /* If the Timer is periodic, reinsert the timer with the new due time */
     if (Timer->Period) {
@@ -304,7 +306,7 @@ KiHandleExpiredTimer(PKTIMER Timer)
         if (!KiInsertTimer(Timer, DueTime)) {
 
            /* FIXME: I will think about how to handle this and fix it ASAP -- Alex */
-           DPRINT("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n");
+           DPRINT1("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n");
         };
     }
     
@@ -336,10 +338,8 @@ KiInsertTimer(PKTIMER Timer,
     
     DPRINT("KiInsertTimer(Timer %x DueTime %I64d)\n", Timer, DueTime.QuadPart);
     
-    /* Set default data */
+    /* Set it as Inserted */
     Timer->Header.Inserted = TRUE;
-    Timer->Header.Absolute = FALSE;
-    if (!Timer->Period) Timer->Header.SignalState = FALSE;
     
     /* Convert to relative time if needed */
     if (DueTime.u.HighPart >= 0) {
index 7f65c81..a6575e9 100644 (file)
@@ -1,11 +1,16 @@
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS project
  * FILE:            ntoskrnl/ke/wait.c
  * PURPOSE:         Manages non-busy waiting
  * 
- * PROGRAMMERS:     Alex Ionescu - Fixes and optimization.
- *                  Gunnar Dalsnes - Implementation
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
+ *                  Phillip Susi
+ */
+
+/* NOTES ********************************************************************
+ *
  */
 
 /* INCLUDES ******************************************************************/
 
 static KSPIN_LOCK DispatcherDatabaseLock;
 
-/* Tells us if the Timer or Event is a Syncronization or Notification Object */
-#define TIMER_OR_EVENT_TYPE 0x7L
+#define KeDispatcherObjectWakeOne(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, FALSE)
+#define KeDispatcherObjectWakeAll(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, TRUE)
 
-/* One of the Reserved Wait Blocks, this one is for the Thread's Timer */
-#define TIMER_WAIT_BLOCK 0x3L
+extern POBJECT_TYPE EXPORTED ExMutantObjectType;
+extern POBJECT_TYPE EXPORTED ExSemaphoreObjectType;
+extern POBJECT_TYPE EXPORTED ExTimerType;
 
 /* FUNCTIONS *****************************************************************/
 
+VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
+                                 ULONG Type,
+                                 ULONG Size,
+                                 ULONG SignalState)
+{
+   Header->Type = (UCHAR)Type;
+   Header->Absolute = 0;
+   Header->Inserted = 0;
+   Header->Size = (UCHAR)Size;
+   Header->SignalState = SignalState;
+   InitializeListHead(&(Header->WaitListHead));
+}
+
+
+KIRQL
+KeAcquireDispatcherDatabaseLock(VOID)
+/*
+ * PURPOSE: Acquires the dispatcher database lock for the caller
+ */
+{
+   KIRQL OldIrql;
+
+   DPRINT("KeAcquireDispatcherDatabaseLock()\n");
+
+   KeAcquireSpinLock (&DispatcherDatabaseLock, &OldIrql);
+   return OldIrql;
+}
+
+
 VOID
-inline
-FASTCALL
-KiCheckAlertability(BOOLEAN Alertable,
-                    PKTHREAD CurrentThread,
-                    KPROCESSOR_MODE WaitMode,
-                    PNTSTATUS Status)
+KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID)
+/*
+ * PURPOSE: Acquires the dispatcher database lock for the caller
+ */
 {
-    /* At this point, we have to do a wait, so make sure we can make the thread Alertable if requested */
-    if (Alertable) {
-    
-        /* If the Thread is Alerted, set the Wait Status accordingly */    
-        if (CurrentThread->Alerted[(int)WaitMode]) {
-            
-            CurrentThread->Alerted[(int)WaitMode] = FALSE;
-            DPRINT("Thread was Alerted\n");
-            *Status = STATUS_ALERTED;
-            
-        /* If there are User APCs Pending, then we can't really be alertable */
-        } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && 
-                    (WaitMode == UserMode)) {
-            
-            DPRINT("APCs are Pending\n");
-            CurrentThread->ApcState.UserApcPending = TRUE;
-            *Status = STATUS_USER_APC;
-        }
-    
-    /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */
-    } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) {
-            DPRINT("APCs are Pending\n");
-            *Status = STATUS_USER_APC;
-    }
+   DPRINT("KeAcquireDispatcherDatabaseLockAtDpcLevel()\n");
+
+   KeAcquireSpinLockAtDpcLevel (&DispatcherDatabaseLock);
+}
+
+
+VOID
+KeReleaseDispatcherDatabaseLock(KIRQL OldIrql)
+{
+  DPRINT("KeReleaseDispatcherDatabaseLock(OldIrql %x)\n",OldIrql);
+  if (!KeIsExecutingDpc() && 
+      OldIrql < DISPATCH_LEVEL && 
+      KeGetCurrentThread() != NULL && 
+      KeGetCurrentThread() == KeGetCurrentKPCR()->PrcbData.IdleThread)
+  {
+    PsDispatchThreadNoLock(THREAD_STATE_READY);
+    KeLowerIrql(OldIrql);
+  }
+  else
+  {
+    KeReleaseSpinLock(&DispatcherDatabaseLock, OldIrql);
+  }
+}
+
+
+VOID
+KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID)
+{
+  DPRINT("KeReleaseDispatcherDatabaseLock()\n");
+
+  KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
+}
+
+
+static BOOLEAN
+KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
+                        PKTHREAD Thread)
+/*
+ * FUNCTION: Perform side effects on object before a wait for a thread is
+ *           satisfied
+ */
+{
+   BOOLEAN Abandoned = FALSE;
+
+   switch (hdr->Type)
+   {
+      case InternalSynchronizationEvent:
+         hdr->SignalState = 0;
+         break;
+      
+      case InternalQueueType:
+         break;
+         
+      case InternalSemaphoreType:
+         hdr->SignalState--;
+         break;
+
+      case InternalProcessType:
+         break;
+
+      case InternalThreadType:
+         break;
+
+      case InternalNotificationEvent:
+         break;
+
+      case InternalSynchronizationTimer:
+         hdr->SignalState = FALSE;
+         break;
+
+      case InternalNotificationTimer:
+         break;
+
+      case InternalMutexType:
+      {
+         PKMUTEX Mutex;
+
+         Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
+         hdr->SignalState--;
+         ASSERT(hdr->SignalState <= 1);
+         if (hdr->SignalState == 0)
+         {
+            if (Thread == NULL)
+            {
+               DPRINT("Thread == NULL!\n");
+               KEBUGCHECK(0);
+            }
+            Abandoned = Mutex->Abandoned;
+            if (Thread != NULL)
+               InsertTailList(&Thread->MutantListHead, &Mutex->MutantListEntry);
+            Mutex->OwnerThread = Thread;
+            Mutex->Abandoned = FALSE;
+         }
+      }
+         break;
+
+      default:
+         DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n", __FILE__, __LINE__, hdr);
+         KEBUGCHECK(0);
+   }
+
+   return Abandoned;
+}
+
+static BOOLEAN
+KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
+                    PKTHREAD Thread)
+{
+   if (hdr->Type == InternalMutexType)
+   {
+      PKMUTEX Mutex;
+
+      Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
+
+      ASSERT(hdr->SignalState <= 1);
+
+      if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) || hdr->SignalState == 1)
+      {
+         return (TRUE);
+      }
+      else
+      {
+         return (FALSE);
+      }
+   }
+
+   if (hdr->SignalState <= 0)
+   {
+      return (FALSE);
+   }
+   else
+   {
+      return (TRUE);
+   }
+}
+
+/* Must be called with the dispatcher lock held */
+BOOLEAN KiAbortWaitThread(PKTHREAD Thread, NTSTATUS WaitStatus)
+{
+   PKWAIT_BLOCK WaitBlock;
+   BOOLEAN WasWaiting;
+
+   /* if we are blocked, we must be waiting on something also */
+   ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != NULL));
+
+   WaitBlock = (PKWAIT_BLOCK)Thread->WaitBlockList;
+   WasWaiting = (WaitBlock != NULL);
+   
+   while (WaitBlock)
+   {
+      RemoveEntryList(&WaitBlock->WaitListEntry);
+      WaitBlock = WaitBlock->NextWaitBlock;
+   }
+   
+   Thread->WaitBlockList = NULL;
+
+   if (WasWaiting)
+   {
+          PsUnblockThread((PETHREAD)Thread, &WaitStatus, 0);
+   }
+   return WasWaiting;
+}
+
+static BOOLEAN
+KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
+                               KPRIORITY increment,
+                               BOOLEAN WakeAll)
+{
+   PKWAIT_BLOCK Waiter;
+   PKWAIT_BLOCK WaiterHead;
+   PLIST_ENTRY EnumEntry;
+   NTSTATUS Status;
+   BOOLEAN Abandoned;
+   BOOLEAN AllSignaled;
+   BOOLEAN WakedAny = FALSE;
+
+   DPRINT("KeDispatcherObjectWakeOnOrAll(hdr %x)\n", hdr);
+   DPRINT ("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
+           hdr->WaitListHead.Flink, hdr->WaitListHead.Blink);
+
+   if (IsListEmpty(&hdr->WaitListHead))
+   {
+      return (FALSE);
+   }
+
+   //enum waiters for this dispatcher object
+   EnumEntry = hdr->WaitListHead.Flink;
+   while (EnumEntry != &hdr->WaitListHead && (WakeAll || !WakedAny))
+   {
+      WaiterHead = CONTAINING_RECORD(EnumEntry, KWAIT_BLOCK, WaitListEntry);
+      DPRINT("current_entry %x current %x\n", EnumEntry, WaiterHead);
+      EnumEntry = EnumEntry->Flink;
+      ASSERT(WaiterHead->Thread != NULL);
+      ASSERT(WaiterHead->Thread->WaitBlockList != NULL);
+
+      Abandoned = FALSE;
+
+      if (WaiterHead->WaitType == WaitAny)
+      {
+         DPRINT("WaitAny: Remove all wait blocks.\n");
+         for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
+         {
+            RemoveEntryList(&Waiter->WaitListEntry);
+         }
+
+         WaiterHead->Thread->WaitBlockList = NULL;
+
+         /*
+          * If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
+          * but thats ok since WakeAll objects has no sideeffects.
+          */
+         Abandoned |= KiSideEffectsBeforeWake(hdr, WaiterHead->Thread);
+      }
+      else
+      {
+         DPRINT("WaitAll: All WaitAll objects must be signaled.\n");
+
+         AllSignaled = TRUE;
+
+         //all WaitAll obj. for thread need to be signaled to satisfy a wake
+         for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
+         {
+            //no need to check hdr since it has to be signaled
+            if (Waiter->WaitType == WaitAll && Waiter->Object != hdr)
+            {
+               if (!KiIsObjectSignalled(Waiter->Object, Waiter->Thread))
+               {
+                  AllSignaled = FALSE;
+                  break;
+               }
+            }
+         }
+
+         if (AllSignaled)
+         {
+            for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
+            {
+               RemoveEntryList(&Waiter->WaitListEntry);
+         
+               if (Waiter->WaitType == WaitAll)
+               {
+                  Abandoned |= KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread);
+               }
+
+               //no WaitAny objects can possibly be signaled since we are here
+               ASSERT(!(Waiter->WaitType == WaitAny
+                                         && KiIsObjectSignalled(Waiter->Object, Waiter->Thread)));
+            }
+
+            WaiterHead->Thread->WaitBlockList = NULL;
+         }
+      }
+
+      if (WaiterHead->Thread->WaitBlockList == NULL)
+      {
+         Status = WaiterHead->WaitKey;
+         if (Abandoned)
+         {
+            DPRINT("Abandoned mutex among objects");
+            Status += STATUS_ABANDONED_WAIT_0;
+         }
+
+         WakedAny = TRUE;
+         DPRINT("Waking %x status = %x\n", WaiterHead->Thread, Status);
+         PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb),
+                         &Status, increment);
+      }
+   }
+
+   return WakedAny;
+}
+
+
+BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
+/*
+ * FUNCTION: Wake threads waiting on a dispatcher object
+ * NOTE: The exact semantics of waking are dependant on the type of object
+ */
+{
+   BOOL Ret;
+
+   DPRINT("Entering KeDispatcherObjectWake(hdr %x)\n",hdr);
+//   DPRINT("hdr->WaitListHead %x hdr->WaitListHead.Flink %x\n",
+//       &hdr->WaitListHead,hdr->WaitListHead.Flink);
+   DPRINT("hdr->Type %x\n",hdr->Type);
+   switch (hdr->Type)
+     {
+      case InternalNotificationEvent:
+       return(KeDispatcherObjectWakeAll(hdr, increment));
+
+      case InternalNotificationTimer:
+       return(KeDispatcherObjectWakeAll(hdr, increment));
+
+      case InternalSynchronizationEvent:
+       return(KeDispatcherObjectWakeOne(hdr, increment));
+
+      case InternalSynchronizationTimer:
+       return(KeDispatcherObjectWakeOne(hdr, increment));
+
+      case InternalQueueType:
+       return(KeDispatcherObjectWakeOne(hdr, increment));
+      
+      case InternalSemaphoreType:
+       DPRINT("hdr->SignalState %d\n", hdr->SignalState);
+       if(hdr->SignalState>0)
+         {
+           do
+             {
+               DPRINT("Waking one semaphore waiter\n");
+               Ret = KeDispatcherObjectWakeOne(hdr, increment);
+             } while(hdr->SignalState > 0 &&  Ret) ;
+           return(Ret);
+         }
+       else return FALSE;
+
+     case InternalProcessType:
+       return(KeDispatcherObjectWakeAll(hdr, increment));
+
+     case InternalThreadType:
+       return(KeDispatcherObjectWakeAll(hdr, increment));
+
+     case InternalMutexType:
+       return(KeDispatcherObjectWakeOne(hdr, increment));
+     }
+   DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type);
+   KEBUGCHECK(0);
+   return(FALSE);
 }
 
 /*
  * @implemented
- *
+ */
+NTSTATUS STDCALL
+KeDelayExecutionThread (KPROCESSOR_MODE        WaitMode,
+                       BOOLEAN         Alertable,
+                       PLARGE_INTEGER  Interval)
+/*
  * FUNCTION: Puts the current thread into an alertable or nonalertable 
  * wait state for a given internal
  * ARGUMENTS:
@@ -72,102 +413,27 @@ KiCheckAlertability(BOOLEAN Alertable,
  *          Interval = Specifies the interval to wait
  * RETURNS: Status
  */
-NTSTATUS 
-STDCALL
-KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
-                       BOOLEAN Alertable,
-                       PLARGE_INTEGER Interval)
 {
-    PKWAIT_BLOCK TimerWaitBlock;
-    PKTIMER ThreadTimer;
-    PKTHREAD CurrentThread = KeGetCurrentThread();
-    NTSTATUS Status;
+   PKTHREAD Thread = KeGetCurrentThread();
 
-    DPRINT("Entering KeDelayExecutionThread\n");
-
-    /* Check if the lock is already held */
-    if (CurrentThread->WaitNext)  {
-        
-        /* Lock is held, disable Wait Next */
-        DPRINT("Lock is held\n");
-        CurrentThread->WaitNext = FALSE;
-        
-    } else {
-        
-        /* Lock not held, acquire it */
-        DPRINT("Lock is not held, acquiring\n");
-        CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-    }
-    
-    /* Use built-in Wait block */
-    TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
-    
-    /* Start Wait Loop */
-    do {
-    
-        /* We are going to wait no matter what (that's the point), so test Alertability */
-        KiCheckAlertability(Alertable, CurrentThread, KernelMode, &Status);
-        
-        /* Set Timer */
-        ThreadTimer = &CurrentThread->Timer;
-        
-        /* Setup the Wait Block */
-        CurrentThread->WaitBlockList = TimerWaitBlock;
-        TimerWaitBlock->Object = (PVOID)ThreadTimer;
-        TimerWaitBlock->Thread = CurrentThread;
-        TimerWaitBlock->WaitKey = (USHORT)STATUS_TIMEOUT;
-        TimerWaitBlock->WaitType = WaitAny;         
-        TimerWaitBlock->NextWaitBlock = NULL;
-    
-        /* Link the timer to this Wait Block */
-        InitializeListHead(&ThreadTimer->Header.WaitListHead);
-        InsertTailList(&ThreadTimer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
-
-        /* Insert the Timer into the Timer Lists and enable it */
-        if (!KiInsertTimer(ThreadTimer, *Interval)) {    
-
-            /* FIXME: Unhandled case...what should we do? */
-            DPRINT1("Could not create timer for KeDelayExecutionThread\n");
-        }    
-        
-        /* Handle Kernel Queues */
-        if (CurrentThread->Queue) {
-                 
-            DPRINT("Waking Queue\n");
-            KiWakeQueue(CurrentThread->Queue);
-        }
-
-        /* Block the Thread */
-        DPRINT("Blocking the Thread: %d, %d, %x\n", Alertable, WaitMode, KeGetCurrentThread());
-        PsBlockThread(&Status, 
-                      Alertable, 
-                      WaitMode, 
-                      DelayExecution);
-    
-        /* Check if we were executing an APC or if we timed out */
-        if (Status != STATUS_KERNEL_APC) {
-           
-            /* This is a good thing */
-            if (Status == STATUS_TIMEOUT) Status = STATUS_SUCCESS;
-            
-            /* Return Status */
-            return Status;
-        }
-        
-        DPRINT("Looping Again\n");
-        CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-    
-    } while (TRUE);
-    
-    /* Release the Lock, we are done */
-    DPRINT("Returning from KeDelayExecutionThread(), %x. Status: %d\n", KeGetCurrentThread(), Status);
-    KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
-    return Status;   
+   KeSetTimer(&Thread->Timer, *Interval, NULL);
+   return (KeWaitForSingleObject(&Thread->Timer,
+                                (WaitMode == KernelMode) ? Executive : UserRequest, /* TMN: Was unconditionally Executive */
+                                WaitMode, /* TMN: Was UserMode */
+                                Alertable,
+                                NULL));
 }
 
 /*
  * @implemented
- *
+ */
+NTSTATUS STDCALL
+KeWaitForSingleObject(PVOID Object,
+                      KWAIT_REASON WaitReason,
+                      KPROCESSOR_MODE WaitMode,
+                      BOOLEAN Alertable,
+                      PLARGE_INTEGER Timeout)
+/*
  * FUNCTION: Puts the current thread into a wait state until the
  * given dispatcher object is set to signalled
  * ARGUMENTS:
@@ -180,174 +446,52 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
  *         Timeout = Optional timeout value
  * RETURNS: Status
  */
-NTSTATUS 
-STDCALL
-KeWaitForSingleObject(PVOID Object,
-                      KWAIT_REASON WaitReason,
-                      KPROCESSOR_MODE WaitMode,
-                      BOOLEAN Alertable,
-                      PLARGE_INTEGER Timeout)
 {
-    PDISPATCHER_HEADER CurrentObject;
-    PKWAIT_BLOCK WaitBlock;
-    PKWAIT_BLOCK TimerWaitBlock;
-    PKTIMER ThreadTimer;
-    PKTHREAD CurrentThread = KeGetCurrentThread();
-    NTSTATUS Status;
-    NTSTATUS WaitStatus;
-
-    DPRINT("Entering KeWaitForSingleObject\n");
-   
-    /* Check if the lock is already held */
-    if (CurrentThread->WaitNext)  {
-        
-        /* Lock is held, disable Wait Next */
-        DPRINT("Lock is held\n");
-        CurrentThread->WaitNext = FALSE;
-        
-    } else {
-        
-        /* Lock not held, acquire it */
-        DPRINT("Lock is not held, acquiring\n");
-        CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-    }
-
-    /* Start the actual Loop */
-    do {
-        
-        /* Get the current Wait Status */
-        WaitStatus = CurrentThread->WaitStatus;
-    
-        /* Append wait block to the KTHREAD wait block list */
-        CurrentThread->WaitBlockList = WaitBlock = &CurrentThread->WaitBlock[0];
-           
-        /* 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)) {
-                    
-            /* Just unwait this guy and exit */
-            if (CurrentObject->SignalState != MINLONG) {
-                    
-                /* It has a normal signal state, so unwait it and return */
-                KiSatisfyObjectWait(CurrentObject, CurrentThread);
-                Status = STATUS_WAIT_0;
-                goto WaitDone;
-                    
-            } else {
-                    
-                /* Is this a Mutant? */
-                if (CurrentObject->Type == MutantObject) {
-                        
-                    /* According to wasm.ru, we must raise this exception (tested and true) */
-                    KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
-                    ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);                    
-                } 
-            }
-        }
-        
-        /* Set up the Wait Block */
-        WaitBlock->Object = CurrentObject;
-        WaitBlock->Thread = CurrentThread;
-        WaitBlock->WaitKey = (USHORT)(STATUS_WAIT_0);
-        WaitBlock->WaitType = WaitAny;                       
-        WaitBlock->NextWaitBlock = NULL;
-                      
-        /* Make sure we can satisfy the Alertable request */
-        KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status);
-    
-        /* Set the Wait Status */
-        CurrentThread->WaitStatus = Status;
-           
-        /* Enable the Timeout Timer if there was any specified */
-        if (Timeout != NULL) {
-              
-            /* However if 0 timeout was specified, then we must fail since we need to peform a wait */
-            if (!Timeout->QuadPart) {
-                
-                /* Return a timeout */
-                Status = STATUS_TIMEOUT;
-                goto WaitDone;
-            }
-                       
-            /* Point to Timer Wait Block and Thread Timer */
-            TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
-            ThreadTimer = &CurrentThread->Timer;
+   return KeWaitForMultipleObjects(1,
+                                   &Object,
+                                   WaitAny,
+                                   WaitReason,
+                                   WaitMode,
+                                   Alertable,
+                                   Timeout,
+                                   NULL);
+}
 
-            /* Connect the Timer Wait Block */
-            WaitBlock->NextWaitBlock = TimerWaitBlock;
-            
-            /* Set up the Timer Wait Block */
-            TimerWaitBlock->Object = (PVOID)ThreadTimer;
-            TimerWaitBlock->Thread = CurrentThread;
-            TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
-            TimerWaitBlock->WaitType = WaitAny;
-            TimerWaitBlock->NextWaitBlock = NULL;
-            
-            /* Link the timer to this Wait Block */
-            InitializeListHead(&ThreadTimer->Header.WaitListHead);
-            InsertTailList(&ThreadTimer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
 
-            /* Insert the Timer into the Timer Lists and enable it */
-            if (!KiInsertTimer(ThreadTimer, *Timeout)) {    
+inline
+PVOID
+KiGetWaitableObjectFromObject(PVOID Object)
+{
+   //special case when waiting on file objects
+   if ( ((PDISPATCHER_HEADER)Object)->Type == InternalFileType)
+   {
+      return &((PFILE_OBJECT)Object)->Event;
+   }
 
-                /* Return a timeout if we couldn't insert the timer for some reason */
-                Status = STATUS_TIMEOUT;
-                goto WaitDone;
-            }    
-        }
+   return Object;
+}
 
-        /* Link the Object to this Wait Block */
-        InsertTailList(&CurrentObject->WaitListHead, &WaitBlock->WaitListEntry);            
-        
-        /* Handle Kernel Queues */
-        if (CurrentThread->Queue) {
-                 
-            DPRINT("Waking Queue\n");
-            KiWakeQueue(CurrentThread->Queue);
-        }
 
-        /* Block the Thread */
-        DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, WaitReason, KeGetCurrentThread());
-        PsBlockThread(&Status, 
-                      Alertable, 
-                      WaitMode, 
-                      (UCHAR)WaitReason);
-    
-        /* Check if we were executing an APC */
-        if (Status != STATUS_KERNEL_APC) {
-           
-            /* Return Status */
-            return Status;
-        }
-        
-        DPRINT("Looping Again\n");
-        CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-    
-    } while (TRUE);
-    
-WaitDone:
-    /* Release the Lock, we are done */
-    DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n", KeGetCurrentThread(), Status);
-    KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
-    return Status;       
+inline BOOL
+KiIsObjectWaitable(PVOID Object)
+{
+    POBJECT_HEADER Header;
+    Header = BODY_TO_HEADER(Object);
+    if (Header->ObjectType == ExEventObjectType ||
+       Header->ObjectType == ExIoCompletionType ||
+       Header->ObjectType == ExMutantObjectType ||
+       Header->ObjectType == ExSemaphoreObjectType ||
+       Header->ObjectType == ExTimerType ||
+       Header->ObjectType == PsProcessType ||
+       Header->ObjectType == PsThreadType ||
+       Header->ObjectType == IoFileObjectType)
+    {
+       return TRUE;
+    }
+    else
+    {
+       return FALSE;
+    }
 }
 
 /*
@@ -363,544 +507,558 @@ KeWaitForMultipleObjects(ULONG Count,
                          PLARGE_INTEGER Timeout,
                          PKWAIT_BLOCK WaitBlockArray)
 {
-    PDISPATCHER_HEADER CurrentObject;
-    PKWAIT_BLOCK WaitBlock;
-    PKWAIT_BLOCK TimerWaitBlock;
-    PKTIMER ThreadTimer;
-    PKTHREAD CurrentThread = KeGetCurrentThread();
-    ULONG AllObjectsSignaled;
-    ULONG WaitIndex;
-    NTSTATUS Status;
-    NTSTATUS WaitStatus;
-
-    DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
-            "PsGetCurrentThread() %x, Timeout %x\n", Count, Object, PsGetCurrentThread(), Timeout);
-
-    /* Set the Current Thread */
-    CurrentThread = KeGetCurrentThread();
-    
-    /* Check if the lock is already held */
-    if (CurrentThread->WaitNext)  {
-        
-        /* Lock is held, disable Wait Next */
-        DPRINT("Lock is held\n");
-        CurrentThread->WaitNext = FALSE;
-        
-    } else {
-        
-        /* Lock not held, acquire it */
-        DPRINT("Lock is not held, acquiring\n");
-        CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-    }
+   DISPATCHER_HEADER *hdr;
+   PKWAIT_BLOCK blk;
+   PKTHREAD CurrentThread;
+   ULONG CountSignaled;
+   ULONG i;
+   NTSTATUS Status;
+   KIRQL OldIrql;
+   BOOLEAN Abandoned;
+   NTSTATUS WaitStatus;
 
-    /* Make sure the Wait Count is valid for the Thread and Maximum Wait Objects */
-    if (!WaitBlockArray) {
-       
-        /* Check in regards to the Thread Object Limit */
-        if (Count > THREAD_WAIT_OBJECTS) {
-            
-            DPRINT1("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
-            KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
-        }
-        
-        /* Use the Thread's Wait Block */
-        WaitBlockArray = &CurrentThread->WaitBlock[0];
-        
-    } else {
-      
-        /* Using our own Block Array. Check in regards to System Object Limit */
-        if (Count > MAXIMUM_WAIT_OBJECTS) {
-            
-            DPRINT1("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
-            KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
-        }
-    }
-    
-    /* Start the actual Loop */
-    do {
-        
-        /* Get the current Wait Status */
-        WaitStatus = CurrentThread->WaitStatus;
-    
-        /* Append wait block to the KTHREAD wait block list */
-        CurrentThread->WaitBlockList = WaitBlock = WaitBlockArray;
-      
-        /* Check if the wait is (already) satisfied */
-        AllObjectsSignaled = TRUE;
-        
-        /* First, we'll try to satisfy the wait directly */
-        for (WaitIndex = 0; WaitIndex < Count; WaitIndex++) {
-            
-            /* 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) {
-                   
-                DPRINT1("Hack used: %x\n", &((PFILE_OBJECT)CurrentObject)->Event);
-                CurrentObject = (PDISPATCHER_HEADER)(&((PFILE_OBJECT)CurrentObject)->Event);
-            }
+   DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
+          "PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread());
 
-            /* Check if the Object is Signaled */
-            if (KiIsObjectSignaled(CurrentObject, CurrentThread)) {
-                
-                /* Check what kind of wait this is */ 
-                if (WaitType == WaitAny) {
-                    
-                    /* This is a Wait Any, so just unwait this guy and exit */
-                    if (CurrentObject->SignalState != MINLONG) {
-                        
-                        /* It has a normal signal state, so unwait it and return */
-                        KiSatisfyObjectWait(CurrentObject, CurrentThread);
-                        Status = STATUS_WAIT_0 | WaitIndex;
-                        goto WaitDone;
-                        
-                    } else {
-                        
-                        /* Is this a Mutant? */
-                        if (CurrentObject->Type == MutantObject) {
-                            
-                            /* According to wasm.ru, we must raise this exception (tested and true) */
-                            KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
-                            ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);                    
-                        } 
-                    }
-                }
-                
-            } else {
-                    
-                /* One of the objects isn't signaled... if this is a WaitAll, we will fail later */
-                AllObjectsSignaled = FALSE;
-            }
+   ASSERT(0 < Count && Count <= MAXIMUM_WAIT_OBJECTS);
 
-            /* Set up a Wait Block for this Object */
-            WaitBlock->Object = CurrentObject;
-            WaitBlock->Thread = CurrentThread;
-            WaitBlock->WaitKey = (USHORT)(STATUS_WAIT_0 + WaitIndex);
-            WaitBlock->WaitType = (USHORT)WaitType;                       
-            WaitBlock->NextWaitBlock = WaitBlock + 1;
-                
-            /* Move to the next Wait Block */
-            WaitBlock = WaitBlock->NextWaitBlock;
-        }
-       
-        /* Return to the Root Wait Block */
-        WaitBlock--;
-        WaitBlock->NextWaitBlock = NULL;
-            
-        /* Check if this is a Wait All and all the objects are signaled */
-        if ((WaitType == WaitAll) && (AllObjectsSignaled)) {
-                                
-            /* Return to the Root Wait Block */
-            WaitBlock = CurrentThread->WaitBlockList;
-            
-            /* Satisfy their Waits and return to the caller */
-            KiSatisifyMultipleObjectWaits(WaitBlock);
-            Status = STATUS_WAIT_0;
-            goto WaitDone;
-        }
-   
-        /* Make sure we can satisfy the Alertable request */
-        KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status);
-    
-        /* Set the Wait Status */
-        CurrentThread->WaitStatus = Status;
-           
-        /* Enable the Timeout Timer if there was any specified */
-        if (Timeout != NULL) {
-              
-            /* However if 0 timeout was specified, then we must fail since we need to peform a wait */
-            if (!Timeout->QuadPart) {
-                
-                /* Return a timeout */
-                Status = STATUS_TIMEOUT;
-                goto WaitDone;
-            }
-            
-            /* Point to Timer Wait Block and Thread Timer */
-            TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
-            ThreadTimer = &CurrentThread->Timer;
+   CurrentThread = KeGetCurrentThread();
 
-            /* Connect the Timer Wait Block */
-            WaitBlock->NextWaitBlock = TimerWaitBlock;
-            
-            /* Set up the Timer Wait Block */
-            TimerWaitBlock->Object = (PVOID)ThreadTimer;
-            TimerWaitBlock->Thread = CurrentThread;
-            TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
-            TimerWaitBlock->WaitType = WaitAny;
-            TimerWaitBlock->NextWaitBlock = NULL;
-            
-            /* Link the timer to this Wait Block */
-            InitializeListHead(&ThreadTimer->Header.WaitListHead);
+   /*
+    * Work out where we are going to put the wait blocks
+    */
+   if (WaitBlockArray == NULL)
+   {
+      if (Count > THREAD_WAIT_OBJECTS)
+      {
+         DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
+         return (STATUS_UNSUCCESSFUL);
+      }
+      WaitBlockArray = &CurrentThread->WaitBlock[0];
+   }
+   else
+   {
+      if (Count > MAXIMUM_WAIT_OBJECTS)
+      {
+         DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
+         return (STATUS_UNSUCCESSFUL);
+      }
+   }
 
-            /* Insert the Timer into the Timer Lists and enable it */
-            if (!KiInsertTimer(ThreadTimer, *Timeout)) {    
 
-                /* Return a timeout if we couldn't insert the timer for some reason */
-                Status = STATUS_TIMEOUT;
-                goto WaitDone;
-            }
-        }
 
-        /* Insert into Object's Wait List*/
-        WaitBlock = CurrentThread->WaitBlockList;
-        while (WaitBlock) {
-            
-            /* Get the Current Object */
-            CurrentObject = WaitBlock->Object;
-    
-            /* Link the Object to this Wait Block */
-            InsertTailList(&CurrentObject->WaitListHead, &WaitBlock->WaitListEntry);
-            
-            /* Move to the next Wait Block */
-            WaitBlock = WaitBlock->NextWaitBlock;
-        }
-        
-        /* Handle Kernel Queues */
-        if (CurrentThread->Queue) {
-                 
-            DPRINT("Waking Queue\n");
-            KiWakeQueue(CurrentThread->Queue);
-        }
-
-        /* Block the Thread */
-        DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, WaitReason, KeGetCurrentThread());
-        PsBlockThread(&Status, 
-                      Alertable, 
-                      WaitMode,
-                      (UCHAR)WaitReason);
-    
-        /* Check if we were executing an APC */
-        if (Status != STATUS_KERNEL_APC) {
-           
-            /* Return Status */
-            return Status;
-        }
-        
-        DPRINT("Looping Again\n");
-        CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-    
-    } while (TRUE);
-    
-WaitDone:
-    /* Release the Lock, we are done */
-    DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n", KeGetCurrentThread(), Status);
-    KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
-    return Status;
-}
+   /*
+    * Set up the timeout if required
+    */
+   if (Timeout != NULL && Timeout->QuadPart != 0)
+   {
+      KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
+   }
 
-VOID
-FASTCALL
-KiSatisfyObjectWait(PDISPATCHER_HEADER Object,
-                    PKTHREAD Thread)
+   do
+   {
+      if (CurrentThread->WaitNext)
+      {
+         CurrentThread->WaitNext = FALSE;
+         OldIrql = CurrentThread->WaitIrql;
+      }
+      else
+      {
+         OldIrql = KeAcquireDispatcherDatabaseLock ();
+      }
 
-{
-    /* Special case for Mutants */
-    if (Object->Type == MutantObject) {
-     
-        /* Decrease the Signal State */
-        Object->SignalState--;
-        
-        /* Check if it's now non-signaled */
-        if (Object->SignalState == 0) {
-        
-            /* Set the Owner Thread */
-            ((PKMUTANT)Object)->OwnerThread = Thread;
-            
-            /* Disable APCs if needed */
-            Thread->KernelApcDisable -= ((PKMUTANT)Object)->ApcDisable;
+    /* Get the current Wait Status */
+    WaitStatus = CurrentThread->WaitStatus;
+   
+    if (Alertable) {
+    
+        /* If the Thread is Alerted, set the Wait Status accordingly */    
+        if (CurrentThread->Alerted[(int)WaitMode]) {
             
-            /* Check if it's abandoned */
-            if (((PKMUTANT)Object)->Abandoned) {
+            CurrentThread->Alerted[(int)WaitMode] = FALSE;
+            DPRINT("Thread was Alerted\n");
+            WaitStatus = STATUS_ALERTED;
             
-                /* Unabandon it */
-                ((PKMUTANT)Object)->Abandoned = FALSE;
-                
-                /* Return Status */
-                Thread->WaitStatus = STATUS_ABANDONED;
-            }
+        /* If there are User APCs Pending, then we can't really be alertable */
+        } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && 
+                   (WaitMode == UserMode)) {
             
-            /* Insert it into the Mutant List */
-            InsertHeadList(&Thread->MutantListHead, &((PKMUTANT)Object)->MutantListEntry);
+            DPRINT1("APCs are Pending\n");
+            CurrentThread->ApcState.UserApcPending = TRUE;
+            WaitStatus = STATUS_USER_APC;
         }
-    
-    } else if ((Object->Type & TIMER_OR_EVENT_TYPE) == EventSynchronizationObject) {
-    
-        /* These guys (Syncronization Timers and Events) just get un-signaled */
-        Object->SignalState = 0;
         
-    } else if (Object->Type == SemaphoreObject) {
+    /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */
+    } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) {
+            DPRINT1("APCs are Pending\n");
+            WaitStatus = STATUS_USER_APC;
+    }
 
-        /* These ones can have multiple signalings, so we only decrease it */
-        Object->SignalState--;
-    } 
-}
+      /*
+       * Check if the wait is (already) satisfied
+       */
+      CountSignaled = 0;
+      Abandoned = FALSE;
+      for (i = 0; i < Count; i++)
+      {
+         hdr = (DISPATCHER_HEADER *) KiGetWaitableObjectFromObject(Object[i]);
 
-VOID
-FASTCALL
-KiWaitTest(PDISPATCHER_HEADER Object,
-           KPRIORITY Increment)
-{
-    PLIST_ENTRY WaitEntry;
-    PLIST_ENTRY WaitList;
-    PKWAIT_BLOCK CurrentWaitBlock;
-    PKWAIT_BLOCK NextWaitBlock;
-    
-    /* Loop the Wait Entries */
-    DPRINT("KiWaitTest for Object: %x\n", Object);
-    WaitList = &Object->WaitListHead;
-    WaitEntry = WaitList->Flink;
-    while ((WaitEntry != WaitList) && (Object->SignalState > 0)) {
-        
-        /* Get the current wait block */
-        CurrentWaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
-        
-        /* Check the current Wait Mode */
-        if (CurrentWaitBlock->WaitType == WaitAny) {
-        
-            /* Easy case, satisfy only this wait */
-            DPRINT("Satisfiying a Wait any\n");
-            WaitEntry = WaitEntry->Blink;
-            KiSatisfyObjectWait(Object, CurrentWaitBlock->Thread);
-        
-        } else {
-        
-            /* Everything must be satisfied */
-            DPRINT("Checking for a Wait All\n");
-            NextWaitBlock = CurrentWaitBlock->NextWaitBlock;
-            
-            /* Loop first to make sure they are valid */
-            while (NextWaitBlock) {
-            
-                /* Check if the object is signaled */
-                if (!KiIsObjectSignaled(Object, CurrentWaitBlock->Thread)) {
-                
-                    /* It's not, move to the next one */
-                    DPRINT1("One of the object is non-signaled, sorry.\n");
-                    goto SkipUnwait;
-                }
-                
-                /* Go to the next Wait block */
-                NextWaitBlock = NextWaitBlock->NextWaitBlock;
+         if (KiIsObjectSignalled(hdr, CurrentThread))
+         {
+            CountSignaled++;
+
+            if (WaitType == WaitAny)
+            {
+               Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
+
+               KeReleaseDispatcherDatabaseLock(OldIrql);               
+               
+               if (Timeout != NULL && Timeout->QuadPart != 0)
+               {
+                  KeCancelTimer(&CurrentThread->Timer);
+               }
+
+               DPRINT("One object is (already) signaled!\n");
+               if (Abandoned == TRUE)
+               {
+                  return (STATUS_ABANDONED_WAIT_0 + i);
+               }
+
+               return (STATUS_WAIT_0 + i);
             }
-                       
-            /* All the objects are signaled, we can satisfy */
-            DPRINT("Satisfiying a Wait All\n");
-            WaitEntry = WaitEntry->Blink;
-            KiSatisifyMultipleObjectWaits(CurrentWaitBlock);
-        }
-        
-        /* All waits satisfied, unwait the thread */
-        DPRINT("Unwaiting the Thread\n");
-        KiAbortWaitThread(CurrentWaitBlock->Thread, CurrentWaitBlock->WaitKey);
+         }
+      }
 
-SkipUnwait:
-        /* Next entry */
-        WaitEntry = WaitEntry->Flink;
-    }
-    
-    DPRINT("Done\n");
-}               
+      Abandoned = FALSE;
+      if ((WaitType == WaitAll) && (CountSignaled == Count))
+      {
+         for (i = 0; i < Count; i++)
+         {
+            hdr = (DISPATCHER_HEADER *) KiGetWaitableObjectFromObject(Object[i]);
+            Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
+         }
 
-/* Must be called with the dispatcher lock held */
-VOID
-FASTCALL 
-KiAbortWaitThread(PKTHREAD Thread, 
-                  NTSTATUS WaitStatus)
-{
-    PKWAIT_BLOCK WaitBlock;
+         KeReleaseDispatcherDatabaseLock(OldIrql);
+         
+         if (Timeout != NULL && Timeout->QuadPart != 0)
+         {
+            KeCancelTimer(&CurrentThread->Timer);
+         }
 
-    /* If we are blocked, we must be waiting on something also */
-    DPRINT("KiAbortWaitThread: %x, Status: %x, %x \n", Thread, WaitStatus, Thread->WaitBlockList);
-    ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != NULL));
+         DPRINT("All objects are (already) signaled!\n");
 
-    /* Remove the Wait Blocks from the list */
-    DPRINT("Removing waits\n");
-    WaitBlock = Thread->WaitBlockList;
-    while (WaitBlock) {
-        
-        /* Remove it */
-        DPRINT("Removing Waitblock: %x, %x\n", WaitBlock, WaitBlock->NextWaitBlock);
-        RemoveEntryList(&WaitBlock->WaitListEntry);
-        
-        /* Go to the next one */
-        WaitBlock = WaitBlock->NextWaitBlock;
-    };
-    
-    /* Check if there's a Thread Timer */
-    if (Thread->Timer.Header.Inserted) {
-    
-        /* Cancel the Thread Timer with the no-lock fastpath */
-        DPRINT("Removing the Thread's Timer\n");
-        Thread->Timer.Header.Inserted = FALSE;
-        RemoveEntryList(&Thread->Timer.TimerListEntry);
-    }
-    
-    /* Increment the Queue's active threads */
-    if (Thread->Queue) {
-    
-        DPRINT("Incrementing Queue's active threads\n");
-        Thread->Queue->CurrentCount++;
-    }
+         if (Abandoned == TRUE)
+         {
+            return (STATUS_ABANDONED_WAIT_0);
+         }
 
-    /* Reschedule the Thread */
-    DPRINT("Unblocking the Thread\n");
-    PsUnblockThread((PETHREAD)Thread, &WaitStatus, 0);
-}
+         return (STATUS_WAIT_0);
+      }
 
-BOOLEAN
-inline
-FASTCALL
-KiIsObjectSignaled(PDISPATCHER_HEADER Object,
-                   PKTHREAD Thread)
-{
-    /* Mutants are...well...mutants! */
-   if (Object->Type == MutantObject) {
-
-        ASSERT(hdr->SignalState <= 1);
-
-        /* 
-         * Because Cutler hates mutants, they are actually signaled if the Signal State is <= 0
-         * Well, only if they are recursivly acquired (i.e if we own it right now).
-         * Of course, they are also signaled if their signal state is 1.
-         */
-        if ((Object->SignalState <= 0 && ((PKMUTANT)Object)->OwnerThread == Thread) || 
-            (Object->SignalState == 1)) {
-            
-            /* Signaled Mutant */
-            return (TRUE);
-            
-        } else {
-            
-            /* Unsignaled Mutant */
-            return (FALSE);
-        }
-    }
-    
-    /* Any other object is not a mutated freak, so let's use logic */
-   return (!Object->SignalState <= 0);
-}
+      //zero timeout is used for testing if the object(s) can be immediately acquired
+      if (Timeout != NULL && Timeout->QuadPart == 0)
+      {
+         KeReleaseDispatcherDatabaseLock(OldIrql);
+         return STATUS_TIMEOUT;
+      }
 
-BOOL
-inline
-FASTCALL
-KiIsObjectWaitable(PVOID Object)
-{
-    POBJECT_HEADER Header;
-    Header = BODY_TO_HEADER(Object);
-    
-    if (Header->ObjectType == ExEventObjectType ||
-        Header->ObjectType == ExIoCompletionType ||
-        Header->ObjectType == ExMutantObjectType ||
-        Header->ObjectType == ExSemaphoreObjectType ||
-        Header->ObjectType == ExTimerType ||
-        Header->ObjectType == PsProcessType ||
-        Header->ObjectType == PsThreadType ||
-        Header->ObjectType == IoFileObjectType) {
-        
-        return TRUE;
-    
-    } else {
-        
-        return FALSE;
-    }
-}
+      /*
+       * Check if we have already timed out
+       */
+      if (Timeout != NULL && KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
+      {
+         KiSideEffectsBeforeWake(&CurrentThread->Timer.Header, CurrentThread);
+         KeReleaseDispatcherDatabaseLock(OldIrql);
+         KeCancelTimer(&CurrentThread->Timer);
+         return (STATUS_TIMEOUT);
+      }
 
-VOID
-inline
-FASTCALL
-KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock)
-{
-    PKTHREAD WaitThread = WaitBlock->Thread;
-    
-    /* Loop through all the Wait Blocks, and wake each Object */
-    while (WaitBlock) {
+      /* Append wait block to the KTHREAD wait block list */
+      CurrentThread->WaitBlockList = blk = WaitBlockArray;
+
+      /*
+       * Set up the wait
+       */
+      CurrentThread->WaitStatus = WaitStatus;;
+
+      for (i = 0; i < Count; i++)
+      {
+         hdr = (DISPATCHER_HEADER *) KiGetWaitableObjectFromObject(Object[i]);
+
+         blk->Object = KiGetWaitableObjectFromObject(Object[i]);
+         blk->Thread = CurrentThread;
+         blk->WaitKey = (USHORT)(STATUS_WAIT_0 + i);
+         blk->WaitType = (USHORT)WaitType;
+
+         if (i == (Count - 1))
+         {
+            if (Timeout != NULL)
+            {
+               blk->NextWaitBlock = &CurrentThread->WaitBlock[3];
+            }
+            else
+            {
+               blk->NextWaitBlock = NULL;
+            }
+         }
+         else
+         {
+            blk->NextWaitBlock = blk + 1;
+         }
+
+         /*
+          * add wait block to disp. obj. wait list
+          * Use FIFO for all waits except for queues which use LIFO
+          */
+         if (WaitReason == WrQueue)
+         {
+            InsertHeadList(&hdr->WaitListHead, &blk->WaitListEntry);
+         }
+         else
+         {
+            InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry);
+         }
+
+         blk = blk->NextWaitBlock;
+      }
+
+      if (Timeout != NULL)
+      {
+         CurrentThread->WaitBlock[3].Object = (PVOID) & CurrentThread->Timer;
+         CurrentThread->WaitBlock[3].Thread = CurrentThread;
+         CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
+         CurrentThread->WaitBlock[3].WaitType = WaitAny;
+         CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
+
+         InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
+                        &CurrentThread->WaitBlock[3].WaitListEntry);
+      }
+
+      //kernel queues
+      if (CurrentThread->Queue && WaitReason != WrQueue)
+      {
+         DPRINT("queue: sleep on something else\n");
+         CurrentThread->Queue->CurrentCount--;  
          
-        /* Wake the Object */
-        KiSatisfyObjectWait(WaitBlock->Object, WaitThread);
-        WaitBlock = WaitBlock->NextWaitBlock;
-    }      
-}
+         //wake another thread
+         if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
+             !IsListEmpty(&CurrentThread->Queue->EntryListHead))
+         {
+            KiDispatcherObjectWake(&CurrentThread->Queue->Header, IO_NO_INCREMENT);
+         }
+      }
 
-VOID
-inline
-FASTCALL
-KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
-                             ULONG Type,
-                             ULONG Size,
-                             ULONG SignalState)
-{
-    Header->Type = (UCHAR)Type;
-    Header->Absolute = 0;
-    Header->Inserted = 0;
-    Header->Size = (UCHAR)Size;
-    Header->SignalState = SignalState;
-    InitializeListHead(&(Header->WaitListHead));
-}
+      PsBlockThread(&Status, Alertable, WaitMode, TRUE, OldIrql, (UCHAR)WaitReason);
 
-KIRQL
-inline
-FASTCALL
-KeAcquireDispatcherDatabaseLock(VOID)
-{
-    KIRQL OldIrql;
+      //kernel queues
+      OldIrql = KeAcquireDispatcherDatabaseLock ();
+      if (CurrentThread->Queue && WaitReason != WrQueue)
+      {
+         DPRINT("queue: wake from something else\n");
+         CurrentThread->Queue->CurrentCount++;
+      }
+      if (Status == STATUS_KERNEL_APC)
+      {
+         CurrentThread->WaitNext = TRUE;
+         CurrentThread->WaitIrql = OldIrql;
+      }
+      else
+      {
+         KeReleaseDispatcherDatabaseLock(OldIrql);
+      }
+      
+   } while (Status == STATUS_KERNEL_APC);
+   
 
-    KeAcquireSpinLock (&DispatcherDatabaseLock, &OldIrql);
-    return OldIrql;
+   if (Timeout != NULL)
+   {
+      KeCancelTimer(&CurrentThread->Timer);
+   }
+
+   DPRINT("Returning from KeWaitForMultipleObjects()\n");
+   return (Status);
 }
 
-VOID
-inline
-FASTCALL
-KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID)
+VOID KeInitializeDispatcher(VOID)
 {
-    KeAcquireSpinLockAtDpcLevel (&DispatcherDatabaseLock);
+   KeInitializeSpinLock(&DispatcherDatabaseLock);
 }
 
-VOID 
-inline
-FASTCALL
-KeInitializeDispatcher(VOID)
+NTSTATUS STDCALL
+NtWaitForMultipleObjects(IN ULONG ObjectCount,
+                        IN PHANDLE ObjectsArray,
+                        IN WAIT_TYPE WaitType,
+                        IN BOOLEAN Alertable,
+                        IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
-    /* Initialize the Dispatcher Lock */
-    KeInitializeSpinLock(&DispatcherDatabaseLock);
+   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;
+
+   DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
+         "TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
+
+   PreviousMode = ExGetPreviousMode();
+
+   if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
+     return STATUS_UNSUCCESSFUL;
+   if (0 == ObjectCount)
+     return STATUS_INVALID_PARAMETER;
+
+   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;
+       
+       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;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   /* 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])->ObjectType->TypeName);
+                Status = STATUS_HANDLE_NOT_WAITABLE;
+                i++;
+              }
+             /* dereference all referenced objects */
+             for (j = 0; j < i; j++)
+               {
+                  ObDereferenceObject(ObjectPtrArray[j]);
+               }
+
+             return(Status);
+          }
+     }
+
+   Status = KeWaitForMultipleObjects(ObjectCount,
+                                     ObjectPtrArray,
+                                     WaitType,
+                                     UserRequest,
+                                     PreviousMode,
+                                     Alertable,
+                                    TimeOut,
+                                     WaitBlockArray);
+
+   /* dereference all objects */
+   for (i = 0; i < ObjectCount; i++)
+     {
+        ObDereferenceObject(ObjectPtrArray[i]);
+     }
+
+   return(Status);
 }
 
-VOID
-inline
-FASTCALL
-KeReleaseDispatcherDatabaseLock(KIRQL OldIrql)
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtWaitForSingleObject(IN HANDLE ObjectHandle,
+                     IN BOOLEAN Alertable,
+                     IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
-    /* If it's the idle thread, dispatch */
-    if (!KeIsExecutingDpc() && OldIrql < DISPATCH_LEVEL && KeGetCurrentThread() != NULL && 
-        KeGetCurrentThread() == KeGetCurrentKPCR()->PrcbData.IdleThread) {
-        
-        PsDispatchThreadNoLock(THREAD_STATE_READY);
-        KeLowerIrql(OldIrql);
-        
-    } else {
-        
-        /* Just release the spin lock */
-        KeReleaseSpinLock(&DispatcherDatabaseLock, OldIrql);
-    }
+   PVOID ObjectPtr;
+   KPROCESSOR_MODE PreviousMode;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
+         ObjectHandle,Alertable,TimeOut);
+
+   PreviousMode = ExGetPreviousMode();
+   
+   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;
+     }
+   }
+
+   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)->ObjectType->TypeName);
+       Status = STATUS_HANDLE_NOT_WAITABLE;
+     }
+   else
+     {
+       Status = KeWaitForSingleObject(ObjectPtr,
+                                     UserRequest,
+                                     PreviousMode,
+                                     Alertable,
+                                     TimeOut);
+     }
+
+   ObDereferenceObject(ObjectPtr);
+
+   return(Status);
 }
 
-VOID
-inline
-FASTCALL
-KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID)
+
+NTSTATUS STDCALL
+NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
+                              IN HANDLE WaitableObjectHandle,
+                              IN BOOLEAN Alertable,
+                              IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
-    KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
-}
+   KPROCESSOR_MODE PreviousMode;
+   DISPATCHER_HEADER* hdr;
+   PVOID SignalObj;
+   PVOID WaitObj;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
 
-/* EOF */
+   PreviousMode = ExGetPreviousMode();
+   
+   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;
+     }
+   }
+   
+   Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
+                                     0,
+                                     NULL,
+                                     PreviousMode,
+                                     &SignalObj,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+
+   Status = ObReferenceObjectByHandle(WaitableObjectHandle,
+                                     SYNCHRONIZE,
+                                     NULL,
+                                     PreviousMode,
+                                     &WaitObj,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       ObDereferenceObject(SignalObj);
+       return Status;
+     }
+
+   hdr = (DISPATCHER_HEADER *)SignalObj;
+   switch (hdr->Type)
+     {
+      case InternalNotificationEvent:
+      case InternalSynchronizationEvent:
+       KeSetEvent(SignalObj,
+                  EVENT_INCREMENT,
+                  TRUE);
+       break;
+
+      case InternalMutexType:
+       KeReleaseMutex(SignalObj,
+                      TRUE);
+       break;
+
+      case InternalSemaphoreType:
+       KeReleaseSemaphore(SignalObj,
+                          SEMAPHORE_INCREMENT,
+                          1,
+                          TRUE);
+       break;
+
+      default:
+       ObDereferenceObject(SignalObj);
+       ObDereferenceObject(WaitObj);
+       return STATUS_OBJECT_TYPE_MISMATCH;
+     }
+
+   Status = KeWaitForSingleObject(WaitObj,
+                                 UserRequest,
+                                 PreviousMode,
+                                 Alertable,
+                                 TimeOut);
+
+   ObDereferenceObject(SignalObj);
+   ObDereferenceObject(WaitObj);
+
+   return Status;
+}
index 4063cc5..461ebe6 100644 (file)
@@ -122,6 +122,7 @@ ExIsResourceAcquiredExclusiveLite@4
 ExIsResourceAcquiredSharedLite@4
 ExLocalTimeToSystemTime@8
 ExNotifyCallback@12
+ExPostSystemEvent@12
 ExQueryPoolBlockSize@8
 ExQueueWorkItem@8
 ExRaiseAccessViolation@0
@@ -529,7 +530,7 @@ Ke386IoSetAccessProcess@8
 Ke386QueryIoAccessMap@8
 Ke386SetIoAccessMap@8
 KeAcquireSpinLockAtDpcLevel@4
-@KeAcquireDispatcherDatabaseLockAtDpcLevel@0
+KeAcquireDispatcherDatabaseLockAtDpcLevel
 @KeAcquireInStackQueuedSpinLockAtDpcLevel@8
 KeAcquireInterruptSpinLock@4
 KeAddSystemServiceTable@20
@@ -610,7 +611,7 @@ KeReadStateSemaphore@4
 KeReadStateTimer@4
 KeRegisterBugCheckCallback@20
 KeRegisterBugCheckReasonCallback@16
-@KeReleaseDispatcherDatabaseLockFromDpcLevel@0
+KeReleaseDispatcherDatabaseLockFromDpcLevel
 @KeReleaseInStackQueuedSpinLockFromDpcLevel@4
 KeReleaseInterruptSpinLock@8
 KeReleaseMutant@16
index fafa73a..1458a0e 100644 (file)
@@ -987,22 +987,6 @@ Language=English
 INVALID_WORK_QUEUE_ITEM
 .
 
-MessageId=0xE1
-Severity=Success
-Facility=System
-SymbolicName=WORKER_THREAD_RETURNED_AT_BAD_IRQL
-Language=English
-WORKER_THREAD_RETURNED_AT_BAD_IRQL
-.
-
-MessageId=0xFA
-Severity=Success
-Facility=System
-SymbolicName=IMPERSONATING_WORKER_THREAD
-Language=English
-IMPERSONATING_WORKER_THREAD
-.
-
 MessageId=0x9A
 Severity=Informational
 Facility=System
diff --git a/reactos/ntoskrnl/ob/wait.c b/reactos/ntoskrnl/ob/wait.c
deleted file mode 100644 (file)
index 1b693c6..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * COPYRIGHT:          See COPYING in the top level directory
- * PROJECT:            ReactOS kernel
- * FILE:               ntoskrnl/ob/wait.c
- * PURPOSE:            Handles Waiting on Objects
- * 
- * PROGRAMMERS:        Alex Ionescu (alex@relsoft.net) - Created file
- *                     David Welch (welch@mcmail.com)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-BOOL inline FASTCALL KiIsObjectWaitable(PVOID Object);
-
-NTSTATUS STDCALL
-NtWaitForMultipleObjects(IN ULONG ObjectCount,
-                        IN PHANDLE ObjectsArray,
-                        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;
-
-   DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
-         "TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
-
-   PreviousMode = ExGetPreviousMode();
-
-   if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
-     return STATUS_UNSUCCESSFUL;
-   if (0 == ObjectCount)
-     return STATUS_INVALID_PARAMETER;
-
-   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;
-       
-       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;
-     
-     if(!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-   }
-
-   /* 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])->ObjectType->TypeName);
-                Status = STATUS_HANDLE_NOT_WAITABLE;
-                i++;
-              }
-             /* dereference all referenced objects */
-             for (j = 0; j < i; j++)
-               {
-                  ObDereferenceObject(ObjectPtrArray[j]);
-               }
-
-             return(Status);
-          }
-     }
-
-   Status = KeWaitForMultipleObjects(ObjectCount,
-                                     ObjectPtrArray,
-                                     WaitType,
-                                     UserRequest,
-                                     PreviousMode,
-                                     Alertable,
-                                    TimeOut,
-                                     WaitBlockArray);
-
-   /* dereference all objects */
-   for (i = 0; i < ObjectCount; i++)
-     {
-        ObDereferenceObject(ObjectPtrArray[i]);
-     }
-
-   return(Status);
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-NtWaitForSingleObject(IN HANDLE ObjectHandle,
-                     IN BOOLEAN Alertable,
-                     IN PLARGE_INTEGER TimeOut  OPTIONAL)
-{
-   PVOID ObjectPtr;
-   KPROCESSOR_MODE PreviousMode;
-   LARGE_INTEGER SafeTimeOut;
-   NTSTATUS Status = STATUS_SUCCESS;
-
-   DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
-         ObjectHandle,Alertable,TimeOut);
-
-   PreviousMode = ExGetPreviousMode();
-   
-   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;
-     }
-   }
-
-   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)->ObjectType->TypeName);
-       Status = STATUS_HANDLE_NOT_WAITABLE;
-     }
-   else
-     {
-       Status = KeWaitForSingleObject(ObjectPtr,
-                                     UserRequest,
-                                     PreviousMode,
-                                     Alertable,
-                                     TimeOut);
-     }
-
-   ObDereferenceObject(ObjectPtr);
-
-   return(Status);
-}
-
-
-NTSTATUS STDCALL
-NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
-                              IN HANDLE WaitableObjectHandle,
-                              IN BOOLEAN Alertable,
-                              IN PLARGE_INTEGER TimeOut  OPTIONAL)
-{
-   KPROCESSOR_MODE PreviousMode;
-   DISPATCHER_HEADER* hdr;
-   PVOID SignalObj;
-   PVOID WaitObj;
-   LARGE_INTEGER SafeTimeOut;
-   NTSTATUS Status = STATUS_SUCCESS;
-
-   PreviousMode = ExGetPreviousMode();
-   
-   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;
-     }
-   }
-   
-   Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
-                                     0,
-                                     NULL,
-                                     PreviousMode,
-                                     &SignalObj,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return Status;
-     }
-
-   Status = ObReferenceObjectByHandle(WaitableObjectHandle,
-                                     SYNCHRONIZE,
-                                     NULL,
-                                     PreviousMode,
-                                     &WaitObj,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       ObDereferenceObject(SignalObj);
-       return Status;
-     }
-
-   hdr = (DISPATCHER_HEADER *)SignalObj;
-   switch (hdr->Type)
-     {
-      case EventNotificationObject:
-      case EventSynchronizationObject:
-       KeSetEvent(SignalObj,
-                  EVENT_INCREMENT,
-                  TRUE);
-       break;
-
-      case MutantObject:
-       KeReleaseMutex(SignalObj,
-                      TRUE);
-       break;
-
-      case SemaphoreObject:
-       KeReleaseSemaphore(SignalObj,
-                          SEMAPHORE_INCREMENT,
-                          1,
-                          TRUE);
-       break;
-
-      default:
-       ObDereferenceObject(SignalObj);
-       ObDereferenceObject(WaitObj);
-       return STATUS_OBJECT_TYPE_MISMATCH;
-     }
-
-   Status = KeWaitForSingleObject(WaitObj,
-                                 UserRequest,
-                                 PreviousMode,
-                                 Alertable,
-                                 TimeOut);
-
-   ObDereferenceObject(SignalObj);
-   ObDereferenceObject(WaitObj);
-
-   return Status;
-}
-
-/* EOF */
index 6344b7e..1837f09 100644 (file)
@@ -204,7 +204,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
 
    oldIrql = KeAcquireDispatcherDatabaseLock();
    CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
-   KiWaitTest(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
+   KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
    KeReleaseDispatcherDatabaseLock (oldIrql);
 
    /* The last thread shall close the door on exit */
@@ -331,7 +331,7 @@ PiTerminateProcess(PEPROCESS Process,
    }
    OldIrql = KeAcquireDispatcherDatabaseLock ();
    Process->Pcb.DispatcherHeader.SignalState = TRUE;
-   KiWaitTest(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
+   KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
    KeReleaseDispatcherDatabaseLock (OldIrql);
    ObDereferenceObject(Process);
    return(STATUS_SUCCESS);
index 94d5f83..ac2f018 100644 (file)
@@ -374,7 +374,7 @@ PsInitProcessManagment(VOID)
    PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
    InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
    KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
-                               ProcessObject,
+                               InternalProcessType,
                                sizeof(EPROCESS),
                                FALSE);
    KProcess = &PsInitialSystemProcess->Pcb;
@@ -823,7 +823,7 @@ exitdereferenceobjects:
    }
 
    KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
-                               ProcessObject,
+                               InternalProcessType,
                                sizeof(EPROCESS),
                                FALSE);
 
index 4c21a91..ee9ad92 100644 (file)
@@ -437,7 +437,6 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
 
            OldThread = CurrentThread;
            CurrentThread = Candidate;
-            
            IdleThread = KeGetCurrentKPCR()->PrcbData.IdleThread;
 
            if (&OldThread->Tcb == IdleThread)
@@ -546,46 +545,49 @@ PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment)
 }
 
 VOID
-STDCALL
-PsBlockThread(PNTSTATUS Status, 
-              UCHAR Alertable, 
-              ULONG WaitMode,
-              UCHAR WaitReason)
+PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
+             BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason)
 {
-    PKTHREAD Thread = KeGetCurrentThread();
-    PKWAIT_BLOCK WaitBlock;
+  KIRQL oldIrql;
+  PKTHREAD KThread;
+  PETHREAD Thread;
+  PKWAIT_BLOCK WaitBlock;
 
-    if (Thread->ApcState.KernelApcPending) {
-    
-        DPRINT("Dispatching Thread as ready (APC!)\n");
-        
-        /* Remove Waits */
-        WaitBlock = Thread->WaitBlockList;
-        while (WaitBlock) {
-            RemoveEntryList (&WaitBlock->WaitListEntry);
-            WaitBlock = WaitBlock->NextWaitBlock;
-        }
-        Thread->WaitBlockList = NULL;
-        
-        /* Dispatch it and return status */
-        PsDispatchThreadNoLock (THREAD_STATE_READY);
-        if (Status != NULL) *Status = STATUS_KERNEL_APC;
-
-    } else {
-
-        /* Set the Thread Data as Requested */
-        DPRINT("Dispatching Thread as blocked\n");
-        Thread->Alertable = Alertable;
-        Thread->WaitMode = (UCHAR)WaitMode;
-        Thread->WaitReason = WaitReason;
-        
-        /* Dispatch it and return status */
-        PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
-        if (Status != NULL) *Status = Thread->WaitStatus;
+  if (!DispatcherLock)
+    {
+      oldIrql = KeAcquireDispatcherDatabaseLock();
     }
-    
-    DPRINT("Releasing Dispatcher Lock\n");
-    KfLowerIrql(Thread->WaitIrql);
+
+  KThread = KeGetCurrentThread();
+  Thread = CONTAINING_RECORD (KThread, ETHREAD, Tcb);
+  if (KThread->ApcState.KernelApcPending)
+  {
+    WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
+    while (WaitBlock)
+      {
+       RemoveEntryList (&WaitBlock->WaitListEntry);
+       WaitBlock = WaitBlock->NextWaitBlock;
+      }
+    Thread->Tcb.WaitBlockList = NULL;
+    PsDispatchThreadNoLock (THREAD_STATE_READY);
+    if (Status != NULL)
+      {
+       *Status = STATUS_KERNEL_APC;
+      }
+  }
+  else
+    {
+      Thread->Tcb.Alertable = Alertable;
+      Thread->Tcb.WaitMode = (UCHAR)WaitMode;
+      Thread->Tcb.WaitReason = WaitReason;
+      PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
+
+      if (Status != NULL)
+       {
+         *Status = Thread->Tcb.WaitStatus;
+       }
+    }
+  KeLowerIrql(WaitIrql);
 }
 
 VOID
@@ -1052,16 +1054,6 @@ NtYieldExecution(VOID)
   return(STATUS_SUCCESS);
 }
 
-/* 
- * NOT EXPORTED
- */
-NTSTATUS
-STDCALL
-NtTestAlert(VOID)
-{
-    /* Check and Alert Thread if needed */
-    return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
-}
 
 /*
  * @implemented
index e7dfab0..c56345c 100644 (file)
@@ -36,32 +36,7 @@ ULONG NlsUnicodeTableOffset = 0;
 
 /* FUNCTIONS *****************************************************************/
 
-VOID 
-INIT_FUNCTION
-STDCALL
-RtlpInitNls(VOID)
-{
-    ULONG_PTR BaseAddress;
-    
-    /* Import NLS Data */ 
-    BaseAddress = CachedModules[AnsiCodepage]->ModStart;
-    RtlpImportAnsiCodePage((PUSHORT)BaseAddress,
-                           CachedModules[AnsiCodepage]->ModEnd - BaseAddress);
-    
-    BaseAddress = CachedModules[OemCodepage]->ModStart;
-    RtlpImportOemCodePage((PUSHORT)BaseAddress,
-                          CachedModules[OemCodepage]->ModEnd - BaseAddress);
-    
-    BaseAddress = CachedModules[UnicodeCasemap]->ModStart;
-    RtlpImportUnicodeCasemap((PUSHORT)BaseAddress,
-                             CachedModules[UnicodeCasemap]->ModEnd - BaseAddress);
-    
-    /* Create initial NLS tables */
-    RtlpCreateInitialNlsTables();
-    
-    /* Create the NLS section */
-    RtlpCreateNlsSection();    
-}
+
 
 VOID INIT_FUNCTION
 RtlpImportAnsiCodePage(PUSHORT TableBase,
index 7b76c79..f52329e 100644 (file)
@@ -180,6 +180,7 @@ NtSetEaFile 4
 NtSetEvent 2
 NtSetHighEventPair 1
 NtSetHighWaitLowEventPair 1
+NtSetHighWaitLowThread 0
 NtSetInformationFile 5
 NtSetInformationKey 4
 NtSetInformationJobObject 4
@@ -191,6 +192,7 @@ NtSetIntervalProfile 2
 NtSetLdtEntries 6
 NtSetLowEventPair 1
 NtSetLowWaitHighEventPair 1
+NtSetLowWaitHighThread 0
 NtSetQuotaInformationFile 4
 NtSetSecurityObject 3
 NtSetSystemEnvironmentValue 2