From cfdb595cc63a7b986aee32952f1eb5a11138c329 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Mon, 14 Mar 2005 02:08:17 +0000 Subject: [PATCH] Alex Ionescu Dispatcher Objects Rewrite (minus Queues, coming in next patch). Global Changes: - Use KOBJECT enumerations for all objects, remove obsoleted ros-internal enumeration. - Reformatting, commenting, and addition of Debug Prints for easier debugging - Properly create Executive Objects. They don't need a creation routine. - Make sure to properly lock and release the Dispatcher Database. Mutex/Mutant: - Correct MUTANT_BASIC_INFORMATION - Return previous state in Kernel Functions, intead of 1 or 0 all the time. - Initialize listhead properly - Removed code duplication between mutant and mutex release. - Fix bugs in release - Add proper exeption if the mutex is not owned. Kernel Queues: - Optimize the code - Use Inserted Flag Timers: - Some changes in setting the default data to allow KiInsertTimer to be called internally by the wait code in the next patch. Events: - Optimize and simplify KeInitializeEvent - Implement KeInitializeEventPair - Fix KePulseEvent. It was completely messed up and also used unneeded Interlocked function. - Fix KeResetEvent. It was not locking the dispatcher lock but using Interlocked. - Fix KeSetEvent. It was not differentiating between Notification and Sycronization events and also signaling the Event even if nobody was waiting on it. Semaphores: - Fix KeReleaseSemaphore. It was not checking if nobody was waiting on it before unwaiting the thread. - Fix not releasing dispatcher database before raising an exception. - Add check to NtCreateSemaphore to make sure the counts make sense. Event Pairs: - Remove Thread Event Pair. They are only used for NT4 QuickLPC which is obsoleted. - Use KeInitializeEventPair svn path=/trunk/; revision=14045 --- reactos/include/ddk/iotypes.h | 2 + reactos/include/ntos/zwtypes.h | 7 +- reactos/ntoskrnl/ex/event.c | 964 ++++++++++++------------- reactos/ntoskrnl/ex/evtpair.c | 859 +++++++++------------- reactos/ntoskrnl/ex/mutant.c | 621 ++++++++-------- reactos/ntoskrnl/ex/rundown.c | 5 +- reactos/ntoskrnl/ex/sem.c | 639 ++++++++-------- reactos/ntoskrnl/ex/timer.c | 120 +-- reactos/ntoskrnl/include/internal/id.h | 19 - reactos/ntoskrnl/include/internal/ke.h | 4 +- reactos/ntoskrnl/include/ntoskrnl.h | 1 - reactos/ntoskrnl/io/create.c | 4 +- reactos/ntoskrnl/io/driver.c | 2 +- reactos/ntoskrnl/io/wmi.c | 14 + reactos/ntoskrnl/ke/device.c | 4 +- reactos/ntoskrnl/ke/event.c | 322 ++++++--- reactos/ntoskrnl/ke/kqueue.c | 405 ++++++----- reactos/ntoskrnl/ke/mutex.c | 342 +++++---- reactos/ntoskrnl/ke/queue.c | 2 +- reactos/ntoskrnl/ke/sem.c | 114 +-- reactos/ntoskrnl/ke/timer.c | 12 +- reactos/ntoskrnl/ke/wait.c | 44 +- reactos/ntoskrnl/ps/process.c | 4 +- reactos/tools/nci/sysfuncs.lst | 2 - 24 files changed, 2238 insertions(+), 2274 deletions(-) delete mode 100644 reactos/ntoskrnl/include/internal/id.h diff --git a/reactos/include/ddk/iotypes.h b/reactos/include/ddk/iotypes.h index bca07696b55..379cfc88a5a 100644 --- a/reactos/include/ddk/iotypes.h +++ b/reactos/include/ddk/iotypes.h @@ -886,6 +886,8 @@ 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 diff --git a/reactos/include/ntos/zwtypes.h b/reactos/include/ntos/zwtypes.h index da23d54efc1..2f7960c65cc 100755 --- a/reactos/include/ntos/zwtypes.h +++ b/reactos/include/ntos/zwtypes.h @@ -58,6 +58,7 @@ typedef enum _KPROFILE_SOURCE ProfileTime } KPROFILE_SOURCE; + // file disposition values #define FILE_SUPERSEDE 0x0000 @@ -1271,9 +1272,9 @@ typedef enum _MUTANT_INFORMATION_CLASS typedef struct _MUTANT_BASIC_INFORMATION { - LONG Count; - BOOLEAN Owned; - BOOLEAN Abandoned; + LONG CurrentCount; + BOOLEAN OwnedByCaller; + BOOLEAN AbandonedState; } MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION; diff --git a/reactos/ntoskrnl/ex/event.c b/reactos/ntoskrnl/ex/event.c index 4db20f50ba5..0e52ef76240 100644 --- a/reactos/ntoskrnl/ex/event.c +++ b/reactos/ntoskrnl/ex/event.c @@ -1,11 +1,11 @@ -/* $Id:$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/nt/event.c * PURPOSE: Named event support * - * PROGRAMMERS: Philip Susi and David Welch + * PROGRAMMERS: Alex Ionescu(alex@relsoft.net) - Fixed bugs/commented + * Philip Susi and David Welch */ /* INCLUDES *****************************************************************/ @@ -19,531 +19,491 @@ 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}; + 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 */ +static const INFORMATION_CLASS_INFO ExEventInfoClass[] = { + + /* EventBasicInformation */ + ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY), }; /* FUNCTIONS *****************************************************************/ -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 +VOID +INIT_FUNCTION ExpInitializeEventImplementation(VOID) { - 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); + /* Create the Event Object Type */ + ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + RtlInitUnicodeString(&ExEventObjectType->TypeName, L"Event"); + 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); } - /* * @implemented */ -NTSTATUS STDCALL +NTSTATUS +STDCALL NtClearEvent(IN HANDLE EventHandle) { - PKEVENT Event; - NTSTATUS Status; + PKEVENT Event; + NTSTATUS Status; + + PAGED_CODE(); - PAGED_CODE(); + /* Reference the Object */ + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + ExGetPreviousMode(), + (PVOID*)&Event, + NULL); - Status = ObReferenceObjectByHandle(EventHandle, - EVENT_MODIFY_STATE, - ExEventObjectType, - ExGetPreviousMode(), - (PVOID*)&Event, - NULL); - if(NT_SUCCESS(Status)) - { - KeClearEvent(Event); - ObDereferenceObject(Event); - } + /* Check for Success */ + if(NT_SUCCESS(Status)) { + + /* Clear the Event and Dereference */ + KeClearEvent(Event); + ObDereferenceObject(Event); + } - return Status; + /* Return Status */ + return Status; } /* * @implemented */ -NTSTATUS STDCALL -NtCreateEvent(OUT PHANDLE EventHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN EVENT_TYPE EventType, - IN BOOLEAN InitialState) -{ - KPROCESSOR_MODE PreviousMode; - PKEVENT Event; - HANDLE hEvent; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - 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; - } - } - - 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 -NtOpenEvent(OUT PHANDLE EventHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - HANDLE hEvent; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - 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; - } - } - - Status = ObOpenObjectByName(ObjectAttributes, - ExEventObjectType, - NULL, - PreviousMode, - DesiredAccess, - NULL, - &hEvent); - - if(NT_SUCCESS(Status)) - { - _SEH_TRY - { - *EventHandle = hEvent; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - - return Status; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtPulseEvent(IN HANDLE EventHandle, - OUT PLONG PreviousState OPTIONAL) -{ - PKEVENT Event; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - 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; - - 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; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtQueryEvent(IN HANDLE EventHandle, - IN EVENT_INFORMATION_CLASS EventInformationClass, - OUT PVOID EventInformation, - IN ULONG EventInformationLength, - OUT PULONG ReturnLength OPTIONAL) -{ - PKEVENT Event; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - 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; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtResetEvent(IN HANDLE EventHandle, - OUT PLONG PreviousState OPTIONAL) -{ - PKEVENT Event; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - 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; - } - } - - Status = ObReferenceObjectByHandle(EventHandle, - EVENT_MODIFY_STATE, - ExEventObjectType, - PreviousMode, - (PVOID*)&Event, - NULL); - if(NT_SUCCESS(Status)) - { - LONG Prev = KeResetEvent(Event); - ObDereferenceObject(Event); - - if(PreviousState != NULL) - { - _SEH_TRY - { - *PreviousState = Prev; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - } - - return Status; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtSetEvent(IN HANDLE EventHandle, - OUT PLONG PreviousState OPTIONAL) -{ - PKEVENT Event; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - 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; - } - } - - 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; -} - - -/* - * @unimplemented - */ -NTSTATUS +NTSTATUS STDCALL -NtTraceEvent( - IN ULONG TraceHandle, - IN ULONG Flags, - IN ULONG TraceHeaderLength, - IN struct _EVENT_TRACE_HEADER* TraceHeader - ) +NtCreateEvent(OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN EVENT_TYPE EventType, + IN BOOLEAN InitialState) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + PKEVENT Event; + HANDLE hEvent; + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + DPRINT("NtCreateEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes); + + /* Check Output Safety */ + if(PreviousMode != KernelMode) { + + _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); + + /* 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; } +/* + * @implemented + */ +NTSTATUS +STDCALL +NtOpenEvent(OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + HANDLE hEvent; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes); + + /* Check Output Safety */ + if(PreviousMode != KernelMode) { + + _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); + + /* 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; +} + +/* + * @implemented + */ +NTSTATUS +STDCALL +NtPulseEvent(IN HANDLE EventHandle, + OUT PLONG PreviousState OPTIONAL) +{ + PKEVENT Event; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + 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; + + 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); + + /* Return it */ + if(PreviousState) { + + _SEH_TRY { + + *PreviousState = Prev; + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; + } + } + + /* Return Status */ + return Status; +} + + +/* + * @implemented + */ +NTSTATUS +STDCALL +NtQueryEvent(IN HANDLE EventHandle, + 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; + + PAGED_CODE(); + DPRINT("NtQueryEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, EventInformationClass); + + /* 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; + } + + /* 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); + } + + /* Return status */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +STDCALL +NtResetEvent(IN HANDLE EventHandle, + OUT PLONG PreviousState OPTIONAL) +{ + PKEVENT Event; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + 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; + } + + /* 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); + + /* Return it */ + if(PreviousState) { + + _SEH_TRY { + + *PreviousState = Prev; + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; + } + } + + /* Return Status */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +STDCALL +NtSetEvent(IN HANDLE EventHandle, + OUT PLONG PreviousState OPTIONAL) +{ + PKEVENT Event; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + DPRINT("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; + } + + /* 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; + } + } + + /* Return Status */ + return Status; +} /* EOF */ diff --git a/reactos/ntoskrnl/ex/evtpair.c b/reactos/ntoskrnl/ex/evtpair.c index 15b05e6bbc3..5bcfb7603ab 100644 --- a/reactos/ntoskrnl/ex/evtpair.c +++ b/reactos/ntoskrnl/ex/evtpair.c @@ -1,11 +1,12 @@ -/* $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: David Welch (welch@mcmail.com) + * PROGRAMMERS: Alex Ionescu (Commented, reorganized, removed Thread Pair, used + * KeInitializeEventPair, added SEH) + * David Welch (welch@mcmail.com) * Skywing (skywing@valhallalegends.com) */ @@ -15,588 +16,404 @@ #define NDEBUG #include -#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 *****************************************************************/ -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 +VOID +INIT_FUNCTION ExpInitializeEventPairImplementation(VOID) { - 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); + /* Create the Event Pair Object Type */ + ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + RtlInitUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair"); + 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); } - -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; - NTSTATUS Status = STATUS_SUCCESS; + PKEVENT_PAIR EventPair; + HANDLE hEventPair; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + DPRINT("NtCreateEventPair: %x\n", EventPairHandle); - PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - - if(PreviousMode == UserMode) - { - _SEH_TRY - { - ProbeForWrite(EventPairHandle, - sizeof(HANDLE), - sizeof(ULONG)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + /* Check Output Safety */ + if(PreviousMode == UserMode) { + + _SEH_TRY { + + ProbeForWrite(EventPairHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; - if(!NT_SUCCESS(Status)) - { - return Status; - } - } + if(!NT_SUCCESS(Status)) return Status; + } + + /* Create the Object */ + DPRINT("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 */ + DPRINT("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; + } + } - 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; + /* Return Status */ + 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; - NTSTATUS Status = STATUS_SUCCESS; + HANDLE hEventPair; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); - PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - - if(PreviousMode == UserMode) - { - _SEH_TRY - { - ProbeForWrite(EventPairHandle, - sizeof(HANDLE), - sizeof(ULONG)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + /* Check Output Safety */ + if(PreviousMode == UserMode) { + + _SEH_TRY { + + ProbeForWrite(EventPairHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } _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; - } + 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; + } - return Status; + /* Return status */ + return Status; } -NTSTATUS STDCALL +NTSTATUS +STDCALL NtSetHighEventPair(IN HANDLE EventPairHandle) { - PKEVENT_PAIR EventPair; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status; + PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status; + + PAGED_CODE(); + DPRINT("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle); - PAGED_CODE(); + /* 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); - DPRINT("NtSetHighEventPair(EventPairHandle %x)\n", - EventPairHandle); - - PreviousMode = ExGetPreviousMode(); + /* 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; - NTSTATUS Status; + PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status; + + PAGED_CODE(); + DPRINT("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); + } - 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; + /* Return status */ + return Status; } - -NTSTATUS STDCALL +NTSTATUS +STDCALL NtSetLowEventPair(IN HANDLE EventPairHandle) { - PKEVENT_PAIR EventPair; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status; - - PAGED_CODE(); + PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + + PAGED_CODE(); + + PreviousMode = ExGetPreviousMode(); - DPRINT("NtSetLowEventPair(EventPairHandle %x)\n", - EventPairHandle); - - PreviousMode = ExGetPreviousMode(); + DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle); - Status = ObReferenceObjectByHandle(EventPairHandle, - SYNCHRONIZE, - ExEventPairObjectType, - PreviousMode, - (PVOID*)&EventPair, - NULL); - if(NT_SUCCESS(Status)) - { - KeSetEvent(&EventPair->LowEvent, - EVENT_INCREMENT, - FALSE); + /* 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); - ObDereferenceObject(EventPair); - } - - return Status; + /* Dereference Object */ + ObDereferenceObject(EventPair); + } + + /* Return status */ + return Status; } NTSTATUS STDCALL NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle) { - PKEVENT_PAIR EventPair; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status; + PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status; + + PAGED_CODE(); + DPRINT("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); + } - PAGED_CODE(); - - DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n", - EventPairHandle); - - PreviousMode = ExGetPreviousMode(); - - 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; + /* Return status */ + return Status; } -NTSTATUS STDCALL +NTSTATUS +STDCALL NtWaitLowEventPair(IN HANDLE EventPairHandle) { - PKEVENT_PAIR EventPair; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status; - - PAGED_CODE(); + PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status; + + PAGED_CODE(); + DPRINT("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); - DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n", - EventPairHandle); - - PreviousMode = ExGetPreviousMode(); + /* Dereference Object */ + ObDereferenceObject(EventPair); + } - Status = ObReferenceObjectByHandle(EventPairHandle, - SYNCHRONIZE, - ExEventPairObjectType, - PreviousMode, - (PVOID*)&EventPair, - NULL); - if(NT_SUCCESS(Status)) - { - KeWaitForSingleObject(&EventPair->LowEvent, - WrEventPair, - PreviousMode, - FALSE, - NULL); - - ObDereferenceObject(EventPair); - } - - return Status; + /* Return status */ + return Status; } - -NTSTATUS STDCALL +NTSTATUS +STDCALL NtWaitHighEventPair(IN HANDLE EventPairHandle) { - PKEVENT_PAIR EventPair; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status; + PKEVENT_PAIR EventPair; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status; + + PAGED_CODE(); + DPRINT("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); + } - PAGED_CODE(); - - DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n", - EventPairHandle); - - PreviousMode = ExGetPreviousMode(); - - Status = ObReferenceObjectByHandle(EventPairHandle, - SYNCHRONIZE, - ExEventPairObjectType, - PreviousMode, - (PVOID*)&EventPair, - NULL); - if(NT_SUCCESS(Status)) - { - KeWaitForSingleObject(&EventPair->HighEvent, - WrEventPair, - PreviousMode, - FALSE, - NULL); - - ObDereferenceObject(EventPair); - } - - return Status; + /* Return status */ + 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 */ diff --git a/reactos/ntoskrnl/ex/mutant.c b/reactos/ntoskrnl/ex/mutant.c index f6a2d4b36c7..8323e8a6b6a 100644 --- a/reactos/ntoskrnl/ex/mutant.c +++ b/reactos/ntoskrnl/ex/mutant.c @@ -1,11 +1,12 @@ -/* $Id:$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/mutant.c - * PURPOSE: Synchronization primitives + * PURPOSE: Executive Management of Mutants * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PROGRAMMERS: Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and + * add more debug output. + * David Welch (welch@cwcom.net) */ /* INCLUDES *****************************************************************/ @@ -17,360 +18,342 @@ 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[] = -{ - ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */ +static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = { + + /* MutantBasicInformation */ + ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), }; /* FUNCTIONS *****************************************************************/ - -NTSTATUS STDCALL -ExpCreateMutant(PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - DPRINT("NtpCreateMutant(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 +VOID +STDCALL ExpDeleteMutant(PVOID ObjectBody) { - DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody); - KeReleaseMutant((PKMUTANT)ObjectBody, - MUTANT_INCREMENT, - TRUE, - FALSE); + DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody); + + /* Make sure to release the Mutant */ + KeReleaseMutant((PKMUTANT)ObjectBody, + MUTANT_INCREMENT, + TRUE, + FALSE); } - -VOID INIT_FUNCTION +VOID +INIT_FUNCTION ExpInitializeMutantImplementation(VOID) { - ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool); + /* Allocate the Object Type */ + ExMutantObjectType = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), TAG('M', 't', 'n', 't')); - 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); + /* Create the Object Type */ + RtlInitUnicodeString(&ExMutantObjectType->TypeName, L"Mutant"); + 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); } - /* * @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; - HANDLE hMutant; - PKMUTEX Mutant; - NTSTATUS Status = STATUS_SUCCESS; - - 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); + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + HANDLE hMutant; + PKMUTANT Mutant; + NTSTATUS Status = STATUS_SUCCESS; - if(NT_SUCCESS(Status)) - { - _SEH_TRY - { - *MutantHandle = hMutant; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - } - - return Status; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtOpenMutant(OUT PHANDLE MutantHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - HANDLE hMutant; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; + PAGED_CODE(); + DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes); - PAGED_CODE(); + /* Check Output Safety */ + if(PreviousMode == UserMode) { + + _SEH_TRY { + + ProbeForWrite(MutantHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; - 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)); + if(!NT_SUCCESS(Status)) return Status; } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + + /* 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); - if(!NT_SUCCESS(Status)) - { - return Status; + /* 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; + } } - } - 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 -NtQueryMutant(IN HANDLE MutantHandle, - IN MUTANT_INFORMATION_CLASS MutantInformationClass, - OUT PVOID MutantInformation, - IN ULONG MutantInformationLength, - OUT PULONG ResultLength OPTIONAL) +NTSTATUS +STDCALL +NtOpenMutant(OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) { - PKMUTANT Mutant; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); + HANDLE hMutant; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes); - 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 -NtReleaseMutant(IN HANDLE MutantHandle, - IN PLONG PreviousCount OPTIONAL) -{ - PKMUTANT Mutant; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - 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; + /* 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; - } - } + if(!NT_SUCCESS(Status)) return Status; + } + + /* Open the Object */ + Status = ObOpenObjectByName(ObjectAttributes, + ExMutantObjectType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hMutant); - 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); + /* Check for success and return handle */ + if(NT_SUCCESS(Status)) { + + _SEH_TRY { + + *MutantHandle = hMutant; + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; + } - if(PreviousCount != NULL) - { - _SEH_TRY - { - *PreviousCount = Prev; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - } + /* Return Status */ + return Status; +} - return Status; +/* + * @implemented + */ +NTSTATUS +STDCALL +NtQueryMutant(IN HANDLE MutantHandle, + 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; + + PAGED_CODE(); + + /* Check buffers and parameters */ + DefaultQueryInfoBufferCheck(MutantInformationClass, + ExMutantInfoClass, + MutantInformation, + MutantInformationLength, + ResultLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) { + + DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status); + return Status; + } + + /* 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 */ + DPRINT("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; +} + + +/* + * @implemented + */ +NTSTATUS +STDCALL +NtReleaseMutant(IN HANDLE MutantHandle, + IN PLONG PreviousCount OPTIONAL) +{ + PKMUTANT Mutant; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + 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)) { + + LONG Prev; + + /* Save the Old State */ + DPRINT("Releasing Mutant\n"); + Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, FALSE, FALSE); + ObDereferenceObject(Mutant); + + /* Return it */ + if(PreviousCount) { + + _SEH_TRY { + + *PreviousCount = Prev; + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; + } + } + + /* Return Status */ + return Status; } /* EOF */ diff --git a/reactos/ntoskrnl/ex/rundown.c b/reactos/ntoskrnl/ex/rundown.c index baf8a38248b..580d9bb4e4e 100644 --- a/reactos/ntoskrnl/ex/rundown.c +++ b/reactos/ntoskrnl/ex/rundown.c @@ -1,11 +1,10 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/rundown.c * PURPOSE: Rundown Protection Functions * - * PROGRAMMERS: No programmer listed. + * PROGRAMMERS: Alex Ionescu & Thomas Weidenmueller - Implementation */ /* INCLUDES *****************************************************************/ diff --git a/reactos/ntoskrnl/ex/sem.c b/reactos/ntoskrnl/ex/sem.c index 274ce8aed1d..e91e317836c 100644 --- a/reactos/ntoskrnl/ex/sem.c +++ b/reactos/ntoskrnl/ex/sem.c @@ -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: David Welch (welch@mcmail.com) + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes. + * David Welch (welch@mcmail.com) */ /* INCLUDES *****************************************************************/ @@ -19,345 +19,336 @@ 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}; + 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 */ +static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = { + + /* SemaphoreBasicInformation */ + ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), }; -/* 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 +VOID +INIT_FUNCTION ExpInitializeSemaphoreImplementation(VOID) { - 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); + + /* Create the Semaphore Object */ + ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + RtlInitUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore"); + 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); } /* * @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; - NTSTATUS Status = STATUS_SUCCESS; + PKSEMAPHORE Semaphore; + HANDLE hSemaphore; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; - PAGED_CODE(); + PAGED_CODE(); - 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); - - ObDereferenceObject(Semaphore); - - if(NT_SUCCESS(Status)) - { - _SEH_TRY - { - *SemaphoreHandle = hSemaphore; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - } - - return Status; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtOpenSemaphore(OUT PHANDLE SemaphoreHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes) -{ - HANDLE hSemaphore; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - 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 -NtQuerySemaphore(IN HANDLE SemaphoreHandle, - IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, - OUT PVOID SemaphoreInformation, - IN ULONG SemaphoreInformationLength, - OUT PULONG ReturnLength OPTIONAL) -{ - PKSEMAPHORE Semaphore; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - 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; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -NtReleaseSemaphore(IN HANDLE SemaphoreHandle, - IN LONG ReleaseCount, - OUT PLONG PreviousCount OPTIONAL) -{ - KPROCESSOR_MODE PreviousMode; - PKSEMAPHORE Semaphore; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - 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); + /* Check Output Safety */ + if(PreviousMode != KernelMode) { + + _SEH_TRY { + + ProbeForWrite(SemaphoreHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; - if(PreviousCount != NULL) - { - _SEH_TRY - { - *PreviousCount = PrevCount; - } - _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; + } + + /* 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; + } + } + + /* Return Status */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +STDCALL +NtOpenSemaphore(OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + HANDLE hSemaphore; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + 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; + } + + /* Return Status */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +STDCALL +NtQuerySemaphore(IN HANDLE SemaphoreHandle, + IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + OUT PVOID SemaphoreInformation, + IN ULONG SemaphoreInformationLength, + OUT PULONG ReturnLength OPTIONAL) +{ + PKSEMAPHORE Semaphore; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + 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)) { + + _SEH_TRY { + + PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation; + + /* 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); } + /* Return status */ return Status; } +/* + * @implemented + */ +NTSTATUS +STDCALL +NtReleaseSemaphore(IN HANDLE SemaphoreHandle, + IN LONG ReleaseCount, + OUT PLONG PreviousCount OPTIONAL) +{ + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + 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; + } + + /* 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); + + /* Return it */ + if(PreviousCount) { + + _SEH_TRY { + + *PreviousCount = PrevCount; + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; + } + } + + /* Return Status */ + return Status; +} + /* EOF */ diff --git a/reactos/ntoskrnl/ex/timer.c b/reactos/ntoskrnl/ex/timer.c index fa0a2540d3d..10cf2b994b2 100644 --- a/reactos/ntoskrnl/ex/timer.c +++ b/reactos/ntoskrnl/ex/timer.c @@ -1,5 +1,4 @@ -/* $Id: nttimer.c 12779 2005-01-04 04:45:00Z gdalsnes $ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/timer.c @@ -124,9 +123,9 @@ ExpTimerApcKernelRoutine(PKAPC Apc, PVOID* SystemArguemnt2) { PETIMER Timer; - PETHREAD CurrentThread = PsGetCurrentThread(); KIRQL OldIrql; - + PETHREAD CurrentThread = PsGetCurrentThread(); + /* We need to find out which Timer we are */ Timer = CONTAINING_RECORD(Apc, ETIMER, TimerApc); DPRINT("ExpTimerApcKernelRoutine(Apc: %x. Timer: %x)\n", Apc, Timer); @@ -176,7 +175,7 @@ ExpInitializeTimerImplementation(VOID) ExTimerType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); /* Create the Executive Timer Object */ - RtlpCreateUnicodeString(&ExTimerType->TypeName, L"Timer", NonPagedPool); + RtlInitUnicodeString(&ExTimerType->TypeName, L"Timer"); ExTimerType->Tag = TAG('T', 'I', 'M', 'T'); ExTimerType->PeakObjects = 0; ExTimerType->PeakHandles = 0; @@ -209,7 +208,7 @@ NtCancelTimer(IN HANDLE TimerHandle, OUT PBOOLEAN CurrentState OPTIONAL) { PETIMER Timer; - KPROCESSOR_MODE PreviousMode; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); BOOLEAN State; KIRQL OldIrql; PETHREAD TimerThread; @@ -217,9 +216,6 @@ NtCancelTimer(IN HANDLE TimerHandle, NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - DPRINT("NtCancelTimer(0x%x, 0x%x)\n", TimerHandle, CurrentState); /* Check Parameter Validity */ @@ -301,10 +297,15 @@ NtCancelTimer(IN HANDLE TimerHandle, /* Make sure it's safe to write to the handle */ if(CurrentState != NULL) { + _SEH_TRY { + *CurrentState = State; + } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); + } _SEH_END; } } @@ -323,28 +324,27 @@ NtCreateTimer(OUT PHANDLE TimerHandle, { PETIMER Timer; HANDLE hTimer; - KPROCESSOR_MODE PreviousMode; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - DPRINT("NtCreateTimer(Handle: %x, Type: %d)\n", TimerHandle, TimerType); /* Check Parameter Validity */ if (PreviousMode != KernelMode) { + _SEH_TRY { + ProbeForWrite(TimerHandle, sizeof(HANDLE), sizeof(ULONG)); } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); + } _SEH_END; - if(!NT_SUCCESS(Status)) { - return Status; - } + if(!NT_SUCCESS(Status)) return Status; } /* Create the Object */ @@ -388,9 +388,13 @@ NtCreateTimer(OUT PHANDLE TimerHandle, /* Make sure it's safe to write to the handle */ _SEH_TRY { + *TimerHandle = hTimer; + } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); + } _SEH_END; } @@ -406,28 +410,28 @@ NtOpenTimer(OUT PHANDLE TimerHandle, IN POBJECT_ATTRIBUTES ObjectAttributes) { HANDLE hTimer; - KPROCESSOR_MODE PreviousMode; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - DPRINT("NtOpenTimer(TimerHandle: %x)\n", TimerHandle); /* Check Parameter Validity */ if (PreviousMode != KernelMode) { + _SEH_TRY { + ProbeForWrite(TimerHandle, sizeof(HANDLE), sizeof(ULONG)); + } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); + } _SEH_END; - if(!NT_SUCCESS(Status)) { - return Status; - } + if(!NT_SUCCESS(Status)) return Status; } /* Open the Timer */ @@ -444,9 +448,13 @@ NtOpenTimer(OUT PHANDLE TimerHandle, /* Make sure it's safe to write to the handle */ _SEH_TRY { + *TimerHandle = hTimer; + } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); + } _SEH_END; } @@ -464,16 +472,13 @@ NtQueryTimer(IN HANDLE TimerHandle, OUT PULONG ReturnLength OPTIONAL) { PETIMER Timer; - KPROCESSOR_MODE PreviousMode; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation; PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass); - + /* Check Validity */ DefaultQueryInfoBufferCheck(TimerInformationClass, ExTimerInfoClass, @@ -498,27 +503,24 @@ NtQueryTimer(IN HANDLE TimerHandle, /* Check for Success */ if(NT_SUCCESS(Status)) { + + /* 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); + + if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION); + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; - switch(TimerInformationClass) { - case TimerBasicInformation: { - /* 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); - - if(ReturnLength != NULL) { - *ReturnLength = sizeof(TIMER_BASIC_INFORMATION); - } - - } _SEH_HANDLE { - Status = _SEH_GetExceptionCode(); - } _SEH_END; - } - } - + /* Dereference Object */ ObDereferenceObject(Timer); } @@ -539,41 +541,40 @@ NtSetTimer(IN HANDLE TimerHandle, PETIMER Timer; KIRQL OldIrql; BOOLEAN State; - KPROCESSOR_MODE PreviousMode; - PETHREAD CurrentThread; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + PETHREAD CurrentThread = PsGetCurrentThread(); LARGE_INTEGER TimerDueTime; PETHREAD TimerThread; BOOLEAN KillTimer = FALSE; NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - CurrentThread = PsGetCurrentThread(); - DPRINT("NtSetTimer(TimerHandle: %x, DueTime: %d, Apc: %x, Period: %d)\n", TimerHandle, DueTime->QuadPart, TimerApcRoutine, Period); /* Check Parameter Validity */ if (PreviousMode != KernelMode) { + _SEH_TRY { + ProbeForRead(DueTime, sizeof(LARGE_INTEGER), sizeof(ULONG)); TimerDueTime = *DueTime; if(PreviousState != NULL) { + ProbeForWrite(PreviousState, sizeof(BOOLEAN), sizeof(BOOLEAN)); } } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); + } _SEH_END; - if(!NT_SUCCESS(Status)) { - return Status; - } + if(!NT_SUCCESS(Status)) return Status; } /* Get the Timer Object */ @@ -689,10 +690,15 @@ NtSetTimer(IN HANDLE TimerHandle, /* Make sure it's safe to write to the handle */ if(PreviousState != NULL) { + _SEH_TRY { + *PreviousState = State; + } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); + } _SEH_END; } } diff --git a/reactos/ntoskrnl/include/internal/id.h b/reactos/ntoskrnl/include/internal/id.h deleted file mode 100644 index 43a29588163..00000000000 --- a/reactos/ntoskrnl/include/internal/id.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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) - - diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index a89cd9784ea..9bfc388d15a 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -172,7 +172,9 @@ 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, IN PKTRAP_FRAME TrapFrame, IN PKNORMAL_ROUTINE NormalRoutine, diff --git a/reactos/ntoskrnl/include/ntoskrnl.h b/reactos/ntoskrnl/include/ntoskrnl.h index c4b8a1ab400..ef8e5ee09be 100755 --- a/reactos/ntoskrnl/include/ntoskrnl.h +++ b/reactos/ntoskrnl/include/ntoskrnl.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/reactos/ntoskrnl/io/create.c b/reactos/ntoskrnl/io/create.c index b507fc51f93..6a2919e630e 100644 --- a/reactos/ntoskrnl/io/create.c +++ b/reactos/ntoskrnl/io/create.c @@ -176,7 +176,7 @@ IopCreateFile(PVOID ObjectBody, FileObject, DeviceObject); FileObject->Vpb = DeviceObject->Vpb; - FileObject->Type = InternalFileType; + FileObject->Type = IO_TYPE_FILE; return(STATUS_SUCCESS); } @@ -240,7 +240,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject, CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject; CreatedFileObject->Vpb = DeviceObject->Vpb; - CreatedFileObject->Type = InternalFileType; + CreatedFileObject->Type = IO_TYPE_FILE; CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN; // shouldn't we initialize the lock event, and several other things here too? diff --git a/reactos/ntoskrnl/io/driver.c b/reactos/ntoskrnl/io/driver.c index 02cdc33e38f..75f02cab213 100644 --- a/reactos/ntoskrnl/io/driver.c +++ b/reactos/ntoskrnl/io/driver.c @@ -160,7 +160,7 @@ IopCreateDriver( RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION)); - Object->Type = InternalDriverType; + Object->Type = IO_TYPE_DRIVER; for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) Object->MajorFunction[i] = IopInvalidDeviceRequest; diff --git a/reactos/ntoskrnl/io/wmi.c b/reactos/ntoskrnl/io/wmi.c index 8b9088270f5..9d01c6b1f55 100644 --- a/reactos/ntoskrnl/io/wmi.c +++ b/reactos/ntoskrnl/io/wmi.c @@ -249,4 +249,18 @@ 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/device.c b/reactos/ntoskrnl/ke/device.c index d813a5cbf9e..31c95551f8e 100644 --- a/reactos/ntoskrnl/ke/device.c +++ b/reactos/ntoskrnl/ke/device.c @@ -64,8 +64,8 @@ KeFlushEntireTb( /* All CPUs need to have the TB flushed. */ if (CurrentCpuOnly == FALSE) { - Prcb = KeGetCurrentPrcb(); - + Prcb = KeGetCurrentPrcb(); + /* How many CPUs is our caller using? */ Process = Prcb->CurrentThread->ApcState.Process; diff --git a/reactos/ntoskrnl/ke/event.c b/reactos/ntoskrnl/ke/event.c index 5ef0e626bf4..c4ab1aac843 100644 --- a/reactos/ntoskrnl/ke/event.c +++ b/reactos/ntoskrnl/ke/event.c @@ -19,121 +19,211 @@ /* * @implemented */ -VOID STDCALL KeClearEvent (PKEVENT Event) +VOID +STDCALL +KeClearEvent(PKEVENT Event) { - DPRINT("KeClearEvent(Event %x)\n", Event); - Event->Header.SignalState = FALSE; + DPRINT("KeClearEvent(Event %x)\n", Event); + + /* Reset Signal State */ + 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) { - 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)); + DPRINT("KeInitializeEvent(Event %x)\n", Event); + + /* Initialize the Dispatcher Header */ + KeInitializeDispatcherHeader(&Event->Header, + Type, + sizeof(Event) / sizeof(ULONG), + State); } /* * @implemented */ -LONG STDCALL KeReadStateEvent (PKEVENT Event) +VOID +STDCALL +KeInitializeEventPair(PKEVENT_PAIR EventPair) { - return(Event->Header.SignalState); -} - -/* - * @implemented - */ -LONG STDCALL KeResetEvent (PKEVENT Event) -{ - /* FIXME: must use interlocked func. everywhere! (wait.c) - * or use dispather lock instead - * -Gunnar */ - return(InterlockedExchange(&(Event->Header.SignalState),0)); -} - -/* - * @implemented - */ -LONG STDCALL KeSetEvent (PKEVENT Event, - KPRIORITY Increment, - BOOLEAN Wait) -{ - KIRQL OldIrql; - int ret; - - 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); + 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); } /* * @implemented */ LONG STDCALL -KePulseEvent (IN PKEVENT Event, - IN KPRIORITY Increment, - IN BOOLEAN Wait) +KePulseEvent(IN PKEVENT Event, + IN KPRIORITY Increment, + IN BOOLEAN Wait) { - KIRQL OldIrql; - LONG Ret; + KIRQL OldIrql; + LONG PreviousState; - 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); + 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 */ + KiDispatcherObjectWake(&Event->Header, Increment); } - else - { - KTHREAD *Thread = KeGetCurrentThread(); - Thread->WaitNext = TRUE; - Thread->WaitIrql = OldIrql; + + /* 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 Ret; + /* Return the previous State */ + return PreviousState; +} + +/* + * @implemented + */ +LONG +STDCALL +KeReadStateEvent(PKEVENT Event) +{ + /* Return the Signal State */ + return Event->Header.SignalState; +} + +/* + * @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; +} + +/* + * @implemented + */ +LONG +STDCALL +KeSetEvent(PKEVENT Event, + KPRIORITY Increment, + 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; + KiDispatcherObjectWake(&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); + } + } + + /* 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 */ + DPRINT("Done: %d\n", PreviousState); + return PreviousState; } /* @@ -141,27 +231,39 @@ KePulseEvent (IN PKEVENT Event, */ VOID STDCALL -KeSetEventBoostPriority( - IN PKEVENT Event, - IN PKTHREAD *Thread OPTIONAL -) +KeSetEventBoostPriority(IN PKEVENT Event, + IN PKTHREAD *Thread OPTIONAL) { - PKTHREAD WaitingThread; - KIRQL OldIrql; - - OldIrql = KeAcquireDispatcherDatabaseLock(); + 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); + } - /* 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); - - KeReleaseDispatcherDatabaseLock(OldIrql); + /* Release the Dispatcher Database Lock */ + KeReleaseDispatcherDatabaseLock(OldIrql); } /* EOF */ diff --git a/reactos/ntoskrnl/ke/kqueue.c b/reactos/ntoskrnl/ke/kqueue.c index 3d10965d4eb..ebd1b743006 100644 --- a/reactos/ntoskrnl/ke/kqueue.c +++ b/reactos/ntoskrnl/ke/kqueue.c @@ -1,11 +1,13 @@ -/* $Id:$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PURPOSE: ReactOS kernel * FILE: ntoskrnl/ke/kqueue.c * PURPOSE: Implement device queues * - * PROGRAMMERS: David Welch (welch@mcmail.com) + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Several optimizations and implement + * usage of Inserted flag + reformat and + * add debug output. + * David Welch (welch@mcmail.com) */ /* INCLUDES ****************************************************************/ @@ -16,157 +18,33 @@ /* FUNCTIONS *****************************************************************/ - /* * @implemented - */ -BOOLEAN STDCALL -KeInsertByKeyDeviceQueue ( - IN PKDEVICE_QUEUE DeviceQueue, - IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry, - IN ULONG SortKey) -{ - DPRINT("KeInsertByKeyDeviceQueue()\n"); - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - - DeviceQueueEntry->SortKey=SortKey; - - KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); - - if (!DeviceQueue->Busy) - { - DeviceQueue->Busy=TRUE; - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - return(FALSE); - } - - /* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */ - InsertAscendingListFIFO(&DeviceQueue->DeviceListHead, - KDEVICE_QUEUE_ENTRY, - DeviceListEntry, - DeviceQueueEntry, - SortKey); - - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - return(TRUE); -} - -/* - * @implemented - */ -PKDEVICE_QUEUE_ENTRY -STDCALL -KeRemoveByKeyDeviceQueue ( - IN PKDEVICE_QUEUE DeviceQueue, - IN ULONG SortKey - ) -{ - PLIST_ENTRY current; - PKDEVICE_QUEUE_ENTRY entry; - - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - ASSERT(DeviceQueue!=NULL); - ASSERT(DeviceQueue->Busy); - - KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); - - /* an attempt to remove an entry from an empty (and busy) queue sets the queue to idle */ - if (IsListEmpty(&DeviceQueue->DeviceListHead)) - { - DeviceQueue->Busy = FALSE; - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - return NULL; - } - - /* find entry with SortKey greater than or equal to the passed-in SortKey */ - current = DeviceQueue->DeviceListHead.Flink; - while (current != &DeviceQueue->DeviceListHead) - { - entry = CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,DeviceListEntry); - if (entry->SortKey >= SortKey) - { - RemoveEntryList(current); - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - return entry; - } - current = current->Flink; - } - - /* if we didn't find a match, return the first entry */ - current = RemoveHeadList(&DeviceQueue->DeviceListHead); - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - - return CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,DeviceListEntry); -} - -/* - * @implemented - */ -PKDEVICE_QUEUE_ENTRY -STDCALL -KeRemoveDeviceQueue ( - IN PKDEVICE_QUEUE DeviceQueue) -/* - * FUNCTION: Removes an entry from a device queue - * ARGUMENTS: - * DeviceQueue = Queue to remove the entry - * RETURNS: The removed entry - */ -{ - PLIST_ENTRY list_entry; - - DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n",DeviceQueue); - - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - ASSERT(DeviceQueue!=NULL); - ASSERT(DeviceQueue->Busy); - - KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); - - /* an attempt to remove an entry from an empty (and busy) queue sets the queue idle */ - if (IsListEmpty(&DeviceQueue->DeviceListHead)) - { - DeviceQueue->Busy = FALSE; - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - return NULL; - } - - list_entry = RemoveHeadList(&DeviceQueue->DeviceListHead); - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - - return CONTAINING_RECORD(list_entry,KDEVICE_QUEUE_ENTRY,DeviceListEntry); -} - -/* - * @implemented - */ -VOID -STDCALL -KeInitializeDeviceQueue ( - IN PKDEVICE_QUEUE DeviceQueue - ) -/* + * * FUNCTION: Intializes a device queue * ARGUMENTS: * DeviceQueue = Device queue to initialize */ +VOID +STDCALL +KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue) { - ASSERT(DeviceQueue!=NULL); - InitializeListHead(&DeviceQueue->DeviceListHead); - DeviceQueue->Busy=FALSE; - KeInitializeSpinLock(&DeviceQueue->Lock); + + /* Initialize the Header */ + DeviceQueue->Type = DeviceQueueObject; + DeviceQueue->Size = sizeof(KDEVICE_QUEUE); + + /* Initialize the Listhead and Spinlock */ + InitializeListHead(&DeviceQueue->DeviceListHead); + KeInitializeSpinLock(&DeviceQueue->Lock); + + /* Set it as busy */ + DeviceQueue->Busy=FALSE; } /* * @implemented - */ -BOOLEAN -STDCALL -KeInsertDeviceQueue ( - IN PKDEVICE_QUEUE DeviceQueue, - IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry - ) -/* + * * FUNCTION: Inserts an entry in a device queue * ARGUMENTS: * DeviceQueue = Queue to insert the entry in @@ -174,58 +52,221 @@ KeInsertDeviceQueue ( * RETURNS: False is the device queue wasn't busy * True otherwise */ +BOOLEAN +STDCALL +KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, + IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry) { - ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + BOOLEAN Inserted; + + DPRINT("KeInsertDeviceQueue(DeviceQueue %x)\n", DeviceQueue); + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Lock the Queue */ + KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); - KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); + if (!DeviceQueue->Busy) { + + /* Set it as busy */ + Inserted = FALSE; + DeviceQueue->Busy = TRUE; + + } else { + + /* Insert it into the list */ + Inserted = TRUE; + InsertTailList(&DeviceQueue->DeviceListHead, + &DeviceQueueEntry->DeviceListEntry); + + + } - if (!DeviceQueue->Busy) - { - DeviceQueue->Busy=TRUE; + /* Sert the Insert state into the entry */ + DeviceQueueEntry->Inserted = Inserted; + + /* Release lock and return */ KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - return(FALSE); - } - - DeviceQueueEntry->SortKey=0; - InsertTailList(&DeviceQueue->DeviceListHead, &DeviceQueueEntry->DeviceListEntry); - - KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); - return(TRUE); + return Inserted; } +/* + * @implemented + */ +BOOLEAN +STDCALL +KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, + IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry, + IN ULONG SortKey) +{ + BOOLEAN Inserted; + + DPRINT("KeInsertByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue); + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Acquire the Lock */ + KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); + + /* Set the Sort Key */ + DeviceQueueEntry->SortKey=SortKey; + + if (!DeviceQueue->Busy) { + + DeviceQueue->Busy=TRUE; + Inserted = FALSE; + + } else { + + /* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */ + InsertAscendingListFIFO(&DeviceQueue->DeviceListHead, + KDEVICE_QUEUE_ENTRY, + DeviceListEntry, + DeviceQueueEntry, + SortKey); + Inserted = TRUE; + } + + /* Reset the Inserted State */ + DeviceQueueEntry->Inserted = Inserted; + + /* Release Lock and Return */ + KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); + return Inserted; +} + +/* + * @implemented + * + * FUNCTION: Removes an entry from a device queue + * ARGUMENTS: + * DeviceQueue = Queue to remove the entry + * RETURNS: The removed entry + */ +PKDEVICE_QUEUE_ENTRY +STDCALL +KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue) +{ + PLIST_ENTRY ListEntry; + PKDEVICE_QUEUE_ENTRY ReturnEntry; + + DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n", DeviceQueue); + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Acquire the Lock */ + KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); + ASSERT(DeviceQueue->Busy); + + /* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */ + if (IsListEmpty(&DeviceQueue->DeviceListHead)) { + DeviceQueue->Busy = FALSE; + ReturnEntry = NULL; + + } else { + + /* Remove the Entry from the List */ + ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead); + ReturnEntry = CONTAINING_RECORD(ListEntry, + KDEVICE_QUEUE_ENTRY, + DeviceListEntry); + + /* Set it as non-inserted */ + ReturnEntry->Inserted = FALSE; + } + + /* Release lock and Return */ + KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); + return ReturnEntry; +} + +/* + * @implemented + */ +PKDEVICE_QUEUE_ENTRY +STDCALL +KeRemoveByKeyDeviceQueue (IN PKDEVICE_QUEUE DeviceQueue, + IN ULONG SortKey) +{ + PLIST_ENTRY ListEntry; + PKDEVICE_QUEUE_ENTRY ReturnEntry; + + DPRINT("KeRemoveByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue); + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Acquire the Lock */ + KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock); + ASSERT(DeviceQueue->Busy); + + /* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */ + if (IsListEmpty(&DeviceQueue->DeviceListHead)) { + + DeviceQueue->Busy = FALSE; + ReturnEntry = NULL; + + } else { + + /* Find entry with SortKey greater than or equal to the passed-in SortKey */ + ListEntry = DeviceQueue->DeviceListHead.Flink; + while (ListEntry != &DeviceQueue->DeviceListHead) { + + /* Get Entry */ + ReturnEntry = CONTAINING_RECORD(ListEntry, + KDEVICE_QUEUE_ENTRY, + DeviceListEntry); + + /* Check if keys match */ + if (ReturnEntry->SortKey >= SortKey) break; + + /* Move to next item */ + ListEntry = ListEntry->Flink; + } + + /* Check if we found something */ + if (ListEntry == &DeviceQueue->DeviceListHead) { + + /* Not found, return the first entry */ + ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead); + ReturnEntry = CONTAINING_RECORD(ListEntry, + KDEVICE_QUEUE_ENTRY, + DeviceListEntry); + } else { + + /* We found it, so just remove it */ + RemoveEntryList(&ReturnEntry->DeviceListEntry); + } + + /* Set it as non-inserted */ + ReturnEntry->Inserted = FALSE; + } + + /* Release lock and Return */ + KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock); + return ReturnEntry; +} /* * @implemented */ BOOLEAN STDCALL -KeRemoveEntryDeviceQueue( - IN PKDEVICE_QUEUE DeviceQueue, - IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry) +KeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, + IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry) { - PLIST_ENTRY current; - KIRQL oldIrql; - PKDEVICE_QUEUE_ENTRY entry; + KIRQL OldIrql; + BOOLEAN OldState; + + DPRINT("KeRemoveEntryDeviceQueue(DeviceQueue %x)\n", DeviceQueue); + ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); - ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); - - KeAcquireSpinLock(&DeviceQueue->Lock, &oldIrql); - - current = DeviceQueue->DeviceListHead.Flink; - while (current != &DeviceQueue->DeviceListHead) - { - entry = CONTAINING_RECORD(current, KDEVICE_QUEUE_ENTRY, DeviceListEntry); - if (DeviceQueueEntry == entry) - { - RemoveEntryList(current); - KeReleaseSpinLock(&DeviceQueue->Lock, oldIrql); - /* entry was in the queue (but not anymore) */ - return TRUE; + /* Acquire the Lock */ + KeAcquireSpinLock(&DeviceQueue->Lock, &OldIrql); + + /* Check/Set Old State */ + if ((OldState = DeviceQueueEntry->Inserted)) { + + /* Remove it */ + DeviceQueueEntry->Inserted = FALSE; + RemoveEntryList(&DeviceQueueEntry->DeviceListEntry); } - current = current->Flink; - } - KeReleaseSpinLock(&DeviceQueue->Lock, oldIrql); - - /* entry wasn't in the queue */ - return FALSE; + /* Unlock and return old state */ + KeReleaseSpinLock(&DeviceQueue->Lock, OldIrql); + return OldState; } diff --git a/reactos/ntoskrnl/ke/mutex.c b/reactos/ntoskrnl/ke/mutex.c index 3532781082c..de7f785c13a 100644 --- a/reactos/ntoskrnl/ke/mutex.c +++ b/reactos/ntoskrnl/ke/mutex.c @@ -1,16 +1,20 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/mutex.c - * PURPOSE: Implements mutex + * PURPOSE: Implements Mutexes and Mutants (that silly davec...) * - * PROGRAMMERS: David Welch (welch@mcmail.com) + * 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) */ /* INCLUDES *****************************************************************/ #include +#define NDEBUG #include /* FUNCTIONS *****************************************************************/ @@ -18,176 +22,212 @@ /* * @implemented */ -VOID STDCALL -KeInitializeMutex(IN PKMUTEX Mutex, - IN ULONG Level) -{ - 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 - */ -LONG STDCALL -KeReadStateMutex(IN PKMUTEX Mutex) -{ - return(Mutex->Header.SignalState); -} - -/* - * @implemented - */ -LONG STDCALL -KeReleaseMutex(IN PKMUTEX Mutex, - IN BOOLEAN Wait) -{ - 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 - */ -NTSTATUS STDCALL -KeWaitForMutexObject(IN PKMUTEX Mutex, - IN KWAIT_REASON WaitReason, - IN KPROCESSOR_MODE WaitMode, - IN BOOLEAN Alertable, - IN PLARGE_INTEGER Timeout) -{ - return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout)); -} - - -/* - * @implemented - */ -VOID STDCALL +VOID +STDCALL KeInitializeMutant(IN PKMUTANT Mutant, - IN BOOLEAN InitialOwner) + IN BOOLEAN InitialOwner) { - if (InitialOwner == TRUE) - { - KeInitializeDispatcherHeader(&Mutant->Header, - InternalMutexType, - sizeof(KMUTANT) / sizeof(ULONG), - 0); - InsertTailList(&KeGetCurrentThread()->MutantListHead, - &Mutant->MutantListEntry); - Mutant->OwnerThread = KeGetCurrentThread(); + 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; } - else - { - KeInitializeDispatcherHeader(&Mutant->Header, - InternalMutexType, - sizeof(KMUTANT) / sizeof(ULONG), - 1); - Mutant->MutantListEntry.Flink = NULL; - Mutant->MutantListEntry.Blink = NULL; - Mutant->OwnerThread = NULL; - } - Mutant->Abandoned = FALSE; - Mutant->ApcDisable = 0; + + /* 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; } /* * @implemented */ -LONG STDCALL +VOID +STDCALL +KeInitializeMutex(IN PKMUTEX Mutex, + IN ULONG Level) +{ + 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); +} + +/* + * @implemented + */ +LONG +STDCALL KeReadStateMutant(IN PKMUTANT Mutant) { - return(Mutant->Header.SignalState); + /* Return the Signal State */ + return(Mutant->Header.SignalState); } /* * @implemented */ -LONG STDCALL -KeReleaseMutant(IN PKMUTANT Mutant, - IN KPRIORITY Increment, - IN BOOLEAN Abandon, - IN BOOLEAN Wait) +LONG +STDCALL +KeReadStateMutex(IN PKMUTEX Mutex) { - KIRQL OldIrql; + /* Return the Signal State */ + return(Mutex->Header.SignalState); +} - 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); +/* + * @implemented + */ +LONG +STDCALL +KeReleaseMutant(IN PKMUTANT Mutant, + IN KPRIORITY Increment, + IN BOOLEAN Abandon, + IN BOOLEAN Wait) +{ + 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; } - else - { - if (Mutant->OwnerThread != NULL) - { - 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"); + KiDispatcherObjectWake(&Mutant->Header, Increment); + } } - if (Mutant->Header.SignalState == 1) - { - Mutant->OwnerThread = NULL; - if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink) - RemoveEntryList(&Mutant->MutantListEntry); - KiDispatcherObjectWake(&Mutant->Header, 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->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 PreviousState; +} - return(0); +/* + * @implemented + */ +LONG +STDCALL +KeReleaseMutex(IN PKMUTEX Mutex, + IN BOOLEAN Wait) +{ + + /* There's no difference at this level between the two */ + return KeReleaseMutant(Mutex, IO_NO_INCREMENT, FALSE, Wait); +} + +/* + * @implemented + */ +NTSTATUS +STDCALL +KeWaitForMutexObject(IN PKMUTEX Mutex, + IN KWAIT_REASON WaitReason, + IN KPROCESSOR_MODE WaitMode, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Timeout) +{ + /* This is a simple macro. Export the function here though */ + return KeWaitForSingleObject(Mutex, + WaitReason, + WaitMode, + Alertable, + Timeout); } /* EOF */ diff --git a/reactos/ntoskrnl/ke/queue.c b/reactos/ntoskrnl/ke/queue.c index 9c478709de8..5cd85f9148f 100644 --- a/reactos/ntoskrnl/ke/queue.c +++ b/reactos/ntoskrnl/ke/queue.c @@ -25,7 +25,7 @@ KeInitializeQueue(IN PKQUEUE Queue, IN ULONG Count OPTIONAL) { KeInitializeDispatcherHeader(&Queue->Header, - InternalQueueType, + QueueObject, sizeof(KQUEUE)/sizeof(ULONG), 0); InitializeListHead(&Queue->EntryListHead); diff --git a/reactos/ntoskrnl/ke/sem.c b/reactos/ntoskrnl/ke/sem.c index 9408e66948c..d90a7fdba99 100644 --- a/reactos/ntoskrnl/ke/sem.c +++ b/reactos/ntoskrnl/ke/sem.c @@ -19,36 +19,39 @@ /* * @implemented */ -VOID STDCALL -KeInitializeSemaphore (PKSEMAPHORE Semaphore, - LONG Count, - LONG Limit) +VOID +STDCALL +KeInitializeSemaphore(PKSEMAPHORE Semaphore, + LONG Count, + LONG Limit) { - KeInitializeDispatcherHeader(&Semaphore->Header, - InternalSemaphoreType, - sizeof(KSEMAPHORE)/sizeof(ULONG), - Count); - Semaphore->Limit=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; } /* * @implemented */ -LONG STDCALL -KeReadStateSemaphore (PKSEMAPHORE Semaphore) +LONG +STDCALL +KeReadStateSemaphore(PKSEMAPHORE Semaphore) { - return(Semaphore->Header.SignalState); + /* Just return the Signal State */ + 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 @@ -68,40 +71,65 @@ KeReleaseSemaphore (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; + ULONG InitialState; + KIRQL OldIrql; + PKTHREAD CurrentThread; - 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); - OldIrql = KeAcquireDispatcherDatabaseLock(); + /* Lock the Dispatcher Database */ + OldIrql = KeAcquireDispatcherDatabaseLock(); - InitialState = Semaphore->Header.SignalState; - if (Semaphore->Limit < (LONG) InitialState + Adjustment || - InitialState > InitialState + Adjustment) - { - ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED); + /* 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); } - Semaphore->Header.SignalState += Adjustment; - if (InitialState == 0) - { - KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT); + /* 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 */ + KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT); } - if (Wait == FALSE) - { - KeReleaseDispatcherDatabaseLock(OldIrql); - } - else - { - KTHREAD *Thread = KeGetCurrentThread(); - Thread->WaitNext = TRUE; - Thread->WaitIrql = OldIrql; + /* 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; } - return(InitialState); + /* Return the previous state */ + return InitialState; } /* EOF */ diff --git a/reactos/ntoskrnl/ke/timer.c b/reactos/ntoskrnl/ke/timer.c index 44f7b19b34a..e2dba4442d4 100644 --- a/reactos/ntoskrnl/ke/timer.c +++ b/reactos/ntoskrnl/ke/timer.c @@ -107,12 +107,11 @@ KeInitializeTimerEx (PKTIMER Timer, /* Initialize the Dispatch Header */ KeInitializeDispatcherHeader(&Timer->Header, - InternalNotificationTimer + Type, + TimerNotificationObject + Type, sizeof(KTIMER) / sizeof(ULONG), FALSE); - /* Initalize the List Head and other data */ - InitializeListHead(&Timer->Header.WaitListHead); + /* Initalize the Other data */ Timer->DueTime.QuadPart = 0; Timer->Period = 0; } @@ -196,7 +195,6 @@ KeSetTimerEx (PKTIMER Timer, Timer->Dpc = Dpc; Timer->Period = Period; Timer->Header.SignalState = FALSE; - Timer->Header.Absolute = FALSE; /* Insert it */ if (!KiInsertTimer(Timer, DueTime)) { @@ -303,7 +301,7 @@ KiHandleExpiredTimer(PKTIMER Timer) if (!KiInsertTimer(Timer, DueTime)) { /* FIXME: I will think about how to handle this and fix it ASAP -- Alex */ - DPRINT1("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n"); + DPRINT("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n"); }; } @@ -335,8 +333,10 @@ KiInsertTimer(PKTIMER Timer, DPRINT("KiInsertTimer(Timer %x DueTime %I64d)\n", Timer, DueTime.QuadPart); - /* Set it as Inserted */ + /* Set default data */ 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) { diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index 017aeb31c4f..b1f630f04b1 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -114,34 +114,34 @@ KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr, switch (hdr->Type) { - case InternalSynchronizationEvent: + case EventSynchronizationObject: hdr->SignalState = 0; break; - case InternalQueueType: + case QueueObject: break; - case InternalSemaphoreType: + case SemaphoreObject: hdr->SignalState--; break; - case InternalProcessType: + case ProcessObject: break; case ThreadObject: break; - case InternalNotificationEvent: + case EventNotificationObject: break; - case InternalSynchronizationTimer: + case TimerSynchronizationObject: hdr->SignalState = FALSE; break; - case InternalNotificationTimer: + case TimerNotificationObject: break; - case InternalMutexType: + case MutantObject: { PKMUTEX Mutex; @@ -176,7 +176,7 @@ static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER * hdr, PKTHREAD Thread) { - if (hdr->Type == InternalMutexType) + if (hdr->Type == MutantObject) { PKMUTEX Mutex; @@ -355,22 +355,22 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment) DPRINT("hdr->Type %x\n",hdr->Type); switch (hdr->Type) { - case InternalNotificationEvent: + case EventNotificationObject: return(KeDispatcherObjectWakeAll(hdr, increment)); - case InternalNotificationTimer: + case TimerNotificationObject: return(KeDispatcherObjectWakeAll(hdr, increment)); - case InternalSynchronizationEvent: + case EventSynchronizationObject: return(KeDispatcherObjectWakeOne(hdr, increment)); - case InternalSynchronizationTimer: + case TimerSynchronizationObject: return(KeDispatcherObjectWakeOne(hdr, increment)); - case InternalQueueType: + case QueueObject: return(KeDispatcherObjectWakeOne(hdr, increment)); - case InternalSemaphoreType: + case SemaphoreObject: DPRINT("hdr->SignalState %d\n", hdr->SignalState); if(hdr->SignalState>0) { @@ -383,13 +383,13 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment) } else return FALSE; - case InternalProcessType: + case ProcessObject: return(KeDispatcherObjectWakeAll(hdr, increment)); case ThreadObject: return(KeDispatcherObjectWakeAll(hdr, increment)); - case InternalMutexType: + case MutantObject: return(KeDispatcherObjectWakeOne(hdr, increment)); } DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type); @@ -463,7 +463,7 @@ PVOID KiGetWaitableObjectFromObject(PVOID Object) { //special case when waiting on file objects - if ( ((PDISPATCHER_HEADER)Object)->Type == InternalFileType) + if ( ((PDISPATCHER_HEADER)Object)->Type == IO_TYPE_FILE) { return &((PFILE_OBJECT)Object)->Event; } @@ -1026,19 +1026,19 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, hdr = (DISPATCHER_HEADER *)SignalObj; switch (hdr->Type) { - case InternalNotificationEvent: - case InternalSynchronizationEvent: + case EventNotificationObject: + case EventSynchronizationObject: KeSetEvent(SignalObj, EVENT_INCREMENT, TRUE); break; - case InternalMutexType: + case MutantObject: KeReleaseMutex(SignalObj, TRUE); break; - case InternalSemaphoreType: + case SemaphoreObject: KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 4715090e2ec..651c8dda8cf 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -388,7 +388,7 @@ PsInitProcessManagment(VOID) PsInitialSystemProcess->Pcb.ThreadQuantum = 6; InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead); KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader, - InternalProcessType, + ProcessObject, sizeof(EPROCESS), FALSE); KProcess = &PsInitialSystemProcess->Pcb; @@ -848,7 +848,7 @@ exitdereferenceobjects: } KeInitializeDispatcherHeader(&KProcess->DispatcherHeader, - InternalProcessType, + ProcessObject, sizeof(EPROCESS), FALSE); diff --git a/reactos/tools/nci/sysfuncs.lst b/reactos/tools/nci/sysfuncs.lst index f52329eb239..7b76c796e9e 100644 --- a/reactos/tools/nci/sysfuncs.lst +++ b/reactos/tools/nci/sysfuncs.lst @@ -180,7 +180,6 @@ NtSetEaFile 4 NtSetEvent 2 NtSetHighEventPair 1 NtSetHighWaitLowEventPair 1 -NtSetHighWaitLowThread 0 NtSetInformationFile 5 NtSetInformationKey 4 NtSetInformationJobObject 4 @@ -192,7 +191,6 @@ NtSetIntervalProfile 2 NtSetLdtEntries 6 NtSetLowEventPair 1 NtSetLowWaitHighEventPair 1 -NtSetLowWaitHighThread 0 NtSetQuotaInformationFile 4 NtSetSecurityObject 3 NtSetSystemEnvironmentValue 2