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:
Thomas Bluemel 2005-03-14 02:08:17 +00:00
parent 865a496525
commit cfdb595cc6
24 changed files with 2238 additions and 2274 deletions

View file

@ -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

View file

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

View file

@ -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 */

View file

@ -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 */

View file

@ -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;
} }

View file

@ -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 *****************************************************************/

View file

@ -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;
} }

View file

@ -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;
} }
} }

View file

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

View file

@ -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,

View file

@ -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>

View file

@ -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?

View file

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

View file

@ -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*/

View file

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

View file

@ -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;
} }

View file

@ -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 */

View file

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

View file

@ -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 */

View file

@ -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) {

View file

@ -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,

View file

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

View file

@ -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