mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 17:13:51 +00:00
Test commit. Not official branch release -- it will follow shortly in 15 minutes. If this ends up in HEAD i will revert immediately (i have svn switched so it shouldn't)
svn path=/trunk/; revision=13776
This commit is contained in:
parent
24fd581490
commit
ecfad8ec74
56 changed files with 6939 additions and 6335 deletions
|
@ -15,7 +15,7 @@ ARCH := i386
|
|||
# be optimze for.
|
||||
#
|
||||
|
||||
OARCH := i486
|
||||
OARCH := pentium2
|
||||
|
||||
#
|
||||
# Whether to compile in the kernel debugger
|
||||
|
@ -30,7 +30,7 @@ DBG := 0
|
|||
#
|
||||
# Whether to compile with optimizations
|
||||
#
|
||||
OPTIMIZED := 0
|
||||
OPTIMIZED := 1
|
||||
|
||||
#
|
||||
# Whether to compile a multiprocessor or single processor version
|
||||
|
|
|
@ -58,7 +58,7 @@ static ULONG gNumberOfControllers = 0;
|
|||
|
||||
/* Queue thread management */
|
||||
static KEVENT QueueThreadTerminate;
|
||||
static PVOID ThreadObject;
|
||||
static PVOID QueueThreadObject;
|
||||
|
||||
|
||||
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
|
||||
|
@ -378,8 +378,8 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
|
|||
KdPrint(("floppy: unloading\n"));
|
||||
|
||||
KeSetEvent(&QueueThreadTerminate, 0, FALSE);
|
||||
KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0);
|
||||
ObDereferenceObject(ThreadObject);
|
||||
KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0);
|
||||
ObDereferenceObject(QueueThreadObject);
|
||||
|
||||
for(i = 0; i < gNumberOfControllers; i++)
|
||||
{
|
||||
|
@ -1152,7 +1152,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject,
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ThreadObject, NULL) != STATUS_SUCCESS)
|
||||
if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
|
||||
{
|
||||
KdPrint(("floppy: Unable to reference returned thread handle; failing init\n"));
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
|
|
@ -30,6 +30,23 @@ typedef enum _WORK_QUEUE_TYPE {
|
|||
MaximumWorkQueue
|
||||
} WORK_QUEUE_TYPE;
|
||||
|
||||
typedef struct _EX_QUEUE_WORKER_INFO {
|
||||
UCHAR QueueDisabled:1;
|
||||
UCHAR MakeThreadsAsNecessary:1;
|
||||
UCHAR WaitMode:1;
|
||||
ULONG WorkerCount:29;
|
||||
} EX_QUEUE_WORKER_INFO, *PEX_QUEUE_WORKER_INFO;
|
||||
|
||||
typedef struct _EX_WORK_QUEUE {
|
||||
KQUEUE WorkerQueue;
|
||||
ULONG DynamicThreadCount;
|
||||
ULONG WorkItemsProcessed;
|
||||
ULONG WorkItemsProcessedLastPass;
|
||||
ULONG QueueDepthLastPass;
|
||||
EX_QUEUE_WORKER_INFO Info;
|
||||
} EX_WORK_QUEUE, *PEX_WORK_QUEUE;
|
||||
|
||||
|
||||
typedef ULONG_PTR ERESOURCE_THREAD, *PERESOURCE_THREAD;
|
||||
|
||||
typedef struct _OWNER_ENTRY
|
||||
|
@ -240,6 +257,10 @@ typedef VOID STDCALL_FUNC
|
|||
PVOID Argument1,
|
||||
PVOID Argument2);
|
||||
|
||||
extern struct _OBJECT_TYPE EXPORTED *ExMutantObjectType;
|
||||
extern struct _OBJECT_TYPE EXPORTED *ExSemaphoreObjectType;
|
||||
extern struct _OBJECT_TYPE EXPORTED *ExTimerType;
|
||||
|
||||
#endif /* __INCLUDE_DDK_EXTYPES_H */
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -36,23 +36,34 @@ typedef VOID STDCALL_FUNC
|
|||
|
||||
struct _DISPATCHER_HEADER;
|
||||
|
||||
typedef enum _KERNEL_OBJECTS {
|
||||
KNotificationEvent = 0,
|
||||
KSynchronizationEvent = 1,
|
||||
KMutant = 2,
|
||||
KProcess = 3,
|
||||
KQueue = 4,
|
||||
KSemaphore = 5,
|
||||
KThread = 6,
|
||||
KNotificationTimer = 8,
|
||||
KSynchronizationTimer = 9,
|
||||
KApc = 18,
|
||||
KDpc = 19,
|
||||
KDeviceQueue = 20,
|
||||
KEventPair = 21,
|
||||
KInterrupt = 22,
|
||||
KProfile = 23
|
||||
} KERNEL_OBJECTS;
|
||||
typedef enum _KOBJECTS {
|
||||
EventNotificationObject = 0,
|
||||
EventSynchronizationObject = 1,
|
||||
MutantObject = 2,
|
||||
ProcessObject = 3,
|
||||
QueueObject = 4,
|
||||
SemaphoreObject = 5,
|
||||
ThreadObject = 6,
|
||||
GateObject = 7,
|
||||
TimerNotificationObject = 8,
|
||||
TimerSynchronizationObject = 9,
|
||||
Spare2Object = 10,
|
||||
Spare3Object = 11,
|
||||
Spare4Object = 12,
|
||||
Spare5Object = 13,
|
||||
Spare6Object = 14,
|
||||
Spare7Object = 15,
|
||||
Spare8Object = 16,
|
||||
Spare9Object = 17,
|
||||
ApcObject = 18,
|
||||
DpcObject = 19,
|
||||
DeviceQueueObject = 20,
|
||||
EventPairObject = 21,
|
||||
InterruptObject = 22,
|
||||
ProfileObject = 23,
|
||||
ThreadedDpcObject = 24,
|
||||
MaximumKernelObject = 25
|
||||
} KOBJECTS;
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
|
|
|
@ -1262,9 +1262,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;
|
||||
|
||||
|
||||
|
|
|
@ -225,7 +225,6 @@ NtSetEaFile@16
|
|||
NtSetEvent@8
|
||||
NtSetHighEventPair@4
|
||||
NtSetHighWaitLowEventPair@4
|
||||
NtSetHighWaitLowThread@0
|
||||
NtSetInformationFile@20
|
||||
NtSetInformationJobObject@16
|
||||
NtSetInformationKey@16
|
||||
|
@ -238,7 +237,6 @@ NtSetIoCompletion@20
|
|||
NtSetLdtEntries@24
|
||||
NtSetLowEventPair@4
|
||||
NtSetLowWaitHighEventPair@4
|
||||
NtSetLowWaitHighThread@0
|
||||
NtSetSecurityObject@12
|
||||
NtSetSystemEnvironmentValue@8
|
||||
NtSetSystemInformation@12
|
||||
|
@ -849,7 +847,6 @@ ZwSetEaFile@16
|
|||
ZwSetEvent@8
|
||||
ZwSetHighEventPair@4
|
||||
ZwSetHighWaitLowEventPair@4
|
||||
ZwSetHighWaitLowThread@0
|
||||
ZwSetInformationFile@20
|
||||
ZwSetInformationKey@16
|
||||
ZwSetInformationObject@16
|
||||
|
@ -861,7 +858,6 @@ ZwSetIoCompletion@20
|
|||
ZwSetLdtEntries@24
|
||||
ZwSetLowEventPair@4
|
||||
ZwSetLowWaitHighEventPair@4
|
||||
ZwSetLowWaitHighThread@0
|
||||
ZwSetSecurityObject@12
|
||||
ZwSetSystemEnvironmentValue@8
|
||||
ZwSetSystemInformation@12
|
||||
|
|
|
@ -101,10 +101,8 @@ OBJECTS_KE = \
|
|||
ke/bug.o \
|
||||
ke/catch.o \
|
||||
ke/clock.o \
|
||||
ke/critical.o \
|
||||
ke/dpc.o \
|
||||
ke/device.o \
|
||||
ke/error.o \
|
||||
ke/event.o \
|
||||
ke/kqueue.o \
|
||||
ke/kthread.o \
|
||||
|
@ -118,7 +116,6 @@ OBJECTS_KE = \
|
|||
ke/spinlock.o \
|
||||
ke/timer.o \
|
||||
ke/wait.o \
|
||||
ke/alert.o
|
||||
|
||||
# Memory Manager (Mm)
|
||||
OBJECTS_MM = \
|
||||
|
@ -219,7 +216,8 @@ OBJECTS_OB = \
|
|||
ob/object.o \
|
||||
ob/sdcache.o \
|
||||
ob/security.o \
|
||||
ob/symlink.o
|
||||
ob/symlink.o \
|
||||
ob/wait.o
|
||||
|
||||
# Process Manager (Ps)
|
||||
OBJECTS_PS = \
|
||||
|
@ -242,6 +240,7 @@ OBJECTS_PS = \
|
|||
OBJECTS_EX = \
|
||||
ex/btree.o \
|
||||
ex/callback.o \
|
||||
ex/error.o \
|
||||
ex/event.o \
|
||||
ex/evtpair.o \
|
||||
ex/fmutex.o \
|
||||
|
|
|
@ -241,6 +241,29 @@ CmiCheckRegistry(BOOLEAN Verbose)
|
|||
CmiCheckByName(Verbose, L"User");
|
||||
}
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
STDCALL
|
||||
CmInitHives(BOOLEAN SetupBoot)
|
||||
{
|
||||
PCHAR BaseAddress;
|
||||
|
||||
/* Load Registry Hives */
|
||||
BaseAddress = (PCHAR)CachedModules[SystemRegistry]->ModStart;
|
||||
CmImportSystemHive(BaseAddress,
|
||||
CachedModules[SystemRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
|
||||
|
||||
BaseAddress = (PCHAR)CachedModules[HardwareRegistry]->ModStart;
|
||||
CmImportHardwareHive(BaseAddress,
|
||||
CachedModules[HardwareRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
|
||||
|
||||
|
||||
/* Create dummy keys if no hardware hive was found */
|
||||
CmImportHardwareHive (NULL, 0);
|
||||
|
||||
/* Initialize volatile registry settings */
|
||||
if (SetupBoot == FALSE) CmInit2((PCHAR)KeLoaderBlock.CommandLine);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
CmInitializeRegistry(VOID)
|
||||
|
|
163
reactos/ntoskrnl/ex/error.c
Normal file
163
reactos/ntoskrnl/ex/error.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ex/error.c
|
||||
* PURPOSE: Error Functions and Status/Exception Dispatching/Raising
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created File
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS ****************************************************************/
|
||||
|
||||
BOOLEAN ExReadyForErrors = FALSE;
|
||||
PEPORT ExpDefaultErrorPort = NULL;
|
||||
PEPROCESS ExpDefaultErrorPortProcess = NULL;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExRaiseAccessViolation(VOID)
|
||||
{
|
||||
/* Raise the Right Status */
|
||||
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExRaiseDatatypeMisalignment (VOID)
|
||||
{
|
||||
/* Raise the Right Status */
|
||||
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExRaiseStatus(IN NTSTATUS Status)
|
||||
{
|
||||
EXCEPTION_RECORD ExceptionRecord;
|
||||
|
||||
DPRINT("ExRaiseStatus(%x)\n", Status);
|
||||
|
||||
/* Set up an Exception Record */
|
||||
ExceptionRecord.ExceptionRecord = NULL;
|
||||
ExceptionRecord.NumberParameters = 0;
|
||||
ExceptionRecord.ExceptionCode = Status;
|
||||
ExceptionRecord.ExceptionFlags = 0;
|
||||
|
||||
/* Call the Rtl Function */
|
||||
RtlRaiseException(&ExceptionRecord);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExRaiseException (PEXCEPTION_RECORD ExceptionRecord)
|
||||
{
|
||||
/* Call the Rtl function */
|
||||
RtlRaiseException(ExceptionRecord);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
ExSystemExceptionFilter(VOID)
|
||||
{
|
||||
return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExRaiseHardError(IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
|
||||
IN PVOID *Parameters,
|
||||
IN HARDERROR_RESPONSE_OPTION ResponseOption,
|
||||
OUT PHARDERROR_RESPONSE Response)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtRaiseHardError(IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
|
||||
IN PVOID *Parameters,
|
||||
IN HARDERROR_RESPONSE_OPTION ResponseOption,
|
||||
OUT PHARDERROR_RESPONSE Response)
|
||||
{
|
||||
DPRINT1("Hard error %x\n", ErrorStatus);
|
||||
|
||||
/* Call the Executive Function (WE SHOULD PUT SEH HERE/CAPTURE!) */
|
||||
ExRaiseHardError(ErrorStatus,
|
||||
NumberOfParameters,
|
||||
UnicodeStringParameterMask,
|
||||
Parameters,
|
||||
ResponseOption,
|
||||
Response);
|
||||
|
||||
/* Return Success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
|
||||
{
|
||||
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* Check if we have the Privilege */
|
||||
if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) {
|
||||
|
||||
DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
|
||||
/* Only called once during bootup, make sure we weren't called yet */
|
||||
if(!ExReadyForErrors) {
|
||||
|
||||
Status = ObReferenceObjectByHandle(PortHandle,
|
||||
0,
|
||||
LpcPortObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&ExpDefaultErrorPort,
|
||||
NULL);
|
||||
|
||||
/* Check for Success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
/* Save the data */
|
||||
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
|
||||
ExReadyForErrors = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -19,531 +19,489 @@
|
|||
POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
|
||||
|
||||
static GENERIC_MAPPING ExpEventMapping = {
|
||||
STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
|
||||
STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
|
||||
EVENT_ALL_ACCESS};
|
||||
STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
|
||||
STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
|
||||
EVENT_ALL_ACCESS};
|
||||
|
||||
static const INFORMATION_CLASS_INFO ExEventInfoClass[] =
|
||||
{
|
||||
ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* EventBasicInformation */
|
||||
static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
|
||||
|
||||
/* EventBasicInformation */
|
||||
ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
|
||||
};
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtpCreateEvent(PVOID ObjectBody,
|
||||
PVOID Parent,
|
||||
PWSTR RemainingPath,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
||||
ObjectBody, Parent, RemainingPath);
|
||||
|
||||
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
|
||||
{
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
ExpInitializeEventImplementation(VOID)
|
||||
{
|
||||
ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
||||
|
||||
RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
|
||||
|
||||
ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
|
||||
ExEventObjectType->PeakObjects = 0;
|
||||
ExEventObjectType->PeakHandles = 0;
|
||||
ExEventObjectType->TotalObjects = 0;
|
||||
ExEventObjectType->TotalHandles = 0;
|
||||
ExEventObjectType->PagedPoolCharge = 0;
|
||||
ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
|
||||
ExEventObjectType->Mapping = &ExpEventMapping;
|
||||
ExEventObjectType->Dump = NULL;
|
||||
ExEventObjectType->Open = NULL;
|
||||
ExEventObjectType->Close = NULL;
|
||||
ExEventObjectType->Delete = NULL;
|
||||
ExEventObjectType->Parse = NULL;
|
||||
ExEventObjectType->Security = NULL;
|
||||
ExEventObjectType->QueryName = NULL;
|
||||
ExEventObjectType->OkayToClose = NULL;
|
||||
ExEventObjectType->Create = NtpCreateEvent;
|
||||
ExEventObjectType->DuplicationNotify = NULL;
|
||||
|
||||
ObpCreateTypeObject(ExEventObjectType);
|
||||
/* Create the Event Object Type */
|
||||
ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
|
||||
RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
|
||||
ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
|
||||
ExEventObjectType->PeakObjects = 0;
|
||||
ExEventObjectType->PeakHandles = 0;
|
||||
ExEventObjectType->TotalObjects = 0;
|
||||
ExEventObjectType->TotalHandles = 0;
|
||||
ExEventObjectType->PagedPoolCharge = 0;
|
||||
ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
|
||||
ExEventObjectType->Mapping = &ExpEventMapping;
|
||||
ExEventObjectType->Dump = NULL;
|
||||
ExEventObjectType->Open = NULL;
|
||||
ExEventObjectType->Close = NULL;
|
||||
ExEventObjectType->Delete = NULL;
|
||||
ExEventObjectType->Parse = NULL;
|
||||
ExEventObjectType->Security = NULL;
|
||||
ExEventObjectType->QueryName = NULL;
|
||||
ExEventObjectType->OkayToClose = NULL;
|
||||
ExEventObjectType->Create = NULL;
|
||||
ExEventObjectType->DuplicationNotify = NULL;
|
||||
ObpCreateTypeObject(ExEventObjectType);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtClearEvent(IN HANDLE EventHandle)
|
||||
{
|
||||
PKEVENT Event;
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
PKEVENT Event;
|
||||
NTSTATUS Status;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Reference the Object */
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
ExGetPreviousMode(),
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
KeClearEvent(Event);
|
||||
ObDereferenceObject(Event);
|
||||
}
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
ExGetPreviousMode(),
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
|
||||
return Status;
|
||||
/* Check for Success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
/* Clear the Event and Dereference */
|
||||
KeClearEvent(Event);
|
||||
ObDereferenceObject(Event);
|
||||
}
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtCreateEvent(OUT PHANDLE EventHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||
IN EVENT_TYPE EventType,
|
||||
IN BOOLEAN InitialState)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PKEVENT Event;
|
||||
HANDLE hEvent;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(EventHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObCreateObject(PreviousMode,
|
||||
ExEventObjectType,
|
||||
ObjectAttributes,
|
||||
PreviousMode,
|
||||
NULL,
|
||||
sizeof(KEVENT),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&Event);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
KeInitializeEvent(Event,
|
||||
EventType,
|
||||
InitialState);
|
||||
|
||||
|
||||
Status = ObInsertObject((PVOID)Event,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
&hEvent);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*EventHandle = hEvent;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtOpenEvent(OUT PHANDLE EventHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
HANDLE hEvent;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(EventHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObOpenObjectByName(ObjectAttributes,
|
||||
ExEventObjectType,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
&hEvent);
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*EventHandle = hEvent;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtPulseEvent(IN HANDLE EventHandle,
|
||||
OUT PLONG PreviousState OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||
EventHandle, PreviousState);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(PreviousState != NULL && PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(PreviousState,
|
||||
sizeof(LONG),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
if(PreviousState != NULL)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*PreviousState = Prev;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtQueryEvent(IN HANDLE EventHandle,
|
||||
IN EVENT_INFORMATION_CLASS EventInformationClass,
|
||||
OUT PVOID EventInformation,
|
||||
IN ULONG EventInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
DefaultQueryInfoBufferCheck(EventInformationClass,
|
||||
ExEventInfoClass,
|
||||
EventInformation,
|
||||
EventInformationLength,
|
||||
ReturnLength,
|
||||
PreviousMode,
|
||||
&Status);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_QUERY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
switch(EventInformationClass)
|
||||
{
|
||||
case EventBasicInformation:
|
||||
{
|
||||
PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
|
||||
|
||||
_SEH_TRY
|
||||
{
|
||||
if (Event->Header.Type == InternalNotificationEvent)
|
||||
BasicInfo->EventType = NotificationEvent;
|
||||
else
|
||||
BasicInfo->EventType = SynchronizationEvent;
|
||||
BasicInfo->EventState = KeReadStateEvent(Event);
|
||||
|
||||
if(ReturnLength != NULL)
|
||||
{
|
||||
*ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
|
||||
}
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
ObDereferenceObject(Event);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtResetEvent(IN HANDLE EventHandle,
|
||||
OUT PLONG PreviousState OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||
EventHandle, PreviousState);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(PreviousState != NULL && PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(PreviousState,
|
||||
sizeof(LONG),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
LONG Prev = KeResetEvent(Event);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
if(PreviousState != NULL)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*PreviousState = Prev;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtSetEvent(IN HANDLE EventHandle,
|
||||
OUT PLONG PreviousState OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||
EventHandle, PreviousState);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(PreviousState != NULL && PreviousMode == UserMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForWrite(PreviousState,
|
||||
sizeof(LONG),
|
||||
sizeof(ULONG));
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
if(PreviousState != NULL)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*PreviousState = Prev;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtTraceEvent(
|
||||
IN ULONG TraceHandle,
|
||||
IN ULONG Flags,
|
||||
IN ULONG TraceHeaderLength,
|
||||
IN struct _EVENT_TRACE_HEADER* TraceHeader
|
||||
)
|
||||
NtCreateEvent(OUT PHANDLE EventHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||
IN EVENT_TYPE EventType,
|
||||
IN BOOLEAN InitialState)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
PKEVENT Event;
|
||||
HANDLE hEvent;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Check Output Safety */
|
||||
if(PreviousMode == UserMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
ProbeForWrite(EventHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Create the Object */
|
||||
Status = ObCreateObject(PreviousMode,
|
||||
ExEventObjectType,
|
||||
ObjectAttributes,
|
||||
PreviousMode,
|
||||
NULL,
|
||||
sizeof(KEVENT),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&Event);
|
||||
|
||||
/* Check for Success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
/* Initalize the Event */
|
||||
KeInitializeEvent(Event,
|
||||
EventType,
|
||||
InitialState);
|
||||
|
||||
/* Insert it */
|
||||
Status = ObInsertObject((PVOID)Event,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
&hEvent);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
/* Check for success and return handle */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
*EventHandle = hEvent;
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtOpenEvent(OUT PHANDLE EventHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
HANDLE hEvent;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
|
||||
|
||||
/* Check Output Safety */
|
||||
if(PreviousMode == UserMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
ProbeForWrite(EventHandle,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Open the Object */
|
||||
Status = ObOpenObjectByName(ObjectAttributes,
|
||||
ExEventObjectType,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
&hEvent);
|
||||
|
||||
/* Check for success and return handle */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
*EventHandle = hEvent;
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtPulseEvent(IN HANDLE EventHandle,
|
||||
OUT PLONG PreviousState OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||
EventHandle, PreviousState);
|
||||
|
||||
/* Check buffer validity */
|
||||
if(PreviousState && PreviousMode == UserMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
ProbeForWrite(PreviousState,
|
||||
sizeof(LONG),
|
||||
sizeof(ULONG));
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Open the Object */
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
|
||||
/* Check for success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
/* Pulse the Event */
|
||||
LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
/* Return it */
|
||||
if(PreviousState) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
*PreviousState = Prev;
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtQueryEvent(IN HANDLE EventHandle,
|
||||
IN EVENT_INFORMATION_CLASS EventInformationClass,
|
||||
OUT PVOID EventInformation,
|
||||
IN ULONG EventInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
|
||||
|
||||
/* Check buffers and class validity */
|
||||
DefaultQueryInfoBufferCheck(EventInformationClass,
|
||||
ExEventInfoClass,
|
||||
EventInformation,
|
||||
EventInformationLength,
|
||||
ReturnLength,
|
||||
PreviousMode,
|
||||
&Status);
|
||||
if(!NT_SUCCESS(Status)) {
|
||||
|
||||
/* Invalid buffers */
|
||||
DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get the Object */
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_QUERY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
|
||||
/* Check for success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
/* Return Event Type and State */
|
||||
BasicInfo->EventType = Event->Header.Type;
|
||||
BasicInfo->EventState = KeReadStateEvent(Event);
|
||||
|
||||
/* Return length */
|
||||
if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
|
||||
/* Dereference the Object */
|
||||
ObDereferenceObject(Event);
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtResetEvent(IN HANDLE EventHandle,
|
||||
OUT PLONG PreviousState OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||
EventHandle, PreviousState);
|
||||
|
||||
/* Check buffer validity */
|
||||
if(PreviousState && PreviousMode == UserMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
ProbeForWrite(PreviousState,
|
||||
sizeof(LONG),
|
||||
sizeof(ULONG));
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Open the Object */
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
|
||||
/* Check for success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
/* Reset the Event */
|
||||
LONG Prev = KeResetEvent(Event);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
/* Return it */
|
||||
if(PreviousState) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
*PreviousState = Prev;
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtSetEvent(IN HANDLE EventHandle,
|
||||
OUT PLONG PreviousState OPTIONAL)
|
||||
{
|
||||
PKEVENT Event;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT1("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
|
||||
EventHandle, PreviousState);
|
||||
|
||||
/* Check buffer validity */
|
||||
if(PreviousState != NULL && PreviousMode == UserMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
ProbeForWrite(PreviousState,
|
||||
sizeof(LONG),
|
||||
sizeof(ULONG));
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Open the Object */
|
||||
Status = ObReferenceObjectByHandle(EventHandle,
|
||||
EVENT_MODIFY_STATE,
|
||||
ExEventObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Event,
|
||||
NULL);
|
||||
|
||||
/* Check for success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
/* Set the Event */
|
||||
LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
|
||||
ObDereferenceObject(Event);
|
||||
|
||||
/* Return it */
|
||||
if(PreviousState) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
*PreviousState = Prev;
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* $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 +15,394 @@
|
|||
#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));
|
||||
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 = 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;
|
||||
|
||||
DPRINT1("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 */
|
||||
DPRINT1("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 */
|
||||
DPRINT1("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();
|
||||
|
||||
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;
|
||||
|
||||
PAGED_CODE();
|
||||
PKEVENT_PAIR EventPair;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("NtSetHighEventPair(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->HighEvent,
|
||||
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->HighEvent, EVENT_INCREMENT, FALSE);
|
||||
|
||||
ObDereferenceObject(EventPair);
|
||||
}
|
||||
/* Dereference Object */
|
||||
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;
|
||||
|
||||
DPRINT1("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 = ExGetPreviousMode();
|
||||
NTSTATUS Status;
|
||||
|
||||
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;
|
||||
|
||||
DPRINT1("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;
|
||||
|
||||
DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
|
||||
EventPairHandle);
|
||||
DPRINT1("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);
|
||||
|
||||
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;
|
||||
|
||||
DPRINT1("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
|
||||
|
||||
/* Open the Object */
|
||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||
SYNCHRONIZE,
|
||||
ExEventPairObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&EventPair,
|
||||
NULL);
|
||||
|
||||
/* Check for Success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
/* Wait for the Event */
|
||||
KeWaitForSingleObject(&EventPair->HighEvent,
|
||||
WrEventPair,
|
||||
PreviousMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
/* Dereference Object */
|
||||
ObDereferenceObject(EventPair);
|
||||
}
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
|
||||
EventPairHandle);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
Status = ObReferenceObjectByHandle(EventPairHandle,
|
||||
SYNCHRONIZE,
|
||||
ExEventPairObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&EventPair,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
KeWaitForSingleObject(&EventPair->HighEvent,
|
||||
WrEventPair,
|
||||
PreviousMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
ObDereferenceObject(EventPair);
|
||||
}
|
||||
|
||||
return Status;
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
#ifdef _ENABLE_THRDEVTPAIR
|
||||
|
||||
/*
|
||||
* Author: Skywing (skywing@valhallalegends.com), 09/08/2003
|
||||
* Note that the eventpair spinlock must be acquired when setting the thread
|
||||
* eventpair via NtSetInformationThread.
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTSYSAPI
|
||||
NTAPI
|
||||
NtSetLowWaitHighThread(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PETHREAD Thread;
|
||||
PKEVENT_PAIR EventPair;
|
||||
NTSTATUS Status;
|
||||
KIRQL Irql;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(!Thread->EventPair)
|
||||
return STATUS_NO_EVENT_PAIR;
|
||||
|
||||
KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
|
||||
|
||||
EventPair = Thread->EventPair;
|
||||
|
||||
if(EventPair)
|
||||
ObReferenceObjectByPointer(EventPair,
|
||||
EVENT_PAIR_ALL_ACCESS,
|
||||
ExEventPairObjectType,
|
||||
UserMode);
|
||||
|
||||
KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
|
||||
|
||||
if(EventPair == NULL)
|
||||
return STATUS_NO_EVENT_PAIR;
|
||||
|
||||
KeSetEvent(&EventPair->LowEvent,
|
||||
EVENT_INCREMENT,
|
||||
TRUE);
|
||||
|
||||
Status = KeWaitForSingleObject(&EventPair->HighEvent,
|
||||
WrEventPair,
|
||||
UserMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
ObDereferenceObject(EventPair);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Author: Skywing (skywing@valhallalegends.com), 09/08/2003
|
||||
* Note that the eventpair spinlock must be acquired when setting the thread
|
||||
* eventpair via NtSetInformationThread.
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTSYSAPI
|
||||
NTAPI
|
||||
NtSetHighWaitLowThread(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PETHREAD Thread;
|
||||
PKEVENT_PAIR EventPair;
|
||||
NTSTATUS Status;
|
||||
KIRQL Irql;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
Thread = PsGetCurrentThread();
|
||||
|
||||
if(!Thread->EventPair)
|
||||
return STATUS_NO_EVENT_PAIR;
|
||||
|
||||
KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
|
||||
|
||||
EventPair = PsGetCurrentThread()->EventPair;
|
||||
|
||||
if(EventPair)
|
||||
ObReferenceObjectByPointer(EventPair,
|
||||
EVENT_PAIR_ALL_ACCESS,
|
||||
ExEventPairObjectType,
|
||||
UserMode);
|
||||
|
||||
KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
|
||||
|
||||
if(EventPair == NULL)
|
||||
return STATUS_NO_EVENT_PAIR;
|
||||
|
||||
KeSetEvent(&EventPair->HighEvent,
|
||||
EVENT_INCREMENT,
|
||||
TRUE);
|
||||
|
||||
Status = KeWaitForSingleObject(&EventPair->LowEvent,
|
||||
WrEventPair,
|
||||
UserMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
ObDereferenceObject(EventPair);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Author: Skywing (skywing@valhallalegends.com), 09/08/2003
|
||||
* Note that the eventpair spinlock must be acquired when waiting on the
|
||||
* eventpair via NtSetLow/HighWaitHigh/LowThread. Additionally, when
|
||||
* deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
|
||||
* be called to release any preexisting eventpair object associated with
|
||||
* the thread. The Microsoft name for this function is not known.
|
||||
*/
|
||||
VOID
|
||||
ExpSwapThreadEventPair(
|
||||
IN PETHREAD Thread,
|
||||
IN PKEVENT_PAIR EventPair
|
||||
)
|
||||
{
|
||||
PKEVENT_PAIR OriginalEventPair;
|
||||
KIRQL Irql;
|
||||
|
||||
KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
|
||||
|
||||
OriginalEventPair = Thread->EventPair;
|
||||
Thread->EventPair = EventPair;
|
||||
|
||||
if(OriginalEventPair)
|
||||
ObDereferenceObject(OriginalEventPair);
|
||||
|
||||
KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
|
||||
}
|
||||
|
||||
#else /* !_ENABLE_THRDEVTPAIR */
|
||||
|
||||
NTSTATUS
|
||||
NTSYSAPI
|
||||
NTAPI
|
||||
NtSetLowWaitHighThread(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DPRINT1("NtSetLowWaitHighThread() not supported anymore (NT4 only)!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTSYSAPI
|
||||
NTAPI
|
||||
NtSetHighWaitLowThread(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DPRINT1("NtSetHighWaitLowThread() not supported anymore (NT4 only)!\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#endif /* _ENABLE_THRDEVTPAIR */
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,21 +1,630 @@
|
|||
/* $Id:$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ex/init.c
|
||||
* PURPOSE: Executive initalization
|
||||
*
|
||||
* PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
|
||||
* and optimized/cleaned it.
|
||||
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
|
||||
*/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#include <ntos/bootvid.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* DATA **********************************************************************/
|
||||
|
||||
extern ULONG MmCoreDumpType;
|
||||
extern CHAR KiTimerSystemAuditing;
|
||||
extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
|
||||
extern ADDRESS_RANGE KeMemoryMap[64];
|
||||
extern ULONG KeMemoryMapRangeCount;
|
||||
extern ULONG_PTR FirstKrnlPhysAddr;
|
||||
extern ULONG_PTR LastKrnlPhysAddr;
|
||||
extern ULONG_PTR LastKernelAddress;
|
||||
extern LOADER_MODULE KeLoaderModules[64];
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
InitSystemSharedUserPage (PCSZ ParameterLine)
|
||||
{
|
||||
UNICODE_STRING ArcDeviceName;
|
||||
UNICODE_STRING ArcName;
|
||||
UNICODE_STRING BootPath;
|
||||
UNICODE_STRING DriveDeviceName;
|
||||
UNICODE_STRING DriveName;
|
||||
WCHAR DriveNameBuffer[20];
|
||||
PCHAR ParamBuffer;
|
||||
PWCHAR ArcNameBuffer;
|
||||
PCHAR p;
|
||||
NTSTATUS Status;
|
||||
ULONG Length;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE Handle;
|
||||
ULONG i;
|
||||
BOOLEAN BootDriveFound = FALSE;
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* The shared user page has been zeroed-out right after creation.
|
||||
* There is NO need to do this again.
|
||||
*/
|
||||
Ki386SetProcessorFeatures();
|
||||
|
||||
/* Set the Version Data */
|
||||
SharedUserData->NtProductType = NtProductWinNt;
|
||||
SharedUserData->ProductTypeIsValid = TRUE;
|
||||
SharedUserData->NtMajorVersion = 5;
|
||||
SharedUserData->NtMinorVersion = 0;
|
||||
|
||||
/*
|
||||
* Retrieve the current dos system path
|
||||
* (e.g.: C:\reactos) from the given arc path
|
||||
* (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
|
||||
* Format: "<arc_name>\<path> [options...]"
|
||||
*/
|
||||
|
||||
/* Create local parameter line copy */
|
||||
ParamBuffer = ExAllocatePool(PagedPool, 256);
|
||||
strcpy (ParamBuffer, (char *)ParameterLine);
|
||||
DPRINT("%s\n", ParamBuffer);
|
||||
|
||||
/* Cut options off */
|
||||
p = strchr (ParamBuffer, ' ');
|
||||
if (p) *p = 0;
|
||||
DPRINT("%s\n", ParamBuffer);
|
||||
|
||||
/* Extract path */
|
||||
p = strchr (ParamBuffer, '\\');
|
||||
if (p) {
|
||||
|
||||
DPRINT("Boot path: %s\n", p);
|
||||
RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
|
||||
*p = 0;
|
||||
|
||||
} else {
|
||||
|
||||
DPRINT("Boot path: %s\n", "\\");
|
||||
RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
|
||||
}
|
||||
DPRINT("Arc name: %s\n", ParamBuffer);
|
||||
|
||||
/* Only ARC Name left - Build full ARC Name */
|
||||
ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
|
||||
swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
|
||||
RtlInitUnicodeString (&ArcName, ArcNameBuffer);
|
||||
DPRINT("Arc name: %wZ\n", &ArcName);
|
||||
|
||||
/* Free ParamBuffer */
|
||||
ExFreePool (ParamBuffer);
|
||||
|
||||
/* Allocate ARC Device Name string */
|
||||
ArcDeviceName.Length = 0;
|
||||
ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
|
||||
ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
|
||||
|
||||
/* Open the Symbolic Link */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&ArcName,
|
||||
OBJ_OPENLINK,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenSymbolicLinkObject(&Handle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
|
||||
/* Free the String */
|
||||
RtlFreeUnicodeString (&ArcName);
|
||||
|
||||
/* Check for Success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
/* Free the Strings */
|
||||
RtlFreeUnicodeString(&BootPath);
|
||||
RtlFreeUnicodeString(&ArcDeviceName);
|
||||
CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
/* Query the Link */
|
||||
Status = NtQuerySymbolicLinkObject(Handle,
|
||||
&ArcDeviceName,
|
||||
&Length);
|
||||
NtClose (Handle);
|
||||
|
||||
/* Check for Success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
/* Free the Strings */
|
||||
RtlFreeUnicodeString(&BootPath);
|
||||
RtlFreeUnicodeString(&ArcDeviceName);
|
||||
CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
|
||||
|
||||
/* Allocate Device Name string */
|
||||
DriveDeviceName.Length = 0;
|
||||
DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
|
||||
DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
|
||||
|
||||
/* Loop Drives */
|
||||
for (i = 0; i < 26; i++) {
|
||||
|
||||
/* Setup the String */
|
||||
swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
|
||||
RtlInitUnicodeString(&DriveName,
|
||||
DriveNameBuffer);
|
||||
|
||||
/* Open the Symbolic Link */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DriveName,
|
||||
OBJ_OPENLINK,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = NtOpenSymbolicLinkObject(&Handle,
|
||||
SYMBOLIC_LINK_ALL_ACCESS,
|
||||
&ObjectAttributes);
|
||||
|
||||
/* If it failed, skip to the next drive */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
DPRINT("Failed to open link %wZ\n", &DriveName);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Query it */
|
||||
Status = NtQuerySymbolicLinkObject(Handle,
|
||||
&DriveDeviceName,
|
||||
&Length);
|
||||
|
||||
/* If it failed, skip to the next drive */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
DPRINT("Failed to query link %wZ\n", &DriveName);
|
||||
continue;
|
||||
}
|
||||
DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
|
||||
|
||||
/* See if we've found the boot drive */
|
||||
if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
|
||||
|
||||
DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
|
||||
swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
|
||||
BootDriveFound = TRUE;
|
||||
}
|
||||
|
||||
/* Close this Link */
|
||||
NtClose (Handle);
|
||||
}
|
||||
|
||||
/* Free all the Strings we have in memory */
|
||||
RtlFreeUnicodeString (&BootPath);
|
||||
RtlFreeUnicodeString (&DriveDeviceName);
|
||||
RtlFreeUnicodeString (&ArcDeviceName);
|
||||
|
||||
/* Make sure we found the Boot Drive */
|
||||
if (BootDriveFound == FALSE) {
|
||||
|
||||
DbgPrint("No system drive found!\n");
|
||||
KEBUGCHECK (NO_BOOT_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
VOID
|
||||
STDCALL
|
||||
ExecuteRuntimeAsserts(VOID)
|
||||
{
|
||||
/*
|
||||
* Fail at runtime if someone has changed various structures without
|
||||
* updating the offsets used for the assembler code.
|
||||
*/
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
|
||||
ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
|
||||
ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
|
||||
ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
|
||||
ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
|
||||
ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
|
||||
ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
|
||||
ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
|
||||
ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
|
||||
ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
|
||||
ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
|
||||
ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
|
||||
ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
|
||||
}
|
||||
|
||||
inline
|
||||
VOID
|
||||
STDCALL
|
||||
ParseAndCacheLoadedModules(PBOOLEAN SetupBoot)
|
||||
{
|
||||
ULONG i;
|
||||
PCHAR Name;
|
||||
|
||||
/* Loop the Module List and get the modules we want */
|
||||
for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
|
||||
|
||||
/* Get the Name of this Module */
|
||||
if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
|
||||
|
||||
/* Save the name */
|
||||
Name = (PCHAR)KeLoaderModules[i].String;
|
||||
|
||||
} else {
|
||||
|
||||
/* No name, skip */
|
||||
Name++;
|
||||
}
|
||||
|
||||
/* Now check for any of the modules we will need later */
|
||||
if (!_stricmp(Name, "ansi.nls")) {
|
||||
|
||||
CachedModules[AnsiCodepage] = &KeLoaderModules[i];
|
||||
|
||||
} else if (!_stricmp(Name, "oem.nls")) {
|
||||
|
||||
CachedModules[OemCodepage] = &KeLoaderModules[i];
|
||||
|
||||
} else if (!_stricmp(Name, "casemap.nls")) {
|
||||
|
||||
CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
|
||||
|
||||
} else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
|
||||
|
||||
CachedModules[SystemRegistry] = &KeLoaderModules[i];
|
||||
*SetupBoot = FALSE;
|
||||
|
||||
} else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
|
||||
|
||||
CachedModules[HardwareRegistry] = &KeLoaderModules[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
VOID
|
||||
STDCALL
|
||||
ParseCommandLine(PULONG MaxMem, PBOOLEAN NoGuiBoot, PBOOLEAN BootLog)
|
||||
{
|
||||
PCHAR p1, p2;
|
||||
|
||||
p1 = (PCHAR)KeLoaderBlock.CommandLine;
|
||||
while(*p1 && (p2 = strchr(p1, '/'))) {
|
||||
|
||||
p2++;
|
||||
if (!_strnicmp(p2, "MAXMEM", 6)) {
|
||||
|
||||
p2 += 6;
|
||||
while (isspace(*p2)) p2++;
|
||||
|
||||
if (*p2 == '=') {
|
||||
|
||||
p2++;
|
||||
|
||||
while(isspace(*p2)) p2++;
|
||||
|
||||
if (isdigit(*p2)) {
|
||||
while (isdigit(*p2)) {
|
||||
*MaxMem = *MaxMem * 10 + *p2 - '0';
|
||||
p2++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
|
||||
|
||||
p2 += 9;
|
||||
*NoGuiBoot = TRUE;
|
||||
|
||||
} else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
|
||||
|
||||
p2 += 9;
|
||||
if (*p2 == ':') {
|
||||
|
||||
p2++;
|
||||
if (!_strnicmp(p2, "FULL", 4)) {
|
||||
|
||||
MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
|
||||
|
||||
} else {
|
||||
|
||||
MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
} else if (!_strnicmp(p2, "BOOTLOG", 7)) {
|
||||
|
||||
p2 += 7;
|
||||
*BootLog = TRUE;
|
||||
}
|
||||
|
||||
p1 = p2;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
STDCALL
|
||||
ExpInitializeExecutive(VOID)
|
||||
{
|
||||
CHAR str[50];
|
||||
UNICODE_STRING EventName;
|
||||
HANDLE InitDoneEventHandle;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
BOOLEAN NoGuiBoot = FALSE;
|
||||
BOOLEAN BootLog = FALSE;
|
||||
ULONG MaxMem = 0;
|
||||
BOOLEAN SetupBoot = TRUE;
|
||||
LARGE_INTEGER Timeout;
|
||||
HANDLE ProcessHandle;
|
||||
HANDLE ThreadHandle;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Check if the structures match the ASM offset constants */
|
||||
ExecuteRuntimeAsserts();
|
||||
|
||||
/* Sets up the Text Sections of the Kernel and HAL for debugging */
|
||||
LdrInit1();
|
||||
|
||||
/* Lower the IRQL to Dispatch Level */
|
||||
KeLowerIrql(DISPATCH_LEVEL);
|
||||
|
||||
/* Sets up the VDM Data */
|
||||
NtEarlyInitVdm();
|
||||
|
||||
/* Parse Command Line Settings */
|
||||
ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog);
|
||||
|
||||
/* Initialize Kernel Memory Address Space */
|
||||
MmInit1(FirstKrnlPhysAddr,
|
||||
LastKrnlPhysAddr,
|
||||
LastKernelAddress,
|
||||
(PADDRESS_RANGE)&KeMemoryMap,
|
||||
KeMemoryMapRangeCount,
|
||||
MaxMem > 8 ? MaxMem : 4096);
|
||||
|
||||
/* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
|
||||
ParseAndCacheLoadedModules(&SetupBoot);
|
||||
|
||||
/* Initialize the kernel debugger */
|
||||
KdInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
|
||||
|
||||
/* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
|
||||
KeInit2();
|
||||
|
||||
/* Bring back the IRQL to Passive */
|
||||
KeLowerIrql(PASSIVE_LEVEL);
|
||||
|
||||
/* Load basic Security for other Managers */
|
||||
if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
|
||||
|
||||
/* Create the Basic Object Manager Types to allow new Object Types */
|
||||
ObInit();
|
||||
|
||||
/* Initialize Lookaside Lists */
|
||||
ExInit2();
|
||||
|
||||
/* Set up Region Maps, Sections and the Paging File */
|
||||
MmInit2();
|
||||
|
||||
/* Initialize Tokens now that the Object Manager is ready */
|
||||
if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
|
||||
|
||||
/* Set 1 CPU for now, we'll increment this later */
|
||||
KeNumberProcessors = 1;
|
||||
|
||||
/* Initalize the Process Manager */
|
||||
PiInitProcessManager();
|
||||
|
||||
/* Break into the Debugger if requested */
|
||||
if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
|
||||
|
||||
/* Initialize all processors */
|
||||
while (!HalAllProcessorsStarted()) {
|
||||
|
||||
PVOID ProcessorStack;
|
||||
|
||||
/* Set up the Kernel and Process Manager for this CPU */
|
||||
KePrepareForApplicationProcessorInit(KeNumberProcessors);
|
||||
PsPrepareForApplicationProcessorInit(KeNumberProcessors);
|
||||
|
||||
/* Allocate a stack for use when booting the processor */
|
||||
ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
|
||||
|
||||
/* Tell HAL a new CPU is being started */
|
||||
HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
|
||||
KeNumberProcessors++;
|
||||
}
|
||||
|
||||
/* Do Phase 1 HAL Initalization */
|
||||
HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
|
||||
|
||||
/* Initialize Basic System Objects and Worker Threads */
|
||||
ExInit3();
|
||||
|
||||
/* Initialize the GDB Stub and break */
|
||||
KdInit1();
|
||||
|
||||
/* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
|
||||
IoInit();
|
||||
|
||||
/* TBD */
|
||||
PoInit();
|
||||
|
||||
/* Initialize the Registry (Hives are NOT yet loaded!) */
|
||||
CmInitializeRegistry();
|
||||
|
||||
/* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
|
||||
MmInit3();
|
||||
|
||||
/* Initialize Cache Views */
|
||||
CcInit();
|
||||
|
||||
/* Hook System Interrupt for the Debugger */
|
||||
KdInit2();
|
||||
|
||||
/* Initialize File Locking */
|
||||
FsRtlpInitFileLockingImplementation();
|
||||
|
||||
/* Report all resources used by hal */
|
||||
HalReportResourceUsage();
|
||||
|
||||
/* Clear the screen to blue */
|
||||
HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
|
||||
|
||||
/* Display version number and copyright/warranty message */
|
||||
HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
|
||||
KERNEL_VERSION_BUILD_STR")\n");
|
||||
HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
|
||||
HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
|
||||
"Public License, and you\n");
|
||||
HalDisplayString("are welcome to change it and/or distribute copies of it "
|
||||
"under certain\n");
|
||||
HalDisplayString("conditions. There is absolutely no warranty for "
|
||||
"ReactOS.\n\n");
|
||||
|
||||
/* Display number of Processors */
|
||||
sprintf(str,
|
||||
"Found %d system processor(s). [%lu MB Memory]\n",
|
||||
KeNumberProcessors,
|
||||
(KeLoaderBlock.MemHigher + 1088)/ 1024);
|
||||
HalDisplayString(str);
|
||||
|
||||
/* Print which Debugger is being used */
|
||||
KdInit3();
|
||||
|
||||
/* Import and create NLS Data and Sections */
|
||||
RtlpInitNls();
|
||||
|
||||
/* Import and Load Registry Hives */
|
||||
CmInitHives(SetupBoot);
|
||||
|
||||
/* Initialize the time zone information from the registry */
|
||||
ExpInitTimeZoneInfo();
|
||||
|
||||
/* Enter the kernel debugger before starting up the boot drivers */
|
||||
#ifdef KDBG
|
||||
KdbEnter();
|
||||
#endif /* KDBG */
|
||||
|
||||
/* Setup Drivers and Root Device Node */
|
||||
IoInit2(BootLog);
|
||||
|
||||
/* Display the boot screen image if not disabled */
|
||||
if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
|
||||
|
||||
/* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
|
||||
IoInit3();
|
||||
|
||||
/* Initialize the Default Locale */
|
||||
PiInitDefaultLocale();
|
||||
|
||||
/* Initialize shared user page. Set dos system path, dos device map, etc. */
|
||||
InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
|
||||
|
||||
/* Create 'ReactOSInitDone' event */
|
||||
RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&EventName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwCreateEvent(&InitDoneEventHandle,
|
||||
EVENT_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
SynchronizationEvent,
|
||||
FALSE);
|
||||
|
||||
/* Check for Success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
|
||||
InitDoneEventHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* Launch initial process */
|
||||
Status = LdrLoadInitialProcess(&ProcessHandle,
|
||||
&ThreadHandle);
|
||||
|
||||
/* Check for success, Bugcheck if we failed */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Wait on the Completion Event */
|
||||
if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
|
||||
|
||||
HANDLE Handles[2]; /* Init event, Initial process */
|
||||
|
||||
/* Setup the Handles to wait on */
|
||||
Handles[0] = InitDoneEventHandle;
|
||||
Handles[1] = ProcessHandle;
|
||||
|
||||
/* Wait for the system to be initialized */
|
||||
Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
|
||||
Status = ZwWaitForMultipleObjects(2,
|
||||
Handles,
|
||||
WaitAny,
|
||||
FALSE,
|
||||
&Timeout);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
|
||||
|
||||
} else if (Status == STATUS_TIMEOUT) {
|
||||
|
||||
DPRINT1("WARNING: System not initialized after 120 seconds.\n");
|
||||
|
||||
} else if (Status == STATUS_WAIT_0 + 1) {
|
||||
|
||||
/* Crash the system if the initial process was terminated. */
|
||||
KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Disable the Boot Logo */
|
||||
if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
|
||||
|
||||
/* Signal the Event and close the handle */
|
||||
ZwSetEvent(InitDoneEventHandle, NULL);
|
||||
ZwClose(InitDoneEventHandle);
|
||||
|
||||
} else {
|
||||
|
||||
/* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
|
||||
if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
|
||||
|
||||
/* Crash the system if the initial process terminates within 5 seconds. */
|
||||
Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
|
||||
Status = ZwWaitForSingleObject(ProcessHandle,
|
||||
FALSE,
|
||||
&Timeout);
|
||||
|
||||
/* Check for timeout, crash if the initial process didn't initalize */
|
||||
if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
|
||||
}
|
||||
|
||||
/* Enable the Clock, close remaining handles */
|
||||
KiTimerSystemAuditing = 1;
|
||||
ZwClose(ThreadHandle);
|
||||
ZwClose(ProcessHandle);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
ExInit2(VOID)
|
||||
{
|
||||
|
@ -25,7 +634,7 @@ ExInit2(VOID)
|
|||
VOID INIT_FUNCTION
|
||||
ExInit3 (VOID)
|
||||
{
|
||||
ExInitializeWorkerThreads();
|
||||
ExpInitializeWorkerThreads();
|
||||
ExpInitializeEventImplementation();
|
||||
ExpInitializeEventPairImplementation();
|
||||
ExpInitializeMutantImplementation();
|
||||
|
@ -35,28 +644,7 @@ ExInit3 (VOID)
|
|||
ExpInitializeProfileImplementation();
|
||||
ExpWin32kInit();
|
||||
ExpInitUuids();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
|
||||
{
|
||||
if (ProcessorFeature >= PROCESSOR_FEATURE_MAX)
|
||||
return(FALSE);
|
||||
|
||||
return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
ExPostSystemEvent (ULONG Unknown1,
|
||||
ULONG Unknown2,
|
||||
ULONG Unknown3)
|
||||
{
|
||||
/* doesn't do anything */
|
||||
ExpInitializeCallbacks();
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/* $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 +19,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 */
|
||||
RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
|
||||
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;
|
||||
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;
|
||||
|
||||
HANDLE hMutant;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
|
||||
|
||||
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;
|
||||
|
||||
/* Check buffers and parameters */
|
||||
DefaultQueryInfoBufferCheck(MutantInformationClass,
|
||||
ExMutantInfoClass,
|
||||
MutantInformation,
|
||||
MutantInformationLength,
|
||||
ResultLength,
|
||||
PreviousMode,
|
||||
&Status);
|
||||
if(!NT_SUCCESS(Status)) {
|
||||
|
||||
DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* 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 */
|
||||
DPRINT1("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)) {
|
||||
|
||||
/* Save the Old State */
|
||||
DPRINT1("Releasing Mutant\n");
|
||||
LONG Prev = KeReleaseMutant(Mutant, MUTANT_INCREMENT, FALSE, FALSE);
|
||||
ObDereferenceObject(Mutant);
|
||||
|
||||
/* Return it */
|
||||
if(PreviousCount) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
*PreviousCount = Prev;
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ex/rundown.c
|
||||
* PURPOSE: Rundown Protection Functions
|
||||
*
|
||||
* PROGRAMMERS: No programmer listed.
|
||||
* PROGRAMMERS: Alex Ionescu & Thomas Weidenmueller - Implementation
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ex/sem.c
|
||||
* PURPOSE: Synchronization primitives
|
||||
*
|
||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes.
|
||||
* David Welch (welch@mcmail.com)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -19,345 +19,336 @@
|
|||
POBJECT_TYPE ExSemaphoreObjectType;
|
||||
|
||||
static GENERIC_MAPPING ExSemaphoreMapping = {
|
||||
STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
|
||||
STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
|
||||
SEMAPHORE_ALL_ACCESS};
|
||||
STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
|
||||
STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
|
||||
SEMAPHORE_ALL_ACCESS};
|
||||
|
||||
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] =
|
||||
{
|
||||
ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SemaphoreBasicInformation */
|
||||
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = {
|
||||
|
||||
/* SemaphoreBasicInformation */
|
||||
ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
|
||||
};
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ExpCreateSemaphore(PVOID ObjectBody,
|
||||
PVOID Parent,
|
||||
PWSTR RemainingPath,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n",
|
||||
ObjectBody, Parent, RemainingPath);
|
||||
|
||||
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
|
||||
{
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
ExpInitializeSemaphoreImplementation(VOID)
|
||||
{
|
||||
ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||
|
||||
RtlpCreateUnicodeString(&ExSemaphoreObjectType->TypeName, L"Semaphore", NonPagedPool);
|
||||
|
||||
ExSemaphoreObjectType->Tag = TAG('S', 'E', 'M', 'T');
|
||||
ExSemaphoreObjectType->PeakObjects = 0;
|
||||
ExSemaphoreObjectType->PeakHandles = 0;
|
||||
ExSemaphoreObjectType->TotalObjects = 0;
|
||||
ExSemaphoreObjectType->TotalHandles = 0;
|
||||
ExSemaphoreObjectType->PagedPoolCharge = 0;
|
||||
ExSemaphoreObjectType->NonpagedPoolCharge = sizeof(KSEMAPHORE);
|
||||
ExSemaphoreObjectType->Mapping = &ExSemaphoreMapping;
|
||||
ExSemaphoreObjectType->Dump = NULL;
|
||||
ExSemaphoreObjectType->Open = NULL;
|
||||
ExSemaphoreObjectType->Close = NULL;
|
||||
ExSemaphoreObjectType->Delete = NULL;
|
||||
ExSemaphoreObjectType->Parse = NULL;
|
||||
ExSemaphoreObjectType->Security = NULL;
|
||||
ExSemaphoreObjectType->QueryName = NULL;
|
||||
ExSemaphoreObjectType->OkayToClose = NULL;
|
||||
ExSemaphoreObjectType->Create = ExpCreateSemaphore;
|
||||
ExSemaphoreObjectType->DuplicationNotify = NULL;
|
||||
|
||||
ObpCreateTypeObject(ExSemaphoreObjectType);
|
||||
|
||||
/* Create the Semaphore Object */
|
||||
ExSemaphoreObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||
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 = 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 == UserMode) {
|
||||
|
||||
_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();
|
||||
PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
|
||||
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 {
|
||||
|
||||
/* 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 */
|
||||
|
|
|
@ -86,6 +86,20 @@ ExGetCurrentProcessorCounts (
|
|||
ProcessorNumber = &ProcNumber;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
|
||||
{
|
||||
/* Quick check to see if it exists at all */
|
||||
if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
|
||||
|
||||
/* Return our support for it */
|
||||
return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
|
||||
OUT PWCHAR ValueBuffer,
|
||||
|
|
|
@ -473,7 +473,7 @@ NtQueryTimer(IN HANDLE TimerHandle,
|
|||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass);
|
||||
|
||||
|
||||
/* Check Validity */
|
||||
DefaultQueryInfoBufferCheck(TimerInformationClass,
|
||||
ExTimerInfoClass,
|
||||
|
@ -498,27 +498,23 @@ NtQueryTimer(IN HANDLE TimerHandle,
|
|||
|
||||
/* Check for Success */
|
||||
if(NT_SUCCESS(Status)) {
|
||||
|
||||
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);
|
||||
/* Return the Basic Information */
|
||||
_SEH_TRY {
|
||||
|
||||
if(ReturnLength != NULL) {
|
||||
*ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
|
||||
}
|
||||
/* 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);
|
||||
|
||||
} _SEH_HANDLE {
|
||||
if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
} _SEH_END;
|
||||
}
|
||||
}
|
||||
} _SEH_END;
|
||||
|
||||
/* Dereference Object */
|
||||
ObDereferenceObject(Timer);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ex/work.c
|
||||
* PURPOSE: Manage system work queues
|
||||
*
|
||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
||||
* PROGRAMMERS: Alex Ionescu - Used correct work queue array and added some fixes and checks.
|
||||
* Gunnar Dalsnes - Implemented
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
@ -25,17 +25,10 @@
|
|||
/*
|
||||
* PURPOSE: Queue of items waiting to be processed at normal priority
|
||||
*/
|
||||
KQUEUE EiNormalWorkQueue;
|
||||
|
||||
KQUEUE EiCriticalWorkQueue;
|
||||
|
||||
KQUEUE EiHyperCriticalWorkQueue;
|
||||
EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
//static NTSTATUS STDCALL
|
||||
static VOID STDCALL
|
||||
ExWorkerThreadEntryPoint(IN PVOID context)
|
||||
/*
|
||||
* FUNCTION: Entry point for a worker thread
|
||||
* ARGUMENTS:
|
||||
|
@ -44,138 +37,138 @@ ExWorkerThreadEntryPoint(IN PVOID context)
|
|||
* NOTE: To kill a worker thread you must queue an item whose callback
|
||||
* calls PsTerminateSystemThread
|
||||
*/
|
||||
static
|
||||
VOID
|
||||
STDCALL
|
||||
ExpWorkerThreadEntryPoint(IN PVOID Context)
|
||||
{
|
||||
|
||||
PWORK_QUEUE_ITEM item;
|
||||
PLIST_ENTRY current;
|
||||
PWORK_QUEUE_ITEM WorkItem;
|
||||
PLIST_ENTRY QueueEntry;
|
||||
WORK_QUEUE_TYPE WorkQueueType;
|
||||
PEX_WORK_QUEUE WorkQueue;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
current = KeRemoveQueue( (PKQUEUE)context, KernelMode, NULL );
|
||||
|
||||
/* can't happend since we do a KernelMode wait (and we're a system thread) */
|
||||
ASSERT((NTSTATUS)current != STATUS_USER_APC);
|
||||
|
||||
/* this should never happend either, since we wait with NULL timeout,
|
||||
* but there's a slight possibility that STATUS_TIMEOUT is returned
|
||||
* at queue rundown in NT (unlikely) -Gunnar
|
||||
*/
|
||||
ASSERT((NTSTATUS)current != STATUS_TIMEOUT);
|
||||
|
||||
/* based on INVALID_WORK_QUEUE_ITEM bugcheck desc. */
|
||||
if (current->Flink == NULL || current->Blink == NULL)
|
||||
{
|
||||
KeBugCheck(INVALID_WORK_QUEUE_ITEM);
|
||||
}
|
||||
|
||||
/* "reinitialize" item (same as done in ExInitializeWorkItem) */
|
||||
current->Flink = NULL;
|
||||
|
||||
item = CONTAINING_RECORD( current, WORK_QUEUE_ITEM, List);
|
||||
item->WorkerRoutine(item->Parameter);
|
||||
|
||||
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
|
||||
{
|
||||
KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
|
||||
KPRIORITY Priority)
|
||||
{
|
||||
ULONG i;
|
||||
PETHREAD Thread;
|
||||
HANDLE hThread;
|
||||
|
||||
|
||||
for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
|
||||
{
|
||||
/* Get Queue Type and Worker Queue */
|
||||
WorkQueueType = (WORK_QUEUE_TYPE)Context;
|
||||
WorkQueue = &ExWorkerQueue[WorkQueueType];
|
||||
|
||||
/* Loop forever */
|
||||
while (TRUE) {
|
||||
|
||||
PsCreateSystemThread(&hThread,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ExWorkerThreadEntryPoint,
|
||||
WorkQueue);
|
||||
ObReferenceObjectByHandle(hThread,
|
||||
THREAD_ALL_ACCESS,
|
||||
PsThreadType,
|
||||
KernelMode,
|
||||
(PVOID*)&Thread,
|
||||
NULL);
|
||||
KeSetPriorityThread(&Thread->Tcb,
|
||||
Priority);
|
||||
ObDereferenceObject(Thread);
|
||||
ZwClose(hThread);
|
||||
}
|
||||
/* Wait for Something to Happen on the Queue */
|
||||
QueueEntry = KeRemoveQueue(&WorkQueue->WorkerQueue, KernelMode, NULL);
|
||||
|
||||
/* Can't happen since we do a KernelMode wait (and we're a system thread) */
|
||||
ASSERT((NTSTATUS)QueueEntry != STATUS_USER_APC);
|
||||
|
||||
/* this should never happen either, since we wait with NULL timeout,
|
||||
* but there's a slight possibility that STATUS_TIMEOUT is returned
|
||||
* at queue rundown in NT (unlikely) -Gunnar
|
||||
*/
|
||||
ASSERT((NTSTATUS)QueueEntry != STATUS_TIMEOUT);
|
||||
|
||||
/* Increment Processed Work Items */
|
||||
InterlockedIncrement(&WorkQueue->WorkItemsProcessed);
|
||||
|
||||
/* Get the Work Item */
|
||||
WorkItem = CONTAINING_RECORD(QueueEntry, WORK_QUEUE_ITEM, List);
|
||||
|
||||
/* Call the Worker Routine */
|
||||
WorkItem->WorkerRoutine(WorkItem->Parameter);
|
||||
|
||||
/* Make sure it returned at right IRQL */
|
||||
if (KeGetCurrentIrql() != PASSIVE_LEVEL) {
|
||||
|
||||
/* FIXME: Make this an Ex */
|
||||
KEBUGCHECK(WORKER_THREAD_RETURNED_AT_BAD_IRQL);
|
||||
}
|
||||
|
||||
/* Make sure it returned with Impersionation Disabled */
|
||||
if (PsGetCurrentThread()->ActiveImpersonationInfo) {
|
||||
|
||||
/* FIXME: Make this an Ex */
|
||||
KEBUGCHECK(IMPERSONATING_WORKER_THREAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
ExInitializeWorkerThreads(VOID)
|
||||
static
|
||||
VOID
|
||||
STDCALL
|
||||
ExpInitializeWorkQueue(WORK_QUEUE_TYPE WorkQueueType,
|
||||
KPRIORITY Priority)
|
||||
{
|
||||
KeInitializeQueue( &EiNormalWorkQueue, NUMBER_OF_WORKER_THREADS );
|
||||
KeInitializeQueue( &EiCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
|
||||
KeInitializeQueue( &EiHyperCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
|
||||
ULONG i;
|
||||
PETHREAD Thread;
|
||||
HANDLE hThread;
|
||||
|
||||
/* Loop through how many threads we need to create */
|
||||
for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) {
|
||||
|
||||
/* Create the System Thread */
|
||||
PsCreateSystemThread(&hThread,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ExpWorkerThreadEntryPoint,
|
||||
(PVOID)WorkQueueType);
|
||||
|
||||
/* Get the Thread */
|
||||
ObReferenceObjectByHandle(hThread,
|
||||
THREAD_SET_INFORMATION,
|
||||
PsThreadType,
|
||||
KernelMode,
|
||||
(PVOID*)&Thread,
|
||||
NULL);
|
||||
|
||||
/* Set the Priority */
|
||||
KeSetPriorityThread(&Thread->Tcb, Priority);
|
||||
|
||||
/* Dereference and close handle */
|
||||
ObDereferenceObject(Thread);
|
||||
ZwClose(hThread);
|
||||
}
|
||||
}
|
||||
|
||||
ExInitializeWorkQueue(&EiNormalWorkQueue,
|
||||
LOW_PRIORITY);
|
||||
ExInitializeWorkQueue(&EiCriticalWorkQueue,
|
||||
LOW_REALTIME_PRIORITY);
|
||||
ExInitializeWorkQueue(&EiHyperCriticalWorkQueue,
|
||||
HIGH_PRIORITY);
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
ExpInitializeWorkerThreads(VOID)
|
||||
{
|
||||
ULONG WorkQueueType;
|
||||
|
||||
/* Initialize the Array */
|
||||
for (WorkQueueType = 0; WorkQueueType < MaximumWorkQueue; WorkQueueType++) {
|
||||
|
||||
RtlZeroMemory(&ExWorkerQueue[WorkQueueType], sizeof(EX_WORK_QUEUE));
|
||||
KeInitializeQueue(&ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
|
||||
}
|
||||
|
||||
/* Create the built-in worker threads for each work queue */
|
||||
ExpInitializeWorkQueue(CriticalWorkQueue, LOW_REALTIME_PRIORITY);
|
||||
ExpInitializeWorkQueue(DelayedWorkQueue, LOW_PRIORITY);
|
||||
ExpInitializeWorkQueue(HyperCriticalWorkQueue, HIGH_PRIORITY);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
ExQueueWorkItem (PWORK_QUEUE_ITEM WorkItem,
|
||||
WORK_QUEUE_TYPE QueueType)
|
||||
/*
|
||||
*
|
||||
* FUNCTION: Inserts a work item in a queue for one of the system worker
|
||||
* threads to process
|
||||
* ARGUMENTS:
|
||||
* WorkItem = Item to insert
|
||||
* QueueType = Queue to insert it in
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExQueueWorkItem(PWORK_QUEUE_ITEM WorkItem,
|
||||
WORK_QUEUE_TYPE QueueType)
|
||||
{
|
||||
ASSERT(WorkItem!=NULL);
|
||||
ASSERT_IRQL(DISPATCH_LEVEL);
|
||||
ASSERT(WorkItem->List.Flink == NULL);
|
||||
/*
|
||||
* Insert the item in the appropiate queue and wake up any thread
|
||||
* waiting for something to do
|
||||
*/
|
||||
switch(QueueType)
|
||||
{
|
||||
case DelayedWorkQueue:
|
||||
KeInsertQueue (
|
||||
&EiNormalWorkQueue,
|
||||
&WorkItem->List
|
||||
);
|
||||
break;
|
||||
|
||||
case CriticalWorkQueue:
|
||||
KeInsertQueue (
|
||||
&EiCriticalWorkQueue,
|
||||
&WorkItem->List
|
||||
);
|
||||
break;
|
||||
|
||||
case HyperCriticalWorkQueue:
|
||||
KeInsertQueue (
|
||||
&EiHyperCriticalWorkQueue,
|
||||
&WorkItem->List
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* Insert the Queue */
|
||||
KeInsertQueue(&ExWorkerQueue[QueueType].WorkerQueue, &WorkItem->List);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -98,24 +98,19 @@ ExInit3(VOID);
|
|||
VOID
|
||||
ExpInitTimeZoneInfo(VOID);
|
||||
VOID
|
||||
ExInitializeWorkerThreads(VOID);
|
||||
ExpInitializeWorkerThreads(VOID);
|
||||
VOID
|
||||
ExpInitLookasideLists(VOID);
|
||||
VOID
|
||||
ExpInitializeCallbacks(VOID);
|
||||
VOID
|
||||
ExpInitUuids(VOID);
|
||||
VOID
|
||||
STDCALL
|
||||
ExpInitializeExecutive(VOID);
|
||||
|
||||
/* OTHER FUNCTIONS **********************************************************/
|
||||
|
||||
#ifdef _ENABLE_THRDEVTPAIR
|
||||
VOID
|
||||
ExpSwapThreadEventPair(
|
||||
IN struct _ETHREAD* Thread,
|
||||
IN struct _KEVENT_PAIR* EventPair
|
||||
);
|
||||
#endif /* _ENABLE_THRDEVTPAIR */
|
||||
|
||||
LONGLONG
|
||||
FASTCALL
|
||||
ExfpInterlockedExchange64(LONGLONG volatile * Destination,
|
||||
|
|
|
@ -2,18 +2,5 @@
|
|||
* 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)
|
||||
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ IoDestroyDriverList(VOID);
|
|||
/* bootlog.c */
|
||||
|
||||
VOID
|
||||
IopInitBootLog(VOID);
|
||||
IopInitBootLog(BOOLEAN StartBootLog);
|
||||
|
||||
VOID
|
||||
IopStartBootLog(VOID);
|
||||
|
|
|
@ -115,6 +115,17 @@ typedef struct _KPROFILE
|
|||
struct _EPROCESS *Process;
|
||||
} KPROFILE, *PKPROFILE;
|
||||
|
||||
/* Cached modules from the loader block */
|
||||
typedef enum _CACHED_MODULE_TYPE {
|
||||
AnsiCodepage,
|
||||
OemCodepage,
|
||||
UnicodeCasemap,
|
||||
SystemRegistry,
|
||||
HardwareRegistry,
|
||||
MaximumCachedModuleType,
|
||||
} CACHED_MODULE_TYPE, *PCACHED_MODULE_TYPE;
|
||||
extern PLOADER_MODULE CachedModules[MaximumCachedModuleType];
|
||||
|
||||
VOID STDCALL
|
||||
DbgBreakPointNoBugCheck(VOID);
|
||||
|
||||
|
@ -144,30 +155,42 @@ VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
|
|||
|
||||
VOID STDCALL KiExpireTimers(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
|
||||
|
||||
KIRQL KeAcquireDispatcherDatabaseLock(VOID);
|
||||
VOID KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
|
||||
VOID KeReleaseDispatcherDatabaseLock(KIRQL Irql);
|
||||
VOID KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
|
||||
KIRQL inline FASTCALL KeAcquireDispatcherDatabaseLock(VOID);
|
||||
VOID inline FASTCALL KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
|
||||
VOID inline FASTCALL KeReleaseDispatcherDatabaseLock(KIRQL Irql);
|
||||
VOID inline FASTCALL KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
|
||||
|
||||
BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment);
|
||||
VOID STDCALL KeExpireTimers(PKDPC Apc,
|
||||
PVOID Arg1,
|
||||
PVOID Arg2,
|
||||
PVOID Arg3);
|
||||
VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
|
||||
VOID inline FASTCALL KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
|
||||
ULONG Size, ULONG SignalState);
|
||||
VOID KeDumpStackFrames(PULONG Frame);
|
||||
BOOLEAN KiTestAlert(VOID);
|
||||
|
||||
BOOLEAN KiAbortWaitThread(struct _KTHREAD* Thread, NTSTATUS WaitStatus);
|
||||
VOID FASTCALL KiAbortWaitThread(struct _KTHREAD* Thread, NTSTATUS WaitStatus);
|
||||
|
||||
BOOLEAN STDCALL KiInsertTimer(PKTIMER Timer, LARGE_INTEGER DueTime);
|
||||
|
||||
VOID inline FASTCALL KiSatisfyObjectWait(PDISPATCHER_HEADER Object, PKTHREAD Thread);
|
||||
|
||||
BOOLEAN inline FASTCALL KiIsObjectSignaled(PDISPATCHER_HEADER Object, PKTHREAD Thread);
|
||||
|
||||
VOID inline FASTCALL KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
|
||||
|
||||
VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
|
||||
|
||||
PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
|
||||
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 KiInitializeUserApc(IN PVOID Reserved,
|
||||
VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
|
||||
IN PKTRAP_FRAME TrapFrame,
|
||||
IN PKNORMAL_ROUTINE NormalRoutine,
|
||||
IN PVOID NormalContext,
|
||||
|
@ -183,6 +206,7 @@ STDCALL
|
|||
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
|
||||
|
||||
BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
|
||||
VOID FASTCALL KiWakeQueue(IN PKQUEUE Queue);
|
||||
PLIST_ENTRY STDCALL KeRundownQueue(IN PKQUEUE Queue);
|
||||
|
||||
extern LARGE_INTEGER SystemBootTime;
|
||||
|
@ -194,7 +218,7 @@ VOID KeInitInterrupts(VOID);
|
|||
VOID KeInitTimer(VOID);
|
||||
VOID KeInitDpc(struct _KPCR* Pcr);
|
||||
VOID KeInitDispatcher(VOID);
|
||||
VOID KeInitializeDispatcher(VOID);
|
||||
VOID inline FASTCALL KeInitializeDispatcher(VOID);
|
||||
VOID KiInitializeSystemClock(VOID);
|
||||
VOID KeInitializeBugCheck(VOID);
|
||||
VOID Phase1Initialization(PVOID Context);
|
||||
|
|
|
@ -29,6 +29,7 @@ extern ULONG NlsUnicodeTableOffset;
|
|||
extern PUSHORT NlsUnicodeUpcaseTable;
|
||||
extern PUSHORT NlsUnicodeLowercaseTable;
|
||||
|
||||
VOID STDCALL RtlpInitNls(VOID);
|
||||
VOID RtlpImportAnsiCodePage(PUSHORT TableBase, ULONG Size);
|
||||
VOID RtlpImportOemCodePage(PUSHORT TableBase, ULONG Size);
|
||||
VOID RtlpImportUnicodeCasemap(PUSHORT TableBase, ULONG Size);
|
||||
|
|
|
@ -49,10 +49,12 @@ VOID ExpInitializeProfileImplementation(VOID);
|
|||
*/
|
||||
VOID MmInitSystem(ULONG Phase, PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG LastKernelAddress);
|
||||
VOID IoInit(VOID);
|
||||
VOID IoInit2(VOID);
|
||||
VOID IoInit2(BOOLEAN BootLog);
|
||||
VOID STDCALL IoInit3(VOID);
|
||||
VOID ObInit(VOID);
|
||||
VOID PsInit(VOID);
|
||||
VOID CmInitializeRegistry(VOID);
|
||||
VOID STDCALL CmInitHives(BOOLEAN SetupBoot);
|
||||
VOID CmInit2(PCHAR CommandLine);
|
||||
VOID CmShutdownRegistry(VOID);
|
||||
BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
|
||||
|
|
|
@ -498,7 +498,9 @@ VOID STDCALL PsExitSpecialApc(PKAPC Apc,
|
|||
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
|
||||
|
||||
NTSTATUS KeReleaseThread(PKTHREAD Thread);
|
||||
|
||||
VOID
|
||||
|
@ -525,8 +527,11 @@ VOID PsUnfreezeProcessThreads(PEPROCESS Process);
|
|||
ULONG PsEnumThreadsByProcess(PEPROCESS Process);
|
||||
PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
|
||||
VOID
|
||||
PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
|
||||
BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason);
|
||||
STDCALL
|
||||
PsBlockThread(PNTSTATUS Status,
|
||||
UCHAR Alertable,
|
||||
ULONG WaitMode,
|
||||
UCHAR WaitReason);
|
||||
VOID
|
||||
PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment);
|
||||
VOID
|
||||
|
|
|
@ -27,13 +27,14 @@ static ERESOURCE IopBootLogResource;
|
|||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
IopInitBootLog(VOID)
|
||||
IopInitBootLog(BOOLEAN StartBootLog)
|
||||
{
|
||||
ExInitializeResourceLite(&IopBootLogResource);
|
||||
if (StartBootLog) IopStartBootLog();
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
VOID INIT_FUNCTION
|
||||
IopStartBootLog(VOID)
|
||||
{
|
||||
IopBootLogCreate = TRUE;
|
||||
|
|
|
@ -176,7 +176,7 @@ IopCreateFile(PVOID ObjectBody,
|
|||
FileObject,
|
||||
DeviceObject);
|
||||
FileObject->Vpb = DeviceObject->Vpb;
|
||||
FileObject->Type = InternalFileType;
|
||||
FileObject->Type = IO_TYPE_FILE;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject,
|
|||
|
||||
CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
|
||||
CreatedFileObject->Vpb = DeviceObject->Vpb;
|
||||
CreatedFileObject->Type = InternalFileType;
|
||||
CreatedFileObject->Type = IO_TYPE_FILE;
|
||||
CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
|
||||
|
||||
// shouldn't we initialize the lock event, and several other things here too?
|
||||
|
|
|
@ -160,7 +160,7 @@ IopCreateDriver(
|
|||
|
||||
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
|
||||
|
||||
Object->Type = InternalDriverType;
|
||||
Object->Type = IO_TYPE_DRIVER;
|
||||
|
||||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||
Object->MajorFunction[i] = IopInvalidDeviceRequest;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/io/iocomp.c
|
||||
|
@ -18,66 +17,48 @@
|
|||
|
||||
POBJECT_TYPE ExIoCompletionType;
|
||||
|
||||
NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
|
||||
NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
|
||||
|
||||
static GENERIC_MAPPING ExIoCompletionMapping =
|
||||
{
|
||||
STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
|
||||
STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
|
||||
IO_COMPLETION_ALL_ACCESS
|
||||
STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
|
||||
STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
|
||||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
|
||||
IO_COMPLETION_ALL_ACCESS
|
||||
};
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
VOID
|
||||
STDCALL
|
||||
IopCreateIoCompletion(
|
||||
PVOID ObjectBody,
|
||||
PVOID Parent,
|
||||
PWSTR RemainingPath,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes
|
||||
)
|
||||
{
|
||||
DPRINT("IopCreateIoCompletion(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
|
||||
IopDeleteIoCompletion(PVOID ObjectBody)
|
||||
{
|
||||
PKQUEUE Queue = ObjectBody;
|
||||
PKQUEUE Queue = ObjectBody;
|
||||
PLIST_ENTRY FirstEntry;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PIO_COMPLETION_PACKET Packet;
|
||||
|
||||
DPRINT("IopDeleteIoCompletion()\n");
|
||||
DPRINT("IopDeleteIoCompletion()\n");
|
||||
|
||||
KeRundownQueue(Queue);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
IoSetCompletionRoutineEx(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PIO_COMPLETION_ROUTINE CompletionRoutine,
|
||||
IN PVOID Context,
|
||||
IN BOOLEAN InvokeOnSuccess,
|
||||
IN BOOLEAN InvokeOnError,
|
||||
IN BOOLEAN InvokeOnCancel
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
/* Rundown the Queue */
|
||||
FirstEntry = KeRundownQueue(Queue);
|
||||
|
||||
/* Clean up the IRPs */
|
||||
if (FirstEntry) {
|
||||
|
||||
CurrentEntry = FirstEntry;
|
||||
do {
|
||||
|
||||
/* Get the Packet */
|
||||
Packet = CONTAINING_RECORD(CurrentEntry, IO_COMPLETION_PACKET, ListEntry);
|
||||
|
||||
/* Go to next Entry */
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
|
||||
/* Free it */
|
||||
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
|
||||
} while (FirstEntry != CurrentEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -85,305 +66,278 @@ IoSetCompletionRoutineEx(
|
|||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
IoSetIoCompletion (
|
||||
IN PVOID IoCompletion,
|
||||
IN PVOID KeyContext,
|
||||
IN PVOID ApcContext,
|
||||
IN NTSTATUS IoStatus,
|
||||
IN ULONG_PTR IoStatusInformation,
|
||||
IN BOOLEAN Quota
|
||||
)
|
||||
IoSetIoCompletion(IN PVOID IoCompletion,
|
||||
IN PVOID KeyContext,
|
||||
IN PVOID ApcContext,
|
||||
IN NTSTATUS IoStatus,
|
||||
IN ULONG_PTR IoStatusInformation,
|
||||
IN BOOLEAN Quota)
|
||||
{
|
||||
PKQUEUE Queue = (PKQUEUE) IoCompletion;
|
||||
PIO_COMPLETION_PACKET Packet;
|
||||
PKQUEUE Queue = (PKQUEUE)IoCompletion;
|
||||
PIO_COMPLETION_PACKET Packet;
|
||||
|
||||
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
|
||||
if (NULL == Packet)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
/* Allocate the Packet */
|
||||
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
|
||||
if (NULL == Packet) return STATUS_NO_MEMORY;
|
||||
|
||||
/* Set up the Packet */
|
||||
Packet->Key = KeyContext;
|
||||
Packet->Context = ApcContext;
|
||||
Packet->IoStatus.Status = IoStatus;
|
||||
Packet->IoStatus.Information = IoStatusInformation;
|
||||
|
||||
/* Insert the Queue */
|
||||
KeInsertQueue(Queue, &Packet->ListEntry);
|
||||
|
||||
Packet->Key = KeyContext;
|
||||
Packet->Context = ApcContext;
|
||||
Packet->IoStatus.Status = IoStatus;
|
||||
Packet->IoStatus.Information = IoStatusInformation;
|
||||
|
||||
KeInsertQueue(Queue, &Packet->ListEntry);
|
||||
/* Return Success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PIO_COMPLETION_ROUTINE CompletionRoutine,
|
||||
IN PVOID Context,
|
||||
IN BOOLEAN InvokeOnSuccess,
|
||||
IN BOOLEAN InvokeOnError,
|
||||
IN BOOLEAN InvokeOnCancel)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
IopInitIoCompletionImplementation(VOID)
|
||||
{
|
||||
ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||
|
||||
RtlpCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion", NonPagedPool);
|
||||
|
||||
ExIoCompletionType->Tag = IOC_TAG;
|
||||
ExIoCompletionType->PeakObjects = 0;
|
||||
ExIoCompletionType->PeakHandles = 0;
|
||||
ExIoCompletionType->TotalObjects = 0;
|
||||
ExIoCompletionType->TotalHandles = 0;
|
||||
ExIoCompletionType->PagedPoolCharge = 0;
|
||||
ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
|
||||
ExIoCompletionType->Mapping = &ExIoCompletionMapping;
|
||||
ExIoCompletionType->Dump = NULL;
|
||||
ExIoCompletionType->Open = NULL;
|
||||
ExIoCompletionType->Close = NULL;
|
||||
ExIoCompletionType->Delete = IopDeleteIoCompletion;
|
||||
ExIoCompletionType->Parse = NULL;
|
||||
ExIoCompletionType->Security = NULL;
|
||||
ExIoCompletionType->QueryName = NULL;
|
||||
ExIoCompletionType->OkayToClose = NULL;
|
||||
ExIoCompletionType->Create = IopCreateIoCompletion;
|
||||
ExIoCompletionType->DuplicationNotify = NULL;
|
||||
/* Create the IO Completion Type */
|
||||
ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||
RtlpCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion", NonPagedPool);
|
||||
ExIoCompletionType->Tag = IOC_TAG;
|
||||
ExIoCompletionType->PeakObjects = 0;
|
||||
ExIoCompletionType->PeakHandles = 0;
|
||||
ExIoCompletionType->TotalObjects = 0;
|
||||
ExIoCompletionType->TotalHandles = 0;
|
||||
ExIoCompletionType->PagedPoolCharge = 0;
|
||||
ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
|
||||
ExIoCompletionType->Mapping = &ExIoCompletionMapping;
|
||||
ExIoCompletionType->Dump = NULL;
|
||||
ExIoCompletionType->Open = NULL;
|
||||
ExIoCompletionType->Close = NULL;
|
||||
ExIoCompletionType->Delete = IopDeleteIoCompletion;
|
||||
ExIoCompletionType->Parse = NULL;
|
||||
ExIoCompletionType->Security = NULL;
|
||||
ExIoCompletionType->QueryName = NULL;
|
||||
ExIoCompletionType->OkayToClose = NULL;
|
||||
ExIoCompletionType->Create = NULL;
|
||||
ExIoCompletionType->DuplicationNotify = NULL;
|
||||
|
||||
ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(IO_COMPLETION_PACKET),
|
||||
IOC_TAG,
|
||||
0);
|
||||
/* Initialize the Lookaside List we'll use for packets */
|
||||
ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(IO_COMPLETION_PACKET),
|
||||
IOC_TAG,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtCreateIoCompletion(
|
||||
OUT PHANDLE IoCompletionHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN ULONG NumberOfConcurrentThreads
|
||||
)
|
||||
NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN ULONG NumberOfConcurrentThreads)
|
||||
{
|
||||
PKQUEUE Queue;
|
||||
NTSTATUS Status;
|
||||
PKQUEUE Queue;
|
||||
NTSTATUS Status;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
|
||||
Status = ObCreateObject(ExGetPreviousMode(),
|
||||
ExIoCompletionType,
|
||||
ObjectAttributes,
|
||||
ExGetPreviousMode(),
|
||||
NULL,
|
||||
sizeof(KQUEUE),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&Queue);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
/* Create the Object */
|
||||
Status = ObCreateObject(PreviousMode,
|
||||
ExIoCompletionType,
|
||||
ObjectAttributes,
|
||||
PreviousMode,
|
||||
NULL,
|
||||
sizeof(KQUEUE),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&Queue);
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
/* Initialize the Queue */
|
||||
KeInitializeQueue(Queue, NumberOfConcurrentThreads);
|
||||
|
||||
/* Insert it */
|
||||
Status = ObInsertObject(Queue,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
IoCompletionHandle);
|
||||
ObDereferenceObject(Queue);
|
||||
}
|
||||
|
||||
Status = ObInsertObject ((PVOID)Queue,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
IoCompletionHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ObDereferenceObject(Queue);
|
||||
return Status;
|
||||
}
|
||||
|
||||
KeInitializeQueue(Queue, NumberOfConcurrentThreads);
|
||||
ObDereferenceObject(Queue);
|
||||
|
||||
|
||||
/* Return Status */
|
||||
return STATUS_SUCCESS;
|
||||
/*
|
||||
}
|
||||
|
||||
CompletionPort = NULL OR ExistingCompletionPort
|
||||
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* Open the Object */
|
||||
Status = ObOpenObjectByName(ObjectAttributes,
|
||||
ExIoCompletionType,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
IoCompletionHandle);
|
||||
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
DesiredAccess:
|
||||
ZERO
|
||||
IO_COMPLETION_QUERY_STATE Query access
|
||||
IO_COMPLETION_MODIFY_STATE Modify access
|
||||
IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL
|
||||
|
||||
ObjectAttributes
|
||||
OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes
|
||||
|
||||
Return Value
|
||||
STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or
|
||||
STATUS_OBJECT_NAME_NOT_FOUND.
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtOpenIoCompletion(
|
||||
OUT PHANDLE IoCompletionHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = ObOpenObjectByName(ObjectAttributes,
|
||||
ExIoCompletionType,
|
||||
NULL,
|
||||
UserMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
IoCompletionHandle); //<- ???
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtQueryIoCompletion(
|
||||
IN HANDLE IoCompletionHandle,
|
||||
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
|
||||
OUT PVOID IoCompletionInformation,
|
||||
IN ULONG IoCompletionInformationLength,
|
||||
OUT PULONG ResultLength OPTIONAL
|
||||
)
|
||||
NtQueryIoCompletion(IN HANDLE IoCompletionHandle,
|
||||
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
|
||||
OUT PVOID IoCompletionInformation,
|
||||
IN ULONG IoCompletionInformationLength,
|
||||
OUT PULONG ResultLength OPTIONAL)
|
||||
{
|
||||
PKQUEUE Queue;
|
||||
NTSTATUS Status;
|
||||
PKQUEUE Queue;
|
||||
NTSTATUS Status;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if (IoCompletionInformationClass != IoCompletionBasicInformation)
|
||||
{
|
||||
return STATUS_INVALID_INFO_CLASS;
|
||||
}
|
||||
if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION))
|
||||
{
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle( IoCompletionHandle,
|
||||
/* Get the Object */
|
||||
Status = ObReferenceObjectByHandle(IoCompletionHandle,
|
||||
IO_COMPLETION_QUERY_STATE,
|
||||
ExIoCompletionType,
|
||||
UserMode,
|
||||
PreviousMode,
|
||||
(PVOID*)&Queue,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth =
|
||||
Queue->Header.SignalState;
|
||||
|
||||
/* Check for Success */
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
/* Return Info */
|
||||
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = KeReadStateQueue(Queue);
|
||||
ObDereferenceObject(Queue);
|
||||
|
||||
ObDereferenceObject(Queue);
|
||||
/* Return Result Length if needed */
|
||||
if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
|
||||
}
|
||||
|
||||
if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
|
||||
}
|
||||
|
||||
return Status;
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dequeues an I/O completion message from an I/O completion object
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtRemoveIoCompletion(
|
||||
IN HANDLE IoCompletionHandle,
|
||||
OUT PVOID *CompletionKey,
|
||||
OUT PVOID *CompletionContext,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
IN PLARGE_INTEGER Timeout OPTIONAL
|
||||
)
|
||||
NtRemoveIoCompletion(IN HANDLE IoCompletionHandle,
|
||||
OUT PVOID *CompletionKey,
|
||||
OUT PVOID *CompletionContext,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
IN PLARGE_INTEGER Timeout OPTIONAL)
|
||||
{
|
||||
PKQUEUE Queue;
|
||||
NTSTATUS Status;
|
||||
PIO_COMPLETION_PACKET Packet;
|
||||
PLIST_ENTRY ListEntry;
|
||||
|
||||
Status = ObReferenceObjectByHandle( IoCompletionHandle,
|
||||
PKQUEUE Queue;
|
||||
NTSTATUS Status;
|
||||
PIO_COMPLETION_PACKET Packet;
|
||||
PLIST_ENTRY ListEntry;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* Open the Object */
|
||||
Status = ObReferenceObjectByHandle(IoCompletionHandle,
|
||||
IO_COMPLETION_MODIFY_STATE,
|
||||
ExIoCompletionType,
|
||||
UserMode,
|
||||
PreviousMode,
|
||||
(PVOID*)&Queue,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check for success */
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
/*
|
||||
Try 2 remove packet from queue. Wait (optionaly) if
|
||||
no packet in queue or max num of threads allready running.
|
||||
*/
|
||||
|
||||
do {
|
||||
|
||||
ListEntry = KeRemoveQueue(Queue, UserMode, Timeout );
|
||||
/* Remove queue */
|
||||
ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout);
|
||||
|
||||
/* Nebbets book says nothing about NtRemoveIoCompletion returning STATUS_USER_APC,
|
||||
and the umode equivalent GetQueuedCompletionStatus says nothing about this either,
|
||||
so my guess it we should restart the operation. Need further investigation. -Gunnar
|
||||
*/
|
||||
|
||||
} while((NTSTATUS)ListEntry == STATUS_USER_APC);
|
||||
|
||||
ObDereferenceObject(Queue);
|
||||
/* If we got a timeout or user_apc back, return the status */
|
||||
if ((NTSTATUS)ListEntry == STATUS_TIMEOUT || (NTSTATUS)ListEntry == STATUS_USER_APC) {
|
||||
|
||||
Status = (NTSTATUS)ListEntry;
|
||||
|
||||
} else {
|
||||
|
||||
/* Get the Packet Data */
|
||||
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
|
||||
|
||||
/* Return it */
|
||||
if (CompletionKey) *CompletionKey = Packet->Key;
|
||||
if (CompletionContext) *CompletionContext = Packet->Context;
|
||||
if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
|
||||
|
||||
/* Free packet */
|
||||
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
|
||||
}
|
||||
|
||||
if ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
|
||||
{
|
||||
return STATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
ASSERT(ListEntry);
|
||||
|
||||
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
|
||||
|
||||
if (CompletionKey) *CompletionKey = Packet->Key;
|
||||
if (CompletionContext) *CompletionContext = Packet->Context;
|
||||
if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
|
||||
|
||||
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
/* Dereference the Object */
|
||||
ObDereferenceObject(Queue);
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ASSOSIERT MED FOB's IoCompletionContext
|
||||
|
||||
typedef struct _IO_COMPLETION_CONTEXT {
|
||||
PVOID Port;
|
||||
ULONG Key;
|
||||
} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Queues an I/O completion message to an I/O completion object
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtSetIoCompletion(
|
||||
IN HANDLE IoCompletionPortHandle,
|
||||
IN PVOID CompletionKey,
|
||||
IN PVOID CompletionContext,
|
||||
IN NTSTATUS CompletionStatus,
|
||||
IN ULONG CompletionInformation
|
||||
)
|
||||
NtSetIoCompletion(IN HANDLE IoCompletionPortHandle,
|
||||
IN PVOID CompletionKey,
|
||||
IN PVOID CompletionContext,
|
||||
IN NTSTATUS CompletionStatus,
|
||||
IN ULONG CompletionInformation)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKQUEUE Queue;
|
||||
|
||||
Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
|
||||
NTSTATUS Status;
|
||||
PKQUEUE Queue;
|
||||
|
||||
/* Get the Object */
|
||||
Status = ObReferenceObjectByHandle(IoCompletionPortHandle,
|
||||
IO_COMPLETION_MODIFY_STATE,
|
||||
ExIoCompletionType,
|
||||
UserMode,
|
||||
ExGetPreviousMode(),
|
||||
(PVOID*)&Queue,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = IoSetIoCompletion(Queue, CompletionKey, CompletionContext,
|
||||
CompletionStatus, CompletionInformation, TRUE);
|
||||
ObDereferenceObject(Queue);
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
||||
/* Check for Success */
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
/* Set the Completion */
|
||||
Status = IoSetIoCompletion(Queue,
|
||||
CompletionKey,
|
||||
CompletionContext,
|
||||
CompletionStatus,
|
||||
CompletionInformation,
|
||||
TRUE);
|
||||
ObDereferenceObject(Queue);
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -553,14 +553,17 @@ IoInit (VOID)
|
|||
}
|
||||
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
IoInit2(VOID)
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
IoInit2(BOOLEAN BootLog)
|
||||
{
|
||||
PDEVICE_NODE DeviceNode;
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
MODULE_OBJECT ModuleObject;
|
||||
NTSTATUS Status;
|
||||
|
||||
IoCreateDriverList();
|
||||
|
||||
KeInitializeSpinLock (&IoStatisticsLock);
|
||||
|
||||
/* Initialize raw filesystem driver */
|
||||
|
@ -605,6 +608,56 @@ IoInit2(VOID)
|
|||
IopInvalidateDeviceRelations(
|
||||
IopRootDeviceNode,
|
||||
BusRelations);
|
||||
|
||||
/* Start boot logging */
|
||||
IopInitBootLog(BootLog);
|
||||
|
||||
/* Load boot start drivers */
|
||||
IopInitializeBootDrivers();
|
||||
}
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
INIT_FUNCTION
|
||||
IoInit3(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Create ARC names for boot devices */
|
||||
IoCreateArcNames();
|
||||
|
||||
/* Create the SystemRoot symbolic link */
|
||||
CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
|
||||
Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
DbgPrint("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
|
||||
DbgPrintErrorMessage (Status);
|
||||
KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
|
||||
}
|
||||
|
||||
/* Start Profiling on a Debug Build */
|
||||
#if defined(KDBG) || defined(DBG)
|
||||
KdbInitProfiling2();
|
||||
#endif /* KDBG */
|
||||
|
||||
/* I/O is now setup for disk access, so start the debugging logger thread. */
|
||||
if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_BOOTLOG)) DebugLogInit2();
|
||||
|
||||
/* Load services for devices found by PnP manager */
|
||||
IopInitializePnpServices(IopRootDeviceNode, FALSE);
|
||||
|
||||
/* Load system start drivers */
|
||||
IopInitializeSystemDrivers();
|
||||
IoDestroyDriverList();
|
||||
|
||||
/* Stop boot logging */
|
||||
IopStopBootLog();
|
||||
|
||||
/* Assign drive letters */
|
||||
IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
/* $Id:$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/alert.c
|
||||
* PURPOSE: Alerts
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||
/*
|
||||
* FUNCTION: Tests whether there are any pending APCs for the current thread
|
||||
* and if so the APCs will be delivered on exit from kernel mode
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
BOOLEAN OldState;
|
||||
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||
|
||||
OldState = Thread->Alerted[AlertMode];
|
||||
|
||||
/* If the Thread is Alerted, Clear it */
|
||||
if (OldState) {
|
||||
Thread->Alerted[AlertMode] = FALSE;
|
||||
} else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) {
|
||||
/* If the mode is User and the Queue isn't empty, set Pending */
|
||||
Thread->ApcState.UserApcPending = TRUE;
|
||||
}
|
||||
|
||||
KiReleaseSpinLock(&Thread->ApcQueueLock);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return OldState;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
KeAlertThread(PKTHREAD Thread, KPROCESSOR_MODE AlertMode)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
|
||||
|
||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
|
||||
/* Return if thread is already alerted. */
|
||||
if (Thread->Alerted[AlertMode] == FALSE)
|
||||
{
|
||||
if (Thread->State == THREAD_STATE_BLOCKED &&
|
||||
(AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
|
||||
Thread->Alertable)
|
||||
{
|
||||
KiAbortWaitThread(Thread, STATUS_ALERTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread->Alerted[AlertMode] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* NOT EXPORTED
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtAlertResumeThread(IN HANDLE ThreadHandle,
|
||||
OUT PULONG SuspendCount)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return(STATUS_NOT_IMPLEMENTED);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* EXPORTED
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtAlertThread (IN HANDLE ThreadHandle)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_SUSPEND_RESUME,
|
||||
PsThreadType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Thread,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* do an alert depending on the processor mode. If some kmode code wants to
|
||||
enforce a umode alert it should call KeAlertThread() directly. If kmode
|
||||
code wants to do a kmode alert it's sufficient to call it with Zw or just
|
||||
use KeAlertThread() directly */
|
||||
|
||||
KeAlertThread(&Thread->Tcb, PreviousMode);
|
||||
|
||||
ObDereferenceObject(Thread);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NOT EXPORTED
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtTestAlert(VOID)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* Check and Alert Thread if needed */
|
||||
|
||||
return KeTestAlertThread(PreviousMode) ? STATUS_ALERTED : STATUS_SUCCESS;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -47,6 +47,17 @@ KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -74,6 +85,20 @@ KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
|
|||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
|
||||
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
|
||||
IN KBUGCHECK_CALLBACK_REASON Reason,
|
||||
IN PUCHAR Component)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
KeBugCheckWithTf(ULONG BugCheckCode,
|
||||
ULONG BugCheckParameter1,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/catch.c
|
||||
|
@ -21,282 +20,206 @@ ULONG
|
|||
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
|
||||
IN PCONTEXT Context);
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiCoprocessorError(VOID)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiUnexpectedInterrupt(VOID)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||
PCONTEXT Context,
|
||||
PKTRAP_FRAME Tf,
|
||||
KPROCESSOR_MODE PreviousMode,
|
||||
BOOLEAN SearchFrames)
|
||||
PCONTEXT Context,
|
||||
PKTRAP_FRAME Tf,
|
||||
KPROCESSOR_MODE PreviousMode,
|
||||
BOOLEAN SearchFrames)
|
||||
{
|
||||
EXCEPTION_DISPOSITION Value;
|
||||
CONTEXT TContext;
|
||||
KD_CONTINUE_TYPE Action = kdHandleException;
|
||||
EXCEPTION_DISPOSITION Value;
|
||||
CONTEXT TContext;
|
||||
KD_CONTINUE_TYPE Action = kdHandleException;
|
||||
|
||||
DPRINT("KiDispatchException() called\n");
|
||||
DPRINT("KiDispatchException() called\n");
|
||||
|
||||
/* Increase number of Exception Dispatches */
|
||||
KeGetCurrentKPCR()->PrcbData.KeExceptionDispatchCount++;
|
||||
|
||||
/* PCR->KeExceptionDispatchCount++; */
|
||||
|
||||
if (Context == NULL)
|
||||
{
|
||||
TContext.ContextFlags = CONTEXT_FULL;
|
||||
if (PreviousMode == UserMode)
|
||||
{
|
||||
TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
|
||||
}
|
||||
if (!Context) {
|
||||
|
||||
/* Assume Full context */
|
||||
TContext.ContextFlags = CONTEXT_FULL;
|
||||
|
||||
/* Check the mode */
|
||||
if (PreviousMode == UserMode) {
|
||||
|
||||
/* Add Debugger Registers if this is User Mode */
|
||||
TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
|
||||
}
|
||||
|
||||
KeTrapFrameToContext(Tf, &TContext);
|
||||
/* Convert the Trapframe into a Context */
|
||||
KeTrapFrameToContext(Tf, &TContext);
|
||||
|
||||
Context = &TContext;
|
||||
/* Use local stack context */
|
||||
Context = &TContext;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
|
||||
{
|
||||
Context->Eip--;
|
||||
#if 0 /* FIXME: Isn't this right? With a break after? */
|
||||
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
|
||||
Context->Eip--;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
|
||||
{
|
||||
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
|
||||
}
|
||||
|
||||
if (Action == kdContinue)
|
||||
{
|
||||
return;
|
||||
/* Check if a Debugger is enabled */
|
||||
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) {
|
||||
|
||||
/* Break into it */
|
||||
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
|
||||
}
|
||||
|
||||
/* If the debugger said continue, then continue */
|
||||
if (Action == kdContinue) return;
|
||||
|
||||
/* If the Debugger couldn't handle it... */
|
||||
if (Action != kdDoNotHandleException) {
|
||||
|
||||
/* See what kind of Exception this is */
|
||||
if (PreviousMode == UserMode) {
|
||||
|
||||
/* User mode exception, search the frames if we have to */
|
||||
if (SearchFrames) {
|
||||
|
||||
if (Action != kdDoNotHandleException)
|
||||
{
|
||||
if (PreviousMode == UserMode)
|
||||
{
|
||||
if (SearchFrames)
|
||||
{
|
||||
PULONG Stack;
|
||||
ULONG CDest;
|
||||
char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
|
||||
PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
|
||||
NTSTATUS StatusOfCopy;
|
||||
PULONG Stack;
|
||||
ULONG CDest;
|
||||
char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
|
||||
PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
|
||||
NTSTATUS StatusOfCopy;
|
||||
|
||||
#ifdef KDBG
|
||||
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
|
||||
Context, Tf, FALSE);
|
||||
if (Action == kdContinue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* Enter KDB if available */
|
||||
Action = KdbEnterDebuggerException(ExceptionRecord,
|
||||
PreviousMode,
|
||||
Context,
|
||||
Tf,
|
||||
FALSE);
|
||||
|
||||
/* Exit if we're continuing */
|
||||
if (Action == kdContinue) return;
|
||||
#endif
|
||||
|
||||
/* FIXME: Forward exception to user mode debugger */
|
||||
/* FIXME: Forward exception to user mode debugger */
|
||||
|
||||
/* FIXME: Check user mode stack for enough space */
|
||||
|
||||
/*
|
||||
* Let usermode try and handle the exception
|
||||
*/
|
||||
Stack = (PULONG)temp_space;
|
||||
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
|
||||
/* Return address */
|
||||
Stack[0] = 0;
|
||||
/* Pointer to EXCEPTION_RECORD structure */
|
||||
Stack[1] = (ULONG)&pNewUserStack[3];
|
||||
/* Pointer to CONTEXT structure */
|
||||
Stack[2] = (ULONG)&pNewUserStack[CDest];
|
||||
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
|
||||
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
|
||||
|
||||
StatusOfCopy = MmCopyToCaller(pNewUserStack,
|
||||
temp_space,
|
||||
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
|
||||
if (NT_SUCCESS(StatusOfCopy))
|
||||
{
|
||||
Tf->Esp = (ULONG)pNewUserStack;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now it really hit the ventilation device. Sorry,
|
||||
* can do nothing but kill the sucker.
|
||||
*/
|
||||
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
|
||||
DPRINT1("User-mode stack was invalid. Terminating target thread\n");
|
||||
}
|
||||
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: Forward the exception to the debugger */
|
||||
|
||||
/* FIXME: Forward the exception to the process exception port */
|
||||
|
||||
#ifdef KDBG
|
||||
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
|
||||
Context, Tf, TRUE);
|
||||
if (Action == kdContinue)
|
||||
{
|
||||
return;
|
||||
/* FIXME: Check user mode stack for enough space */
|
||||
|
||||
/* Let usermode try and handle the exception. Setup Stack */
|
||||
Stack = (PULONG)temp_space;
|
||||
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
|
||||
/* Return Address */
|
||||
Stack[0] = 0;
|
||||
/* Pointer to EXCEPTION_RECORD structure */
|
||||
Stack[1] = (ULONG)&pNewUserStack[3];
|
||||
/* Pointer to CONTEXT structure */
|
||||
Stack[2] = (ULONG)&pNewUserStack[CDest];
|
||||
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
|
||||
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
|
||||
|
||||
/* Copy Stack */
|
||||
StatusOfCopy = MmCopyToCaller(pNewUserStack,
|
||||
temp_space,
|
||||
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
|
||||
|
||||
/* Check for success */
|
||||
if (NT_SUCCESS(StatusOfCopy)) {
|
||||
|
||||
/* Set new Stack Pointer */
|
||||
Tf->Esp = (ULONG)pNewUserStack;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Now it really hit the ventilation device. Sorry,
|
||||
* can do nothing but kill the sucker.
|
||||
*/
|
||||
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
|
||||
DPRINT1("User-mode stack was invalid. Terminating target thread\n");
|
||||
}
|
||||
|
||||
/* Set EIP to the User-mode Dispathcer */
|
||||
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: Forward the exception to the debugger */
|
||||
|
||||
/* FIXME: Forward the exception to the process exception port */
|
||||
|
||||
|
||||
#ifdef KDBG
|
||||
/* Enter KDB if available */
|
||||
Action = KdbEnterDebuggerException(ExceptionRecord,
|
||||
PreviousMode,
|
||||
Context,
|
||||
Tf,
|
||||
TRUE);
|
||||
|
||||
/* Exit if we're continuing */
|
||||
if (Action == kdContinue) return;
|
||||
#endif
|
||||
|
||||
/* Terminate the offending thread */
|
||||
DPRINT1("Unhandled UserMode exception, terminating thread\n");
|
||||
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* PreviousMode == KernelMode */
|
||||
/* Terminate the offending thread */
|
||||
DPRINT1("Unhandled UserMode exception, terminating thread\n");
|
||||
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
|
||||
|
||||
} else {
|
||||
|
||||
/* This is Kernel Mode */
|
||||
#ifdef KDBG
|
||||
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
|
||||
Context, Tf, FALSE);
|
||||
if (Action == kdContinue)
|
||||
{
|
||||
return;
|
||||
/* Enter KDB if available */
|
||||
Action = KdbEnterDebuggerException(ExceptionRecord,
|
||||
PreviousMode,
|
||||
Context,
|
||||
Tf,
|
||||
FALSE);
|
||||
|
||||
/* Exit if we're continuing */
|
||||
if (Action == kdContinue) return;
|
||||
#endif
|
||||
|
||||
/* Dispatch the Exception */
|
||||
Value = RtlpDispatchException (ExceptionRecord, Context);
|
||||
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
|
||||
|
||||
/* If RtlpDispatchException() did not handle the exception then bugcheck */
|
||||
if (Value != ExceptionContinueExecution ||
|
||||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)) {
|
||||
|
||||
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n", ExceptionRecord->ExceptionAddress);
|
||||
#ifdef KDBG
|
||||
/* Enter KDB if available */
|
||||
Action = KdbEnterDebuggerException(ExceptionRecord,
|
||||
PreviousMode,
|
||||
Context,
|
||||
Tf,
|
||||
TRUE);
|
||||
|
||||
/* Exit if we're continuing */
|
||||
if (Action == kdContinue) return;
|
||||
#endif
|
||||
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
|
||||
}
|
||||
#endif
|
||||
|
||||
Value = RtlpDispatchException (ExceptionRecord, Context);
|
||||
|
||||
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
|
||||
/*
|
||||
* If RtlpDispatchException() does not handle the exception then
|
||||
* bugcheck
|
||||
*/
|
||||
if (Value != ExceptionContinueExecution ||
|
||||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
|
||||
{
|
||||
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
|
||||
ExceptionRecord->ExceptionAddress );
|
||||
#ifdef KDBG
|
||||
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
|
||||
Context, Tf, TRUE);
|
||||
if (Action == kdContinue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
ExRaiseAccessViolation (VOID)
|
||||
{
|
||||
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
ExRaiseDatatypeMisalignment (VOID)
|
||||
{
|
||||
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
ExRaiseStatus (IN NTSTATUS Status)
|
||||
{
|
||||
EXCEPTION_RECORD ExceptionRecord;
|
||||
|
||||
DPRINT("ExRaiseStatus(%x)\n", Status);
|
||||
|
||||
ExceptionRecord.ExceptionRecord = NULL;
|
||||
ExceptionRecord.NumberParameters = 0;
|
||||
ExceptionRecord.ExceptionCode = Status;
|
||||
ExceptionRecord.ExceptionFlags = 0;
|
||||
|
||||
RtlRaiseException(&ExceptionRecord);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExRaiseException (
|
||||
PEXCEPTION_RECORD ExceptionRecord
|
||||
)
|
||||
{
|
||||
RtlRaiseException(ExceptionRecord);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
ExSystemExceptionFilter(VOID)
|
||||
{
|
||||
return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
ExRaiseHardError (
|
||||
IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
|
||||
IN PVOID *Parameters,
|
||||
IN HARDERROR_RESPONSE_OPTION ResponseOption,
|
||||
OUT PHARDERROR_RESPONSE Response
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeDeregisterBugCheckReasonCallback(
|
||||
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
ULONG
|
||||
STDCALL
|
||||
KeGetRecommendedSharedDataAlignment(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeRegisterBugCheckReasonCallback(
|
||||
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
|
||||
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
|
||||
IN KBUGCHECK_CALLBACK_REASON Reason,
|
||||
IN PUCHAR Component
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/critical.c
|
||||
* PURPOSE: Implement critical regions
|
||||
*
|
||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL KeEnterCriticalRegion (VOID)
|
||||
{
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
|
||||
DPRINT("KeEnterCriticalRegion()\n");
|
||||
|
||||
if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
|
||||
|
||||
Thread->KernelApcDisable--;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL KeLeaveCriticalRegion (VOID)
|
||||
{
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
|
||||
DPRINT("KeLeaveCriticalRegion()\n");
|
||||
|
||||
if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
|
||||
|
||||
/* Reference: http://www.ntfsd.org/archive/ntfsd0104/msg0203.html */
|
||||
if(++Thread->KernelApcDisable == 0)
|
||||
{
|
||||
if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]))
|
||||
{
|
||||
Thread->ApcState.KernelApcPending = TRUE;
|
||||
HalRequestSoftwareInterrupt(APC_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -24,15 +24,15 @@
|
|||
/* TYPES *******************************************************************/
|
||||
|
||||
#define MAX_QUANTUM 0x7F
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
KeInitDpc(PKPCR Pcr)
|
||||
/*
|
||||
* FUNCTION: Initialize DPC handling
|
||||
*/
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
KeInitDpc(PKPCR Pcr)
|
||||
{
|
||||
InitializeListHead(&Pcr->PrcbData.DpcData[0].DpcListHead);
|
||||
KeInitializeEvent(Pcr->PrcbData.DpcEvent, 0, 0);
|
||||
|
@ -47,9 +47,9 @@ KeInitDpc(PKPCR Pcr)
|
|||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeInitializeThreadedDpc(PKDPC Dpc,
|
||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
||||
PVOID DeferredContext)
|
||||
KeInitializeThreadedDpc(PKDPC Dpc,
|
||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
||||
PVOID DeferredContext)
|
||||
/*
|
||||
* FUNCTION:
|
||||
* Initalizes a Threaded DPC and registers the DeferredRoutine for it.
|
||||
|
@ -60,24 +60,18 @@ KeInitializeThreadedDpc(PKDPC Dpc,
|
|||
* NOTE: Callers can be running at any IRQL.
|
||||
*/
|
||||
{
|
||||
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||
//Dpc->Type = KThreadedDpc;
|
||||
Dpc->Number= 0;
|
||||
Dpc->Importance= MediumImportance;
|
||||
Dpc->DeferredRoutine = DeferredRoutine;
|
||||
Dpc->DeferredContext = DeferredContext;
|
||||
Dpc->DpcData = NULL;
|
||||
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||
Dpc->Type = ThreadedDpcObject;
|
||||
Dpc->Number= 0;
|
||||
Dpc->Importance= MediumImportance;
|
||||
Dpc->DeferredRoutine = DeferredRoutine;
|
||||
Dpc->DeferredContext = DeferredContext;
|
||||
Dpc->DpcData = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeInitializeDpc (PKDPC Dpc,
|
||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
||||
PVOID DeferredContext)
|
||||
/*
|
||||
*
|
||||
* FUNCTION:
|
||||
* Initalizes a DPC and registers the DeferredRoutine for it.
|
||||
* ARGUMENTS:
|
||||
|
@ -86,24 +80,24 @@ KeInitializeDpc (PKDPC Dpc,
|
|||
* DeferredContext = Parameter to be passed to the callback routine.
|
||||
* NOTE: Callers can be running at any IRQL.
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeInitializeDpc(PKDPC Dpc,
|
||||
PKDEFERRED_ROUTINE DeferredRoutine,
|
||||
PVOID DeferredContext)
|
||||
{
|
||||
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||
Dpc->Type = KDpc;
|
||||
Dpc->Number= 0;
|
||||
Dpc->Importance= MediumImportance;
|
||||
Dpc->DeferredRoutine = DeferredRoutine;
|
||||
Dpc->DeferredContext = DeferredContext;
|
||||
Dpc->DpcData = NULL;
|
||||
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||
Dpc->Type = DpcObject;
|
||||
Dpc->Number= 0;
|
||||
Dpc->Importance= MediumImportance;
|
||||
Dpc->DeferredRoutine = DeferredRoutine;
|
||||
Dpc->DeferredContext = DeferredContext;
|
||||
Dpc->DpcData = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
KeInsertQueueDpc (PKDPC Dpc,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
/*
|
||||
*
|
||||
* FUNCTION:
|
||||
* Queues a DPC for execution when the IRQL of a processor
|
||||
* drops below DISPATCH_LEVEL
|
||||
|
@ -155,124 +149,141 @@ KeInsertQueueDpc (PKDPC Dpc,
|
|||
* is greater that the target depth or the minimum DPC rate is less than the
|
||||
* target rate.
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeInsertQueueDpc(PKDPC Dpc,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PKPCR Pcr;
|
||||
KIRQL OldIrql;
|
||||
PKPCR Pcr;
|
||||
|
||||
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
|
||||
Dpc, SystemArgument1, SystemArgument2);
|
||||
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
|
||||
Dpc, SystemArgument1, SystemArgument2);
|
||||
|
||||
/* Check IRQL and Raise it to HIGH_LEVEL */
|
||||
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Check if this is a Thread DPC, which we don't support (yet) */
|
||||
//if (Dpc->Type == KThreadedDpc) {
|
||||
// return FALSE;
|
||||
// KeLowerIrql(OldIrql);
|
||||
//}
|
||||
/* Check IRQL and Raise it to HIGH_LEVEL */
|
||||
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Check if this is a Thread DPC, which we don't support (yet) */
|
||||
if (Dpc->Type == ThreadedDpcObject) {
|
||||
return FALSE;
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Get the right PCR for this CPU */
|
||||
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
||||
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
|
||||
Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE);
|
||||
} else {
|
||||
ASSERT (Dpc->Number < KeNumberProcessors);
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
Dpc->Number = KeGetCurrentProcessorNumber();
|
||||
}
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
/* Get the right PCR for this CPU */
|
||||
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
||||
|
||||
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
|
||||
Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE);
|
||||
|
||||
} else {
|
||||
|
||||
ASSERT (Dpc->Number < KeNumberProcessors);
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
Dpc->Number = KeGetCurrentProcessorNumber();
|
||||
}
|
||||
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#else
|
||||
Pcr = (PKPCR)KPCR_BASE;
|
||||
Pcr = (PKPCR)KPCR_BASE;
|
||||
#endif
|
||||
|
||||
/* Get the DPC Data */
|
||||
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
|
||||
DPRINT("DPC Already Inserted");
|
||||
/* Get the DPC Data */
|
||||
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
|
||||
|
||||
DPRINT("DPC Already Inserted");
|
||||
#ifdef CONFIG_SMP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
KeLowerIrql(OldIrql);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Make sure the lists are free if the Queue is 0 */
|
||||
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
|
||||
ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
|
||||
} else {
|
||||
ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
|
||||
}
|
||||
KeLowerIrql(OldIrql);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Make sure the lists are free if the Queue is 0 */
|
||||
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
|
||||
|
||||
ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
|
||||
} else {
|
||||
|
||||
ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
|
||||
}
|
||||
|
||||
/* Now we can play with the DPC safely */
|
||||
Dpc->SystemArgument1=SystemArgument1;
|
||||
Dpc->SystemArgument2=SystemArgument2;
|
||||
Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
|
||||
Pcr->PrcbData.DpcData[0].DpcCount++;
|
||||
|
||||
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
|
||||
if (Dpc->Importance == HighImportance) {
|
||||
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
||||
} else {
|
||||
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
||||
}
|
||||
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
||||
/* Now we can play with the DPC safely */
|
||||
Dpc->SystemArgument1=SystemArgument1;
|
||||
Dpc->SystemArgument2=SystemArgument2;
|
||||
Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
|
||||
Pcr->PrcbData.DpcData[0].DpcCount++;
|
||||
|
||||
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
|
||||
if (Dpc->Importance == HighImportance) {
|
||||
|
||||
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
||||
} else {
|
||||
|
||||
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
|
||||
}
|
||||
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
||||
|
||||
/* Make sure a DPC isn't executing already and respect rules outlined above. */
|
||||
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Check if this is the same CPU */
|
||||
if (Pcr != KeGetCurrentKPCR()) {
|
||||
/* Send IPI if High Importance */
|
||||
if ((Dpc->Importance == HighImportance) ||
|
||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
|
||||
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
||||
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
|
||||
} else {
|
||||
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
|
||||
}
|
||||
/* Make sure a DPC isn't executing already and respect rules outlined above. */
|
||||
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Check if this is the same CPU */
|
||||
if (Pcr != KeGetCurrentKPCR()) {
|
||||
|
||||
/* Send IPI if High Importance */
|
||||
if ((Dpc->Importance == HighImportance) ||
|
||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
|
||||
|
||||
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
|
||||
|
||||
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
|
||||
} else {
|
||||
|
||||
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
/* Request an Interrupt only if the DPC isn't low priority */
|
||||
if ((Dpc->Importance != LowImportance) ||
|
||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
|
||||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
|
||||
|
||||
/* Request Interrupt */
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Request an Interrupt only if the DPC isn't low priority */
|
||||
if ((Dpc->Importance != LowImportance) ||
|
||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
|
||||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
|
||||
|
||||
/* Request Interrupt */
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
|
||||
/* Request an Interrupt only if the DPC isn't low priority */
|
||||
if ((Dpc->Importance != LowImportance) ||
|
||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
|
||||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
|
||||
|
||||
/* Request Interrupt */
|
||||
DPRINT("Requesting Interrupt\n");
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
||||
}
|
||||
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
|
||||
|
||||
/* Request an Interrupt only if the DPC isn't low priority */
|
||||
if ((Dpc->Importance != LowImportance) ||
|
||||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
|
||||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
|
||||
|
||||
/* Request Interrupt */
|
||||
DPRINT("Requesting Interrupt\n");
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
Pcr->PrcbData.DpcInterruptRequested = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_SMP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
/* Lower IRQL */
|
||||
KeLowerIrql(OldIrql);
|
||||
return(TRUE);
|
||||
/* Lower IRQL */
|
||||
KeLowerIrql(OldIrql);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN STDCALL
|
||||
KeRemoveQueueDpc (PKDPC Dpc)
|
||||
/*
|
||||
*
|
||||
* FUNCTION:
|
||||
* Removes DPC object from the system dpc queue
|
||||
* ARGUMENTS:
|
||||
|
@ -281,33 +292,36 @@ KeRemoveQueueDpc (PKDPC Dpc)
|
|||
* TRUE if the DPC was in the queue
|
||||
* FALSE otherwise
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeRemoveQueueDpc(PKDPC Dpc)
|
||||
{
|
||||
BOOLEAN WasInQueue;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Raise IRQL */
|
||||
DPRINT("Removing DPC: %x\n", Dpc);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
BOOLEAN WasInQueue;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Raise IRQL */
|
||||
DPRINT("Removing DPC: %x\n", Dpc);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
#ifdef CONFIG_SMP
|
||||
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
||||
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
||||
#endif
|
||||
|
||||
/* First make sure the DPC lock isn't being held */
|
||||
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
|
||||
if (Dpc->DpcData) {
|
||||
|
||||
/* Remove the DPC */
|
||||
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
|
||||
RemoveEntryList(&Dpc->DpcListEntry);
|
||||
|
||||
/* First make sure the DPC lock isn't being held */
|
||||
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
|
||||
if (Dpc->DpcData) {
|
||||
|
||||
/* Remove the DPC */
|
||||
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
|
||||
RemoveEntryList(&Dpc->DpcListEntry);
|
||||
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_SMP
|
||||
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
|
||||
#endif
|
||||
|
||||
/* Return if the DPC was in the queue or not */
|
||||
KeLowerIrql(OldIrql);
|
||||
return WasInQueue;
|
||||
/* Return if the DPC was in the queue or not */
|
||||
KeLowerIrql(OldIrql);
|
||||
return WasInQueue;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -323,7 +337,8 @@ KeFlushQueuedDpcs(VOID)
|
|||
* Called when deleting a Driver.
|
||||
*/
|
||||
{
|
||||
if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
/* Request an interrupt if needed */
|
||||
if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -332,10 +347,11 @@ KeFlushQueuedDpcs(VOID)
|
|||
BOOLEAN
|
||||
STDCALL
|
||||
KeIsExecutingDpc(
|
||||
VOID
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
|
||||
/* Return if the Dpc Routine is active */
|
||||
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -349,39 +365,41 @@ KeIsExecutingDpc(
|
|||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeSetImportanceDpc (IN PKDPC Dpc,
|
||||
IN KDPC_IMPORTANCE Importance)
|
||||
KeSetImportanceDpc (IN PKDPC Dpc,
|
||||
IN KDPC_IMPORTANCE Importance)
|
||||
{
|
||||
Dpc->Importance = Importance;
|
||||
/* Set the DPC Importance */
|
||||
Dpc->Importance = Importance;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* FUNCTION: Specifies on which processor the DPC will run
|
||||
* ARGUMENTS:
|
||||
* Dpc = Initalizes DPC
|
||||
* Number = Processor number
|
||||
* RETURNS: None
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
KeSetTargetProcessorDpc (IN PKDPC Dpc,
|
||||
IN CCHAR Number)
|
||||
VOID
|
||||
STDCALL
|
||||
KeSetTargetProcessorDpc(IN PKDPC Dpc,
|
||||
IN CCHAR Number)
|
||||
{
|
||||
if (Number >= MAXIMUM_PROCESSORS)
|
||||
{
|
||||
Dpc->Number = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(Number < KeNumberProcessors);
|
||||
Dpc->Number = Number + MAXIMUM_PROCESSORS;
|
||||
}
|
||||
/* Check how many CPUs are on the system */
|
||||
if (Number >= MAXIMUM_PROCESSORS) {
|
||||
|
||||
/* No CPU Number */
|
||||
Dpc->Number = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* Set the Number Specified */
|
||||
ASSERT(Number < KeNumberProcessors);
|
||||
Dpc->Number = Number + MAXIMUM_PROCESSORS;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
KiQuantumEnd(VOID)
|
||||
/*
|
||||
* FUNCTION:
|
||||
* Called when a quantum end occurs to check if priority should be changed
|
||||
|
@ -389,152 +407,173 @@ KiQuantumEnd(VOID)
|
|||
* NOTES:
|
||||
* Called when deleting a Driver.
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiQuantumEnd(VOID)
|
||||
{
|
||||
PKPRCB Prcb;
|
||||
PKTHREAD CurrentThread;
|
||||
KIRQL OldIrql;
|
||||
PKPROCESS Process;
|
||||
KPRIORITY OldPriority;
|
||||
KPRIORITY NewPriority;
|
||||
|
||||
/* Lock dispatcher, get current thread */
|
||||
Prcb = &KeGetCurrentKPCR()->PrcbData;
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
OldIrql = KeRaiseIrqlToSynchLevel();
|
||||
|
||||
/* Get the Thread's Process */
|
||||
Process = CurrentThread->ApcState.Process;
|
||||
|
||||
/* Set DPC Event if requested */
|
||||
if (Prcb->DpcSetEventRequest) {
|
||||
KeSetEvent(Prcb->DpcEvent, 0, 0);
|
||||
}
|
||||
|
||||
/* Check if Quantum expired */
|
||||
if (CurrentThread->Quantum <= 0) {
|
||||
/* Set the new Quantum */
|
||||
CurrentThread->Quantum = Process->ThreadQuantum;
|
||||
|
||||
/* Calculate new priority */
|
||||
OldPriority = CurrentThread->Priority;
|
||||
if (OldPriority < LOW_REALTIME_PRIORITY) {
|
||||
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
|
||||
if (NewPriority < CurrentThread->BasePriority) {
|
||||
NewPriority = CurrentThread->BasePriority;
|
||||
}
|
||||
CurrentThread->PriorityDecrement = 0;
|
||||
if (OldPriority != NewPriority) {
|
||||
/* Set new Priority */
|
||||
CurrentThread->Priority = NewPriority;
|
||||
} else {
|
||||
/* Queue new thread if none is already */
|
||||
if (Prcb->NextThread == NULL) {
|
||||
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
|
||||
} else {
|
||||
/* Make the current thread non-premeptive if a new thread is queued */
|
||||
CurrentThread->Preempted = FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Set the Quantum back to Maximum */
|
||||
//if (CurrentThread->DisableQuantum) {
|
||||
// CurrentThread->Quantum = MAX_QUANTUM;
|
||||
//}
|
||||
}
|
||||
}
|
||||
/* Dispatch the Thread */
|
||||
KeLowerIrql(DISPATCH_LEVEL);
|
||||
PsDispatchThread(THREAD_STATE_READY);
|
||||
}
|
||||
PKPRCB Prcb;
|
||||
PKTHREAD CurrentThread;
|
||||
KIRQL OldIrql;
|
||||
PKPROCESS Process;
|
||||
KPRIORITY OldPriority;
|
||||
KPRIORITY NewPriority;
|
||||
|
||||
/* Lock dispatcher, get current thread */
|
||||
Prcb = &KeGetCurrentKPCR()->PrcbData;
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
OldIrql = KeRaiseIrqlToSynchLevel();
|
||||
|
||||
/* Get the Thread's Process */
|
||||
Process = CurrentThread->ApcState.Process;
|
||||
|
||||
/* Set DPC Event if requested */
|
||||
if (Prcb->DpcSetEventRequest) {
|
||||
KeSetEvent(Prcb->DpcEvent, 0, 0);
|
||||
}
|
||||
|
||||
/* Check if Quantum expired */
|
||||
if (CurrentThread->Quantum <= 0) {
|
||||
/* Set the new Quantum */
|
||||
CurrentThread->Quantum = Process->ThreadQuantum;
|
||||
|
||||
/* Calculate new priority */
|
||||
OldPriority = CurrentThread->Priority;
|
||||
if (OldPriority < LOW_REALTIME_PRIORITY) {
|
||||
|
||||
/* Set the New Priority and add the Priority Decrement */
|
||||
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
|
||||
|
||||
/* Don't go out of bounds */
|
||||
if (NewPriority < CurrentThread->BasePriority) NewPriority = CurrentThread->BasePriority;
|
||||
|
||||
/* Reset the priority decrement */
|
||||
CurrentThread->PriorityDecrement = 0;
|
||||
|
||||
/* Set a new priority if needed */
|
||||
if (OldPriority != NewPriority) {
|
||||
|
||||
/* Set new Priority */
|
||||
CurrentThread->Priority = NewPriority;
|
||||
|
||||
} else {
|
||||
|
||||
/* Queue new thread if none is already */
|
||||
if (Prcb->NextThread == NULL) {
|
||||
|
||||
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
|
||||
|
||||
} else {
|
||||
|
||||
/* Make the current thread non-premeptive if a new thread is queued */
|
||||
CurrentThread->Preempted = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
/* Set the Quantum back to Maximum */
|
||||
//if (CurrentThread->DisableQuantum) {
|
||||
// CurrentThread->Quantum = MAX_QUANTUM;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
/* Dispatch the Thread */
|
||||
KeLowerIrql(DISPATCH_LEVEL);
|
||||
PsDispatchThread(THREAD_STATE_READY);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiDispatchInterrupt(VOID)
|
||||
/*
|
||||
*
|
||||
* FUNCTION:
|
||||
* Called whenever a system interrupt is generated at DISPATCH_LEVEL.
|
||||
* It delivers queued DPCs and dispatches a new thread if need be.
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiDispatchInterrupt(VOID)
|
||||
{
|
||||
PLIST_ENTRY DpcEntry;
|
||||
PKDPC Dpc;
|
||||
KIRQL OldIrql;
|
||||
PKPCR Pcr;
|
||||
PLIST_ENTRY DpcEntry;
|
||||
PKDPC Dpc;
|
||||
KIRQL OldIrql;
|
||||
PKPCR Pcr;
|
||||
|
||||
DPRINT("Dispatching Interrupts\n");
|
||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||
DPRINT("Dispatching Interrupts\n");
|
||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||
|
||||
/* Set DPC Deliver to Active */
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
/* Set DPC Deliver to Active */
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
|
||||
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
|
||||
/* Raise IRQL */
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
#ifdef CONFIG_SMP
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
|
||||
/* Raise IRQL */
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
#ifdef CONFIG_SMP
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
||||
|
||||
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
|
||||
/* Loop while we have entries */
|
||||
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
|
||||
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
|
||||
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
|
||||
|
||||
/* Get the DPC call it */
|
||||
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
|
||||
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
|
||||
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
||||
Dpc->DpcData = NULL;
|
||||
Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
|
||||
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
|
||||
/* Loop while we have entries */
|
||||
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
|
||||
|
||||
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
|
||||
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
|
||||
|
||||
/* Get the DPC call it */
|
||||
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
|
||||
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
|
||||
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
|
||||
Dpc->DpcData = NULL;
|
||||
Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
|
||||
#ifdef CONFIG_SMP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
/* Disable/Enabled Interrupts and Call the DPC */
|
||||
KeLowerIrql(OldIrql);
|
||||
DPRINT("Calling DPC: %x\n", Dpc);
|
||||
Dpc->DeferredRoutine(Dpc,
|
||||
Dpc->DeferredContext,
|
||||
Dpc->SystemArgument1,
|
||||
Dpc->SystemArgument2);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
/* Disable/Enabled Interrupts and Call the DPC */
|
||||
KeLowerIrql(OldIrql);
|
||||
DPRINT("Calling DPC: %x\n", Dpc);
|
||||
Dpc->DeferredRoutine(Dpc,
|
||||
Dpc->DeferredContext,
|
||||
Dpc->SystemArgument1,
|
||||
Dpc->SystemArgument2);
|
||||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
/*
|
||||
* If the dpc routine drops the irql below DISPATCH_LEVEL,
|
||||
* a thread switch can occur and after the next thread switch
|
||||
* the execution may start on an other processor.
|
||||
*/
|
||||
if (Pcr != KeGetCurrentKPCR()) {
|
||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
||||
}
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
/*
|
||||
* If the dpc routine drops the irql below DISPATCH_LEVEL,
|
||||
* a thread switch can occur and after the next thread switch
|
||||
* the execution may start on an other processor.
|
||||
*/
|
||||
if (Pcr != KeGetCurrentKPCR()) {
|
||||
|
||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
Pcr = KeGetCurrentKPCR();
|
||||
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
Pcr->PrcbData.DpcRoutineActive = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Clear DPC Flags */
|
||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
||||
Pcr->PrcbData.DpcInterruptRequested = FALSE;
|
||||
}
|
||||
/* Clear DPC Flags */
|
||||
Pcr->PrcbData.DpcRoutineActive = FALSE;
|
||||
Pcr->PrcbData.DpcInterruptRequested = FALSE;
|
||||
#ifdef CONFIG_SMP
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
|
||||
#endif
|
||||
|
||||
/* DPC Dispatching Ended, re-enable interrupts */
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
DPRINT("Checking for Quantum End\n");
|
||||
/* If we have Quantum End, call the function */
|
||||
if (Pcr->PrcbData.QuantumEnd) {
|
||||
Pcr->PrcbData.QuantumEnd = FALSE;
|
||||
KiQuantumEnd();
|
||||
}
|
||||
|
||||
/* DPC Dispatching Ended, re-enable interrupts */
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
DPRINT("Checking for Quantum End\n");
|
||||
|
||||
/* If we have Quantum End, call the function */
|
||||
if (Pcr->PrcbData.QuantumEnd) {
|
||||
|
||||
Pcr->PrcbData.QuantumEnd = FALSE;
|
||||
KiQuantumEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/error.c
|
||||
* PURPOSE: Error reason setting/getting
|
||||
*
|
||||
* PROGRAMMERS: David Welch
|
||||
*/
|
||||
|
||||
/* INCLUDE *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
BOOLEAN ExReadyForErrors = FALSE;
|
||||
PEPORT ExpDefaultErrorPort = NULL;
|
||||
PEPROCESS ExpDefaultErrorPortProcess = NULL;
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiCoprocessorError(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KiUnexpectedInterrupt(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtRaiseHardError(IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
|
||||
IN PVOID *Parameters,
|
||||
IN HARDERROR_RESPONSE_OPTION ResponseOption,
|
||||
OUT PHARDERROR_RESPONSE Response)
|
||||
{
|
||||
DPRINT1("Hard error %x\n", ErrorStatus);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
|
||||
PreviousMode))
|
||||
{
|
||||
DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
|
||||
/* serialization shouldn't be required here as it usually is just called once
|
||||
during startup */
|
||||
|
||||
if(!ExReadyForErrors)
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(PortHandle,
|
||||
0,
|
||||
LpcPortObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&ExpDefaultErrorPort,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
|
||||
ExReadyForErrors = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id:$
|
||||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -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 */
|
||||
KiWaitTest(&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;
|
||||
KiWaitTest(&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 */
|
||||
|
|
|
@ -200,7 +200,7 @@ _Ki386ContextSwitch:
|
|||
*/
|
||||
sti
|
||||
|
||||
call _KeReleaseDispatcherDatabaseLockFromDpcLevel
|
||||
call @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
|
||||
|
||||
cmpl $0, _PiNrThreadsAwaitingReaping
|
||||
je 5f
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -3,14 +3,19 @@
|
|||
* 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 +23,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");
|
||||
KiWaitTest(&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 */
|
||||
|
|
|
@ -16,245 +16,482 @@
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
||||
LONG STDCALL KiInsertQueue(IN PKQUEUE Queue, IN PLIST_ENTRY Entry, BOOLEAN Head);
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID STDCALL
|
||||
VOID
|
||||
STDCALL
|
||||
KeInitializeQueue(IN PKQUEUE Queue,
|
||||
IN ULONG Count OPTIONAL)
|
||||
IN ULONG Count OPTIONAL)
|
||||
{
|
||||
KeInitializeDispatcherHeader(&Queue->Header,
|
||||
InternalQueueType,
|
||||
sizeof(KQUEUE)/sizeof(ULONG),
|
||||
0);
|
||||
InitializeListHead(&Queue->EntryListHead);
|
||||
InitializeListHead(&Queue->ThreadListHead);
|
||||
Queue->CurrentCount = 0;
|
||||
Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
|
||||
DPRINT("KeInitializeQueue %x\n", Queue);
|
||||
|
||||
/* Initialize the Header */
|
||||
KeInitializeDispatcherHeader(&Queue->Header,
|
||||
QueueObject,
|
||||
sizeof(KQUEUE)/sizeof(ULONG),
|
||||
0);
|
||||
|
||||
/* Initialize the Lists */
|
||||
InitializeListHead(&Queue->EntryListHead);
|
||||
InitializeListHead(&Queue->ThreadListHead);
|
||||
|
||||
/* Set the Current and Maximum Count */
|
||||
Queue->CurrentCount = 0;
|
||||
Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* Returns number of entries in the queue
|
||||
*/
|
||||
LONG STDCALL
|
||||
KeReadStateQueue(IN PKQUEUE Queue)
|
||||
{
|
||||
return(Queue->Header.SignalState);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the previous number of entries in the queue
|
||||
*/
|
||||
LONG STDCALL
|
||||
KiInsertQueue(
|
||||
IN PKQUEUE Queue,
|
||||
IN PLIST_ENTRY Entry,
|
||||
BOOLEAN Head
|
||||
)
|
||||
{
|
||||
ULONG InitialState;
|
||||
|
||||
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
|
||||
|
||||
InitialState = Queue->Header.SignalState;
|
||||
|
||||
if (Head)
|
||||
{
|
||||
InsertHeadList(&Queue->EntryListHead, Entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertTailList(&Queue->EntryListHead, Entry);
|
||||
}
|
||||
|
||||
//inc. num entries in queue
|
||||
Queue->Header.SignalState++;
|
||||
|
||||
/* Why the KeGetCurrentThread()->Queue != Queue?
|
||||
* KiInsertQueue might be called from an APC for the current thread.
|
||||
* -Gunnar
|
||||
*/
|
||||
if (Queue->CurrentCount < Queue->MaximumCount &&
|
||||
!IsListEmpty(&Queue->Header.WaitListHead) &&
|
||||
KeGetCurrentThread()->Queue != Queue)
|
||||
{
|
||||
KiDispatcherObjectWake(&Queue->Header, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return InitialState;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
LONG
|
||||
STDCALL
|
||||
KeInsertHeadQueue(IN PKQUEUE Queue,
|
||||
IN PLIST_ENTRY Entry)
|
||||
IN PLIST_ENTRY Entry)
|
||||
{
|
||||
LONG Result;
|
||||
KIRQL OldIrql;
|
||||
LONG PreviousState;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("KeInsertHeadQueue %x\n", Queue);
|
||||
|
||||
/* Lock the Dispatcher Database */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Insert the Queue */
|
||||
PreviousState = KiInsertQueue(Queue, Entry, TRUE);
|
||||
|
||||
/* Release the Dispatcher Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
Result = KiInsertQueue(Queue,Entry,TRUE);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
return Result;
|
||||
/* Return previous State */
|
||||
return PreviousState;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
KeInsertQueue(IN PKQUEUE Queue,
|
||||
IN PLIST_ENTRY Entry)
|
||||
IN PLIST_ENTRY Entry)
|
||||
{
|
||||
LONG Result;
|
||||
KIRQL OldIrql;
|
||||
LONG PreviousState;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("KeInsertQueue %x\n", Queue);
|
||||
|
||||
/* Lock the Dispatcher Database */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Insert the Queue */
|
||||
PreviousState = KiInsertQueue(Queue, Entry, FALSE);
|
||||
|
||||
/* Release the Dispatcher Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
Result = KiInsertQueue(Queue,Entry,FALSE);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
return Result;
|
||||
/* Return previous State */
|
||||
return PreviousState;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* Returns number of entries in the queue
|
||||
*/
|
||||
LONG
|
||||
STDCALL
|
||||
KeReadStateQueue(IN PKQUEUE Queue)
|
||||
{
|
||||
/* Returns the Signal State */
|
||||
return(Queue->Header.SignalState);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PLIST_ENTRY STDCALL
|
||||
PLIST_ENTRY
|
||||
STDCALL
|
||||
KeRemoveQueue(IN PKQUEUE Queue,
|
||||
IN KPROCESSOR_MODE WaitMode,
|
||||
IN PLARGE_INTEGER Timeout OPTIONAL)
|
||||
IN KPROCESSOR_MODE WaitMode,
|
||||
IN PLARGE_INTEGER Timeout OPTIONAL)
|
||||
{
|
||||
|
||||
PLIST_ENTRY ListEntry;
|
||||
NTSTATUS Status;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY ListEntry;
|
||||
NTSTATUS Status;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
KIRQL OldIrql;
|
||||
PKQUEUE PreviousQueue;
|
||||
PKWAIT_BLOCK WaitBlock;
|
||||
PKWAIT_BLOCK TimerWaitBlock;
|
||||
PKTIMER Timer;
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||
DPRINT("KeRemoveQueue %x\n", Queue);
|
||||
|
||||
/* Check if the Lock is already held */
|
||||
if (Thread->WaitNext) {
|
||||
|
||||
DPRINT("Lock is already held\n");
|
||||
|
||||
} else {
|
||||
|
||||
/* Lock the Dispatcher Database */
|
||||
DPRINT("Lock not held, acquiring\n");
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
Thread->WaitIrql = OldIrql;
|
||||
}
|
||||
|
||||
if (Thread->Queue != Queue)
|
||||
{
|
||||
/*
|
||||
* INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
|
||||
* Queue->ThreadListHead when the thread registers with the queue and unlinked when
|
||||
* the thread registers with a new queue. The Thread->Queue already tells us what
|
||||
* queue the thread is registered with.
|
||||
* -Gunnar
|
||||
*/
|
||||
/* This is needed so that we can set the new queue right here, before additional processing */
|
||||
PreviousQueue = Thread->Queue;
|
||||
Thread->Queue = Queue;
|
||||
|
||||
//unregister thread from previous queue (if any)
|
||||
if (Thread->Queue)
|
||||
{
|
||||
RemoveEntryList(&Thread->QueueListEntry);
|
||||
Thread->Queue->CurrentCount--;
|
||||
|
||||
if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount &&
|
||||
!IsListEmpty(&Thread->Queue->EntryListHead))
|
||||
{
|
||||
KiDispatcherObjectWake(&Thread->Queue->Header, 0);
|
||||
}
|
||||
/* Check if this is a different queue */
|
||||
if (Queue != PreviousQueue) {
|
||||
|
||||
/*
|
||||
* INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
|
||||
* Queue->ThreadListHead when the thread registers with the queue and unlinked when
|
||||
* the thread registers with a new queue. The Thread->Queue already tells us what
|
||||
* queue the thread is registered with.
|
||||
* -Gunnar
|
||||
*/
|
||||
DPRINT("Different Queue\n");
|
||||
if (PreviousQueue) {
|
||||
|
||||
/* Remove from this list */
|
||||
DPRINT("Removing Old Queue\n");
|
||||
RemoveEntryList(&Thread->QueueListEntry);
|
||||
|
||||
/* Wake the queue */
|
||||
DPRINT("Activating new thread\n");
|
||||
KiWakeQueue(PreviousQueue);
|
||||
}
|
||||
|
||||
// register thread with this queue
|
||||
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
|
||||
Thread->Queue = Queue;
|
||||
}
|
||||
else /* if (Thread->Queue == Queue) */
|
||||
{
|
||||
//dec. num running threads
|
||||
Queue->CurrentCount--;
|
||||
}
|
||||
/* Insert in this new Queue */
|
||||
DPRINT("Inserting new Queue!\n");
|
||||
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
|
||||
|
||||
|
||||
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (Queue->CurrentCount < Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
|
||||
{
|
||||
ListEntry = RemoveHeadList(&Queue->EntryListHead);
|
||||
//dec. num entries in queue
|
||||
Queue->Header.SignalState--;
|
||||
//inc. num running threads
|
||||
Queue->CurrentCount++;
|
||||
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return ListEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
//inform KeWaitXxx that we are holding disp. lock
|
||||
Thread->WaitNext = TRUE;
|
||||
Thread->WaitIrql = OldIrql;
|
||||
} else {
|
||||
|
||||
/* Same queue, decrement waiting threads */
|
||||
DPRINT("Same Queue!\n");
|
||||
Queue->CurrentCount--;
|
||||
}
|
||||
|
||||
/* Loop until the queue is processed */
|
||||
while (TRUE) {
|
||||
|
||||
/* Get the Entry */
|
||||
ListEntry = Queue->EntryListHead.Flink;
|
||||
|
||||
/* Check if the counts are valid and if there is still a queued entry */
|
||||
if ((Queue->CurrentCount < Queue->MaximumCount) &&
|
||||
(ListEntry != &Queue->EntryListHead)) {
|
||||
|
||||
/* Remove the Entry and Save it */
|
||||
DPRINT("Removing Queue Entry. CurrentCount: %d, Maximum Count: %d\n",
|
||||
Queue->CurrentCount, Queue->MaximumCount);
|
||||
ListEntry = RemoveHeadList(&Queue->EntryListHead);
|
||||
|
||||
/* Decrease the number of entries */
|
||||
Queue->Header.SignalState--;
|
||||
|
||||
/* Increase numbef of running threads */
|
||||
Queue->CurrentCount++;
|
||||
|
||||
/* Check if the entry is valid. If not, bugcheck */
|
||||
if (!ListEntry->Flink || !ListEntry->Blink) {
|
||||
|
||||
KEBUGCHECK(INVALID_WORK_QUEUE_ITEM);
|
||||
}
|
||||
|
||||
/* Remove the Entry */
|
||||
RemoveEntryList(ListEntry);
|
||||
|
||||
/* Nothing to wait on */
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
/* Do the wait */
|
||||
DPRINT("Waiting on Queue Entry. CurrentCount: %d, Maximum Count: %d\n",
|
||||
Queue->CurrentCount, Queue->MaximumCount);
|
||||
|
||||
/* Use the Thread's Wait Block, it's big enough */
|
||||
Thread->WaitBlockList = &Thread->WaitBlock[0];
|
||||
|
||||
/* Fail if there's an APC Pending */
|
||||
if (WaitMode == UserMode && Thread->ApcState.UserApcPending) {
|
||||
|
||||
/* Return the status and increase the pending threads */
|
||||
ListEntry = (PLIST_ENTRY)STATUS_USER_APC;
|
||||
Queue->CurrentCount++;
|
||||
|
||||
/* Nothing to wait on */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Build the Wait Block */
|
||||
WaitBlock = &Thread->WaitBlock[0];
|
||||
WaitBlock->Object = (PVOID)Queue;
|
||||
WaitBlock->WaitKey = STATUS_SUCCESS;
|
||||
WaitBlock->WaitType = WaitAny;
|
||||
WaitBlock->Thread = Thread;
|
||||
WaitBlock->NextWaitBlock = NULL;
|
||||
|
||||
Thread->WaitStatus = STATUS_SUCCESS;
|
||||
|
||||
/* We need to wait for the object... check if we have a timeout */
|
||||
if (Timeout) {
|
||||
|
||||
/* If it's zero, then don't do any waiting */
|
||||
if (!Timeout->QuadPart) {
|
||||
|
||||
/* Instant Timeout, return the status and increase the pending threads */
|
||||
DPRINT("Queue Wait has timed out\n");
|
||||
ListEntry = (PLIST_ENTRY)STATUS_TIMEOUT;
|
||||
Queue->CurrentCount++;
|
||||
|
||||
/* Nothing to wait on */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the Timer. We'll use the internal function so that we can
|
||||
* hold on to the dispatcher lock.
|
||||
*/
|
||||
Timer = &Thread->Timer;
|
||||
TimerWaitBlock = &Thread->WaitBlock[1];
|
||||
|
||||
Status = KeWaitForSingleObject(Queue,
|
||||
WrQueue,
|
||||
WaitMode,
|
||||
TRUE, //bAlertable
|
||||
Timeout);
|
||||
|
||||
if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
|
||||
{
|
||||
return (PVOID)Status;
|
||||
}
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||
}
|
||||
}
|
||||
/* Set up the Timer Wait Block */
|
||||
TimerWaitBlock->Object = (PVOID)Timer;
|
||||
TimerWaitBlock->Thread = Thread;
|
||||
TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
|
||||
TimerWaitBlock->WaitType = WaitAny;
|
||||
TimerWaitBlock->NextWaitBlock = NULL;
|
||||
|
||||
/* Link the timer to this Wait Block */
|
||||
InitializeListHead(&Timer->Header.WaitListHead);
|
||||
InsertTailList(&Timer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
|
||||
|
||||
/* Create Timer */
|
||||
DPRINT("Creating Timer with timeout %I64d\n", *Timeout);
|
||||
KiInsertTimer(Timer, *Timeout);
|
||||
}
|
||||
|
||||
/* Insert the wait block into the Queues's wait list */
|
||||
WaitBlock = Thread->WaitBlockList;
|
||||
InsertTailList(&Queue->Header.WaitListHead, &WaitBlock->WaitListEntry);
|
||||
|
||||
/* Block the Thread */
|
||||
DPRINT("Blocking the Thread: %x %x!\n", KeGetCurrentThread(), Thread);
|
||||
PsBlockThread(&Status,
|
||||
FALSE,
|
||||
WaitMode,
|
||||
WrQueue);
|
||||
|
||||
/* Reset the wait reason */
|
||||
Thread->WaitReason = 0;
|
||||
|
||||
/* Check if we were executing an APC */
|
||||
if (Status != STATUS_KERNEL_APC) {
|
||||
|
||||
/* Done Waiting */
|
||||
DPRINT("Done waking queue. Thread: %x %x!\n", KeGetCurrentThread(), Thread);
|
||||
return (PLIST_ENTRY)Status;
|
||||
}
|
||||
|
||||
/* Acquire again the lock */
|
||||
DPRINT("Looping again\n");
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Save the new IRQL and decrease number of waiting threads */
|
||||
Thread->WaitIrql = OldIrql;
|
||||
Queue->CurrentCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock Database and return */
|
||||
KeReleaseDispatcherDatabaseLock(Thread->WaitIrql);
|
||||
DPRINT("Returning. CurrentCount: %d, Maximum Count: %d\n",
|
||||
Queue->CurrentCount, Queue->MaximumCount);
|
||||
return ListEntry;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PLIST_ENTRY STDCALL
|
||||
PLIST_ENTRY
|
||||
STDCALL
|
||||
KeRundownQueue(IN PKQUEUE Queue)
|
||||
{
|
||||
PLIST_ENTRY EnumEntry;
|
||||
PKTHREAD Thread;
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY EnumEntry;
|
||||
PLIST_ENTRY FirstEntry;
|
||||
PKTHREAD Thread;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
|
||||
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
|
||||
|
||||
/* I'm just guessing how this should work:-/
|
||||
* -Gunnar
|
||||
*/
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||
/* Get the Dispatcher Lock */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
//no thread must wait on queue at rundown
|
||||
ASSERT(IsListEmpty(&Queue->Header.WaitListHead));
|
||||
/* Get the First Empty Entry */
|
||||
FirstEntry = Queue->EntryListHead.Flink;
|
||||
|
||||
/* Make sure the list is not empty */
|
||||
if (FirstEntry == &Queue->EntryListHead) {
|
||||
|
||||
/* It is, so don't return anything */
|
||||
EnumEntry = NULL;
|
||||
|
||||
// unlink threads and clear their Thread->Queue
|
||||
while (!IsListEmpty(&Queue->ThreadListHead))
|
||||
{
|
||||
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
|
||||
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
|
||||
Thread->Queue = NULL;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Remove it */
|
||||
RemoveEntryList(&Queue->EntryListHead);
|
||||
}
|
||||
|
||||
/* Unlink threads and clear their Thread->Queue */
|
||||
while (!IsListEmpty(&Queue->ThreadListHead)) {
|
||||
|
||||
/* Get the Entry and Remove it */
|
||||
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
|
||||
|
||||
/* Get the Entry's Thread */
|
||||
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
|
||||
|
||||
/* Kill its Queue */
|
||||
Thread->Queue = NULL;
|
||||
}
|
||||
|
||||
if (IsListEmpty(&Queue->EntryListHead))
|
||||
{
|
||||
EnumEntry = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumEntry = Queue->EntryListHead.Flink;
|
||||
}
|
||||
/* Release the lock and return */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return FirstEntry;
|
||||
}
|
||||
|
||||
KeReleaseDispatcherDatabaseLock (OldIrql);
|
||||
/*
|
||||
* Called when a thread which has a queue entry is entering a wait state
|
||||
*/
|
||||
VOID
|
||||
FASTCALL
|
||||
KiWakeQueue(IN PKQUEUE Queue)
|
||||
{
|
||||
PLIST_ENTRY QueueEntry;
|
||||
PLIST_ENTRY WaitEntry;
|
||||
PKWAIT_BLOCK WaitBlock;
|
||||
|
||||
/* Decrement the number of active threads */
|
||||
DPRINT("KiWakeQueue: %x. Thread: %x\n", Queue, KeGetCurrentThread());
|
||||
Queue->CurrentCount--;
|
||||
|
||||
/* Make sure the counts are OK */
|
||||
if (Queue->CurrentCount < Queue->MaximumCount) {
|
||||
|
||||
/* Get the Queue Entry */
|
||||
QueueEntry = Queue->EntryListHead.Flink;
|
||||
|
||||
/* Get the Wait Entry */
|
||||
WaitEntry = Queue->Header.WaitListHead.Blink;
|
||||
DPRINT("Queue Count is ok, Queue entries: %x, %x\n", QueueEntry, WaitEntry);
|
||||
|
||||
/* Make sure that the Queue List isn't empty and that this entry is valid */
|
||||
if (!IsListEmpty(&Queue->Header.WaitListHead) &&
|
||||
(QueueEntry != &Queue->EntryListHead)) {
|
||||
|
||||
/* Remove this entry */
|
||||
DPRINT("Queue in List, removing it\n");
|
||||
RemoveEntryList(QueueEntry);
|
||||
QueueEntry->Flink = NULL;
|
||||
|
||||
/* Decrease the Signal State */
|
||||
Queue->Header.SignalState--;
|
||||
|
||||
/* Unwait the Thread */
|
||||
DPRINT("Unwaiting Thread\n");
|
||||
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
|
||||
KiAbortWaitThread(WaitBlock->Thread, (NTSTATUS)QueueEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EnumEntry;
|
||||
/*
|
||||
* Returns the previous number of entries in the queue
|
||||
*/
|
||||
LONG
|
||||
STDCALL
|
||||
KiInsertQueue(IN PKQUEUE Queue,
|
||||
IN PLIST_ENTRY Entry,
|
||||
BOOLEAN Head)
|
||||
{
|
||||
ULONG InitialState;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
PKWAIT_BLOCK WaitBlock;
|
||||
PLIST_ENTRY WaitEntry;
|
||||
|
||||
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
|
||||
|
||||
/* Save the old state */
|
||||
InitialState = Queue->Header.SignalState;
|
||||
|
||||
/* Get the Entry */
|
||||
WaitEntry = Queue->Header.WaitListHead.Blink;
|
||||
DPRINT("Initial State, WaitEntry: %d, %x\n", InitialState, WaitEntry);
|
||||
|
||||
/*
|
||||
* Why the KeGetCurrentThread()->Queue != Queue?
|
||||
* KiInsertQueue might be called from an APC for the current thread.
|
||||
* -Gunnar
|
||||
*/
|
||||
if ((Queue->CurrentCount < Queue->MaximumCount) &&
|
||||
(WaitEntry != &Queue->Header.WaitListHead) &&
|
||||
((Thread->Queue != Queue) || (Thread->WaitReason != WrQueue))) {
|
||||
|
||||
/* Remove the wait entry */
|
||||
DPRINT("Removing Entry\n");
|
||||
RemoveEntryList(WaitEntry);
|
||||
|
||||
/* Get the Wait Block and Thread */
|
||||
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
|
||||
DPRINT("Got wait block: %x\n", WaitBlock);
|
||||
Thread = WaitBlock->Thread;
|
||||
|
||||
/* Reset the wait reason */
|
||||
Thread->WaitReason = 0;
|
||||
|
||||
/* Increase the waiting threads */
|
||||
Queue->CurrentCount++;
|
||||
|
||||
/* Check if there's a Thread Timer */
|
||||
if (Thread->Timer.Header.Inserted) {
|
||||
|
||||
/* Cancel the Thread Timer with the no-lock fastpath */
|
||||
DPRINT("Removing the Thread's Timer\n");
|
||||
Thread->Timer.Header.Inserted = FALSE;
|
||||
RemoveEntryList(&Thread->Timer.TimerListEntry);
|
||||
}
|
||||
|
||||
/* Reschedule the Thread */
|
||||
DPRINT("Unblocking the Thread\n");
|
||||
PsUnblockThread((PETHREAD)Thread, (PNTSTATUS)&Entry, 0);
|
||||
|
||||
} else {
|
||||
|
||||
/* Increase the Entries */
|
||||
DPRINT("Adding new Queue Entry: %d %d\n", Head, Queue->Header.SignalState);
|
||||
Queue->Header.SignalState++;
|
||||
|
||||
if (Head) {
|
||||
|
||||
InsertHeadList(&Queue->EntryListHead, Entry);
|
||||
|
||||
} else {
|
||||
|
||||
InsertTailList(&Queue->EntryListHead, Entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the previous state */
|
||||
DPRINT("Returning\n");
|
||||
return InitialState;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -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 */
|
||||
KiWaitTest(&Semaphore->Header, SEMAPHORE_INCREMENT);
|
||||
}
|
||||
|
||||
if (Wait == FALSE)
|
||||
{
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
KTHREAD *Thread = KeGetCurrentThread();
|
||||
Thread->WaitNext = TRUE;
|
||||
Thread->WaitIrql = OldIrql;
|
||||
/* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
|
||||
if (Wait == FALSE) {
|
||||
|
||||
/* Release the Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
} else {
|
||||
|
||||
/* Set a wait */
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
CurrentThread->WaitNext = TRUE;
|
||||
CurrentThread->WaitIrql = OldIrql;
|
||||
}
|
||||
|
||||
return(InitialState);
|
||||
/* Return the previous state */
|
||||
return InitialState;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -107,12 +107,11 @@ KeInitializeTimerEx (PKTIMER Timer,
|
|||
|
||||
/* Initialize the Dispatch Header */
|
||||
KeInitializeDispatcherHeader(&Timer->Header,
|
||||
InternalNotificationTimer + Type,
|
||||
TimerNotificationObject + Type,
|
||||
sizeof(KTIMER) / sizeof(ULONG),
|
||||
FALSE);
|
||||
|
||||
/* Initalize the List Head and other data */
|
||||
InitializeListHead(&Timer->Header.WaitListHead);
|
||||
/* Initalize the Other data */
|
||||
Timer->DueTime.QuadPart = 0;
|
||||
Timer->Period = 0;
|
||||
}
|
||||
|
@ -196,7 +195,6 @@ KeSetTimerEx (PKTIMER Timer,
|
|||
Timer->Dpc = Dpc;
|
||||
Timer->Period = Period;
|
||||
Timer->Header.SignalState = FALSE;
|
||||
Timer->Header.Absolute = FALSE;
|
||||
|
||||
/* Insert it */
|
||||
if (!KiInsertTimer(Timer, DueTime)) {
|
||||
|
@ -296,7 +294,7 @@ KiHandleExpiredTimer(PKTIMER Timer)
|
|||
/* Set it as Signaled */
|
||||
DPRINT("Setting Timer as Signaled\n");
|
||||
Timer->Header.SignalState = TRUE;
|
||||
KiDispatcherObjectWake(&Timer->Header, 0);
|
||||
KiWaitTest(&Timer->Header, 0);
|
||||
|
||||
/* If the Timer is periodic, reinsert the timer with the new due time */
|
||||
if (Timer->Period) {
|
||||
|
@ -306,7 +304,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");
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -338,8 +336,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) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -122,7 +122,6 @@ ExIsResourceAcquiredExclusiveLite@4
|
|||
ExIsResourceAcquiredSharedLite@4
|
||||
ExLocalTimeToSystemTime@8
|
||||
ExNotifyCallback@12
|
||||
ExPostSystemEvent@12
|
||||
ExQueryPoolBlockSize@8
|
||||
ExQueueWorkItem@8
|
||||
ExRaiseAccessViolation@0
|
||||
|
@ -530,7 +529,7 @@ Ke386IoSetAccessProcess@8
|
|||
Ke386QueryIoAccessMap@8
|
||||
Ke386SetIoAccessMap@8
|
||||
KeAcquireSpinLockAtDpcLevel@4
|
||||
KeAcquireDispatcherDatabaseLockAtDpcLevel
|
||||
@KeAcquireDispatcherDatabaseLockAtDpcLevel@0
|
||||
@KeAcquireInStackQueuedSpinLockAtDpcLevel@8
|
||||
KeAcquireInterruptSpinLock@4
|
||||
KeAddSystemServiceTable@20
|
||||
|
@ -611,7 +610,7 @@ KeReadStateSemaphore@4
|
|||
KeReadStateTimer@4
|
||||
KeRegisterBugCheckCallback@20
|
||||
KeRegisterBugCheckReasonCallback@16
|
||||
KeReleaseDispatcherDatabaseLockFromDpcLevel
|
||||
@KeReleaseDispatcherDatabaseLockFromDpcLevel@0
|
||||
@KeReleaseInStackQueuedSpinLockFromDpcLevel@4
|
||||
KeReleaseInterruptSpinLock@8
|
||||
KeReleaseMutant@16
|
||||
|
|
|
@ -987,6 +987,22 @@ Language=English
|
|||
INVALID_WORK_QUEUE_ITEM
|
||||
.
|
||||
|
||||
MessageId=0xE1
|
||||
Severity=Success
|
||||
Facility=System
|
||||
SymbolicName=WORKER_THREAD_RETURNED_AT_BAD_IRQL
|
||||
Language=English
|
||||
WORKER_THREAD_RETURNED_AT_BAD_IRQL
|
||||
.
|
||||
|
||||
MessageId=0xFA
|
||||
Severity=Success
|
||||
Facility=System
|
||||
SymbolicName=IMPERSONATING_WORKER_THREAD
|
||||
Language=English
|
||||
IMPERSONATING_WORKER_THREAD
|
||||
.
|
||||
|
||||
MessageId=0x9A
|
||||
Severity=Informational
|
||||
Facility=System
|
||||
|
|
300
reactos/ntoskrnl/ob/wait.c
Normal file
300
reactos/ntoskrnl/ob/wait.c
Normal file
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ob/wait.c
|
||||
* PURPOSE: Handles Waiting on Objects
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created file
|
||||
* David Welch (welch@mcmail.com)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
BOOL inline FASTCALL KiIsObjectWaitable(PVOID Object);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtWaitForMultipleObjects(IN ULONG ObjectCount,
|
||||
IN PHANDLE ObjectsArray,
|
||||
IN WAIT_TYPE WaitType,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
{
|
||||
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
|
||||
HANDLE SafeObjectsArray[MAXIMUM_WAIT_OBJECTS];
|
||||
PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
|
||||
ULONG i, j;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
|
||||
"TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
if (0 == ObjectCount)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if(PreviousMode != KernelMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForRead(ObjectsArray,
|
||||
ObjectCount * sizeof(ObjectsArray[0]),
|
||||
sizeof(ULONG));
|
||||
/* make a copy so we don't have to guard with SEH later and keep track of
|
||||
what objects we referenced in case dereferencing pointers suddenly fails */
|
||||
RtlCopyMemory(SafeObjectsArray, ObjectsArray, ObjectCount * sizeof(ObjectsArray[0]));
|
||||
ObjectsArray = SafeObjectsArray;
|
||||
|
||||
if(TimeOut != NULL)
|
||||
{
|
||||
ProbeForRead(TimeOut,
|
||||
sizeof(LARGE_INTEGER),
|
||||
sizeof(ULONG));
|
||||
/* make a local copy of the timeout on the stack */
|
||||
SafeTimeOut = *TimeOut;
|
||||
TimeOut = &SafeTimeOut;
|
||||
}
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* reference all objects */
|
||||
for (i = 0; i < ObjectCount; i++)
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(ObjectsArray[i],
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
&ObjectPtrArray[i],
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i]))
|
||||
{
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Waiting for object type '%wZ' is not supported\n",
|
||||
&BODY_TO_HEADER(ObjectPtrArray[i])->ObjectType->TypeName);
|
||||
Status = STATUS_HANDLE_NOT_WAITABLE;
|
||||
i++;
|
||||
}
|
||||
/* dereference all referenced objects */
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
ObDereferenceObject(ObjectPtrArray[j]);
|
||||
}
|
||||
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
|
||||
Status = KeWaitForMultipleObjects(ObjectCount,
|
||||
ObjectPtrArray,
|
||||
WaitType,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
TimeOut,
|
||||
WaitBlockArray);
|
||||
|
||||
/* dereference all objects */
|
||||
for (i = 0; i < ObjectCount; i++)
|
||||
{
|
||||
ObDereferenceObject(ObjectPtrArray[i]);
|
||||
}
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtWaitForSingleObject(IN HANDLE ObjectHandle,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
{
|
||||
PVOID ObjectPtr;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
|
||||
ObjectHandle,Alertable,TimeOut);
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(TimeOut != NULL && PreviousMode != KernelMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForRead(TimeOut,
|
||||
sizeof(LARGE_INTEGER),
|
||||
sizeof(ULONG));
|
||||
/* make a copy on the stack */
|
||||
SafeTimeOut = *TimeOut;
|
||||
TimeOut = &SafeTimeOut;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(ObjectHandle,
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
&ObjectPtr,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
if (!KiIsObjectWaitable(ObjectPtr))
|
||||
{
|
||||
DPRINT1("Waiting for object type '%wZ' is not supported\n",
|
||||
&BODY_TO_HEADER(ObjectPtr)->ObjectType->TypeName);
|
||||
Status = STATUS_HANDLE_NOT_WAITABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = KeWaitForSingleObject(ObjectPtr,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
TimeOut);
|
||||
}
|
||||
|
||||
ObDereferenceObject(ObjectPtr);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
|
||||
IN HANDLE WaitableObjectHandle,
|
||||
IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER TimeOut OPTIONAL)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
DISPATCHER_HEADER* hdr;
|
||||
PVOID SignalObj;
|
||||
PVOID WaitObj;
|
||||
LARGE_INTEGER SafeTimeOut;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if(TimeOut != NULL && PreviousMode != KernelMode)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForRead(TimeOut,
|
||||
sizeof(LARGE_INTEGER),
|
||||
sizeof(ULONG));
|
||||
/* make a copy on the stack */
|
||||
SafeTimeOut = *TimeOut;
|
||||
TimeOut = &SafeTimeOut;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
|
||||
0,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
&SignalObj,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(WaitableObjectHandle,
|
||||
SYNCHRONIZE,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
&WaitObj,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ObDereferenceObject(SignalObj);
|
||||
return Status;
|
||||
}
|
||||
|
||||
hdr = (DISPATCHER_HEADER *)SignalObj;
|
||||
switch (hdr->Type)
|
||||
{
|
||||
case EventNotificationObject:
|
||||
case EventSynchronizationObject:
|
||||
KeSetEvent(SignalObj,
|
||||
EVENT_INCREMENT,
|
||||
TRUE);
|
||||
break;
|
||||
|
||||
case MutantObject:
|
||||
KeReleaseMutex(SignalObj,
|
||||
TRUE);
|
||||
break;
|
||||
|
||||
case SemaphoreObject:
|
||||
KeReleaseSemaphore(SignalObj,
|
||||
SEMAPHORE_INCREMENT,
|
||||
1,
|
||||
TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
ObDereferenceObject(SignalObj);
|
||||
ObDereferenceObject(WaitObj);
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
Status = KeWaitForSingleObject(WaitObj,
|
||||
UserRequest,
|
||||
PreviousMode,
|
||||
Alertable,
|
||||
TimeOut);
|
||||
|
||||
ObDereferenceObject(SignalObj);
|
||||
ObDereferenceObject(WaitObj);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -204,7 +204,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
|
|||
|
||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
|
||||
KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
|
||||
KiWaitTest(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
|
||||
KeReleaseDispatcherDatabaseLock (oldIrql);
|
||||
|
||||
/* The last thread shall close the door on exit */
|
||||
|
@ -331,7 +331,7 @@ PiTerminateProcess(PEPROCESS Process,
|
|||
}
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||
Process->Pcb.DispatcherHeader.SignalState = TRUE;
|
||||
KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
|
||||
KiWaitTest(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
|
||||
KeReleaseDispatcherDatabaseLock (OldIrql);
|
||||
ObDereferenceObject(Process);
|
||||
return(STATUS_SUCCESS);
|
||||
|
|
|
@ -374,7 +374,7 @@ PsInitProcessManagment(VOID)
|
|||
PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
|
||||
InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
|
||||
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
|
||||
InternalProcessType,
|
||||
ProcessObject,
|
||||
sizeof(EPROCESS),
|
||||
FALSE);
|
||||
KProcess = &PsInitialSystemProcess->Pcb;
|
||||
|
@ -823,7 +823,7 @@ exitdereferenceobjects:
|
|||
}
|
||||
|
||||
KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
|
||||
InternalProcessType,
|
||||
ProcessObject,
|
||||
sizeof(EPROCESS),
|
||||
FALSE);
|
||||
|
||||
|
|
|
@ -437,6 +437,7 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
|
|||
|
||||
OldThread = CurrentThread;
|
||||
CurrentThread = Candidate;
|
||||
|
||||
IdleThread = KeGetCurrentKPCR()->PrcbData.IdleThread;
|
||||
|
||||
if (&OldThread->Tcb == IdleThread)
|
||||
|
@ -545,49 +546,46 @@ PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment)
|
|||
}
|
||||
|
||||
VOID
|
||||
PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
|
||||
BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason)
|
||||
STDCALL
|
||||
PsBlockThread(PNTSTATUS Status,
|
||||
UCHAR Alertable,
|
||||
ULONG WaitMode,
|
||||
UCHAR WaitReason)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PKTHREAD KThread;
|
||||
PETHREAD Thread;
|
||||
PKWAIT_BLOCK WaitBlock;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
PKWAIT_BLOCK WaitBlock;
|
||||
|
||||
if (!DispatcherLock)
|
||||
{
|
||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
if (Thread->ApcState.KernelApcPending) {
|
||||
|
||||
DPRINT("Dispatching Thread as ready (APC!)\n");
|
||||
|
||||
/* Remove Waits */
|
||||
WaitBlock = Thread->WaitBlockList;
|
||||
while (WaitBlock) {
|
||||
RemoveEntryList (&WaitBlock->WaitListEntry);
|
||||
WaitBlock = WaitBlock->NextWaitBlock;
|
||||
}
|
||||
Thread->WaitBlockList = NULL;
|
||||
|
||||
/* Dispatch it and return status */
|
||||
PsDispatchThreadNoLock (THREAD_STATE_READY);
|
||||
if (Status != NULL) *Status = STATUS_KERNEL_APC;
|
||||
|
||||
} else {
|
||||
|
||||
/* Set the Thread Data as Requested */
|
||||
DPRINT("Dispatching Thread as blocked\n");
|
||||
Thread->Alertable = Alertable;
|
||||
Thread->WaitMode = (UCHAR)WaitMode;
|
||||
Thread->WaitReason = WaitReason;
|
||||
|
||||
/* Dispatch it and return status */
|
||||
PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
|
||||
if (Status != NULL) *Status = Thread->WaitStatus;
|
||||
}
|
||||
|
||||
KThread = KeGetCurrentThread();
|
||||
Thread = CONTAINING_RECORD (KThread, ETHREAD, Tcb);
|
||||
if (KThread->ApcState.KernelApcPending)
|
||||
{
|
||||
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
|
||||
while (WaitBlock)
|
||||
{
|
||||
RemoveEntryList (&WaitBlock->WaitListEntry);
|
||||
WaitBlock = WaitBlock->NextWaitBlock;
|
||||
}
|
||||
Thread->Tcb.WaitBlockList = NULL;
|
||||
PsDispatchThreadNoLock (THREAD_STATE_READY);
|
||||
if (Status != NULL)
|
||||
{
|
||||
*Status = STATUS_KERNEL_APC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread->Tcb.Alertable = Alertable;
|
||||
Thread->Tcb.WaitMode = (UCHAR)WaitMode;
|
||||
Thread->Tcb.WaitReason = WaitReason;
|
||||
PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
|
||||
|
||||
if (Status != NULL)
|
||||
{
|
||||
*Status = Thread->Tcb.WaitStatus;
|
||||
}
|
||||
}
|
||||
KeLowerIrql(WaitIrql);
|
||||
|
||||
DPRINT("Releasing Dispatcher Lock\n");
|
||||
KfLowerIrql(Thread->WaitIrql);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -1054,6 +1052,16 @@ NtYieldExecution(VOID)
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOT EXPORTED
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtTestAlert(VOID)
|
||||
{
|
||||
/* Check and Alert Thread if needed */
|
||||
return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
|
|
|
@ -36,7 +36,32 @@ ULONG NlsUnicodeTableOffset = 0;
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
STDCALL
|
||||
RtlpInitNls(VOID)
|
||||
{
|
||||
ULONG_PTR BaseAddress;
|
||||
|
||||
/* Import NLS Data */
|
||||
BaseAddress = CachedModules[AnsiCodepage]->ModStart;
|
||||
RtlpImportAnsiCodePage((PUSHORT)BaseAddress,
|
||||
CachedModules[AnsiCodepage]->ModEnd - BaseAddress);
|
||||
|
||||
BaseAddress = CachedModules[OemCodepage]->ModStart;
|
||||
RtlpImportOemCodePage((PUSHORT)BaseAddress,
|
||||
CachedModules[OemCodepage]->ModEnd - BaseAddress);
|
||||
|
||||
BaseAddress = CachedModules[UnicodeCasemap]->ModStart;
|
||||
RtlpImportUnicodeCasemap((PUSHORT)BaseAddress,
|
||||
CachedModules[UnicodeCasemap]->ModEnd - BaseAddress);
|
||||
|
||||
/* Create initial NLS tables */
|
||||
RtlpCreateInitialNlsTables();
|
||||
|
||||
/* Create the NLS section */
|
||||
RtlpCreateNlsSection();
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
RtlpImportAnsiCodePage(PUSHORT TableBase,
|
||||
|
|
|
@ -180,7 +180,6 @@ NtSetEaFile 4
|
|||
NtSetEvent 2
|
||||
NtSetHighEventPair 1
|
||||
NtSetHighWaitLowEventPair 1
|
||||
NtSetHighWaitLowThread 0
|
||||
NtSetInformationFile 5
|
||||
NtSetInformationKey 4
|
||||
NtSetInformationJobObject 4
|
||||
|
@ -192,7 +191,6 @@ NtSetIntervalProfile 2
|
|||
NtSetLdtEntries 6
|
||||
NtSetLowEventPair 1
|
||||
NtSetLowWaitHighEventPair 1
|
||||
NtSetLowWaitHighThread 0
|
||||
NtSetQuotaInformationFile 4
|
||||
NtSetSecurityObject 3
|
||||
NtSetSystemEnvironmentValue 2
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue