mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 23:33:01 +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
|
#endif
|
||||||
|
|
||||||
#define IO_TYPE_DRIVER 4L
|
#define IO_TYPE_DRIVER 4L
|
||||||
|
#define IO_TYPE_FILE 0x0F5L
|
||||||
|
|
||||||
#define DRVO_UNLOAD_INVOKED 0x1L
|
#define DRVO_UNLOAD_INVOKED 0x1L
|
||||||
#define DRVO_LEGACY_DRIVER 0x2L
|
#define DRVO_LEGACY_DRIVER 0x2L
|
||||||
#define DRVO_BUILTIN_DRIVER 0x4L
|
#define DRVO_BUILTIN_DRIVER 0x4L
|
||||||
|
|
|
@ -58,6 +58,7 @@ typedef enum _KPROFILE_SOURCE
|
||||||
ProfileTime
|
ProfileTime
|
||||||
} KPROFILE_SOURCE;
|
} KPROFILE_SOURCE;
|
||||||
|
|
||||||
|
|
||||||
// file disposition values
|
// file disposition values
|
||||||
|
|
||||||
#define FILE_SUPERSEDE 0x0000
|
#define FILE_SUPERSEDE 0x0000
|
||||||
|
@ -1271,9 +1272,9 @@ typedef enum _MUTANT_INFORMATION_CLASS
|
||||||
|
|
||||||
typedef struct _MUTANT_BASIC_INFORMATION
|
typedef struct _MUTANT_BASIC_INFORMATION
|
||||||
{
|
{
|
||||||
LONG Count;
|
LONG CurrentCount;
|
||||||
BOOLEAN Owned;
|
BOOLEAN OwnedByCaller;
|
||||||
BOOLEAN Abandoned;
|
BOOLEAN AbandonedState;
|
||||||
} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
|
} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* $Id:$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/nt/event.c
|
* FILE: ntoskrnl/nt/event.c
|
||||||
* PURPOSE: Named event support
|
* PURPOSE: Named event support
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: Philip Susi and David Welch
|
* PROGRAMMERS: Alex Ionescu(alex@relsoft.net) - Fixed bugs/commented
|
||||||
|
* Philip Susi and David Welch
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -24,38 +24,21 @@ static GENERIC_MAPPING ExpEventMapping = {
|
||||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
|
||||||
EVENT_ALL_ACCESS};
|
EVENT_ALL_ACCESS};
|
||||||
|
|
||||||
static const INFORMATION_CLASS_INFO ExEventInfoClass[] =
|
static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
|
||||||
{
|
|
||||||
ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* EventBasicInformation */
|
/* EventBasicInformation */
|
||||||
|
ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
VOID
|
||||||
NtpCreateEvent(PVOID ObjectBody,
|
INIT_FUNCTION
|
||||||
PVOID Parent,
|
|
||||||
PWSTR RemainingPath,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
|
||||||
{
|
|
||||||
DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
|
||||||
ObjectBody, Parent, RemainingPath);
|
|
||||||
|
|
||||||
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
|
|
||||||
{
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
|
||||||
ExpInitializeEventImplementation(VOID)
|
ExpInitializeEventImplementation(VOID)
|
||||||
{
|
{
|
||||||
|
/* Create the Event Object Type */
|
||||||
ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
||||||
|
RtlInitUnicodeString(&ExEventObjectType->TypeName, L"Event");
|
||||||
RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
|
|
||||||
|
|
||||||
ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
|
ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
|
||||||
ExEventObjectType->PeakObjects = 0;
|
ExEventObjectType->PeakObjects = 0;
|
||||||
ExEventObjectType->PeakHandles = 0;
|
ExEventObjectType->PeakHandles = 0;
|
||||||
|
@ -72,17 +55,16 @@ ExpInitializeEventImplementation(VOID)
|
||||||
ExEventObjectType->Security = NULL;
|
ExEventObjectType->Security = NULL;
|
||||||
ExEventObjectType->QueryName = NULL;
|
ExEventObjectType->QueryName = NULL;
|
||||||
ExEventObjectType->OkayToClose = NULL;
|
ExEventObjectType->OkayToClose = NULL;
|
||||||
ExEventObjectType->Create = NtpCreateEvent;
|
ExEventObjectType->Create = NULL;
|
||||||
ExEventObjectType->DuplicationNotify = NULL;
|
ExEventObjectType->DuplicationNotify = NULL;
|
||||||
|
|
||||||
ObpCreateTypeObject(ExEventObjectType);
|
ObpCreateTypeObject(ExEventObjectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtClearEvent(IN HANDLE EventHandle)
|
NtClearEvent(IN HANDLE EventHandle)
|
||||||
{
|
{
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
|
@ -90,18 +72,23 @@ NtClearEvent(IN HANDLE EventHandle)
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Reference the Object */
|
||||||
Status = ObReferenceObjectByHandle(EventHandle,
|
Status = ObReferenceObjectByHandle(EventHandle,
|
||||||
EVENT_MODIFY_STATE,
|
EVENT_MODIFY_STATE,
|
||||||
ExEventObjectType,
|
ExEventObjectType,
|
||||||
ExGetPreviousMode(),
|
ExGetPreviousMode(),
|
||||||
(PVOID*)&Event,
|
(PVOID*)&Event,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Clear the Event and Dereference */
|
||||||
KeClearEvent(Event);
|
KeClearEvent(Event);
|
||||||
ObDereferenceObject(Event);
|
ObDereferenceObject(Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,42 +96,40 @@ NtClearEvent(IN HANDLE EventHandle)
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtCreateEvent(OUT PHANDLE EventHandle,
|
NtCreateEvent(OUT PHANDLE EventHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||||
IN EVENT_TYPE EventType,
|
IN EVENT_TYPE EventType,
|
||||||
IN BOOLEAN InitialState)
|
IN BOOLEAN InitialState)
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
HANDLE hEvent;
|
HANDLE hEvent;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtCreateEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode != KernelMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(EventHandle,
|
ProbeForWrite(EventHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create the Object */
|
||||||
Status = ObCreateObject(PreviousMode,
|
Status = ObCreateObject(PreviousMode,
|
||||||
ExEventObjectType,
|
ExEventObjectType,
|
||||||
ObjectAttributes,
|
ObjectAttributes,
|
||||||
|
@ -154,13 +139,16 @@ NtCreateEvent(OUT PHANDLE EventHandle,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(PVOID*)&Event);
|
(PVOID*)&Event);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Initalize the Event */
|
||||||
KeInitializeEvent(Event,
|
KeInitializeEvent(Event,
|
||||||
EventType,
|
EventType,
|
||||||
InitialState);
|
InitialState);
|
||||||
|
|
||||||
|
/* Insert it */
|
||||||
Status = ObInsertObject((PVOID)Event,
|
Status = ObInsertObject((PVOID)Event,
|
||||||
NULL,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
|
@ -169,62 +157,59 @@ NtCreateEvent(OUT PHANDLE EventHandle,
|
||||||
&hEvent);
|
&hEvent);
|
||||||
ObDereferenceObject(Event);
|
ObDereferenceObject(Event);
|
||||||
|
|
||||||
if(NT_SUCCESS(Status))
|
/* Check for success and return handle */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*EventHandle = hEvent;
|
*EventHandle = hEvent;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtOpenEvent(OUT PHANDLE EventHandle,
|
NtOpenEvent(OUT PHANDLE EventHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
HANDLE hEvent;
|
HANDLE hEvent;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
|
DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode != KernelMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(EventHandle,
|
ProbeForWrite(EventHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObOpenObjectByName(ObjectAttributes,
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
ExEventObjectType,
|
ExEventObjectType,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -233,86 +218,88 @@ NtOpenEvent(OUT PHANDLE EventHandle,
|
||||||
NULL,
|
NULL,
|
||||||
&hEvent);
|
&hEvent);
|
||||||
|
|
||||||
if(NT_SUCCESS(Status))
|
/* Check for success and return handle */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*EventHandle = hEvent;
|
*EventHandle = hEvent;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtPulseEvent(IN HANDLE EventHandle,
|
NtPulseEvent(IN HANDLE EventHandle,
|
||||||
OUT PLONG PreviousState OPTIONAL)
|
OUT PLONG PreviousState OPTIONAL)
|
||||||
{
|
{
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
|
DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||||
EventHandle, PreviousState);
|
EventHandle, PreviousState);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check buffer validity */
|
||||||
|
if(PreviousState && PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousState != NULL && PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(PreviousState,
|
ProbeForWrite(PreviousState,
|
||||||
sizeof(LONG),
|
sizeof(LONG),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObReferenceObjectByHandle(EventHandle,
|
Status = ObReferenceObjectByHandle(EventHandle,
|
||||||
EVENT_MODIFY_STATE,
|
EVENT_MODIFY_STATE,
|
||||||
ExEventObjectType,
|
ExEventObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Event,
|
(PVOID*)&Event,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Pulse the Event */
|
||||||
LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
|
LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
|
||||||
ObDereferenceObject(Event);
|
ObDereferenceObject(Event);
|
||||||
|
|
||||||
if(PreviousState != NULL)
|
/* Return it */
|
||||||
{
|
if(PreviousState) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*PreviousState = Prev;
|
*PreviousState = Prev;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +307,8 @@ NtPulseEvent(IN HANDLE EventHandle,
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtQueryEvent(IN HANDLE EventHandle,
|
NtQueryEvent(IN HANDLE EventHandle,
|
||||||
IN EVENT_INFORMATION_CLASS EventInformationClass,
|
IN EVENT_INFORMATION_CLASS EventInformationClass,
|
||||||
OUT PVOID EventInformation,
|
OUT PVOID EventInformation,
|
||||||
|
@ -328,13 +316,14 @@ NtQueryEvent(IN HANDLE EventHandle,
|
||||||
OUT PULONG ReturnLength OPTIONAL)
|
OUT PULONG ReturnLength OPTIONAL)
|
||||||
{
|
{
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtQueryEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, EventInformationClass);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check buffers and class validity */
|
||||||
|
|
||||||
DefaultQueryInfoBufferCheck(EventInformationClass,
|
DefaultQueryInfoBufferCheck(EventInformationClass,
|
||||||
ExEventInfoClass,
|
ExEventInfoClass,
|
||||||
EventInformation,
|
EventInformation,
|
||||||
|
@ -342,208 +331,179 @@ NtQueryEvent(IN HANDLE EventHandle,
|
||||||
ReturnLength,
|
ReturnLength,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
&Status);
|
&Status);
|
||||||
if(!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status)) {
|
||||||
{
|
|
||||||
DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status);
|
/* Invalid buffers */
|
||||||
|
DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the Object */
|
||||||
Status = ObReferenceObjectByHandle(EventHandle,
|
Status = ObReferenceObjectByHandle(EventHandle,
|
||||||
EVENT_QUERY_STATE,
|
EVENT_QUERY_STATE,
|
||||||
ExEventObjectType,
|
ExEventObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Event,
|
(PVOID*)&Event,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
switch(EventInformationClass)
|
|
||||||
{
|
|
||||||
case EventBasicInformation:
|
|
||||||
{
|
|
||||||
PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
|
|
||||||
|
|
||||||
_SEH_TRY
|
/* Check for success */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
if (Event->Header.Type == InternalNotificationEvent)
|
|
||||||
BasicInfo->EventType = NotificationEvent;
|
_SEH_TRY {
|
||||||
else
|
|
||||||
BasicInfo->EventType = SynchronizationEvent;
|
/* Return Event Type and State */
|
||||||
|
BasicInfo->EventType = Event->Header.Type;
|
||||||
BasicInfo->EventState = KeReadStateEvent(Event);
|
BasicInfo->EventState = KeReadStateEvent(Event);
|
||||||
|
|
||||||
if(ReturnLength != NULL)
|
/* Return length */
|
||||||
{
|
if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
|
||||||
*ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
|
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
} _SEH_END;
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Dereference the Object */
|
||||||
ObDereferenceObject(Event);
|
ObDereferenceObject(Event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtResetEvent(IN HANDLE EventHandle,
|
NtResetEvent(IN HANDLE EventHandle,
|
||||||
OUT PLONG PreviousState OPTIONAL)
|
OUT PLONG PreviousState OPTIONAL)
|
||||||
{
|
{
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||||
EventHandle, PreviousState);
|
EventHandle, PreviousState);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check buffer validity */
|
||||||
|
if(PreviousState && PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousState != NULL && PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(PreviousState,
|
ProbeForWrite(PreviousState,
|
||||||
sizeof(LONG),
|
sizeof(LONG),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObReferenceObjectByHandle(EventHandle,
|
Status = ObReferenceObjectByHandle(EventHandle,
|
||||||
EVENT_MODIFY_STATE,
|
EVENT_MODIFY_STATE,
|
||||||
ExEventObjectType,
|
ExEventObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Event,
|
(PVOID*)&Event,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Reset the Event */
|
||||||
LONG Prev = KeResetEvent(Event);
|
LONG Prev = KeResetEvent(Event);
|
||||||
ObDereferenceObject(Event);
|
ObDereferenceObject(Event);
|
||||||
|
|
||||||
if(PreviousState != NULL)
|
/* Return it */
|
||||||
{
|
if(PreviousState) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*PreviousState = Prev;
|
*PreviousState = Prev;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtSetEvent(IN HANDLE EventHandle,
|
NtSetEvent(IN HANDLE EventHandle,
|
||||||
OUT PLONG PreviousState OPTIONAL)
|
OUT PLONG PreviousState OPTIONAL)
|
||||||
{
|
{
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||||
EventHandle, PreviousState);
|
EventHandle, PreviousState);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check buffer validity */
|
||||||
|
if(PreviousState != NULL && PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousState != NULL && PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(PreviousState,
|
ProbeForWrite(PreviousState,
|
||||||
sizeof(LONG),
|
sizeof(LONG),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObReferenceObjectByHandle(EventHandle,
|
Status = ObReferenceObjectByHandle(EventHandle,
|
||||||
EVENT_MODIFY_STATE,
|
EVENT_MODIFY_STATE,
|
||||||
ExEventObjectType,
|
ExEventObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Event,
|
(PVOID*)&Event,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Set the Event */
|
||||||
LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
|
LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
|
||||||
ObDereferenceObject(Event);
|
ObDereferenceObject(Event);
|
||||||
|
|
||||||
if(PreviousState != NULL)
|
/* Return it */
|
||||||
{
|
if(PreviousState) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*PreviousState = Prev;
|
*PreviousState = Prev;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
STDCALL
|
|
||||||
NtTraceEvent(
|
|
||||||
IN ULONG TraceHandle,
|
|
||||||
IN ULONG Flags,
|
|
||||||
IN ULONG TraceHeaderLength,
|
|
||||||
IN struct _EVENT_TRACE_HEADER* TraceHeader
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/* $Id: evtpair.c 12779 2005-01-04 04:45:00Z gdalsnes $
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ex/evtpair.c
|
* FILE: ntoskrnl/ex/evtpair.c
|
||||||
* PURPOSE: Support for event pairs
|
* 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)
|
* Skywing (skywing@valhallalegends.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -15,15 +16,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
#ifndef NTSYSAPI
|
|
||||||
#define NTSYSAPI
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NTAPI
|
|
||||||
#define NTAPI STDCALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
|
POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
|
||||||
|
@ -34,33 +26,16 @@ static GENERIC_MAPPING ExEventPairMapping = {
|
||||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||||
EVENT_PAIR_ALL_ACCESS};
|
EVENT_PAIR_ALL_ACCESS};
|
||||||
|
|
||||||
static KSPIN_LOCK ExThreadEventPairSpinLock;
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
VOID
|
||||||
ExpCreateEventPair(PVOID ObjectBody,
|
INIT_FUNCTION
|
||||||
PVOID Parent,
|
|
||||||
PWSTR RemainingPath,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
|
||||||
{
|
|
||||||
DPRINT("ExpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
|
||||||
ObjectBody, Parent, RemainingPath);
|
|
||||||
|
|
||||||
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
|
|
||||||
{
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
|
||||||
ExpInitializeEventPairImplementation(VOID)
|
ExpInitializeEventPairImplementation(VOID)
|
||||||
{
|
{
|
||||||
|
/* Create the Event Pair Object Type */
|
||||||
ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
||||||
|
RtlInitUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair");
|
||||||
RtlpCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair", NonPagedPool);
|
|
||||||
ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a');
|
ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a');
|
||||||
ExEventPairObjectType->PeakObjects = 0;
|
ExEventPairObjectType->PeakObjects = 0;
|
||||||
ExEventPairObjectType->PeakHandles = 0;
|
ExEventPairObjectType->PeakHandles = 0;
|
||||||
|
@ -77,48 +52,44 @@ ExpInitializeEventPairImplementation(VOID)
|
||||||
ExEventPairObjectType->Security = NULL;
|
ExEventPairObjectType->Security = NULL;
|
||||||
ExEventPairObjectType->QueryName = NULL;
|
ExEventPairObjectType->QueryName = NULL;
|
||||||
ExEventPairObjectType->OkayToClose = NULL;
|
ExEventPairObjectType->OkayToClose = NULL;
|
||||||
ExEventPairObjectType->Create = ExpCreateEventPair;
|
ExEventPairObjectType->Create = NULL;
|
||||||
ExEventPairObjectType->DuplicationNotify = NULL;
|
ExEventPairObjectType->DuplicationNotify = NULL;
|
||||||
|
|
||||||
KeInitializeSpinLock(&ExThreadEventPairSpinLock);
|
|
||||||
ObpCreateTypeObject(ExEventPairObjectType);
|
ObpCreateTypeObject(ExEventPairObjectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
STDCALL
|
||||||
NtCreateEventPair(OUT PHANDLE EventPairHandle,
|
NtCreateEventPair(OUT PHANDLE EventPairHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
PKEVENT_PAIR EventPair;
|
PKEVENT_PAIR EventPair;
|
||||||
HANDLE hEventPair;
|
HANDLE hEventPair;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtCreateEventPair: %x\n", EventPairHandle);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(EventPairHandle,
|
ProbeForWrite(EventPairHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create the Object */
|
||||||
|
DPRINT("Creating EventPair\n");
|
||||||
Status = ObCreateObject(PreviousMode,
|
Status = ObCreateObject(PreviousMode,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
ObjectAttributes,
|
ObjectAttributes,
|
||||||
|
@ -128,16 +99,16 @@ NtCreateEventPair(OUT PHANDLE EventPairHandle,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(PVOID*)&EventPair);
|
(PVOID*)&EventPair);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeInitializeEvent(&EventPair->LowEvent,
|
|
||||||
SynchronizationEvent,
|
|
||||||
FALSE);
|
|
||||||
KeInitializeEvent(&EventPair->HighEvent,
|
|
||||||
SynchronizationEvent,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
Status = ObInsertObject ((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,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
0,
|
0,
|
||||||
|
@ -145,56 +116,55 @@ NtCreateEventPair(OUT PHANDLE EventPairHandle,
|
||||||
&hEventPair);
|
&hEventPair);
|
||||||
ObDereferenceObject(EventPair);
|
ObDereferenceObject(EventPair);
|
||||||
|
|
||||||
if(NT_SUCCESS(Status))
|
/* Check for success and return handle */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*EventPairHandle = hEventPair;
|
*EventPairHandle = hEventPair;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
STDCALL
|
||||||
NtOpenEventPair(OUT PHANDLE EventPairHandle,
|
NtOpenEventPair(OUT PHANDLE EventPairHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
HANDLE hEventPair;
|
HANDLE hEventPair;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(EventPairHandle,
|
ProbeForWrite(EventPairHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObOpenObjectByName(ObjectAttributes,
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -202,96 +172,101 @@ NtOpenEventPair(OUT PHANDLE EventPairHandle,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
NULL,
|
NULL,
|
||||||
&hEventPair);
|
&hEventPair);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for success and return handle */
|
||||||
_SEH_TRY
|
if(NT_SUCCESS(Status)) {
|
||||||
{
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
*EventPairHandle = hEventPair;
|
*EventPairHandle = hEventPair;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtSetHighEventPair(IN HANDLE EventPairHandle)
|
NtSetHighEventPair(IN HANDLE EventPairHandle)
|
||||||
{
|
{
|
||||||
PKEVENT_PAIR EventPair;
|
PKEVENT_PAIR EventPair;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
|
||||||
|
|
||||||
DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
|
/* Open the Object */
|
||||||
EventPairHandle);
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||||
SYNCHRONIZE,
|
SYNCHRONIZE,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&EventPair,
|
(PVOID*)&EventPair,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeSetEvent(&EventPair->HighEvent,
|
|
||||||
EVENT_INCREMENT,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Set the Event */
|
||||||
|
KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
ObDereferenceObject(EventPair);
|
ObDereferenceObject(EventPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
STDCALL
|
||||||
NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
|
NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
|
||||||
{
|
{
|
||||||
PKEVENT_PAIR EventPair;
|
PKEVENT_PAIR EventPair;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
|
||||||
|
|
||||||
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n",
|
/* Open the Object */
|
||||||
EventPairHandle);
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||||
SYNCHRONIZE,
|
SYNCHRONIZE,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&EventPair,
|
(PVOID*)&EventPair,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeSetEvent(&EventPair->HighEvent,
|
|
||||||
EVENT_INCREMENT,
|
|
||||||
TRUE);
|
|
||||||
|
|
||||||
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Set the Event */
|
||||||
|
KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
/* Wait for the Other one */
|
||||||
KeWaitForSingleObject(&EventPair->LowEvent,
|
KeWaitForSingleObject(&EventPair->LowEvent,
|
||||||
WrEventPair,
|
WrEventPair,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
ObDereferenceObject(EventPair);
|
ObDereferenceObject(EventPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
STDCALL
|
||||||
NtSetLowEventPair(IN HANDLE EventPairHandle)
|
NtSetLowEventPair(IN HANDLE EventPairHandle)
|
||||||
{
|
{
|
||||||
PKEVENT_PAIR EventPair;
|
PKEVENT_PAIR EventPair;
|
||||||
|
@ -300,26 +275,29 @@ NtSetLowEventPair(IN HANDLE EventPairHandle)
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
|
|
||||||
EventPairHandle);
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
PreviousMode = ExGetPreviousMode();
|
||||||
|
|
||||||
|
DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||||
SYNCHRONIZE,
|
SYNCHRONIZE,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&EventPair,
|
(PVOID*)&EventPair,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeSetEvent(&EventPair->LowEvent,
|
|
||||||
EVENT_INCREMENT,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Set the Event */
|
||||||
|
KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
ObDereferenceObject(EventPair);
|
ObDereferenceObject(EventPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,275 +306,114 @@ NTSTATUS STDCALL
|
||||||
NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
|
NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
|
||||||
{
|
{
|
||||||
PKEVENT_PAIR EventPair;
|
PKEVENT_PAIR EventPair;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
|
||||||
|
|
||||||
DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
|
/* Open the Object */
|
||||||
EventPairHandle);
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||||
SYNCHRONIZE,
|
SYNCHRONIZE,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&EventPair,
|
(PVOID*)&EventPair,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeSetEvent(&EventPair->LowEvent,
|
|
||||||
EVENT_INCREMENT,
|
|
||||||
TRUE);
|
|
||||||
|
|
||||||
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Set the Event */
|
||||||
|
KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
/* Wait for the Other one */
|
||||||
KeWaitForSingleObject(&EventPair->HighEvent,
|
KeWaitForSingleObject(&EventPair->HighEvent,
|
||||||
WrEventPair,
|
WrEventPair,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
ObDereferenceObject(EventPair);
|
ObDereferenceObject(EventPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtWaitLowEventPair(IN HANDLE EventPairHandle)
|
NtWaitLowEventPair(IN HANDLE EventPairHandle)
|
||||||
{
|
{
|
||||||
PKEVENT_PAIR EventPair;
|
PKEVENT_PAIR EventPair;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
|
||||||
|
|
||||||
DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
|
/* Open the Object */
|
||||||
EventPairHandle);
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||||
SYNCHRONIZE,
|
SYNCHRONIZE,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&EventPair,
|
(PVOID*)&EventPair,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Wait for the Event */
|
||||||
KeWaitForSingleObject(&EventPair->LowEvent,
|
KeWaitForSingleObject(&EventPair->LowEvent,
|
||||||
WrEventPair,
|
WrEventPair,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
ObDereferenceObject(EventPair);
|
ObDereferenceObject(EventPair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
STDCALL
|
||||||
NtWaitHighEventPair(IN HANDLE EventPairHandle)
|
NtWaitHighEventPair(IN HANDLE EventPairHandle)
|
||||||
{
|
{
|
||||||
PKEVENT_PAIR EventPair;
|
PKEVENT_PAIR EventPair;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
|
||||||
|
|
||||||
DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
|
/* Open the Object */
|
||||||
EventPairHandle);
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||||
SYNCHRONIZE,
|
SYNCHRONIZE,
|
||||||
ExEventPairObjectType,
|
ExEventPairObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&EventPair,
|
(PVOID*)&EventPair,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for Success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Wait for the Event */
|
||||||
KeWaitForSingleObject(&EventPair->HighEvent,
|
KeWaitForSingleObject(&EventPair->HighEvent,
|
||||||
WrEventPair,
|
WrEventPair,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
ObDereferenceObject(EventPair);
|
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 */
|
/* EOF */
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/* $Id:$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ex/mutant.c
|
* 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 *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -22,52 +23,39 @@ static GENERIC_MAPPING ExpMutantMapping = {
|
||||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
|
||||||
MUTANT_ALL_ACCESS};
|
MUTANT_ALL_ACCESS};
|
||||||
|
|
||||||
static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
|
static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = {
|
||||||
{
|
|
||||||
ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */
|
/* MutantBasicInformation */
|
||||||
|
ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
NTSTATUS STDCALL
|
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
|
|
||||||
ExpDeleteMutant(PVOID ObjectBody)
|
ExpDeleteMutant(PVOID ObjectBody)
|
||||||
{
|
{
|
||||||
DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
|
|
||||||
|
|
||||||
|
DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody);
|
||||||
|
|
||||||
|
/* Make sure to release the Mutant */
|
||||||
KeReleaseMutant((PKMUTANT)ObjectBody,
|
KeReleaseMutant((PKMUTANT)ObjectBody,
|
||||||
MUTANT_INCREMENT,
|
MUTANT_INCREMENT,
|
||||||
TRUE,
|
TRUE,
|
||||||
FALSE);
|
FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
VOID INIT_FUNCTION
|
INIT_FUNCTION
|
||||||
ExpInitializeMutantImplementation(VOID)
|
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');
|
/* Create the Object Type */
|
||||||
|
RtlInitUnicodeString(&ExMutantObjectType->TypeName, L"Mutant");
|
||||||
|
ExMutantObjectType->Tag = TAG('M', 't', 'n', 't');
|
||||||
ExMutantObjectType->PeakObjects = 0;
|
ExMutantObjectType->PeakObjects = 0;
|
||||||
ExMutantObjectType->PeakHandles = 0;
|
ExMutantObjectType->PeakHandles = 0;
|
||||||
ExMutantObjectType->TotalObjects = 0;
|
ExMutantObjectType->TotalObjects = 0;
|
||||||
|
@ -83,51 +71,47 @@ ExpInitializeMutantImplementation(VOID)
|
||||||
ExMutantObjectType->Security = NULL;
|
ExMutantObjectType->Security = NULL;
|
||||||
ExMutantObjectType->QueryName = NULL;
|
ExMutantObjectType->QueryName = NULL;
|
||||||
ExMutantObjectType->OkayToClose = NULL;
|
ExMutantObjectType->OkayToClose = NULL;
|
||||||
ExMutantObjectType->Create = ExpCreateMutant;
|
ExMutantObjectType->Create = NULL;
|
||||||
ExMutantObjectType->DuplicationNotify = NULL;
|
ExMutantObjectType->DuplicationNotify = NULL;
|
||||||
|
|
||||||
ObpCreateTypeObject(ExMutantObjectType);
|
ObpCreateTypeObject(ExMutantObjectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtCreateMutant(OUT PHANDLE MutantHandle,
|
NtCreateMutant(OUT PHANDLE MutantHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||||
IN BOOLEAN InitialOwner)
|
IN BOOLEAN InitialOwner)
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
HANDLE hMutant;
|
HANDLE hMutant;
|
||||||
PKMUTEX Mutant;
|
PKMUTANT Mutant;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(MutantHandle,
|
ProbeForWrite(MutantHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create the Mutant Object*/
|
||||||
Status = ObCreateObject(PreviousMode,
|
Status = ObCreateObject(PreviousMode,
|
||||||
ExMutantObjectType,
|
ExMutantObjectType,
|
||||||
ObjectAttributes,
|
ObjectAttributes,
|
||||||
|
@ -137,11 +121,15 @@ NtCreateMutant(OUT PHANDLE MutantHandle,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(PVOID*)&Mutant);
|
(PVOID*)&Mutant);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeInitializeMutant(Mutant,
|
|
||||||
InitialOwner);
|
|
||||||
|
|
||||||
|
/* Check for success */
|
||||||
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Initalize the Kernel Mutant */
|
||||||
|
DPRINT("Initializing the Mutant\n");
|
||||||
|
KeInitializeMutant(Mutant, InitialOwner);
|
||||||
|
|
||||||
|
/* Insert the Object */
|
||||||
Status = ObInsertObject((PVOID)Mutant,
|
Status = ObInsertObject((PVOID)Mutant,
|
||||||
NULL,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
|
@ -150,62 +138,59 @@ NtCreateMutant(OUT PHANDLE MutantHandle,
|
||||||
&hMutant);
|
&hMutant);
|
||||||
ObDereferenceObject(Mutant);
|
ObDereferenceObject(Mutant);
|
||||||
|
|
||||||
if(NT_SUCCESS(Status))
|
/* Check for success and return handle */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*MutantHandle = hMutant;
|
*MutantHandle = hMutant;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtOpenMutant(OUT PHANDLE MutantHandle,
|
NtOpenMutant(OUT PHANDLE MutantHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
HANDLE hMutant;
|
HANDLE hMutant;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
|
DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(MutantHandle,
|
ProbeForWrite(MutantHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObOpenObjectByName(ObjectAttributes,
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
ExMutantObjectType,
|
ExMutantObjectType,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -214,27 +199,29 @@ NtOpenMutant(OUT PHANDLE MutantHandle,
|
||||||
NULL,
|
NULL,
|
||||||
&hMutant);
|
&hMutant);
|
||||||
|
|
||||||
if(NT_SUCCESS(Status))
|
/* Check for success and return handle */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*MutantHandle = hMutant;
|
*MutantHandle = hMutant;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtQueryMutant(IN HANDLE MutantHandle,
|
NtQueryMutant(IN HANDLE MutantHandle,
|
||||||
IN MUTANT_INFORMATION_CLASS MutantInformationClass,
|
IN MUTANT_INFORMATION_CLASS MutantInformationClass,
|
||||||
OUT PVOID MutantInformation,
|
OUT PVOID MutantInformation,
|
||||||
|
@ -242,13 +229,13 @@ NtQueryMutant(IN HANDLE MutantHandle,
|
||||||
OUT PULONG ResultLength OPTIONAL)
|
OUT PULONG ResultLength OPTIONAL)
|
||||||
{
|
{
|
||||||
PKMUTANT Mutant;
|
PKMUTANT Mutant;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check buffers and parameters */
|
||||||
|
|
||||||
DefaultQueryInfoBufferCheck(MutantInformationClass,
|
DefaultQueryInfoBufferCheck(MutantInformationClass,
|
||||||
ExMutantInfoClass,
|
ExMutantInfoClass,
|
||||||
MutantInformation,
|
MutantInformation,
|
||||||
|
@ -256,53 +243,44 @@ NtQueryMutant(IN HANDLE MutantHandle,
|
||||||
ResultLength,
|
ResultLength,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
&Status);
|
&Status);
|
||||||
if(!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status)) {
|
||||||
{
|
|
||||||
DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
|
DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObReferenceObjectByHandle(MutantHandle,
|
Status = ObReferenceObjectByHandle(MutantHandle,
|
||||||
MUTANT_QUERY_STATE,
|
MUTANT_QUERY_STATE,
|
||||||
ExMutantObjectType,
|
ExMutantObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Mutant,
|
(PVOID*)&Mutant,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
/* Check for Status */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
switch(MutantInformationClass)
|
|
||||||
{
|
|
||||||
case MutantBasicInformation:
|
|
||||||
{
|
|
||||||
PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
|
|
||||||
|
|
||||||
_SEH_TRY
|
_SEH_TRY {
|
||||||
{
|
|
||||||
BasicInfo->Count = KeReadStateMutant(Mutant);
|
/* Fill out the Basic Information Requested */
|
||||||
BasicInfo->Owned = (Mutant->OwnerThread != NULL);
|
DPRINT("Returning Mutant Information\n");
|
||||||
BasicInfo->Abandoned = Mutant->Abandoned;
|
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 {
|
||||||
|
|
||||||
if(ResultLength != NULL)
|
|
||||||
{
|
|
||||||
*ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
} _SEH_END;
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Release the Object */
|
||||||
ObDereferenceObject(Mutant);
|
ObDereferenceObject(Mutant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,66 +288,71 @@ NtQueryMutant(IN HANDLE MutantHandle,
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtReleaseMutant(IN HANDLE MutantHandle,
|
NtReleaseMutant(IN HANDLE MutantHandle,
|
||||||
IN PLONG PreviousCount OPTIONAL)
|
IN PLONG PreviousCount OPTIONAL)
|
||||||
{
|
{
|
||||||
PKMUTANT Mutant;
|
PKMUTANT Mutant;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
|
DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
|
||||||
MutantHandle, PreviousCount);
|
MutantHandle,
|
||||||
|
PreviousCount);
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode == UserMode && PreviousCount) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousCount != NULL && PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(PreviousCount,
|
ProbeForWrite(PreviousCount,
|
||||||
sizeof(LONG),
|
sizeof(LONG),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObReferenceObjectByHandle(MutantHandle,
|
Status = ObReferenceObjectByHandle(MutantHandle,
|
||||||
MUTANT_QUERY_STATE,
|
MUTANT_QUERY_STATE,
|
||||||
ExMutantObjectType,
|
ExMutantObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Mutant,
|
(PVOID*)&Mutant,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for Success and release if such */
|
||||||
LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE);
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
LONG Prev;
|
||||||
|
|
||||||
|
/* Save the Old State */
|
||||||
|
DPRINT("Releasing Mutant\n");
|
||||||
|
Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, FALSE, FALSE);
|
||||||
ObDereferenceObject(Mutant);
|
ObDereferenceObject(Mutant);
|
||||||
|
|
||||||
if(PreviousCount != NULL)
|
/* Return it */
|
||||||
{
|
if(PreviousCount) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*PreviousCount = Prev;
|
*PreviousCount = Prev;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ex/rundown.c
|
* FILE: ntoskrnl/ex/rundown.c
|
||||||
* PURPOSE: Rundown Protection Functions
|
* PURPOSE: Rundown Protection Functions
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: No programmer listed.
|
* PROGRAMMERS: Alex Ionescu & Thomas Weidenmueller - Implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ex/sem.c
|
* FILE: ntoskrnl/ex/sem.c
|
||||||
* PURPOSE: Synchronization primitives
|
* PURPOSE: Synchronization primitives
|
||||||
*
|
*
|
||||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes.
|
||||||
|
* David Welch (welch@mcmail.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -24,37 +24,20 @@ static GENERIC_MAPPING ExSemaphoreMapping = {
|
||||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
|
||||||
SEMAPHORE_ALL_ACCESS};
|
SEMAPHORE_ALL_ACCESS};
|
||||||
|
|
||||||
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
|
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = {
|
||||||
{
|
|
||||||
ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */
|
/* SemaphoreBasicInformation */
|
||||||
|
ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
VOID
|
||||||
|
INIT_FUNCTION
|
||||||
NTSTATUS STDCALL
|
|
||||||
ExpCreateSemaphore(PVOID ObjectBody,
|
|
||||||
PVOID Parent,
|
|
||||||
PWSTR RemainingPath,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
|
||||||
{
|
|
||||||
DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
|
||||||
ObjectBody, Parent, RemainingPath);
|
|
||||||
|
|
||||||
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
|
|
||||||
{
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
|
||||||
ExpInitializeSemaphoreImplementation(VOID)
|
ExpInitializeSemaphoreImplementation(VOID)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/* Create the Semaphore Object */
|
||||||
ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||||
|
RtlInitUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore");
|
||||||
RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool);
|
|
||||||
|
|
||||||
ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
|
ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
|
||||||
ExSemaphoreObjectType->PeakObjects = 0;
|
ExSemaphoreObjectType->PeakObjects = 0;
|
||||||
ExSemaphoreObjectType->PeakHandles = 0;
|
ExSemaphoreObjectType->PeakHandles = 0;
|
||||||
|
@ -71,16 +54,16 @@ ExpInitializeSemaphoreImplementation(VOID)
|
||||||
ExSemaphoreObjectType->Security = NULL;
|
ExSemaphoreObjectType->Security = NULL;
|
||||||
ExSemaphoreObjectType->QueryName = NULL;
|
ExSemaphoreObjectType->QueryName = NULL;
|
||||||
ExSemaphoreObjectType->OkayToClose = NULL;
|
ExSemaphoreObjectType->OkayToClose = NULL;
|
||||||
ExSemaphoreObjectType->Create = ExpCreateSemaphore;
|
ExSemaphoreObjectType->Create = NULL;
|
||||||
ExSemaphoreObjectType->DuplicationNotify = NULL;
|
ExSemaphoreObjectType->DuplicationNotify = NULL;
|
||||||
|
|
||||||
ObpCreateTypeObject(ExSemaphoreObjectType);
|
ObpCreateTypeObject(ExSemaphoreObjectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
|
NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||||
|
@ -89,33 +72,36 @@ NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
|
||||||
{
|
{
|
||||||
PKSEMAPHORE Semaphore;
|
PKSEMAPHORE Semaphore;
|
||||||
HANDLE hSemaphore;
|
HANDLE hSemaphore;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode != KernelMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(SemaphoreHandle,
|
ProbeForWrite(SemaphoreHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
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,
|
Status = ObCreateObject(PreviousMode,
|
||||||
ExSemaphoreObjectType,
|
ExSemaphoreObjectType,
|
||||||
ObjectAttributes,
|
ObjectAttributes,
|
||||||
|
@ -125,75 +111,76 @@ NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(PVOID*)&Semaphore);
|
(PVOID*)&Semaphore);
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for Success */
|
||||||
|
if (NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Initialize it */
|
||||||
KeInitializeSemaphore(Semaphore,
|
KeInitializeSemaphore(Semaphore,
|
||||||
InitialCount,
|
InitialCount,
|
||||||
MaximumCount);
|
MaximumCount);
|
||||||
|
|
||||||
Status = ObInsertObject ((PVOID)Semaphore,
|
/* Insert it into the Object Tree */
|
||||||
|
Status = ObInsertObject((PVOID)Semaphore,
|
||||||
NULL,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
&hSemaphore);
|
&hSemaphore);
|
||||||
|
|
||||||
ObDereferenceObject(Semaphore);
|
ObDereferenceObject(Semaphore);
|
||||||
|
|
||||||
if(NT_SUCCESS(Status))
|
/* Check for success and return handle */
|
||||||
{
|
if(NT_SUCCESS(Status)) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*SemaphoreHandle = hSemaphore;
|
*SemaphoreHandle = hSemaphore;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
|
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
HANDLE hSemaphore;
|
HANDLE hSemaphore;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check Output Safety */
|
||||||
|
if(PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(SemaphoreHandle,
|
ProbeForWrite(SemaphoreHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open the Object */
|
||||||
Status = ObOpenObjectByName(ObjectAttributes,
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
ExSemaphoreObjectType,
|
ExSemaphoreObjectType,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -201,27 +188,30 @@ NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
NULL,
|
NULL,
|
||||||
&hSemaphore);
|
&hSemaphore);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for success and return handle */
|
||||||
_SEH_TRY
|
if(NT_SUCCESS(Status)) {
|
||||||
{
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
*SemaphoreHandle = hSemaphore;
|
*SemaphoreHandle = hSemaphore;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
|
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
|
||||||
IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
|
IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
|
||||||
OUT PVOID SemaphoreInformation,
|
OUT PVOID SemaphoreInformation,
|
||||||
|
@ -229,13 +219,12 @@ NtQuerySemaphore(IN HANDLE SemaphoreHandle,
|
||||||
OUT PULONG ReturnLength OPTIONAL)
|
OUT PULONG ReturnLength OPTIONAL)
|
||||||
{
|
{
|
||||||
PKSEMAPHORE Semaphore;
|
PKSEMAPHORE Semaphore;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check buffers and class validity */
|
||||||
|
|
||||||
DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
|
DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
|
||||||
ExSemaphoreInfoClass,
|
ExSemaphoreInfoClass,
|
||||||
SemaphoreInformation,
|
SemaphoreInformation,
|
||||||
|
@ -243,120 +232,122 @@ NtQuerySemaphore(IN HANDLE SemaphoreHandle,
|
||||||
ReturnLength,
|
ReturnLength,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
&Status);
|
&Status);
|
||||||
if(!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status)) {
|
||||||
{
|
|
||||||
DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
|
/* Invalid buffers */
|
||||||
|
DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the Object */
|
||||||
Status = ObReferenceObjectByHandle(SemaphoreHandle,
|
Status = ObReferenceObjectByHandle(SemaphoreHandle,
|
||||||
SEMAPHORE_QUERY_STATE,
|
SEMAPHORE_QUERY_STATE,
|
||||||
ExSemaphoreObjectType,
|
ExSemaphoreObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Semaphore,
|
(PVOID*)&Semaphore,
|
||||||
NULL);
|
NULL);
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for success */
|
||||||
switch(SemaphoreInformationClass)
|
if(NT_SUCCESS(Status)) {
|
||||||
{
|
|
||||||
case SemaphoreBasicInformation:
|
_SEH_TRY {
|
||||||
{
|
|
||||||
PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
|
PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
|
||||||
|
|
||||||
_SEH_TRY
|
/* Return the basic information */
|
||||||
{
|
|
||||||
BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
|
BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
|
||||||
BasicInfo->MaximumCount = Semaphore->Limit;
|
BasicInfo->MaximumCount = Semaphore->Limit;
|
||||||
|
|
||||||
if(ReturnLength != NULL)
|
/* Return length */
|
||||||
{
|
if(ReturnLength) *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
|
||||||
*ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
|
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
} _SEH_END;
|
||||||
Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Dereference the Object */
|
||||||
ObDereferenceObject(Semaphore);
|
ObDereferenceObject(Semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
|
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
|
||||||
IN LONG ReleaseCount,
|
IN LONG ReleaseCount,
|
||||||
OUT PLONG PreviousCount OPTIONAL)
|
OUT PLONG PreviousCount OPTIONAL)
|
||||||
{
|
{
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
PKSEMAPHORE Semaphore;
|
PKSEMAPHORE Semaphore;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
/* Check buffer validity */
|
||||||
|
if(PreviousCount != NULL && PreviousMode == UserMode) {
|
||||||
|
|
||||||
|
_SEH_TRY {
|
||||||
|
|
||||||
if(PreviousCount != NULL && PreviousMode == UserMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(PreviousCount,
|
ProbeForWrite(PreviousCount,
|
||||||
sizeof(LONG),
|
sizeof(LONG),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
}
|
} _SEH_HANDLE {
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
} _SEH_END;
|
||||||
{
|
|
||||||
return Status;
|
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,
|
Status = ObReferenceObjectByHandle(SemaphoreHandle,
|
||||||
SEMAPHORE_MODIFY_STATE,
|
SEMAPHORE_MODIFY_STATE,
|
||||||
ExSemaphoreObjectType,
|
ExSemaphoreObjectType,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
(PVOID*)&Semaphore,
|
(PVOID*)&Semaphore,
|
||||||
NULL);
|
NULL);
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
/* Check for success */
|
||||||
|
if (NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
|
/* Release the semaphore */
|
||||||
LONG PrevCount = KeReleaseSemaphore(Semaphore,
|
LONG PrevCount = KeReleaseSemaphore(Semaphore,
|
||||||
IO_NO_INCREMENT,
|
IO_NO_INCREMENT,
|
||||||
ReleaseCount,
|
ReleaseCount,
|
||||||
FALSE);
|
FALSE);
|
||||||
ObDereferenceObject(Semaphore);
|
ObDereferenceObject(Semaphore);
|
||||||
|
|
||||||
if(PreviousCount != NULL)
|
/* Return it */
|
||||||
{
|
if(PreviousCount) {
|
||||||
_SEH_TRY
|
|
||||||
{
|
_SEH_TRY {
|
||||||
|
|
||||||
*PreviousCount = PrevCount;
|
*PreviousCount = PrevCount;
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
} _SEH_HANDLE {
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
}
|
|
||||||
_SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return Status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* $Id: nttimer.c 12779 2005-01-04 04:45:00Z gdalsnes $
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ex/timer.c
|
* FILE: ntoskrnl/ex/timer.c
|
||||||
|
@ -124,8 +123,8 @@ ExpTimerApcKernelRoutine(PKAPC Apc,
|
||||||
PVOID* SystemArguemnt2)
|
PVOID* SystemArguemnt2)
|
||||||
{
|
{
|
||||||
PETIMER Timer;
|
PETIMER Timer;
|
||||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||||
|
|
||||||
/* We need to find out which Timer we are */
|
/* We need to find out which Timer we are */
|
||||||
Timer = CONTAINING_RECORD(Apc, ETIMER, TimerApc);
|
Timer = CONTAINING_RECORD(Apc, ETIMER, TimerApc);
|
||||||
|
@ -176,7 +175,7 @@ ExpInitializeTimerImplementation(VOID)
|
||||||
ExTimerType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
ExTimerType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||||
|
|
||||||
/* Create the Executive Timer Object */
|
/* Create the Executive Timer Object */
|
||||||
RtlpCreateUnicodeString(&ExTimerType->TypeName, L"Timer", NonPagedPool);
|
RtlInitUnicodeString(&ExTimerType->TypeName, L"Timer");
|
||||||
ExTimerType->Tag = TAG('T', 'I', 'M', 'T');
|
ExTimerType->Tag = TAG('T', 'I', 'M', 'T');
|
||||||
ExTimerType->PeakObjects = 0;
|
ExTimerType->PeakObjects = 0;
|
||||||
ExTimerType->PeakHandles = 0;
|
ExTimerType->PeakHandles = 0;
|
||||||
|
@ -209,7 +208,7 @@ NtCancelTimer(IN HANDLE TimerHandle,
|
||||||
OUT PBOOLEAN CurrentState OPTIONAL)
|
OUT PBOOLEAN CurrentState OPTIONAL)
|
||||||
{
|
{
|
||||||
PETIMER Timer;
|
PETIMER Timer;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
BOOLEAN State;
|
BOOLEAN State;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PETHREAD TimerThread;
|
PETHREAD TimerThread;
|
||||||
|
@ -217,9 +216,6 @@ NtCancelTimer(IN HANDLE TimerHandle,
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
DPRINT("NtCancelTimer(0x%x, 0x%x)\n", TimerHandle, CurrentState);
|
DPRINT("NtCancelTimer(0x%x, 0x%x)\n", TimerHandle, CurrentState);
|
||||||
|
|
||||||
/* Check Parameter Validity */
|
/* Check Parameter Validity */
|
||||||
|
@ -301,10 +297,15 @@ NtCancelTimer(IN HANDLE TimerHandle,
|
||||||
|
|
||||||
/* Make sure it's safe to write to the handle */
|
/* Make sure it's safe to write to the handle */
|
||||||
if(CurrentState != NULL) {
|
if(CurrentState != NULL) {
|
||||||
|
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
*CurrentState = State;
|
*CurrentState = State;
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
} _SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,28 +324,27 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
|
||||||
{
|
{
|
||||||
PETIMER Timer;
|
PETIMER Timer;
|
||||||
HANDLE hTimer;
|
HANDLE hTimer;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
DPRINT("NtCreateTimer(Handle: %x, Type: %d)\n", TimerHandle, TimerType);
|
DPRINT("NtCreateTimer(Handle: %x, Type: %d)\n", TimerHandle, TimerType);
|
||||||
|
|
||||||
/* Check Parameter Validity */
|
/* Check Parameter Validity */
|
||||||
if (PreviousMode != KernelMode) {
|
if (PreviousMode != KernelMode) {
|
||||||
|
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
ProbeForWrite(TimerHandle,
|
ProbeForWrite(TimerHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
} _SEH_END;
|
} _SEH_END;
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status)) {
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the Object */
|
/* Create the Object */
|
||||||
|
@ -388,9 +388,13 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
|
||||||
|
|
||||||
/* Make sure it's safe to write to the handle */
|
/* Make sure it's safe to write to the handle */
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
*TimerHandle = hTimer;
|
*TimerHandle = hTimer;
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
} _SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,28 +410,28 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
HANDLE hTimer;
|
HANDLE hTimer;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
DPRINT("NtOpenTimer(TimerHandle: %x)\n", TimerHandle);
|
DPRINT("NtOpenTimer(TimerHandle: %x)\n", TimerHandle);
|
||||||
|
|
||||||
/* Check Parameter Validity */
|
/* Check Parameter Validity */
|
||||||
if (PreviousMode != KernelMode) {
|
if (PreviousMode != KernelMode) {
|
||||||
|
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
ProbeForWrite(TimerHandle,
|
ProbeForWrite(TimerHandle,
|
||||||
sizeof(HANDLE),
|
sizeof(HANDLE),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
} _SEH_END;
|
} _SEH_END;
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status)) {
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the Timer */
|
/* Open the Timer */
|
||||||
|
@ -444,9 +448,13 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
|
||||||
|
|
||||||
/* Make sure it's safe to write to the handle */
|
/* Make sure it's safe to write to the handle */
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
*TimerHandle = hTimer;
|
*TimerHandle = hTimer;
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
} _SEH_END;
|
} _SEH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,14 +472,11 @@ NtQueryTimer(IN HANDLE TimerHandle,
|
||||||
OUT PULONG ReturnLength OPTIONAL)
|
OUT PULONG ReturnLength OPTIONAL)
|
||||||
{
|
{
|
||||||
PETIMER Timer;
|
PETIMER Timer;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation;
|
PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass);
|
DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass);
|
||||||
|
|
||||||
/* Check Validity */
|
/* Check Validity */
|
||||||
|
@ -499,8 +504,6 @@ NtQueryTimer(IN HANDLE TimerHandle,
|
||||||
/* Check for Success */
|
/* Check for Success */
|
||||||
if(NT_SUCCESS(Status)) {
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
switch(TimerInformationClass) {
|
|
||||||
case TimerBasicInformation: {
|
|
||||||
/* Return the Basic Information */
|
/* Return the Basic Information */
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
|
@ -509,16 +512,15 @@ NtQueryTimer(IN HANDLE TimerHandle,
|
||||||
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
|
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
|
||||||
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
|
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
|
||||||
|
|
||||||
if(ReturnLength != NULL) {
|
if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
|
||||||
*ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
Status = _SEH_GetExceptionCode();
|
|
||||||
} _SEH_END;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
|
} _SEH_END;
|
||||||
|
|
||||||
|
/* Dereference Object */
|
||||||
ObDereferenceObject(Timer);
|
ObDereferenceObject(Timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,41 +541,40 @@ NtSetTimer(IN HANDLE TimerHandle,
|
||||||
PETIMER Timer;
|
PETIMER Timer;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
BOOLEAN State;
|
BOOLEAN State;
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
PETHREAD CurrentThread;
|
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||||
LARGE_INTEGER TimerDueTime;
|
LARGE_INTEGER TimerDueTime;
|
||||||
PETHREAD TimerThread;
|
PETHREAD TimerThread;
|
||||||
BOOLEAN KillTimer = FALSE;
|
BOOLEAN KillTimer = FALSE;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
CurrentThread = PsGetCurrentThread();
|
|
||||||
|
|
||||||
DPRINT("NtSetTimer(TimerHandle: %x, DueTime: %d, Apc: %x, Period: %d)\n", TimerHandle, DueTime->QuadPart, TimerApcRoutine, Period);
|
DPRINT("NtSetTimer(TimerHandle: %x, DueTime: %d, Apc: %x, Period: %d)\n", TimerHandle, DueTime->QuadPart, TimerApcRoutine, Period);
|
||||||
|
|
||||||
/* Check Parameter Validity */
|
/* Check Parameter Validity */
|
||||||
if (PreviousMode != KernelMode) {
|
if (PreviousMode != KernelMode) {
|
||||||
|
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
ProbeForRead(DueTime,
|
ProbeForRead(DueTime,
|
||||||
sizeof(LARGE_INTEGER),
|
sizeof(LARGE_INTEGER),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
TimerDueTime = *DueTime;
|
TimerDueTime = *DueTime;
|
||||||
|
|
||||||
if(PreviousState != NULL) {
|
if(PreviousState != NULL) {
|
||||||
|
|
||||||
ProbeForWrite(PreviousState,
|
ProbeForWrite(PreviousState,
|
||||||
sizeof(BOOLEAN),
|
sizeof(BOOLEAN),
|
||||||
sizeof(BOOLEAN));
|
sizeof(BOOLEAN));
|
||||||
}
|
}
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
} _SEH_END;
|
} _SEH_END;
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status)) {
|
if(!NT_SUCCESS(Status)) return Status;
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the Timer Object */
|
/* Get the Timer Object */
|
||||||
|
@ -689,10 +690,15 @@ NtSetTimer(IN HANDLE TimerHandle,
|
||||||
|
|
||||||
/* Make sure it's safe to write to the handle */
|
/* Make sure it's safe to write to the handle */
|
||||||
if(PreviousState != NULL) {
|
if(PreviousState != NULL) {
|
||||||
|
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
*PreviousState = State;
|
*PreviousState = State;
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
} _SEH_END;
|
} _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)
|
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,8 @@ VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
|
||||||
PVOID Reserved,
|
PVOID Reserved,
|
||||||
PKTRAP_FRAME TrapFrame);
|
PKTRAP_FRAME TrapFrame);
|
||||||
|
|
||||||
|
VOID STDCALL KeInitializeEventPair(PKEVENT_PAIR EventPair);
|
||||||
|
|
||||||
VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
|
VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
|
||||||
IN PKTRAP_FRAME TrapFrame,
|
IN PKTRAP_FRAME TrapFrame,
|
||||||
IN PKNORMAL_ROUTINE NormalRoutine,
|
IN PKNORMAL_ROUTINE NormalRoutine,
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <ntdll/ldr.h>
|
#include <ntdll/ldr.h>
|
||||||
#include <internal/ctype.h>
|
#include <internal/ctype.h>
|
||||||
#include <internal/ntoskrnl.h>
|
#include <internal/ntoskrnl.h>
|
||||||
#include <internal/id.h>
|
|
||||||
#include <internal/ke.h>
|
#include <internal/ke.h>
|
||||||
#include <internal/i386/segment.h>
|
#include <internal/i386/segment.h>
|
||||||
#include <internal/i386/mm.h>
|
#include <internal/i386/mm.h>
|
||||||
|
|
|
@ -176,7 +176,7 @@ IopCreateFile(PVOID ObjectBody,
|
||||||
FileObject,
|
FileObject,
|
||||||
DeviceObject);
|
DeviceObject);
|
||||||
FileObject->Vpb = DeviceObject->Vpb;
|
FileObject->Vpb = DeviceObject->Vpb;
|
||||||
FileObject->Type = InternalFileType;
|
FileObject->Type = IO_TYPE_FILE;
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject,
|
||||||
|
|
||||||
CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
|
CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
|
||||||
CreatedFileObject->Vpb = DeviceObject->Vpb;
|
CreatedFileObject->Vpb = DeviceObject->Vpb;
|
||||||
CreatedFileObject->Type = InternalFileType;
|
CreatedFileObject->Type = IO_TYPE_FILE;
|
||||||
CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
|
CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
|
||||||
|
|
||||||
// shouldn't we initialize the lock event, and several other things here too?
|
// shouldn't we initialize the lock event, and several other things here too?
|
||||||
|
|
|
@ -160,7 +160,7 @@ IopCreateDriver(
|
||||||
|
|
||||||
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
|
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
|
||||||
|
|
||||||
Object->Type = InternalDriverType;
|
Object->Type = IO_TYPE_DRIVER;
|
||||||
|
|
||||||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||||
Object->MajorFunction[i] = IopInvalidDeviceRequest;
|
Object->MajorFunction[i] = IopInvalidDeviceRequest;
|
||||||
|
|
|
@ -249,4 +249,18 @@ IoWMIDeviceObjectToInstanceName(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
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*/
|
/*Eof*/
|
||||||
|
|
|
@ -19,140 +19,240 @@
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID STDCALL KeClearEvent (PKEVENT Event)
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KeClearEvent(PKEVENT Event)
|
||||||
{
|
{
|
||||||
DPRINT("KeClearEvent(Event %x)\n", Event);
|
DPRINT("KeClearEvent(Event %x)\n", Event);
|
||||||
|
|
||||||
|
/* Reset Signal State */
|
||||||
Event->Header.SignalState = FALSE;
|
Event->Header.SignalState = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
LONG STDCALL KeReadStateEvent (PKEVENT Event)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
LONG STDCALL
|
|
||||||
KePulseEvent (IN PKEVENT Event,
|
|
||||||
IN KPRIORITY Increment,
|
|
||||||
IN BOOLEAN Wait)
|
|
||||||
{
|
|
||||||
KIRQL OldIrql;
|
|
||||||
LONG Ret;
|
|
||||||
|
|
||||||
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
|
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
|
||||||
Ret = InterlockedExchange(&Event->Header.SignalState,1);
|
|
||||||
KiDispatcherObjectWake(&Event->Header, Increment);
|
|
||||||
InterlockedExchange(&(Event->Header.SignalState),0);
|
|
||||||
|
|
||||||
if (Wait == FALSE)
|
|
||||||
{
|
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KTHREAD *Thread = KeGetCurrentThread();
|
|
||||||
Thread->WaitNext = TRUE;
|
|
||||||
Thread->WaitIrql = OldIrql;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeSetEventBoostPriority(
|
KeInitializeEvent(PKEVENT Event,
|
||||||
IN PKEVENT Event,
|
EVENT_TYPE Type,
|
||||||
IN PKTHREAD *Thread OPTIONAL
|
BOOLEAN State)
|
||||||
)
|
{
|
||||||
|
DPRINT("KeInitializeEvent(Event %x)\n", Event);
|
||||||
|
|
||||||
|
/* Initialize the Dispatcher Header */
|
||||||
|
KeInitializeDispatcherHeader(&Event->Header,
|
||||||
|
Type,
|
||||||
|
sizeof(Event) / sizeof(ULONG),
|
||||||
|
State);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KeInitializeEventPair(PKEVENT_PAIR EventPair)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
LONG PreviousState;
|
||||||
|
|
||||||
|
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
|
||||||
|
|
||||||
|
/* Lock the Dispatcher Database */
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
|
/* Save the Old State */
|
||||||
|
PreviousState = Event->Header.SignalState;
|
||||||
|
|
||||||
|
/* Check if we are non-signaled and we have stuff in the Wait Queue */
|
||||||
|
if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead)) {
|
||||||
|
|
||||||
|
/* Set the Event to Signaled */
|
||||||
|
Event->Header.SignalState = 1;
|
||||||
|
|
||||||
|
/* Wake the Event */
|
||||||
|
KiDispatcherObjectWake(&Event->Header, Increment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unsignal it */
|
||||||
|
Event->Header.SignalState = 0;
|
||||||
|
|
||||||
|
/* Check what wait state was requested */
|
||||||
|
if (Wait == FALSE) {
|
||||||
|
|
||||||
|
/* Wait not requested, release Dispatcher Database and return */
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Return Locked and with a Wait */
|
||||||
|
KTHREAD *Thread = KeGetCurrentThread();
|
||||||
|
Thread->WaitNext = TRUE;
|
||||||
|
Thread->WaitIrql = OldIrql;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the previous State */
|
||||||
|
return PreviousState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KeSetEventBoostPriority(IN PKEVENT Event,
|
||||||
|
IN PKTHREAD *Thread OPTIONAL)
|
||||||
{
|
{
|
||||||
PKTHREAD WaitingThread;
|
PKTHREAD WaitingThread;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
DPRINT("KeSetEventBoostPriority(Event %x, Thread %x)\n",Event,Thread);
|
||||||
|
|
||||||
|
/* Acquire Dispatcher Database Lock */
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
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 */
|
/* 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;
|
WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
|
||||||
|
KWAIT_BLOCK,
|
||||||
|
WaitListEntry)->Thread;
|
||||||
|
|
||||||
/* Return it to caller if requested */
|
/* Return it to caller if requested */
|
||||||
if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
|
if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
|
||||||
|
@ -160,7 +260,9 @@ KeSetEventBoostPriority(
|
||||||
/* Reset the Quantum and Unwait the Thread */
|
/* Reset the Quantum and Unwait the Thread */
|
||||||
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
|
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
|
||||||
KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
|
KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the Dispatcher Database Lock */
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
/* $Id:$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PURPOSE: ReactOS kernel
|
* PURPOSE: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/kqueue.c
|
* FILE: ntoskrnl/ke/kqueue.c
|
||||||
* PURPOSE: Implement device queues
|
* 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 ****************************************************************/
|
/* INCLUDES ****************************************************************/
|
||||||
|
@ -16,157 +18,33 @@
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @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
|
* FUNCTION: Intializes a device queue
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
* DeviceQueue = Device queue to initialize
|
* DeviceQueue = Device queue to initialize
|
||||||
*/
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
|
||||||
{
|
{
|
||||||
ASSERT(DeviceQueue!=NULL);
|
|
||||||
|
/* Initialize the Header */
|
||||||
|
DeviceQueue->Type = DeviceQueueObject;
|
||||||
|
DeviceQueue->Size = sizeof(KDEVICE_QUEUE);
|
||||||
|
|
||||||
|
/* Initialize the Listhead and Spinlock */
|
||||||
InitializeListHead(&DeviceQueue->DeviceListHead);
|
InitializeListHead(&DeviceQueue->DeviceListHead);
|
||||||
DeviceQueue->Busy=FALSE;
|
|
||||||
KeInitializeSpinLock(&DeviceQueue->Lock);
|
KeInitializeSpinLock(&DeviceQueue->Lock);
|
||||||
|
|
||||||
|
/* Set it as busy */
|
||||||
|
DeviceQueue->Busy=FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
BOOLEAN
|
|
||||||
STDCALL
|
|
||||||
KeInsertDeviceQueue (
|
|
||||||
IN PKDEVICE_QUEUE DeviceQueue,
|
|
||||||
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
|
|
||||||
)
|
|
||||||
/*
|
|
||||||
* FUNCTION: Inserts an entry in a device queue
|
* FUNCTION: Inserts an entry in a device queue
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
* DeviceQueue = Queue to insert the entry in
|
* DeviceQueue = Queue to insert the entry in
|
||||||
|
@ -174,58 +52,221 @@ KeInsertDeviceQueue (
|
||||||
* RETURNS: False is the device queue wasn't busy
|
* RETURNS: False is the device queue wasn't busy
|
||||||
* True otherwise
|
* True otherwise
|
||||||
*/
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
STDCALL
|
||||||
|
KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
|
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
|
||||||
{
|
{
|
||||||
|
BOOLEAN Inserted;
|
||||||
|
|
||||||
|
DPRINT("KeInsertDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
|
||||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
/* Lock the Queue */
|
||||||
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
|
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
|
||||||
|
|
||||||
if (!DeviceQueue->Busy)
|
if (!DeviceQueue->Busy) {
|
||||||
{
|
|
||||||
DeviceQueue->Busy=TRUE;
|
/* Set it as busy */
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
|
Inserted = FALSE;
|
||||||
return(FALSE);
|
DeviceQueue->Busy = TRUE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Insert it into the list */
|
||||||
|
Inserted = TRUE;
|
||||||
|
InsertTailList(&DeviceQueue->DeviceListHead,
|
||||||
|
&DeviceQueueEntry->DeviceListEntry);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceQueueEntry->SortKey=0;
|
/* Sert the Insert state into the entry */
|
||||||
InsertTailList(&DeviceQueue->DeviceListHead, &DeviceQueueEntry->DeviceListEntry);
|
DeviceQueueEntry->Inserted = Inserted;
|
||||||
|
|
||||||
|
/* Release lock and return */
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
|
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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN STDCALL
|
BOOLEAN STDCALL
|
||||||
KeRemoveEntryDeviceQueue(
|
KeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
|
||||||
IN PKDEVICE_QUEUE DeviceQueue,
|
|
||||||
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
|
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY current;
|
KIRQL OldIrql;
|
||||||
KIRQL oldIrql;
|
BOOLEAN OldState;
|
||||||
PKDEVICE_QUEUE_ENTRY entry;
|
|
||||||
|
|
||||||
|
DPRINT("KeRemoveEntryDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
|
||||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||||
|
|
||||||
KeAcquireSpinLock(&DeviceQueue->Lock, &oldIrql);
|
/* Acquire the Lock */
|
||||||
|
KeAcquireSpinLock(&DeviceQueue->Lock, &OldIrql);
|
||||||
|
|
||||||
current = DeviceQueue->DeviceListHead.Flink;
|
/* Check/Set Old State */
|
||||||
while (current != &DeviceQueue->DeviceListHead)
|
if ((OldState = DeviceQueueEntry->Inserted)) {
|
||||||
{
|
|
||||||
entry = CONTAINING_RECORD(current, KDEVICE_QUEUE_ENTRY, DeviceListEntry);
|
/* Remove it */
|
||||||
if (DeviceQueueEntry == entry)
|
DeviceQueueEntry->Inserted = FALSE;
|
||||||
{
|
RemoveEntryList(&DeviceQueueEntry->DeviceListEntry);
|
||||||
RemoveEntryList(current);
|
|
||||||
KeReleaseSpinLock(&DeviceQueue->Lock, oldIrql);
|
|
||||||
/* entry was in the queue (but not anymore) */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
current = current->Flink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseSpinLock(&DeviceQueue->Lock, oldIrql);
|
/* Unlock and return old state */
|
||||||
|
KeReleaseSpinLock(&DeviceQueue->Lock, OldIrql);
|
||||||
/* entry wasn't in the queue */
|
return OldState;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/ke/mutex.c
|
* 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 *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
@ -18,110 +22,50 @@
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID STDCALL
|
VOID
|
||||||
KeInitializeMutex(IN PKMUTEX Mutex,
|
STDCALL
|
||||||
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
|
|
||||||
KeInitializeMutant(IN PKMUTANT Mutant,
|
KeInitializeMutant(IN PKMUTANT Mutant,
|
||||||
IN BOOLEAN InitialOwner)
|
IN BOOLEAN InitialOwner)
|
||||||
{
|
{
|
||||||
if (InitialOwner == TRUE)
|
ULONG Signaled = TRUE;
|
||||||
{
|
PKTHREAD CurrentThread = NULL;
|
||||||
KeInitializeDispatcherHeader(&Mutant->Header,
|
KIRQL OldIrql;
|
||||||
InternalMutexType,
|
|
||||||
sizeof(KMUTANT) / sizeof(ULONG),
|
DPRINT("KeInitializeMutant: %x\n", Mutant);
|
||||||
0);
|
|
||||||
InsertTailList(&KeGetCurrentThread()->MutantListHead,
|
/* Check if we have an initial owner */
|
||||||
&Mutant->MutantListEntry);
|
if (InitialOwner == TRUE) {
|
||||||
Mutant->OwnerThread = KeGetCurrentThread();
|
|
||||||
}
|
/* In this case, the object is not signaled */
|
||||||
else
|
Signaled = FALSE;
|
||||||
{
|
|
||||||
KeInitializeDispatcherHeader(&Mutant->Header,
|
/* We also need to associate a thread */
|
||||||
InternalMutexType,
|
CurrentThread = KeGetCurrentThread();
|
||||||
sizeof(KMUTANT) / sizeof(ULONG),
|
|
||||||
1);
|
/* We're about to touch the Thread, so lock the Dispatcher */
|
||||||
Mutant->MutantListEntry.Flink = NULL;
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
Mutant->MutantListEntry.Blink = NULL;
|
|
||||||
|
/* 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;
|
Mutant->OwnerThread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now we set up the Dispatcher Header */
|
||||||
|
KeInitializeDispatcherHeader(&Mutant->Header,
|
||||||
|
MutantObject,
|
||||||
|
sizeof(KMUTANT) / sizeof(ULONG),
|
||||||
|
Signaled);
|
||||||
|
|
||||||
|
/* Initialize the default data */
|
||||||
|
Mutant->OwnerThread = CurrentThread;
|
||||||
Mutant->Abandoned = FALSE;
|
Mutant->Abandoned = FALSE;
|
||||||
Mutant->ApcDisable = 0;
|
Mutant->ApcDisable = 0;
|
||||||
}
|
}
|
||||||
|
@ -129,65 +73,161 @@ KeInitializeMutant(IN PKMUTANT Mutant,
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @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)
|
KeReadStateMutant(IN PKMUTANT Mutant)
|
||||||
{
|
{
|
||||||
|
/* Return the Signal State */
|
||||||
return(Mutant->Header.SignalState);
|
return(Mutant->Header.SignalState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
LONG STDCALL
|
LONG
|
||||||
|
STDCALL
|
||||||
|
KeReadStateMutex(IN PKMUTEX Mutex)
|
||||||
|
{
|
||||||
|
/* Return the Signal State */
|
||||||
|
return(Mutex->Header.SignalState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
LONG
|
||||||
|
STDCALL
|
||||||
KeReleaseMutant(IN PKMUTANT Mutant,
|
KeReleaseMutant(IN PKMUTANT Mutant,
|
||||||
IN KPRIORITY Increment,
|
IN KPRIORITY Increment,
|
||||||
IN BOOLEAN Abandon,
|
IN BOOLEAN Abandon,
|
||||||
IN BOOLEAN Wait)
|
IN BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
LONG PreviousState;
|
||||||
|
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||||
|
|
||||||
|
DPRINT("KeReleaseMutant: %x\n", Mutant);
|
||||||
|
|
||||||
|
/* Lock the Dispatcher Database */
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
if (Abandon == FALSE)
|
|
||||||
{
|
/* Save the Previous State */
|
||||||
if (Mutant->OwnerThread != NULL && Mutant->OwnerThread != KeGetCurrentThread())
|
PreviousState = Mutant->Header.SignalState;
|
||||||
{
|
|
||||||
DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutant->OwnerThread %p CurrentThread %p\n",
|
/* Check if it is to be abandonned */
|
||||||
Mutant->OwnerThread,
|
if (Abandon == FALSE) {
|
||||||
KeGetCurrentThread());
|
|
||||||
KEBUGCHECK(THREAD_NOT_MUTEX_OWNER);
|
/* 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++;
|
Mutant->Header.SignalState++;
|
||||||
ASSERT(Mutant->Header.SignalState <= 1);
|
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
/* It's going to be abandonned */
|
||||||
if (Mutant->OwnerThread != NULL)
|
DPRINT("Abandonning the Mutant\n");
|
||||||
{
|
|
||||||
Mutant->Header.SignalState = 1;
|
Mutant->Header.SignalState = 1;
|
||||||
Mutant->Abandoned = TRUE;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mutant->Header.SignalState == 1)
|
/* Remove the Owning Thread and wake it */
|
||||||
{
|
|
||||||
Mutant->OwnerThread = NULL;
|
Mutant->OwnerThread = NULL;
|
||||||
if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
|
|
||||||
RemoveEntryList(&Mutant->MutantListEntry);
|
/* 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);
|
KiDispatcherObjectWake(&Mutant->Header, Increment);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Wait == FALSE)
|
/* 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);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
}
|
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
KTHREAD *Thread = KeGetCurrentThread();
|
/* Set a wait */
|
||||||
Thread->WaitNext = TRUE;
|
CurrentThread->WaitNext = TRUE;
|
||||||
Thread->WaitIrql = OldIrql;
|
CurrentThread->WaitIrql = OldIrql;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0);
|
/* Return the previous state */
|
||||||
|
return PreviousState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @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 */
|
/* EOF */
|
||||||
|
|
|
@ -25,7 +25,7 @@ KeInitializeQueue(IN PKQUEUE Queue,
|
||||||
IN ULONG Count OPTIONAL)
|
IN ULONG Count OPTIONAL)
|
||||||
{
|
{
|
||||||
KeInitializeDispatcherHeader(&Queue->Header,
|
KeInitializeDispatcherHeader(&Queue->Header,
|
||||||
InternalQueueType,
|
QueueObject,
|
||||||
sizeof(KQUEUE)/sizeof(ULONG),
|
sizeof(KQUEUE)/sizeof(ULONG),
|
||||||
0);
|
0);
|
||||||
InitializeListHead(&Queue->EntryListHead);
|
InitializeListHead(&Queue->EntryListHead);
|
||||||
|
|
|
@ -19,36 +19,39 @@
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
VOID STDCALL
|
VOID
|
||||||
KeInitializeSemaphore (PKSEMAPHORE Semaphore,
|
STDCALL
|
||||||
|
KeInitializeSemaphore(PKSEMAPHORE Semaphore,
|
||||||
LONG Count,
|
LONG Count,
|
||||||
LONG Limit)
|
LONG Limit)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
DPRINT("KeInitializeSemaphore Sem: %x\n", Semaphore);
|
||||||
|
|
||||||
|
/* Simply Initialize the Header */
|
||||||
KeInitializeDispatcherHeader(&Semaphore->Header,
|
KeInitializeDispatcherHeader(&Semaphore->Header,
|
||||||
InternalSemaphoreType,
|
SemaphoreObject,
|
||||||
sizeof(KSEMAPHORE)/sizeof(ULONG),
|
sizeof(KSEMAPHORE)/sizeof(ULONG),
|
||||||
Count);
|
Count);
|
||||||
Semaphore->Limit=Limit;
|
|
||||||
|
/* Set the Limit */
|
||||||
|
Semaphore->Limit = Limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
LONG STDCALL
|
LONG
|
||||||
KeReadStateSemaphore (PKSEMAPHORE Semaphore)
|
STDCALL
|
||||||
|
KeReadStateSemaphore(PKSEMAPHORE Semaphore)
|
||||||
{
|
{
|
||||||
|
/* Just return the Signal State */
|
||||||
return(Semaphore->Header.SignalState);
|
return(Semaphore->Header.SignalState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*
|
||||||
LONG STDCALL
|
|
||||||
KeReleaseSemaphore (PKSEMAPHORE Semaphore,
|
|
||||||
KPRIORITY Increment,
|
|
||||||
LONG Adjustment,
|
|
||||||
BOOLEAN Wait)
|
|
||||||
/*
|
|
||||||
* FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
|
* FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
|
||||||
* routine supplies a runtime priority boost for waiting threads. If this
|
* routine supplies a runtime priority boost for waiting threads. If this
|
||||||
* call sets the semaphore to the Signaled state, the semaphore count is
|
* 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
|
* RETURNS: If the return value is zero, the previous state of the semaphore
|
||||||
* object is Not-Signaled.
|
* object is Not-Signaled.
|
||||||
*/
|
*/
|
||||||
|
LONG
|
||||||
|
STDCALL
|
||||||
|
KeReleaseSemaphore(PKSEMAPHORE Semaphore,
|
||||||
|
KPRIORITY Increment,
|
||||||
|
LONG Adjustment,
|
||||||
|
BOOLEAN Wait)
|
||||||
|
|
||||||
{
|
{
|
||||||
ULONG InitialState;
|
ULONG InitialState;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
PKTHREAD CurrentThread;
|
||||||
|
|
||||||
DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
|
DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n",
|
||||||
"Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
|
Semaphore,
|
||||||
|
Increment,
|
||||||
|
Adjustment,
|
||||||
|
Wait);
|
||||||
|
|
||||||
|
/* Lock the Dispatcher Database */
|
||||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
|
||||||
|
/* Save the Old State */
|
||||||
InitialState = Semaphore->Header.SignalState;
|
InitialState = Semaphore->Header.SignalState;
|
||||||
|
|
||||||
|
/* Check if the Limit was exceeded */
|
||||||
if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
|
if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
|
||||||
InitialState > InitialState + Adjustment)
|
InitialState > InitialState + Adjustment) {
|
||||||
{
|
|
||||||
|
/* Raise an error if it was exceeded */
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
|
ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now set the new state */
|
||||||
Semaphore->Header.SignalState += Adjustment;
|
Semaphore->Header.SignalState += Adjustment;
|
||||||
if (InitialState == 0)
|
|
||||||
{
|
/* Check if we should wake it */
|
||||||
|
if (InitialState == 0 && !IsListEmpty(&Semaphore->Header.WaitListHead)) {
|
||||||
|
|
||||||
|
/* Wake the Semaphore */
|
||||||
KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT);
|
KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Wait == FALSE)
|
/* 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);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
}
|
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
KTHREAD *Thread = KeGetCurrentThread();
|
/* Set a wait */
|
||||||
Thread->WaitNext = TRUE;
|
CurrentThread = KeGetCurrentThread();
|
||||||
Thread->WaitIrql = OldIrql;
|
CurrentThread->WaitNext = TRUE;
|
||||||
|
CurrentThread->WaitIrql = OldIrql;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(InitialState);
|
/* Return the previous state */
|
||||||
|
return InitialState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -107,12 +107,11 @@ KeInitializeTimerEx (PKTIMER Timer,
|
||||||
|
|
||||||
/* Initialize the Dispatch Header */
|
/* Initialize the Dispatch Header */
|
||||||
KeInitializeDispatcherHeader(&Timer->Header,
|
KeInitializeDispatcherHeader(&Timer->Header,
|
||||||
InternalNotificationTimer + Type,
|
TimerNotificationObject + Type,
|
||||||
sizeof(KTIMER) / sizeof(ULONG),
|
sizeof(KTIMER) / sizeof(ULONG),
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
/* Initalize the List Head and other data */
|
/* Initalize the Other data */
|
||||||
InitializeListHead(&Timer->Header.WaitListHead);
|
|
||||||
Timer->DueTime.QuadPart = 0;
|
Timer->DueTime.QuadPart = 0;
|
||||||
Timer->Period = 0;
|
Timer->Period = 0;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +195,6 @@ KeSetTimerEx (PKTIMER Timer,
|
||||||
Timer->Dpc = Dpc;
|
Timer->Dpc = Dpc;
|
||||||
Timer->Period = Period;
|
Timer->Period = Period;
|
||||||
Timer->Header.SignalState = FALSE;
|
Timer->Header.SignalState = FALSE;
|
||||||
Timer->Header.Absolute = FALSE;
|
|
||||||
|
|
||||||
/* Insert it */
|
/* Insert it */
|
||||||
if (!KiInsertTimer(Timer, DueTime)) {
|
if (!KiInsertTimer(Timer, DueTime)) {
|
||||||
|
@ -303,7 +301,7 @@ KiHandleExpiredTimer(PKTIMER Timer)
|
||||||
if (!KiInsertTimer(Timer, DueTime)) {
|
if (!KiInsertTimer(Timer, DueTime)) {
|
||||||
|
|
||||||
/* FIXME: I will think about how to handle this and fix it ASAP -- Alex */
|
/* 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);
|
DPRINT("KiInsertTimer(Timer %x DueTime %I64d)\n", Timer, DueTime.QuadPart);
|
||||||
|
|
||||||
/* Set it as Inserted */
|
/* Set default data */
|
||||||
Timer->Header.Inserted = TRUE;
|
Timer->Header.Inserted = TRUE;
|
||||||
|
Timer->Header.Absolute = FALSE;
|
||||||
|
if (!Timer->Period) Timer->Header.SignalState = FALSE;
|
||||||
|
|
||||||
/* Convert to relative time if needed */
|
/* Convert to relative time if needed */
|
||||||
if (DueTime.u.HighPart >= 0) {
|
if (DueTime.u.HighPart >= 0) {
|
||||||
|
|
|
@ -114,34 +114,34 @@ KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
|
||||||
|
|
||||||
switch (hdr->Type)
|
switch (hdr->Type)
|
||||||
{
|
{
|
||||||
case InternalSynchronizationEvent:
|
case EventSynchronizationObject:
|
||||||
hdr->SignalState = 0;
|
hdr->SignalState = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalQueueType:
|
case QueueObject:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalSemaphoreType:
|
case SemaphoreObject:
|
||||||
hdr->SignalState--;
|
hdr->SignalState--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalProcessType:
|
case ProcessObject:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ThreadObject:
|
case ThreadObject:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalNotificationEvent:
|
case EventNotificationObject:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalSynchronizationTimer:
|
case TimerSynchronizationObject:
|
||||||
hdr->SignalState = FALSE;
|
hdr->SignalState = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalNotificationTimer:
|
case TimerNotificationObject:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalMutexType:
|
case MutantObject:
|
||||||
{
|
{
|
||||||
PKMUTEX Mutex;
|
PKMUTEX Mutex;
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ static BOOLEAN
|
||||||
KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
|
KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
|
||||||
PKTHREAD Thread)
|
PKTHREAD Thread)
|
||||||
{
|
{
|
||||||
if (hdr->Type == InternalMutexType)
|
if (hdr->Type == MutantObject)
|
||||||
{
|
{
|
||||||
PKMUTEX Mutex;
|
PKMUTEX Mutex;
|
||||||
|
|
||||||
|
@ -355,22 +355,22 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
|
||||||
DPRINT("hdr->Type %x\n",hdr->Type);
|
DPRINT("hdr->Type %x\n",hdr->Type);
|
||||||
switch (hdr->Type)
|
switch (hdr->Type)
|
||||||
{
|
{
|
||||||
case InternalNotificationEvent:
|
case EventNotificationObject:
|
||||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||||
|
|
||||||
case InternalNotificationTimer:
|
case TimerNotificationObject:
|
||||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||||
|
|
||||||
case InternalSynchronizationEvent:
|
case EventSynchronizationObject:
|
||||||
return(KeDispatcherObjectWakeOne(hdr, increment));
|
return(KeDispatcherObjectWakeOne(hdr, increment));
|
||||||
|
|
||||||
case InternalSynchronizationTimer:
|
case TimerSynchronizationObject:
|
||||||
return(KeDispatcherObjectWakeOne(hdr, increment));
|
return(KeDispatcherObjectWakeOne(hdr, increment));
|
||||||
|
|
||||||
case InternalQueueType:
|
case QueueObject:
|
||||||
return(KeDispatcherObjectWakeOne(hdr, increment));
|
return(KeDispatcherObjectWakeOne(hdr, increment));
|
||||||
|
|
||||||
case InternalSemaphoreType:
|
case SemaphoreObject:
|
||||||
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
|
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
|
||||||
if(hdr->SignalState>0)
|
if(hdr->SignalState>0)
|
||||||
{
|
{
|
||||||
|
@ -383,13 +383,13 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
|
||||||
}
|
}
|
||||||
else return FALSE;
|
else return FALSE;
|
||||||
|
|
||||||
case InternalProcessType:
|
case ProcessObject:
|
||||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||||
|
|
||||||
case ThreadObject:
|
case ThreadObject:
|
||||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||||
|
|
||||||
case InternalMutexType:
|
case MutantObject:
|
||||||
return(KeDispatcherObjectWakeOne(hdr, increment));
|
return(KeDispatcherObjectWakeOne(hdr, increment));
|
||||||
}
|
}
|
||||||
DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type);
|
DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type);
|
||||||
|
@ -463,7 +463,7 @@ PVOID
|
||||||
KiGetWaitableObjectFromObject(PVOID Object)
|
KiGetWaitableObjectFromObject(PVOID Object)
|
||||||
{
|
{
|
||||||
//special case when waiting on file objects
|
//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;
|
return &((PFILE_OBJECT)Object)->Event;
|
||||||
}
|
}
|
||||||
|
@ -1026,19 +1026,19 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
|
||||||
hdr = (DISPATCHER_HEADER *)SignalObj;
|
hdr = (DISPATCHER_HEADER *)SignalObj;
|
||||||
switch (hdr->Type)
|
switch (hdr->Type)
|
||||||
{
|
{
|
||||||
case InternalNotificationEvent:
|
case EventNotificationObject:
|
||||||
case InternalSynchronizationEvent:
|
case EventSynchronizationObject:
|
||||||
KeSetEvent(SignalObj,
|
KeSetEvent(SignalObj,
|
||||||
EVENT_INCREMENT,
|
EVENT_INCREMENT,
|
||||||
TRUE);
|
TRUE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalMutexType:
|
case MutantObject:
|
||||||
KeReleaseMutex(SignalObj,
|
KeReleaseMutex(SignalObj,
|
||||||
TRUE);
|
TRUE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InternalSemaphoreType:
|
case SemaphoreObject:
|
||||||
KeReleaseSemaphore(SignalObj,
|
KeReleaseSemaphore(SignalObj,
|
||||||
SEMAPHORE_INCREMENT,
|
SEMAPHORE_INCREMENT,
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -388,7 +388,7 @@ PsInitProcessManagment(VOID)
|
||||||
PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
|
PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
|
||||||
InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
|
InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
|
||||||
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
|
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
|
||||||
InternalProcessType,
|
ProcessObject,
|
||||||
sizeof(EPROCESS),
|
sizeof(EPROCESS),
|
||||||
FALSE);
|
FALSE);
|
||||||
KProcess = &PsInitialSystemProcess->Pcb;
|
KProcess = &PsInitialSystemProcess->Pcb;
|
||||||
|
@ -848,7 +848,7 @@ exitdereferenceobjects:
|
||||||
}
|
}
|
||||||
|
|
||||||
KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
|
KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
|
||||||
InternalProcessType,
|
ProcessObject,
|
||||||
sizeof(EPROCESS),
|
sizeof(EPROCESS),
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,6 @@ NtSetEaFile 4
|
||||||
NtSetEvent 2
|
NtSetEvent 2
|
||||||
NtSetHighEventPair 1
|
NtSetHighEventPair 1
|
||||||
NtSetHighWaitLowEventPair 1
|
NtSetHighWaitLowEventPair 1
|
||||||
NtSetHighWaitLowThread 0
|
|
||||||
NtSetInformationFile 5
|
NtSetInformationFile 5
|
||||||
NtSetInformationKey 4
|
NtSetInformationKey 4
|
||||||
NtSetInformationJobObject 4
|
NtSetInformationJobObject 4
|
||||||
|
@ -192,7 +191,6 @@ NtSetIntervalProfile 2
|
||||||
NtSetLdtEntries 6
|
NtSetLdtEntries 6
|
||||||
NtSetLowEventPair 1
|
NtSetLowEventPair 1
|
||||||
NtSetLowWaitHighEventPair 1
|
NtSetLowWaitHighEventPair 1
|
||||||
NtSetLowWaitHighThread 0
|
|
||||||
NtSetQuotaInformationFile 4
|
NtSetQuotaInformationFile 4
|
||||||
NtSetSecurityObject 3
|
NtSetSecurityObject 3
|
||||||
NtSetSystemEnvironmentValue 2
|
NtSetSystemEnvironmentValue 2
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue