mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Alex Ionescu <ionucu@videotron.ca>
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
This commit is contained in:
parent
865a496525
commit
cfdb595cc6
24 changed files with 2238 additions and 2274 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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 <internal/debug.h>
|
||||
|
||||
#ifndef NTSYSAPI
|
||||
#define NTSYSAPI
|
||||
#endif
|
||||
|
||||
#ifndef NTAPI
|
||||
#define NTAPI STDCALL
|
||||
#endif
|
||||
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
|
||||
|
||||
static GENERIC_MAPPING ExEventPairMapping = {
|
||||
STANDARD_RIGHTS_READ,
|
||||
STANDARD_RIGHTS_WRITE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||
EVENT_PAIR_ALL_ACCESS};
|
||||
STANDARD_RIGHTS_READ,
|
||||
STANDARD_RIGHTS_WRITE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||
EVENT_PAIR_ALL_ACCESS};
|
||||
|
||||
static KSPIN_LOCK ExThreadEventPairSpinLock;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 *****************************************************************/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <ntdll/ldr.h>
|
||||
#include <internal/ctype.h>
|
||||
#include <internal/ntoskrnl.h>
|
||||
#include <internal/id.h>
|
||||
#include <internal/ke.h>
|
||||
#include <internal/i386/segment.h>
|
||||
#include <internal/i386/mm.h>
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue