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
#define IO_TYPE_DRIVER 4L
#define IO_TYPE_FILE 0x0F5L
#define DRVO_UNLOAD_INVOKED 0x1L
#define DRVO_LEGACY_DRIVER 0x2L
#define DRVO_BUILTIN_DRIVER 0x4L

View file

@ -58,6 +58,7 @@ typedef enum _KPROFILE_SOURCE
ProfileTime
} KPROFILE_SOURCE;
// file disposition values
#define FILE_SUPERSEDE 0x0000
@ -1271,9 +1272,9 @@ typedef enum _MUTANT_INFORMATION_CLASS
typedef struct _MUTANT_BASIC_INFORMATION
{
LONG Count;
BOOLEAN Owned;
BOOLEAN Abandoned;
LONG CurrentCount;
BOOLEAN OwnedByCaller;
BOOLEAN AbandonedState;
} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;

File diff suppressed because it is too large Load diff

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
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/evtpair.c
* PURPOSE: Support for event pairs
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
* PROGRAMMERS: Alex Ionescu (Commented, reorganized, removed Thread Pair, used
* KeInitializeEventPair, added SEH)
* David Welch (welch@mcmail.com)
* Skywing (skywing@valhallalegends.com)
*/
@ -15,588 +16,404 @@
#define NDEBUG
#include <internal/debug.h>
#ifndef NTSYSAPI
#define NTSYSAPI
#endif
#ifndef NTAPI
#define NTAPI STDCALL
#endif
/* GLOBALS *******************************************************************/
POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
static GENERIC_MAPPING ExEventPairMapping = {
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
EVENT_PAIR_ALL_ACCESS};
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
EVENT_PAIR_ALL_ACCESS};
static KSPIN_LOCK ExThreadEventPairSpinLock;
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
ExpCreateEventPair(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
DPRINT("ExpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
}
VOID INIT_FUNCTION
VOID
INIT_FUNCTION
ExpInitializeEventPairImplementation(VOID)
{
ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
RtlpCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair", NonPagedPool);
ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a');
ExEventPairObjectType->PeakObjects = 0;
ExEventPairObjectType->PeakHandles = 0;
ExEventPairObjectType->TotalObjects = 0;
ExEventPairObjectType->TotalHandles = 0;
ExEventPairObjectType->PagedPoolCharge = 0;
ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR);
ExEventPairObjectType->Mapping = &ExEventPairMapping;
ExEventPairObjectType->Dump = NULL;
ExEventPairObjectType->Open = NULL;
ExEventPairObjectType->Close = NULL;
ExEventPairObjectType->Delete = NULL;
ExEventPairObjectType->Parse = NULL;
ExEventPairObjectType->Security = NULL;
ExEventPairObjectType->QueryName = NULL;
ExEventPairObjectType->OkayToClose = NULL;
ExEventPairObjectType->Create = ExpCreateEventPair;
ExEventPairObjectType->DuplicationNotify = NULL;
KeInitializeSpinLock(&ExThreadEventPairSpinLock);
ObpCreateTypeObject(ExEventPairObjectType);
/* Create the Event Pair Object Type */
ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
RtlInitUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair");
ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a');
ExEventPairObjectType->PeakObjects = 0;
ExEventPairObjectType->PeakHandles = 0;
ExEventPairObjectType->TotalObjects = 0;
ExEventPairObjectType->TotalHandles = 0;
ExEventPairObjectType->PagedPoolCharge = 0;
ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR);
ExEventPairObjectType->Mapping = &ExEventPairMapping;
ExEventPairObjectType->Dump = NULL;
ExEventPairObjectType->Open = NULL;
ExEventPairObjectType->Close = NULL;
ExEventPairObjectType->Delete = NULL;
ExEventPairObjectType->Parse = NULL;
ExEventPairObjectType->Security = NULL;
ExEventPairObjectType->QueryName = NULL;
ExEventPairObjectType->OkayToClose = NULL;
ExEventPairObjectType->Create = NULL;
ExEventPairObjectType->DuplicationNotify = NULL;
ObpCreateTypeObject(ExEventPairObjectType);
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtCreateEventPair(OUT PHANDLE EventPairHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
PKEVENT_PAIR EventPair;
HANDLE hEventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PKEVENT_PAIR EventPair;
HANDLE hEventPair;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtCreateEventPair: %x\n", EventPairHandle);
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(EventPairHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(EventPairHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
if(!NT_SUCCESS(Status)) return Status;
}
/* Create the Object */
DPRINT("Creating EventPair\n");
Status = ObCreateObject(PreviousMode,
ExEventPairObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KEVENT_PAIR),
0,
0,
(PVOID*)&EventPair);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Initalize the Event */
DPRINT("Initializing EventPair\n");
KeInitializeEventPair(EventPair);
/* Insert it */
Status = ObInsertObject((PVOID)EventPair,
NULL,
DesiredAccess,
0,
NULL,
&hEventPair);
ObDereferenceObject(EventPair);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*EventPairHandle = hEventPair;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
Status = ObCreateObject(PreviousMode,
ExEventPairObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KEVENT_PAIR),
0,
0,
(PVOID*)&EventPair);
if(NT_SUCCESS(Status))
{
KeInitializeEvent(&EventPair->LowEvent,
SynchronizationEvent,
FALSE);
KeInitializeEvent(&EventPair->HighEvent,
SynchronizationEvent,
FALSE);
Status = ObInsertObject ((PVOID)EventPair,
NULL,
DesiredAccess,
0,
NULL,
&hEventPair);
ObDereferenceObject(EventPair);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*EventPairHandle = hEventPair;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status;
/* Return Status */
return Status;
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtOpenEventPair(OUT PHANDLE EventPairHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hEventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
HANDLE hEventPair;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(EventPairHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(EventPairHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObOpenObjectByName(ObjectAttributes,
ExEventPairObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hEventPair);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*EventPairHandle = hEventPair;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExEventPairObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hEventPair);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*EventPairHandle = hEventPair;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
return Status;
/* Return status */
return Status;
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtSetHighEventPair(IN HANDLE EventPairHandle)
{
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
PAGED_CODE();
/* Open the Object */
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Set the Event */
KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
/* Dereference Object */
ObDereferenceObject(EventPair);
}
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeSetEvent(&EventPair->HighEvent,
EVENT_INCREMENT,
FALSE);
ObDereferenceObject(EventPair);
}
return Status;
/* Return status */
return Status;
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
{
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
/* Open the Object */
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Set the Event */
KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
/* Wait for the Other one */
KeWaitForSingleObject(&EventPair->LowEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
/* Dereference Object */
ObDereferenceObject(EventPair);
}
PAGED_CODE();
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeSetEvent(&EventPair->HighEvent,
EVENT_INCREMENT,
TRUE);
KeWaitForSingleObject(&EventPair->LowEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
}
return Status;
/* Return status */
return Status;
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtSetLowEventPair(IN HANDLE EventPairHandle)
{
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PAGED_CODE();
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeSetEvent(&EventPair->LowEvent,
EVENT_INCREMENT,
FALSE);
/* Open the Object */
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Set the Event */
KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
ObDereferenceObject(EventPair);
}
return Status;
/* Dereference Object */
ObDereferenceObject(EventPair);
}
/* Return status */
return Status;
}
NTSTATUS STDCALL
NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
{
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
/* Open the Object */
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Set the Event */
KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
/* Wait for the Other one */
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
/* Dereference Object */
ObDereferenceObject(EventPair);
}
PAGED_CODE();
DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeSetEvent(&EventPair->LowEvent,
EVENT_INCREMENT,
TRUE);
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
}
return Status;
/* Return status */
return Status;
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtWaitLowEventPair(IN HANDLE EventPairHandle)
{
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PAGED_CODE();
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
/* Open the Object */
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Wait for the Event */
KeWaitForSingleObject(&EventPair->LowEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
/* Dereference Object */
ObDereferenceObject(EventPair);
}
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeWaitForSingleObject(&EventPair->LowEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
}
return Status;
/* Return status */
return Status;
}
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtWaitHighEventPair(IN HANDLE EventPairHandle)
{
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
/* Open the Object */
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Wait for the Event */
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
/* Dereference Object */
ObDereferenceObject(EventPair);
}
PAGED_CODE();
DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
}
return Status;
/* Return status */
return Status;
}
#ifdef _ENABLE_THRDEVTPAIR
/*
* Author: Skywing (skywing@valhallalegends.com), 09/08/2003
* Note that the eventpair spinlock must be acquired when setting the thread
* eventpair via NtSetInformationThread.
* @implemented
*/
NTSTATUS
NTSYSAPI
NTAPI
NtSetLowWaitHighThread(
VOID
)
{
PETHREAD Thread;
PKEVENT_PAIR EventPair;
NTSTATUS Status;
KIRQL Irql;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(!Thread->EventPair)
return STATUS_NO_EVENT_PAIR;
KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
EventPair = Thread->EventPair;
if(EventPair)
ObReferenceObjectByPointer(EventPair,
EVENT_PAIR_ALL_ACCESS,
ExEventPairObjectType,
UserMode);
KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
if(EventPair == NULL)
return STATUS_NO_EVENT_PAIR;
KeSetEvent(&EventPair->LowEvent,
EVENT_INCREMENT,
TRUE);
Status = KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
UserMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
return Status;
}
/*
* Author: Skywing (skywing@valhallalegends.com), 09/08/2003
* Note that the eventpair spinlock must be acquired when setting the thread
* eventpair via NtSetInformationThread.
* @implemented
*/
NTSTATUS
NTSYSAPI
NTAPI
NtSetHighWaitLowThread(
VOID
)
{
PETHREAD Thread;
PKEVENT_PAIR EventPair;
NTSTATUS Status;
KIRQL Irql;
PAGED_CODE();
Thread = PsGetCurrentThread();
if(!Thread->EventPair)
return STATUS_NO_EVENT_PAIR;
KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
EventPair = PsGetCurrentThread()->EventPair;
if(EventPair)
ObReferenceObjectByPointer(EventPair,
EVENT_PAIR_ALL_ACCESS,
ExEventPairObjectType,
UserMode);
KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
if(EventPair == NULL)
return STATUS_NO_EVENT_PAIR;
KeSetEvent(&EventPair->HighEvent,
EVENT_INCREMENT,
TRUE);
Status = KeWaitForSingleObject(&EventPair->LowEvent,
WrEventPair,
UserMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
return Status;
}
/*
* Author: Skywing (skywing@valhallalegends.com), 09/08/2003
* Note that the eventpair spinlock must be acquired when waiting on the
* eventpair via NtSetLow/HighWaitHigh/LowThread. Additionally, when
* deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
* be called to release any preexisting eventpair object associated with
* the thread. The Microsoft name for this function is not known.
*/
VOID
ExpSwapThreadEventPair(
IN PETHREAD Thread,
IN PKEVENT_PAIR EventPair
)
{
PKEVENT_PAIR OriginalEventPair;
KIRQL Irql;
KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
OriginalEventPair = Thread->EventPair;
Thread->EventPair = EventPair;
if(OriginalEventPair)
ObDereferenceObject(OriginalEventPair);
KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
}
#else /* !_ENABLE_THRDEVTPAIR */
NTSTATUS
NTSYSAPI
NTAPI
NtSetLowWaitHighThread(
VOID
)
{
DPRINT1("NtSetLowWaitHighThread() not supported anymore (NT4 only)!\n");
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTSYSAPI
NTAPI
NtSetHighWaitLowThread(
VOID
)
{
DPRINT1("NtSetHighWaitLowThread() not supported anymore (NT4 only)!\n");
return STATUS_NOT_IMPLEMENTED;
}
#endif /* _ENABLE_THRDEVTPAIR */
/* EOF */

View file

@ -1,11 +1,12 @@
/* $Id:$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/mutant.c
* PURPOSE: Synchronization primitives
* PURPOSE: Executive Management of Mutants
*
* PROGRAMMERS: David Welch (welch@cwcom.net)
* PROGRAMMERS: Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and
* add more debug output.
* David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
@ -17,360 +18,342 @@
POBJECT_TYPE ExMutantObjectType = NULL;
static GENERIC_MAPPING ExpMutantMapping = {
STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
MUTANT_ALL_ACCESS};
STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE,
MUTANT_ALL_ACCESS};
static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
{
ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */
static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = {
/* MutantBasicInformation */
ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
};
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
ExpCreateMutant(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
}
VOID STDCALL
VOID
STDCALL
ExpDeleteMutant(PVOID ObjectBody)
{
DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
KeReleaseMutant((PKMUTANT)ObjectBody,
MUTANT_INCREMENT,
TRUE,
FALSE);
DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody);
/* Make sure to release the Mutant */
KeReleaseMutant((PKMUTANT)ObjectBody,
MUTANT_INCREMENT,
TRUE,
FALSE);
}
VOID INIT_FUNCTION
VOID
INIT_FUNCTION
ExpInitializeMutantImplementation(VOID)
{
ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
/* Allocate the Object Type */
ExMutantObjectType = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), TAG('M', 't', 'n', 't'));
ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T');
ExMutantObjectType->PeakObjects = 0;
ExMutantObjectType->PeakHandles = 0;
ExMutantObjectType->TotalObjects = 0;
ExMutantObjectType->TotalHandles = 0;
ExMutantObjectType->PagedPoolCharge = 0;
ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
ExMutantObjectType->Mapping = &ExpMutantMapping;
ExMutantObjectType->Dump = NULL;
ExMutantObjectType->Open = NULL;
ExMutantObjectType->Close = NULL;
ExMutantObjectType->Delete = ExpDeleteMutant;
ExMutantObjectType->Parse = NULL;
ExMutantObjectType->Security = NULL;
ExMutantObjectType->QueryName = NULL;
ExMutantObjectType->OkayToClose = NULL;
ExMutantObjectType->Create = ExpCreateMutant;
ExMutantObjectType->DuplicationNotify = NULL;
ObpCreateTypeObject(ExMutantObjectType);
/* Create the Object Type */
RtlInitUnicodeString(&ExMutantObjectType->TypeName, L"Mutant");
ExMutantObjectType->Tag = TAG('M', 't', 'n', 't');
ExMutantObjectType->PeakObjects = 0;
ExMutantObjectType->PeakHandles = 0;
ExMutantObjectType->TotalObjects = 0;
ExMutantObjectType->TotalHandles = 0;
ExMutantObjectType->PagedPoolCharge = 0;
ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT);
ExMutantObjectType->Mapping = &ExpMutantMapping;
ExMutantObjectType->Dump = NULL;
ExMutantObjectType->Open = NULL;
ExMutantObjectType->Close = NULL;
ExMutantObjectType->Delete = ExpDeleteMutant;
ExMutantObjectType->Parse = NULL;
ExMutantObjectType->Security = NULL;
ExMutantObjectType->QueryName = NULL;
ExMutantObjectType->OkayToClose = NULL;
ExMutantObjectType->Create = NULL;
ExMutantObjectType->DuplicationNotify = NULL;
ObpCreateTypeObject(ExMutantObjectType);
}
/*
* @implemented
*/
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtCreateMutant(OUT PHANDLE MutantHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN BOOLEAN InitialOwner)
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN BOOLEAN InitialOwner)
{
KPROCESSOR_MODE PreviousMode;
HANDLE hMutant;
PKMUTEX Mutant;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(MutantHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObCreateObject(PreviousMode,
ExMutantObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KMUTANT),
0,
0,
(PVOID*)&Mutant);
if(NT_SUCCESS(Status))
{
KeInitializeMutant(Mutant,
InitialOwner);
Status = ObInsertObject((PVOID)Mutant,
NULL,
DesiredAccess,
0,
NULL,
&hMutant);
ObDereferenceObject(Mutant);
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
HANDLE hMutant;
PKMUTANT Mutant;
NTSTATUS Status = STATUS_SUCCESS;
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*MutantHandle = hMutant;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtOpenMutant(OUT PHANDLE MutantHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hMutant;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
PAGED_CODE();
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(MutantHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(MutantHandle,
sizeof(HANDLE),
sizeof(ULONG));
if(!NT_SUCCESS(Status)) return Status;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Create the Mutant Object*/
Status = ObCreateObject(PreviousMode,
ExMutantObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KMUTANT),
0,
0,
(PVOID*)&Mutant);
/* Check for success */
if(NT_SUCCESS(Status)) {
/* Initalize the Kernel Mutant */
DPRINT("Initializing the Mutant\n");
KeInitializeMutant(Mutant, InitialOwner);
if(!NT_SUCCESS(Status))
{
return Status;
/* Insert the Object */
Status = ObInsertObject((PVOID)Mutant,
NULL,
DesiredAccess,
0,
NULL,
&hMutant);
ObDereferenceObject(Mutant);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*MutantHandle = hMutant;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
}
Status = ObOpenObjectByName(ObjectAttributes,
ExMutantObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hMutant);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*MutantHandle = hMutant;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtQueryMutant(IN HANDLE MutantHandle,
IN MUTANT_INFORMATION_CLASS MutantInformationClass,
OUT PVOID MutantInformation,
IN ULONG MutantInformationLength,
OUT PULONG ResultLength OPTIONAL)
NTSTATUS
STDCALL
NtOpenMutant(OUT PHANDLE MutantHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
PKMUTANT Mutant;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
HANDLE hMutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
PreviousMode = ExGetPreviousMode();
DefaultQueryInfoBufferCheck(MutantInformationClass,
ExMutantInfoClass,
MutantInformation,
MutantInformationLength,
ResultLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
return Status;
}
Status = ObReferenceObjectByHandle(MutantHandle,
MUTANT_QUERY_STATE,
ExMutantObjectType,
PreviousMode,
(PVOID*)&Mutant,
NULL);
if(NT_SUCCESS(Status))
{
switch(MutantInformationClass)
{
case MutantBasicInformation:
{
PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
_SEH_TRY
{
BasicInfo->Count = KeReadStateMutant(Mutant);
BasicInfo->Owned = (Mutant->OwnerThread != NULL);
BasicInfo->Abandoned = Mutant->Abandoned;
if(ResultLength != NULL)
{
*ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
}
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
ObDereferenceObject(Mutant);
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtReleaseMutant(IN HANDLE MutantHandle,
IN PLONG PreviousCount OPTIONAL)
{
PKMUTANT Mutant;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
MutantHandle, PreviousCount);
PreviousMode = ExGetPreviousMode();
if(PreviousCount != NULL && PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(PreviousCount,
sizeof(LONG),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(MutantHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExMutantObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hMutant);
Status = ObReferenceObjectByHandle(MutantHandle,
MUTANT_QUERY_STATE,
ExMutantObjectType,
PreviousMode,
(PVOID*)&Mutant,
NULL);
if(NT_SUCCESS(Status))
{
LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, 0, FALSE);
ObDereferenceObject(Mutant);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*MutantHandle = hMutant;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
if(PreviousCount != NULL)
{
_SEH_TRY
{
*PreviousCount = Prev;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
/* Return Status */
return Status;
}
return Status;
/*
* @implemented
*/
NTSTATUS
STDCALL
NtQueryMutant(IN HANDLE MutantHandle,
IN MUTANT_INFORMATION_CLASS MutantInformationClass,
OUT PVOID MutantInformation,
IN ULONG MutantInformationLength,
OUT PULONG ResultLength OPTIONAL)
{
PKMUTANT Mutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
PAGED_CODE();
/* Check buffers and parameters */
DefaultQueryInfoBufferCheck(MutantInformationClass,
ExMutantInfoClass,
MutantInformation,
MutantInformationLength,
ResultLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status)) {
DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status);
return Status;
}
/* Open the Object */
Status = ObReferenceObjectByHandle(MutantHandle,
MUTANT_QUERY_STATE,
ExMutantObjectType,
PreviousMode,
(PVOID*)&Mutant,
NULL);
/* Check for Status */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
/* Fill out the Basic Information Requested */
DPRINT("Returning Mutant Information\n");
BasicInfo->CurrentCount = KeReadStateMutant(Mutant);
BasicInfo->OwnedByCaller = (Mutant->OwnerThread == KeGetCurrentThread());
BasicInfo->AbandonedState = Mutant->Abandoned;
/* Return the Result Length if requested */
if(ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* Release the Object */
ObDereferenceObject(Mutant);
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtReleaseMutant(IN HANDLE MutantHandle,
IN PLONG PreviousCount OPTIONAL)
{
PKMUTANT Mutant;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
MutantHandle,
PreviousCount);
/* Check Output Safety */
if(PreviousMode == UserMode && PreviousCount) {
_SEH_TRY {
ProbeForWrite(PreviousCount,
sizeof(LONG),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObReferenceObjectByHandle(MutantHandle,
MUTANT_QUERY_STATE,
ExMutantObjectType,
PreviousMode,
(PVOID*)&Mutant,
NULL);
/* Check for Success and release if such */
if(NT_SUCCESS(Status)) {
LONG Prev;
/* Save the Old State */
DPRINT("Releasing Mutant\n");
Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, FALSE, FALSE);
ObDereferenceObject(Mutant);
/* Return it */
if(PreviousCount) {
_SEH_TRY {
*PreviousCount = Prev;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/* EOF */

View file

@ -1,11 +1,10 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/rundown.c
* PURPOSE: Rundown Protection Functions
*
* PROGRAMMERS: No programmer listed.
* PROGRAMMERS: Alex Ionescu & Thomas Weidenmueller - Implementation
*/
/* INCLUDES *****************************************************************/

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
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/sem.c
* PURPOSE: Synchronization primitives
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes.
* David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
@ -19,345 +19,336 @@
POBJECT_TYPE ExSemaphoreObjectType;
static GENERIC_MAPPING ExSemaphoreMapping = {
STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
SEMAPHORE_ALL_ACCESS};
STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
SEMAPHORE_ALL_ACCESS};
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
{
ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = {
/* SemaphoreBasicInformation */
ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
};
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
ExpCreateSemaphore(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
}
VOID INIT_FUNCTION
VOID
INIT_FUNCTION
ExpInitializeSemaphoreImplementation(VOID)
{
ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool);
ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
ExSemaphoreObjectType->PeakObjects = 0;
ExSemaphoreObjectType->PeakHandles = 0;
ExSemaphoreObjectType->TotalObjects = 0;
ExSemaphoreObjectType->TotalHandles = 0;
ExSemaphoreObjectType->PagedPoolCharge = 0;
ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE);
ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping;
ExSemaphoreObjectType->Dump = NULL;
ExSemaphoreObjectType->Open = NULL;
ExSemaphoreObjectType->Close = NULL;
ExSemaphoreObjectType->Delete = NULL;
ExSemaphoreObjectType->Parse = NULL;
ExSemaphoreObjectType->Security = NULL;
ExSemaphoreObjectType->QueryName = NULL;
ExSemaphoreObjectType->OkayToClose = NULL;
ExSemaphoreObjectType->Create = ExpCreateSemaphore;
ExSemaphoreObjectType->DuplicationNotify = NULL;
ObpCreateTypeObject(ExSemaphoreObjectType);
/* Create the Semaphore Object */
ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
RtlInitUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore");
ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
ExSemaphoreObjectType->PeakObjects = 0;
ExSemaphoreObjectType->PeakHandles = 0;
ExSemaphoreObjectType->TotalObjects = 0;
ExSemaphoreObjectType->TotalHandles = 0;
ExSemaphoreObjectType->PagedPoolCharge = 0;
ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE);
ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping;
ExSemaphoreObjectType->Dump = NULL;
ExSemaphoreObjectType->Open = NULL;
ExSemaphoreObjectType->Close = NULL;
ExSemaphoreObjectType->Delete = NULL;
ExSemaphoreObjectType->Parse = NULL;
ExSemaphoreObjectType->Security = NULL;
ExSemaphoreObjectType->QueryName = NULL;
ExSemaphoreObjectType->OkayToClose = NULL;
ExSemaphoreObjectType->Create = NULL;
ExSemaphoreObjectType->DuplicationNotify = NULL;
ObpCreateTypeObject(ExSemaphoreObjectType);
}
/*
* @implemented
*/
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN LONG InitialCount,
IN LONG MaximumCount)
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN LONG InitialCount,
IN LONG MaximumCount)
{
PKSEMAPHORE Semaphore;
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PKSEMAPHORE Semaphore;
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(SemaphoreHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObCreateObject(PreviousMode,
ExSemaphoreObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KSEMAPHORE),
0,
0,
(PVOID*)&Semaphore);
if (NT_SUCCESS(Status))
{
KeInitializeSemaphore(Semaphore,
InitialCount,
MaximumCount);
Status = ObInsertObject ((PVOID)Semaphore,
NULL,
DesiredAccess,
0,
NULL,
&hSemaphore);
ObDereferenceObject(Semaphore);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*SemaphoreHandle = hSemaphore;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(SemaphoreHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObOpenObjectByName(ObjectAttributes,
ExSemaphoreObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hSemaphore);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*SemaphoreHandle = hSemaphore;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
OUT PVOID SemaphoreInformation,
IN ULONG SemaphoreInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
PKSEMAPHORE Semaphore;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
ExSemaphoreInfoClass,
SemaphoreInformation,
SemaphoreInformationLength,
ReturnLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
return Status;
}
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_QUERY_STATE,
ExSemaphoreObjectType,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
if(NT_SUCCESS(Status))
{
switch(SemaphoreInformationClass)
{
case SemaphoreBasicInformation:
{
PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
_SEH_TRY
{
BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
BasicInfo->MaximumCount = Semaphore->Limit;
if(ReturnLength != NULL)
{
*ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
}
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
ObDereferenceObject(Semaphore);
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
IN LONG ReleaseCount,
OUT PLONG PreviousCount OPTIONAL)
{
KPROCESSOR_MODE PreviousMode;
PKSEMAPHORE Semaphore;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousCount != NULL && PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(PreviousCount,
sizeof(LONG),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_MODIFY_STATE,
ExSemaphoreObjectType,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
if (NT_SUCCESS(Status))
{
LONG PrevCount = KeReleaseSemaphore(Semaphore,
IO_NO_INCREMENT,
ReleaseCount,
FALSE);
ObDereferenceObject(Semaphore);
/* Check Output Safety */
if(PreviousMode != KernelMode) {
_SEH_TRY {
ProbeForWrite(SemaphoreHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(PreviousCount != NULL)
{
_SEH_TRY
{
*PreviousCount = PrevCount;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
if(!NT_SUCCESS(Status)) return Status;
}
/* Make sure the counts make sense */
if (!MaximumCount || !InitialCount || InitialCount > MaximumCount) {
DPRINT("Invalid Count Data!\n");
return STATUS_INVALID_PARAMETER;
}
/* Create the Semaphore Object */
Status = ObCreateObject(PreviousMode,
ExSemaphoreObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KSEMAPHORE),
0,
0,
(PVOID*)&Semaphore);
/* Check for Success */
if (NT_SUCCESS(Status)) {
/* Initialize it */
KeInitializeSemaphore(Semaphore,
InitialCount,
MaximumCount);
/* Insert it into the Object Tree */
Status = ObInsertObject((PVOID)Semaphore,
NULL,
DesiredAccess,
0,
NULL,
&hSemaphore);
ObDereferenceObject(Semaphore);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*SemaphoreHandle = hSemaphore;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(SemaphoreHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExSemaphoreObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hSemaphore);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*SemaphoreHandle = hSemaphore;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
OUT PVOID SemaphoreInformation,
IN ULONG SemaphoreInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
PKSEMAPHORE Semaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check buffers and class validity */
DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
ExSemaphoreInfoClass,
SemaphoreInformation,
SemaphoreInformationLength,
ReturnLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status)) {
/* Invalid buffers */
DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
return Status;
}
/* Get the Object */
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_QUERY_STATE,
ExSemaphoreObjectType,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
/* Check for success */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
/* Return the basic information */
BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
BasicInfo->MaximumCount = Semaphore->Limit;
/* Return length */
if(ReturnLength) *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* Dereference the Object */
ObDereferenceObject(Semaphore);
}
/* Return status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
IN LONG ReleaseCount,
OUT PLONG PreviousCount OPTIONAL)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PKSEMAPHORE Semaphore;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check buffer validity */
if(PreviousCount != NULL && PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(PreviousCount,
sizeof(LONG),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Make sure count makes sense */
if (!ReleaseCount) {
DPRINT("Invalid Release Count\n");
return STATUS_INVALID_PARAMETER;
}
/* Get the Object */
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_MODIFY_STATE,
ExSemaphoreObjectType,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
/* Check for success */
if (NT_SUCCESS(Status)) {
/* Release the semaphore */
LONG PrevCount = KeReleaseSemaphore(Semaphore,
IO_NO_INCREMENT,
ReleaseCount,
FALSE);
ObDereferenceObject(Semaphore);
/* Return it */
if(PreviousCount) {
_SEH_TRY {
*PreviousCount = PrevCount;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/* EOF */

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
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/timer.c
@ -124,9 +123,9 @@ ExpTimerApcKernelRoutine(PKAPC Apc,
PVOID* SystemArguemnt2)
{
PETIMER Timer;
PETHREAD CurrentThread = PsGetCurrentThread();
KIRQL OldIrql;
PETHREAD CurrentThread = PsGetCurrentThread();
/* We need to find out which Timer we are */
Timer = CONTAINING_RECORD(Apc, ETIMER, TimerApc);
DPRINT("ExpTimerApcKernelRoutine(Apc: %x. Timer: %x)\n", Apc, Timer);
@ -176,7 +175,7 @@ ExpInitializeTimerImplementation(VOID)
ExTimerType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
/* Create the Executive Timer Object */
RtlpCreateUnicodeString(&ExTimerType->TypeName, L"Timer", NonPagedPool);
RtlInitUnicodeString(&ExTimerType->TypeName, L"Timer");
ExTimerType->Tag = TAG('T', 'I', 'M', 'T');
ExTimerType->PeakObjects = 0;
ExTimerType->PeakHandles = 0;
@ -209,7 +208,7 @@ NtCancelTimer(IN HANDLE TimerHandle,
OUT PBOOLEAN CurrentState OPTIONAL)
{
PETIMER Timer;
KPROCESSOR_MODE PreviousMode;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
BOOLEAN State;
KIRQL OldIrql;
PETHREAD TimerThread;
@ -217,9 +216,6 @@ NtCancelTimer(IN HANDLE TimerHandle,
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DPRINT("NtCancelTimer(0x%x, 0x%x)\n", TimerHandle, CurrentState);
/* Check Parameter Validity */
@ -301,10 +297,15 @@ NtCancelTimer(IN HANDLE TimerHandle,
/* Make sure it's safe to write to the handle */
if(CurrentState != NULL) {
_SEH_TRY {
*CurrentState = State;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
@ -323,28 +324,27 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
{
PETIMER Timer;
HANDLE hTimer;
KPROCESSOR_MODE PreviousMode;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DPRINT("NtCreateTimer(Handle: %x, Type: %d)\n", TimerHandle, TimerType);
/* Check Parameter Validity */
if (PreviousMode != KernelMode) {
_SEH_TRY {
ProbeForWrite(TimerHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) {
return Status;
}
if(!NT_SUCCESS(Status)) return Status;
}
/* Create the Object */
@ -388,9 +388,13 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
/* Make sure it's safe to write to the handle */
_SEH_TRY {
*TimerHandle = hTimer;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
@ -406,28 +410,28 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hTimer;
KPROCESSOR_MODE PreviousMode;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DPRINT("NtOpenTimer(TimerHandle: %x)\n", TimerHandle);
/* Check Parameter Validity */
if (PreviousMode != KernelMode) {
_SEH_TRY {
ProbeForWrite(TimerHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) {
return Status;
}
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Timer */
@ -444,9 +448,13 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
/* Make sure it's safe to write to the handle */
_SEH_TRY {
*TimerHandle = hTimer;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
@ -464,16 +472,13 @@ NtQueryTimer(IN HANDLE TimerHandle,
OUT PULONG ReturnLength OPTIONAL)
{
PETIMER Timer;
KPROCESSOR_MODE PreviousMode;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass);
/* Check Validity */
DefaultQueryInfoBufferCheck(TimerInformationClass,
ExTimerInfoClass,
@ -498,27 +503,24 @@ NtQueryTimer(IN HANDLE TimerHandle,
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Return the Basic Information */
_SEH_TRY {
/* FIXME: Interrupt correction based on Interrupt Time */
DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
switch(TimerInformationClass) {
case TimerBasicInformation: {
/* Return the Basic Information */
_SEH_TRY {
/* FIXME: Interrupt correction based on Interrupt Time */
DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
if(ReturnLength != NULL) {
*ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
}
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Dereference Object */
ObDereferenceObject(Timer);
}
@ -539,41 +541,40 @@ NtSetTimer(IN HANDLE TimerHandle,
PETIMER Timer;
KIRQL OldIrql;
BOOLEAN State;
KPROCESSOR_MODE PreviousMode;
PETHREAD CurrentThread;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PETHREAD CurrentThread = PsGetCurrentThread();
LARGE_INTEGER TimerDueTime;
PETHREAD TimerThread;
BOOLEAN KillTimer = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
CurrentThread = PsGetCurrentThread();
DPRINT("NtSetTimer(TimerHandle: %x, DueTime: %d, Apc: %x, Period: %d)\n", TimerHandle, DueTime->QuadPart, TimerApcRoutine, Period);
/* Check Parameter Validity */
if (PreviousMode != KernelMode) {
_SEH_TRY {
ProbeForRead(DueTime,
sizeof(LARGE_INTEGER),
sizeof(ULONG));
TimerDueTime = *DueTime;
if(PreviousState != NULL) {
ProbeForWrite(PreviousState,
sizeof(BOOLEAN),
sizeof(BOOLEAN));
}
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) {
return Status;
}
if(!NT_SUCCESS(Status)) return Status;
}
/* Get the Timer Object */
@ -689,10 +690,15 @@ NtSetTimer(IN HANDLE TimerHandle,
/* Make sure it's safe to write to the handle */
if(PreviousState != NULL) {
_SEH_TRY {
*PreviousState = State;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}

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

@ -172,7 +172,9 @@ VOID KeContextToTrapFrame(PCONTEXT Context, PKTRAP_FRAME TrapFrame);
VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame);
VOID STDCALL KeInitializeEventPair(PKEVENT_PAIR EventPair);
VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
IN PKTRAP_FRAME TrapFrame,
IN PKNORMAL_ROUTINE NormalRoutine,

View file

@ -30,7 +30,6 @@
#include <ntdll/ldr.h>
#include <internal/ctype.h>
#include <internal/ntoskrnl.h>
#include <internal/id.h>
#include <internal/ke.h>
#include <internal/i386/segment.h>
#include <internal/i386/mm.h>

View file

@ -176,7 +176,7 @@ IopCreateFile(PVOID ObjectBody,
FileObject,
DeviceObject);
FileObject->Vpb = DeviceObject->Vpb;
FileObject->Type = InternalFileType;
FileObject->Type = IO_TYPE_FILE;
return(STATUS_SUCCESS);
}
@ -240,7 +240,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject,
CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
CreatedFileObject->Vpb = DeviceObject->Vpb;
CreatedFileObject->Type = InternalFileType;
CreatedFileObject->Type = IO_TYPE_FILE;
CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
// shouldn't we initialize the lock event, and several other things here too?

View file

@ -160,7 +160,7 @@ IopCreateDriver(
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
Object->Type = InternalDriverType;
Object->Type = IO_TYPE_DRIVER;
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
Object->MajorFunction[i] = IopInvalidDeviceRequest;

View file

@ -249,4 +249,18 @@ IoWMIDeviceObjectToInstanceName(
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
NtTraceEvent(IN ULONG TraceHandle,
IN ULONG Flags,
IN ULONG TraceHeaderLength,
IN struct _EVENT_TRACE_HEADER* TraceHeader)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*Eof*/

View file

@ -64,8 +64,8 @@ KeFlushEntireTb(
/* All CPUs need to have the TB flushed. */
if (CurrentCpuOnly == FALSE) {
Prcb = KeGetCurrentPrcb();
Prcb = KeGetCurrentPrcb();
/* How many CPUs is our caller using? */
Process = Prcb->CurrentThread->ApcState.Process;

View file

@ -19,121 +19,211 @@
/*
* @implemented
*/
VOID STDCALL KeClearEvent (PKEVENT Event)
VOID
STDCALL
KeClearEvent(PKEVENT Event)
{
DPRINT("KeClearEvent(Event %x)\n", Event);
Event->Header.SignalState = FALSE;
DPRINT("KeClearEvent(Event %x)\n", Event);
/* Reset Signal State */
Event->Header.SignalState = FALSE;
}
/*
* @implemented
*/
VOID STDCALL KeInitializeEvent (PKEVENT Event,
EVENT_TYPE Type,
BOOLEAN State)
VOID
STDCALL
KeInitializeEvent(PKEVENT Event,
EVENT_TYPE Type,
BOOLEAN State)
{
ULONG IType;
if (Type == NotificationEvent)
{
IType = InternalNotificationEvent;
}
else if (Type == SynchronizationEvent)
{
IType = InternalSynchronizationEvent;
}
else
{
ASSERT(FALSE);
return;
}
KeInitializeDispatcherHeader(&(Event->Header),
IType,
sizeof(Event)/sizeof(ULONG),State);
InitializeListHead(&(Event->Header.WaitListHead));
DPRINT("KeInitializeEvent(Event %x)\n", Event);
/* Initialize the Dispatcher Header */
KeInitializeDispatcherHeader(&Event->Header,
Type,
sizeof(Event) / sizeof(ULONG),
State);
}
/*
* @implemented
*/
LONG STDCALL KeReadStateEvent (PKEVENT Event)
VOID
STDCALL
KeInitializeEventPair(PKEVENT_PAIR EventPair)
{
return(Event->Header.SignalState);
}
/*
* @implemented
*/
LONG STDCALL KeResetEvent (PKEVENT Event)
{
/* FIXME: must use interlocked func. everywhere! (wait.c)
* or use dispather lock instead
* -Gunnar */
return(InterlockedExchange(&(Event->Header.SignalState),0));
}
/*
* @implemented
*/
LONG STDCALL KeSetEvent (PKEVENT Event,
KPRIORITY Increment,
BOOLEAN Wait)
{
KIRQL OldIrql;
int ret;
DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
OldIrql = KeAcquireDispatcherDatabaseLock();
ret = InterlockedExchange(&Event->Header.SignalState,1);
KiDispatcherObjectWake(&Event->Header, Increment);
if (Wait == FALSE)
{
KeReleaseDispatcherDatabaseLock(OldIrql);
}
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
return(ret);
DPRINT("KeInitializeEventPair(Event %x)\n", EventPair);
/* Initialize the Event Pair Type and Size */
EventPair->Type = EventPairObject;
EventPair->Size = sizeof(KEVENT_PAIR);
/* Initialize the two Events */
KeInitializeEvent(&EventPair->LowEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&EventPair->HighEvent, SynchronizationEvent, FALSE);
}
/*
* @implemented
*/
LONG STDCALL
KePulseEvent (IN PKEVENT Event,
IN KPRIORITY Increment,
IN BOOLEAN Wait)
KePulseEvent(IN PKEVENT Event,
IN KPRIORITY Increment,
IN BOOLEAN Wait)
{
KIRQL OldIrql;
LONG Ret;
KIRQL OldIrql;
LONG PreviousState;
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
OldIrql = KeAcquireDispatcherDatabaseLock();
Ret = InterlockedExchange(&Event->Header.SignalState,1);
KiDispatcherObjectWake(&Event->Header, Increment);
InterlockedExchange(&(Event->Header.SignalState),0);
if (Wait == FALSE)
{
KeReleaseDispatcherDatabaseLock(OldIrql);
DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the Old State */
PreviousState = Event->Header.SignalState;
/* Check if we are non-signaled and we have stuff in the Wait Queue */
if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead)) {
/* Set the Event to Signaled */
Event->Header.SignalState = 1;
/* Wake the Event */
KiDispatcherObjectWake(&Event->Header, Increment);
}
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
/* Unsignal it */
Event->Header.SignalState = 0;
/* Check what wait state was requested */
if (Wait == FALSE) {
/* Wait not requested, release Dispatcher Database and return */
KeReleaseDispatcherDatabaseLock(OldIrql);
} else {
/* Return Locked and with a Wait */
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
return Ret;
/* Return the previous State */
return PreviousState;
}
/*
* @implemented
*/
LONG
STDCALL
KeReadStateEvent(PKEVENT Event)
{
/* Return the Signal State */
return Event->Header.SignalState;
}
/*
* @implemented
*/
LONG
STDCALL
KeResetEvent(PKEVENT Event)
{
KIRQL OldIrql;
LONG PreviousState;
DPRINT("KeResetEvent(Event %x)\n",Event);
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the Previous State */
PreviousState = Event->Header.SignalState;
/* Set it to zero */
Event->Header.SignalState = 0;
/* Release Dispatcher Database and return previous state */
KeReleaseDispatcherDatabaseLock(OldIrql);
return PreviousState;
}
/*
* @implemented
*/
LONG
STDCALL
KeSetEvent(PKEVENT Event,
KPRIORITY Increment,
BOOLEAN Wait)
{
KIRQL OldIrql;
LONG PreviousState;
PKWAIT_BLOCK WaitBlock;
DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
/* Lock the Dispathcer Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the Previous State */
PreviousState = Event->Header.SignalState;
/* Check if we have stuff in the Wait Queue */
if (IsListEmpty(&Event->Header.WaitListHead)) {
/* Set the Event to Signaled */
DPRINT("Empty Wait Queue, Signal the Event\n");
Event->Header.SignalState = 1;
} else {
/* Get the Wait Block */
WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
KWAIT_BLOCK,
WaitListEntry);
/* Check the type of event */
if (Event->Header.Type == NotificationEvent || WaitBlock->WaitType == WaitAll) {
if (PreviousState == 0) {
/* We must do a full wait satisfaction */
DPRINT("Notification Event or WaitAll, Wait on the Event and Signal\n");
Event->Header.SignalState = 1;
KiDispatcherObjectWake(&Event->Header, Increment);
}
} else {
/* We can satisfy wait simply by waking the thread, since our signal state is 0 now */
DPRINT("WaitAny or Sync Event, just unwait the thread\n");
KiAbortWaitThread(WaitBlock->Thread, WaitBlock->WaitKey);
}
}
/* Check what wait state was requested */
if (Wait == FALSE) {
/* Wait not requested, release Dispatcher Database and return */
KeReleaseDispatcherDatabaseLock(OldIrql);
} else {
/* Return Locked and with a Wait */
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
/* Return the previous State */
DPRINT("Done: %d\n", PreviousState);
return PreviousState;
}
/*
@ -141,27 +231,39 @@ KePulseEvent (IN PKEVENT Event,
*/
VOID
STDCALL
KeSetEventBoostPriority(
IN PKEVENT Event,
IN PKTHREAD *Thread OPTIONAL
)
KeSetEventBoostPriority(IN PKEVENT Event,
IN PKTHREAD *Thread OPTIONAL)
{
PKTHREAD WaitingThread;
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock();
PKTHREAD WaitingThread;
KIRQL OldIrql;
DPRINT("KeSetEventBoostPriority(Event %x, Thread %x)\n",Event,Thread);
/* Acquire Dispatcher Database Lock */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* If our wait list is empty, then signal the event and return */
if (IsListEmpty(&Event->Header.WaitListHead)) {
Event->Header.SignalState = 1;
} else {
/* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
KWAIT_BLOCK,
WaitListEntry)->Thread;
/* Return it to caller if requested */
if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
/* Reset the Quantum and Unwait the Thread */
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
}
/* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
/* Return it to caller if requested */
if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
/* Reset the Quantum and Unwait the Thread */
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
KeReleaseDispatcherDatabaseLock(OldIrql);
/* Release the Dispatcher Database Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
}
/* EOF */

View file

@ -1,11 +1,13 @@
/* $Id:$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: ReactOS kernel
* FILE: ntoskrnl/ke/kqueue.c
* PURPOSE: Implement device queues
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Several optimizations and implement
* usage of Inserted flag + reformat and
* add debug output.
* David Welch (welch@mcmail.com)
*/
/* INCLUDES ****************************************************************/
@ -16,157 +18,33 @@
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
BOOLEAN STDCALL
KeInsertByKeyDeviceQueue (
IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
IN ULONG SortKey)
{
DPRINT("KeInsertByKeyDeviceQueue()\n");
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
DeviceQueueEntry->SortKey=SortKey;
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
if (!DeviceQueue->Busy)
{
DeviceQueue->Busy=TRUE;
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return(FALSE);
}
/* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */
InsertAscendingListFIFO(&DeviceQueue->DeviceListHead,
KDEVICE_QUEUE_ENTRY,
DeviceListEntry,
DeviceQueueEntry,
SortKey);
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return(TRUE);
}
/*
* @implemented
*/
PKDEVICE_QUEUE_ENTRY
STDCALL
KeRemoveByKeyDeviceQueue (
IN PKDEVICE_QUEUE DeviceQueue,
IN ULONG SortKey
)
{
PLIST_ENTRY current;
PKDEVICE_QUEUE_ENTRY entry;
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
ASSERT(DeviceQueue!=NULL);
ASSERT(DeviceQueue->Busy);
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
/* an attempt to remove an entry from an empty (and busy) queue sets the queue to idle */
if (IsListEmpty(&DeviceQueue->DeviceListHead))
{
DeviceQueue->Busy = FALSE;
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return NULL;
}
/* find entry with SortKey greater than or equal to the passed-in SortKey */
current = DeviceQueue->DeviceListHead.Flink;
while (current != &DeviceQueue->DeviceListHead)
{
entry = CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,DeviceListEntry);
if (entry->SortKey >= SortKey)
{
RemoveEntryList(current);
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return entry;
}
current = current->Flink;
}
/* if we didn't find a match, return the first entry */
current = RemoveHeadList(&DeviceQueue->DeviceListHead);
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,DeviceListEntry);
}
/*
* @implemented
*/
PKDEVICE_QUEUE_ENTRY
STDCALL
KeRemoveDeviceQueue (
IN PKDEVICE_QUEUE DeviceQueue)
/*
* FUNCTION: Removes an entry from a device queue
* ARGUMENTS:
* DeviceQueue = Queue to remove the entry
* RETURNS: The removed entry
*/
{
PLIST_ENTRY list_entry;
DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n",DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
ASSERT(DeviceQueue!=NULL);
ASSERT(DeviceQueue->Busy);
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
/* an attempt to remove an entry from an empty (and busy) queue sets the queue idle */
if (IsListEmpty(&DeviceQueue->DeviceListHead))
{
DeviceQueue->Busy = FALSE;
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return NULL;
}
list_entry = RemoveHeadList(&DeviceQueue->DeviceListHead);
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return CONTAINING_RECORD(list_entry,KDEVICE_QUEUE_ENTRY,DeviceListEntry);
}
/*
* @implemented
*/
VOID
STDCALL
KeInitializeDeviceQueue (
IN PKDEVICE_QUEUE DeviceQueue
)
/*
*
* FUNCTION: Intializes a device queue
* ARGUMENTS:
* DeviceQueue = Device queue to initialize
*/
VOID
STDCALL
KeInitializeDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
{
ASSERT(DeviceQueue!=NULL);
InitializeListHead(&DeviceQueue->DeviceListHead);
DeviceQueue->Busy=FALSE;
KeInitializeSpinLock(&DeviceQueue->Lock);
/* Initialize the Header */
DeviceQueue->Type = DeviceQueueObject;
DeviceQueue->Size = sizeof(KDEVICE_QUEUE);
/* Initialize the Listhead and Spinlock */
InitializeListHead(&DeviceQueue->DeviceListHead);
KeInitializeSpinLock(&DeviceQueue->Lock);
/* Set it as busy */
DeviceQueue->Busy=FALSE;
}
/*
* @implemented
*/
BOOLEAN
STDCALL
KeInsertDeviceQueue (
IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
)
/*
*
* FUNCTION: Inserts an entry in a device queue
* ARGUMENTS:
* DeviceQueue = Queue to insert the entry in
@ -174,58 +52,221 @@ KeInsertDeviceQueue (
* RETURNS: False is the device queue wasn't busy
* True otherwise
*/
BOOLEAN
STDCALL
KeInsertDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
{
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
BOOLEAN Inserted;
DPRINT("KeInsertDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Lock the Queue */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
if (!DeviceQueue->Busy) {
/* Set it as busy */
Inserted = FALSE;
DeviceQueue->Busy = TRUE;
} else {
/* Insert it into the list */
Inserted = TRUE;
InsertTailList(&DeviceQueue->DeviceListHead,
&DeviceQueueEntry->DeviceListEntry);
}
if (!DeviceQueue->Busy)
{
DeviceQueue->Busy=TRUE;
/* Sert the Insert state into the entry */
DeviceQueueEntry->Inserted = Inserted;
/* Release lock and return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return(FALSE);
}
DeviceQueueEntry->SortKey=0;
InsertTailList(&DeviceQueue->DeviceListHead, &DeviceQueueEntry->DeviceListEntry);
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return(TRUE);
return Inserted;
}
/*
* @implemented
*/
BOOLEAN
STDCALL
KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
IN ULONG SortKey)
{
BOOLEAN Inserted;
DPRINT("KeInsertByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Acquire the Lock */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
/* Set the Sort Key */
DeviceQueueEntry->SortKey=SortKey;
if (!DeviceQueue->Busy) {
DeviceQueue->Busy=TRUE;
Inserted = FALSE;
} else {
/* Insert new entry after the last entry with SortKey less or equal to passed-in SortKey */
InsertAscendingListFIFO(&DeviceQueue->DeviceListHead,
KDEVICE_QUEUE_ENTRY,
DeviceListEntry,
DeviceQueueEntry,
SortKey);
Inserted = TRUE;
}
/* Reset the Inserted State */
DeviceQueueEntry->Inserted = Inserted;
/* Release Lock and Return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return Inserted;
}
/*
* @implemented
*
* FUNCTION: Removes an entry from a device queue
* ARGUMENTS:
* DeviceQueue = Queue to remove the entry
* RETURNS: The removed entry
*/
PKDEVICE_QUEUE_ENTRY
STDCALL
KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
{
PLIST_ENTRY ListEntry;
PKDEVICE_QUEUE_ENTRY ReturnEntry;
DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Acquire the Lock */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
ASSERT(DeviceQueue->Busy);
/* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */
if (IsListEmpty(&DeviceQueue->DeviceListHead)) {
DeviceQueue->Busy = FALSE;
ReturnEntry = NULL;
} else {
/* Remove the Entry from the List */
ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
ReturnEntry = CONTAINING_RECORD(ListEntry,
KDEVICE_QUEUE_ENTRY,
DeviceListEntry);
/* Set it as non-inserted */
ReturnEntry->Inserted = FALSE;
}
/* Release lock and Return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return ReturnEntry;
}
/*
* @implemented
*/
PKDEVICE_QUEUE_ENTRY
STDCALL
KeRemoveByKeyDeviceQueue (IN PKDEVICE_QUEUE DeviceQueue,
IN ULONG SortKey)
{
PLIST_ENTRY ListEntry;
PKDEVICE_QUEUE_ENTRY ReturnEntry;
DPRINT("KeRemoveByKeyDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Acquire the Lock */
KeAcquireSpinLockAtDpcLevel(&DeviceQueue->Lock);
ASSERT(DeviceQueue->Busy);
/* An attempt to remove an entry from an empty (and busy) queue sets the queue idle */
if (IsListEmpty(&DeviceQueue->DeviceListHead)) {
DeviceQueue->Busy = FALSE;
ReturnEntry = NULL;
} else {
/* Find entry with SortKey greater than or equal to the passed-in SortKey */
ListEntry = DeviceQueue->DeviceListHead.Flink;
while (ListEntry != &DeviceQueue->DeviceListHead) {
/* Get Entry */
ReturnEntry = CONTAINING_RECORD(ListEntry,
KDEVICE_QUEUE_ENTRY,
DeviceListEntry);
/* Check if keys match */
if (ReturnEntry->SortKey >= SortKey) break;
/* Move to next item */
ListEntry = ListEntry->Flink;
}
/* Check if we found something */
if (ListEntry == &DeviceQueue->DeviceListHead) {
/* Not found, return the first entry */
ListEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
ReturnEntry = CONTAINING_RECORD(ListEntry,
KDEVICE_QUEUE_ENTRY,
DeviceListEntry);
} else {
/* We found it, so just remove it */
RemoveEntryList(&ReturnEntry->DeviceListEntry);
}
/* Set it as non-inserted */
ReturnEntry->Inserted = FALSE;
}
/* Release lock and Return */
KeReleaseSpinLockFromDpcLevel(&DeviceQueue->Lock);
return ReturnEntry;
}
/*
* @implemented
*/
BOOLEAN STDCALL
KeRemoveEntryDeviceQueue(
IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
KeRemoveEntryDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue,
IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry)
{
PLIST_ENTRY current;
KIRQL oldIrql;
PKDEVICE_QUEUE_ENTRY entry;
KIRQL OldIrql;
BOOLEAN OldState;
DPRINT("KeRemoveEntryDeviceQueue(DeviceQueue %x)\n", DeviceQueue);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
KeAcquireSpinLock(&DeviceQueue->Lock, &oldIrql);
current = DeviceQueue->DeviceListHead.Flink;
while (current != &DeviceQueue->DeviceListHead)
{
entry = CONTAINING_RECORD(current, KDEVICE_QUEUE_ENTRY, DeviceListEntry);
if (DeviceQueueEntry == entry)
{
RemoveEntryList(current);
KeReleaseSpinLock(&DeviceQueue->Lock, oldIrql);
/* entry was in the queue (but not anymore) */
return TRUE;
/* Acquire the Lock */
KeAcquireSpinLock(&DeviceQueue->Lock, &OldIrql);
/* Check/Set Old State */
if ((OldState = DeviceQueueEntry->Inserted)) {
/* Remove it */
DeviceQueueEntry->Inserted = FALSE;
RemoveEntryList(&DeviceQueueEntry->DeviceListEntry);
}
current = current->Flink;
}
KeReleaseSpinLock(&DeviceQueue->Lock, oldIrql);
/* entry wasn't in the queue */
return FALSE;
/* Unlock and return old state */
KeReleaseSpinLock(&DeviceQueue->Lock, OldIrql);
return OldState;
}

View file

@ -1,16 +1,20 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/mutex.c
* PURPOSE: Implements mutex
* PURPOSE: Implements Mutexes and Mutants (that silly davec...)
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
* PROGRAMMERS:
* Alex Ionescu (alex@relsoft.net) - Reorganized/commented some of the code.
* Simplified some functions, fixed some return values and
* corrected some minor bugs, added debug output.
* David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS *****************************************************************/
@ -18,176 +22,212 @@
/*
* @implemented
*/
VOID STDCALL
KeInitializeMutex(IN PKMUTEX Mutex,
IN ULONG Level)
{
KeInitializeDispatcherHeader(&Mutex->Header,
InternalMutexType,
sizeof(KMUTEX) / sizeof(ULONG),
1);
Mutex->MutantListEntry.Flink = NULL;
Mutex->MutantListEntry.Blink = NULL;
Mutex->OwnerThread = NULL;
Mutex->Abandoned = FALSE;
Mutex->ApcDisable = 1;
}
/*
* @implemented
*/
LONG STDCALL
KeReadStateMutex(IN PKMUTEX Mutex)
{
return(Mutex->Header.SignalState);
}
/*
* @implemented
*/
LONG STDCALL
KeReleaseMutex(IN PKMUTEX Mutex,
IN BOOLEAN Wait)
{
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock();
if (Mutex->OwnerThread != KeGetCurrentThread())
{
DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutex %p\n", Mutex);
KEBUGCHECK(THREAD_NOT_MUTEX_OWNER);
}
Mutex->Header.SignalState++;
ASSERT(Mutex->Header.SignalState <= 1);
if (Mutex->Header.SignalState == 1)
{
Mutex->OwnerThread = NULL;
if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
RemoveEntryList(&Mutex->MutantListEntry);
KiDispatcherObjectWake(&Mutex->Header, IO_NO_INCREMENT);
}
if (Wait == FALSE)
{
KeReleaseDispatcherDatabaseLock(OldIrql);
}
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
return(0);
}
/*
* @implemented
*/
NTSTATUS STDCALL
KeWaitForMutexObject(IN PKMUTEX Mutex,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout)
{
return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout));
}
/*
* @implemented
*/
VOID STDCALL
VOID
STDCALL
KeInitializeMutant(IN PKMUTANT Mutant,
IN BOOLEAN InitialOwner)
IN BOOLEAN InitialOwner)
{
if (InitialOwner == TRUE)
{
KeInitializeDispatcherHeader(&Mutant->Header,
InternalMutexType,
sizeof(KMUTANT) / sizeof(ULONG),
0);
InsertTailList(&KeGetCurrentThread()->MutantListHead,
&Mutant->MutantListEntry);
Mutant->OwnerThread = KeGetCurrentThread();
ULONG Signaled = TRUE;
PKTHREAD CurrentThread = NULL;
KIRQL OldIrql;
DPRINT("KeInitializeMutant: %x\n", Mutant);
/* Check if we have an initial owner */
if (InitialOwner == TRUE) {
/* In this case, the object is not signaled */
Signaled = FALSE;
/* We also need to associate a thread */
CurrentThread = KeGetCurrentThread();
/* We're about to touch the Thread, so lock the Dispatcher */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* And insert it into its list */
InsertTailList(&CurrentThread->MutantListHead, &Mutant->MutantListEntry);
/* Release Dispatcher Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
DPRINT("Mutant with Initial Owner\n");
} else {
/* In this case, we don't have an owner yet */
Mutant->OwnerThread = NULL;
}
else
{
KeInitializeDispatcherHeader(&Mutant->Header,
InternalMutexType,
sizeof(KMUTANT) / sizeof(ULONG),
1);
Mutant->MutantListEntry.Flink = NULL;
Mutant->MutantListEntry.Blink = NULL;
Mutant->OwnerThread = NULL;
}
Mutant->Abandoned = FALSE;
Mutant->ApcDisable = 0;
/* Now we set up the Dispatcher Header */
KeInitializeDispatcherHeader(&Mutant->Header,
MutantObject,
sizeof(KMUTANT) / sizeof(ULONG),
Signaled);
/* Initialize the default data */
Mutant->OwnerThread = CurrentThread;
Mutant->Abandoned = FALSE;
Mutant->ApcDisable = 0;
}
/*
* @implemented
*/
LONG STDCALL
VOID
STDCALL
KeInitializeMutex(IN PKMUTEX Mutex,
IN ULONG Level)
{
DPRINT("KeInitializeMutex: %x\n", Mutex);
/* Set up the Dispatcher Header */
KeInitializeDispatcherHeader(&Mutex->Header,
MutantObject,
sizeof(KMUTEX) / sizeof(ULONG),
1);
/* Initialize the default data */
Mutex->OwnerThread = NULL;
Mutex->Abandoned = FALSE;
Mutex->ApcDisable = 1;
InitializeListHead(&Mutex->Header.WaitListHead);
}
/*
* @implemented
*/
LONG
STDCALL
KeReadStateMutant(IN PKMUTANT Mutant)
{
return(Mutant->Header.SignalState);
/* Return the Signal State */
return(Mutant->Header.SignalState);
}
/*
* @implemented
*/
LONG STDCALL
KeReleaseMutant(IN PKMUTANT Mutant,
IN KPRIORITY Increment,
IN BOOLEAN Abandon,
IN BOOLEAN Wait)
LONG
STDCALL
KeReadStateMutex(IN PKMUTEX Mutex)
{
KIRQL OldIrql;
/* Return the Signal State */
return(Mutex->Header.SignalState);
}
OldIrql = KeAcquireDispatcherDatabaseLock();
if (Abandon == FALSE)
{
if (Mutant->OwnerThread != NULL && Mutant->OwnerThread != KeGetCurrentThread())
{
DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutant->OwnerThread %p CurrentThread %p\n",
Mutant->OwnerThread,
KeGetCurrentThread());
KEBUGCHECK(THREAD_NOT_MUTEX_OWNER);
}
Mutant->Header.SignalState++;
ASSERT(Mutant->Header.SignalState <= 1);
/*
* @implemented
*/
LONG
STDCALL
KeReleaseMutant(IN PKMUTANT Mutant,
IN KPRIORITY Increment,
IN BOOLEAN Abandon,
IN BOOLEAN Wait)
{
KIRQL OldIrql;
LONG PreviousState;
PKTHREAD CurrentThread = KeGetCurrentThread();
DPRINT("KeReleaseMutant: %x\n", Mutant);
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the Previous State */
PreviousState = Mutant->Header.SignalState;
/* Check if it is to be abandonned */
if (Abandon == FALSE) {
/* Make sure that the Owner Thread is the current Thread */
if (Mutant->OwnerThread != CurrentThread) {
DPRINT1("Trying to touch a Mutant that the caller doesn't own!\n");
ExRaiseStatus(STATUS_MUTANT_NOT_OWNED);
}
/* If the thread owns it, then increase the signal state */
Mutant->Header.SignalState++;
} else {
/* It's going to be abandonned */
DPRINT("Abandonning the Mutant\n");
Mutant->Header.SignalState = 1;
Mutant->Abandoned = TRUE;
}
else
{
if (Mutant->OwnerThread != NULL)
{
Mutant->Header.SignalState = 1;
Mutant->Abandoned = TRUE;
}
/* Check if the signal state is only single */
if (Mutant->Header.SignalState == 1) {
if (PreviousState <= 0) {
DPRINT("Removing Mutant\n");
RemoveEntryList(&Mutant->MutantListEntry);
}
/* Remove the Owning Thread and wake it */
Mutant->OwnerThread = NULL;
/* Check if the Wait List isn't empty */
DPRINT("Checking whether to wake the Mutant\n");
if (!IsListEmpty(&Mutant->Header.WaitListHead)) {
/* Wake the Mutant */
DPRINT("Waking the Mutant\n");
KiDispatcherObjectWake(&Mutant->Header, Increment);
}
}
if (Mutant->Header.SignalState == 1)
{
Mutant->OwnerThread = NULL;
if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
RemoveEntryList(&Mutant->MutantListEntry);
KiDispatcherObjectWake(&Mutant->Header, Increment);
/* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
if (Wait == FALSE) {
/* Release the Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
} else {
/* Set a wait */
CurrentThread->WaitNext = TRUE;
CurrentThread->WaitIrql = OldIrql;
}
if (Wait == FALSE)
{
KeReleaseDispatcherDatabaseLock(OldIrql);
}
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
/* Return the previous state */
return PreviousState;
}
return(0);
/*
* @implemented
*/
LONG
STDCALL
KeReleaseMutex(IN PKMUTEX Mutex,
IN BOOLEAN Wait)
{
/* There's no difference at this level between the two */
return KeReleaseMutant(Mutex, IO_NO_INCREMENT, FALSE, Wait);
}
/*
* @implemented
*/
NTSTATUS
STDCALL
KeWaitForMutexObject(IN PKMUTEX Mutex,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout)
{
/* This is a simple macro. Export the function here though */
return KeWaitForSingleObject(Mutex,
WaitReason,
WaitMode,
Alertable,
Timeout);
}
/* EOF */

View file

@ -25,7 +25,7 @@ KeInitializeQueue(IN PKQUEUE Queue,
IN ULONG Count OPTIONAL)
{
KeInitializeDispatcherHeader(&Queue->Header,
InternalQueueType,
QueueObject,
sizeof(KQUEUE)/sizeof(ULONG),
0);
InitializeListHead(&Queue->EntryListHead);

View file

@ -19,36 +19,39 @@
/*
* @implemented
*/
VOID STDCALL
KeInitializeSemaphore (PKSEMAPHORE Semaphore,
LONG Count,
LONG Limit)
VOID
STDCALL
KeInitializeSemaphore(PKSEMAPHORE Semaphore,
LONG Count,
LONG Limit)
{
KeInitializeDispatcherHeader(&Semaphore->Header,
InternalSemaphoreType,
sizeof(KSEMAPHORE)/sizeof(ULONG),
Count);
Semaphore->Limit=Limit;
DPRINT("KeInitializeSemaphore Sem: %x\n", Semaphore);
/* Simply Initialize the Header */
KeInitializeDispatcherHeader(&Semaphore->Header,
SemaphoreObject,
sizeof(KSEMAPHORE)/sizeof(ULONG),
Count);
/* Set the Limit */
Semaphore->Limit = Limit;
}
/*
* @implemented
*/
LONG STDCALL
KeReadStateSemaphore (PKSEMAPHORE Semaphore)
LONG
STDCALL
KeReadStateSemaphore(PKSEMAPHORE Semaphore)
{
return(Semaphore->Header.SignalState);
/* Just return the Signal State */
return(Semaphore->Header.SignalState);
}
/*
* @implemented
*/
LONG STDCALL
KeReleaseSemaphore (PKSEMAPHORE Semaphore,
KPRIORITY Increment,
LONG Adjustment,
BOOLEAN Wait)
/*
*
* FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
* routine supplies a runtime priority boost for waiting threads. If this
* call sets the semaphore to the Signaled state, the semaphore count is
@ -68,40 +71,65 @@ KeReleaseSemaphore (PKSEMAPHORE Semaphore,
* RETURNS: If the return value is zero, the previous state of the semaphore
* object is Not-Signaled.
*/
LONG
STDCALL
KeReleaseSemaphore(PKSEMAPHORE Semaphore,
KPRIORITY Increment,
LONG Adjustment,
BOOLEAN Wait)
{
ULONG InitialState;
KIRQL OldIrql;
ULONG InitialState;
KIRQL OldIrql;
PKTHREAD CurrentThread;
DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
"Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n",
Semaphore,
Increment,
Adjustment,
Wait);
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
InitialState = Semaphore->Header.SignalState;
if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
InitialState > InitialState + Adjustment)
{
ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
/* Save the Old State */
InitialState = Semaphore->Header.SignalState;
/* Check if the Limit was exceeded */
if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
InitialState > InitialState + Adjustment) {
/* Raise an error if it was exceeded */
KeReleaseDispatcherDatabaseLock(OldIrql);
ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
}
Semaphore->Header.SignalState += Adjustment;
if (InitialState == 0)
{
KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT);
/* Now set the new state */
Semaphore->Header.SignalState += Adjustment;
/* Check if we should wake it */
if (InitialState == 0 && !IsListEmpty(&Semaphore->Header.WaitListHead)) {
/* Wake the Semaphore */
KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_INCREMENT);
}
if (Wait == FALSE)
{
KeReleaseDispatcherDatabaseLock(OldIrql);
}
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
/* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
if (Wait == FALSE) {
/* Release the Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
} else {
/* Set a wait */
CurrentThread = KeGetCurrentThread();
CurrentThread->WaitNext = TRUE;
CurrentThread->WaitIrql = OldIrql;
}
return(InitialState);
/* Return the previous state */
return InitialState;
}
/* EOF */

View file

@ -107,12 +107,11 @@ KeInitializeTimerEx (PKTIMER Timer,
/* Initialize the Dispatch Header */
KeInitializeDispatcherHeader(&Timer->Header,
InternalNotificationTimer + Type,
TimerNotificationObject + Type,
sizeof(KTIMER) / sizeof(ULONG),
FALSE);
/* Initalize the List Head and other data */
InitializeListHead(&Timer->Header.WaitListHead);
/* Initalize the Other data */
Timer->DueTime.QuadPart = 0;
Timer->Period = 0;
}
@ -196,7 +195,6 @@ KeSetTimerEx (PKTIMER Timer,
Timer->Dpc = Dpc;
Timer->Period = Period;
Timer->Header.SignalState = FALSE;
Timer->Header.Absolute = FALSE;
/* Insert it */
if (!KiInsertTimer(Timer, DueTime)) {
@ -303,7 +301,7 @@ KiHandleExpiredTimer(PKTIMER Timer)
if (!KiInsertTimer(Timer, DueTime)) {
/* FIXME: I will think about how to handle this and fix it ASAP -- Alex */
DPRINT1("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n");
DPRINT("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n");
};
}
@ -335,8 +333,10 @@ KiInsertTimer(PKTIMER Timer,
DPRINT("KiInsertTimer(Timer %x DueTime %I64d)\n", Timer, DueTime.QuadPart);
/* Set it as Inserted */
/* Set default data */
Timer->Header.Inserted = TRUE;
Timer->Header.Absolute = FALSE;
if (!Timer->Period) Timer->Header.SignalState = FALSE;
/* Convert to relative time if needed */
if (DueTime.u.HighPart >= 0) {

View file

@ -114,34 +114,34 @@ KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
switch (hdr->Type)
{
case InternalSynchronizationEvent:
case EventSynchronizationObject:
hdr->SignalState = 0;
break;
case InternalQueueType:
case QueueObject:
break;
case InternalSemaphoreType:
case SemaphoreObject:
hdr->SignalState--;
break;
case InternalProcessType:
case ProcessObject:
break;
case ThreadObject:
break;
case InternalNotificationEvent:
case EventNotificationObject:
break;
case InternalSynchronizationTimer:
case TimerSynchronizationObject:
hdr->SignalState = FALSE;
break;
case InternalNotificationTimer:
case TimerNotificationObject:
break;
case InternalMutexType:
case MutantObject:
{
PKMUTEX Mutex;
@ -176,7 +176,7 @@ static BOOLEAN
KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
PKTHREAD Thread)
{
if (hdr->Type == InternalMutexType)
if (hdr->Type == MutantObject)
{
PKMUTEX Mutex;
@ -355,22 +355,22 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
DPRINT("hdr->Type %x\n",hdr->Type);
switch (hdr->Type)
{
case InternalNotificationEvent:
case EventNotificationObject:
return(KeDispatcherObjectWakeAll(hdr, increment));
case InternalNotificationTimer:
case TimerNotificationObject:
return(KeDispatcherObjectWakeAll(hdr, increment));
case InternalSynchronizationEvent:
case EventSynchronizationObject:
return(KeDispatcherObjectWakeOne(hdr, increment));
case InternalSynchronizationTimer:
case TimerSynchronizationObject:
return(KeDispatcherObjectWakeOne(hdr, increment));
case InternalQueueType:
case QueueObject:
return(KeDispatcherObjectWakeOne(hdr, increment));
case InternalSemaphoreType:
case SemaphoreObject:
DPRINT("hdr->SignalState %d\n", hdr->SignalState);
if(hdr->SignalState>0)
{
@ -383,13 +383,13 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
}
else return FALSE;
case InternalProcessType:
case ProcessObject:
return(KeDispatcherObjectWakeAll(hdr, increment));
case ThreadObject:
return(KeDispatcherObjectWakeAll(hdr, increment));
case InternalMutexType:
case MutantObject:
return(KeDispatcherObjectWakeOne(hdr, increment));
}
DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type);
@ -463,7 +463,7 @@ PVOID
KiGetWaitableObjectFromObject(PVOID Object)
{
//special case when waiting on file objects
if ( ((PDISPATCHER_HEADER)Object)->Type == InternalFileType)
if ( ((PDISPATCHER_HEADER)Object)->Type == IO_TYPE_FILE)
{
return &((PFILE_OBJECT)Object)->Event;
}
@ -1026,19 +1026,19 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
hdr = (DISPATCHER_HEADER *)SignalObj;
switch (hdr->Type)
{
case InternalNotificationEvent:
case InternalSynchronizationEvent:
case EventNotificationObject:
case EventSynchronizationObject:
KeSetEvent(SignalObj,
EVENT_INCREMENT,
TRUE);
break;
case InternalMutexType:
case MutantObject:
KeReleaseMutex(SignalObj,
TRUE);
break;
case InternalSemaphoreType:
case SemaphoreObject:
KeReleaseSemaphore(SignalObj,
SEMAPHORE_INCREMENT,
1,

View file

@ -388,7 +388,7 @@ PsInitProcessManagment(VOID)
PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
InternalProcessType,
ProcessObject,
sizeof(EPROCESS),
FALSE);
KProcess = &PsInitialSystemProcess->Pcb;
@ -848,7 +848,7 @@ exitdereferenceobjects:
}
KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
InternalProcessType,
ProcessObject,
sizeof(EPROCESS),
FALSE);

View file

@ -180,7 +180,6 @@ NtSetEaFile 4
NtSetEvent 2
NtSetHighEventPair 1
NtSetHighWaitLowEventPair 1
NtSetHighWaitLowThread 0
NtSetInformationFile 5
NtSetInformationKey 4
NtSetInformationJobObject 4
@ -192,7 +191,6 @@ NtSetIntervalProfile 2
NtSetLdtEntries 6
NtSetLowEventPair 1
NtSetLowWaitHighEventPair 1
NtSetLowWaitHighThread 0
NtSetQuotaInformationFile 4
NtSetSecurityObject 3
NtSetSystemEnvironmentValue 2