# be optimze for.
#
-OARCH := pentium2
+OARCH := i486
#
# Whether to compile in the kernel debugger
#
# Whether to compile with optimizations
#
-OPTIMIZED := 1
+OPTIMIZED := 0
#
# Whether to compile a multiprocessor or single processor version
/* Queue thread management */
static KEVENT QueueThreadTerminate;
-static PVOID QueueThreadObject;
+static PVOID ThreadObject;
\f
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
KdPrint(("floppy: unloading\n"));
KeSetEvent(&QueueThreadTerminate, 0, FALSE);
- KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0);
- ObDereferenceObject(QueueThreadObject);
+ KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0);
+ ObDereferenceObject(ThreadObject);
for(i = 0; i < gNumberOfControllers; i++)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
- if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
+ if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ThreadObject, NULL) != STATUS_SUCCESS)
{
KdPrint(("floppy: Unable to reference returned thread handle; failing init\n"));
return STATUS_UNSUCCESSFUL;
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
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 */
#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
struct _DISPATCHER_HEADER;
-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;
+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;
#include <pshpack1.h>
typedef struct _MUTANT_BASIC_INFORMATION
{
- LONG CurrentCount;
- BOOLEAN OwnedByCaller;
- BOOLEAN AbandonedState;
+ LONG Count;
+ BOOLEAN Owned;
+ BOOLEAN Abandoned;
} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
NtSetEvent@8
NtSetHighEventPair@4
NtSetHighWaitLowEventPair@4
+NtSetHighWaitLowThread@0
NtSetInformationFile@20
NtSetInformationJobObject@16
NtSetInformationKey@16
NtSetLdtEntries@24
NtSetLowEventPair@4
NtSetLowWaitHighEventPair@4
+NtSetLowWaitHighThread@0
NtSetSecurityObject@12
NtSetSystemEnvironmentValue@8
NtSetSystemInformation@12
ZwSetEvent@8
ZwSetHighEventPair@4
ZwSetHighWaitLowEventPair@4
+ZwSetHighWaitLowThread@0
ZwSetInformationFile@20
ZwSetInformationKey@16
ZwSetInformationObject@16
ZwSetLdtEntries@24
ZwSetLowEventPair@4
ZwSetLowWaitHighEventPair@4
+ZwSetLowWaitHighThread@0
ZwSetSecurityObject@12
ZwSetSystemEnvironmentValue@8
ZwSetSystemInformation@12
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 \
ke/spinlock.o \
ke/timer.o \
ke/wait.o \
+ ke/alert.o
# Memory Manager (Mm)
OBJECTS_MM = \
ob/object.o \
ob/sdcache.o \
ob/security.o \
- ob/symlink.o \
- ob/wait.o
+ ob/symlink.o
# Process Manager (Ps)
OBJECTS_PS = \
OBJECTS_EX = \
ex/btree.o \
ex/callback.o \
- ex/error.o \
ex/event.o \
ex/evtpair.o \
ex/fmutex.o \
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)
+++ /dev/null
-/*
- * 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 */
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};
-
-static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
-
- /* EventBasicInformation */
- ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
+ 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 */
};
/* FUNCTIONS *****************************************************************/
-VOID
-INIT_FUNCTION
+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
ExpInitializeEventImplementation(VOID)
{
- /* 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);
+ 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);
}
+
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtClearEvent(IN HANDLE EventHandle)
{
- PKEVENT Event;
- NTSTATUS Status;
-
- PAGED_CODE();
+ PKEVENT Event;
+ NTSTATUS Status;
- /* Reference the Object */
- Status = ObReferenceObjectByHandle(EventHandle,
- EVENT_MODIFY_STATE,
- ExEventObjectType,
- ExGetPreviousMode(),
- (PVOID*)&Event,
- NULL);
+ PAGED_CODE();
- /* Check for Success */
- if(NT_SUCCESS(Status)) {
-
- /* Clear the Event and Dereference */
- KeClearEvent(Event);
- ObDereferenceObject(Event);
- }
+ Status = ObReferenceObjectByHandle(EventHandle,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ ExGetPreviousMode(),
+ (PVOID*)&Event,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ KeClearEvent(Event);
+ ObDereferenceObject(Event);
+ }
- /* Return Status */
- return Status;
+ return Status;
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtCreateEvent(OUT PHANDLE EventHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
- IN EVENT_TYPE EventType,
- IN BOOLEAN InitialState)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN EVENT_TYPE EventType,
+ IN BOOLEAN InitialState)
{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- PKEVENT Event;
- HANDLE hEvent;
- NTSTATUS Status = STATUS_SUCCESS;
+ KPROCESSOR_MODE PreviousMode;
+ PKEVENT Event;
+ HANDLE hEvent;
+ NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE();
+ PAGED_CODE();
- /* Check Output Safety */
- if(PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(EventHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ 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;
- }
-
- /* 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);
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
- /* 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;
+ 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
+NTSTATUS STDCALL
NtOpenEvent(OUT PHANDLE EventHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- HANDLE hEvent;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ HANDLE hEvent;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
+ 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;
- }
-
- /* Open the Object */
- Status = ObOpenObjectByName(ObjectAttributes,
- ExEventObjectType,
- NULL,
- PreviousMode,
- DesiredAccess,
- NULL,
- &hEvent);
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ 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;
- }
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *EventHandle = hEvent;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
- /* Return status */
- return Status;
+ return Status;
}
+
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtPulseEvent(IN HANDLE EventHandle,
- OUT PLONG PreviousState OPTIONAL)
+ OUT PLONG PreviousState OPTIONAL)
{
- PKEVENT Event;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ PKEVENT Event;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
+ PAGED_CODE();
- 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);
+ 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;
- /* Return it */
- if(PreviousState) {
-
- _SEH_TRY {
-
- *PreviousState = Prev;
-
- } _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 */
return Status;
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtQueryEvent(IN HANDLE EventHandle,
- IN EVENT_INFORMATION_CLASS EventInformationClass,
- OUT PVOID EventInformation,
- IN ULONG EventInformationLength,
- OUT PULONG ReturnLength OPTIONAL)
+ 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;
- }
+ PKEVENT Event;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
- /* 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);
+ 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 */
return Status;
}
+
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtResetEvent(IN HANDLE EventHandle,
- OUT PLONG PreviousState OPTIONAL)
+ OUT PLONG PreviousState OPTIONAL)
{
- PKEVENT Event;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ PKEVENT Event;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
- }
+ 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;
+ }
+ }
- /* 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);
+ Status = ObReferenceObjectByHandle(EventHandle,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ PreviousMode,
+ (PVOID*)&Event,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ LONG Prev = KeResetEvent(Event);
+ ObDereferenceObject(Event);
- /* Return it */
- if(PreviousState) {
-
- _SEH_TRY {
-
- *PreviousState = Prev;
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
- }
+ if(PreviousState != NULL)
+ {
+ _SEH_TRY
+ {
+ *PreviousState = Prev;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
}
- /* Return Status */
return Status;
}
+
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtSetEvent(IN HANDLE EventHandle,
- OUT PLONG PreviousState OPTIONAL)
+ OUT PLONG PreviousState OPTIONAL)
{
- PKEVENT Event;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ PKEVENT Event;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
- }
+ 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;
+ }
+ }
- /* 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;
- }
+ 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 */
return Status;
}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+NtTraceEvent(
+ IN ULONG TraceHandle,
+ IN ULONG Flags,
+ IN ULONG TraceHeaderLength,
+ IN struct _EVENT_TRACE_HEADER* TraceHeader
+ )
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
/* EOF */
-/*
+/* $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: Alex Ionescu (Commented, reorganized, removed Thread Pair, used KeInitializeEventPair, added SEH)
- * David Welch (welch@mcmail.com)
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
* Skywing (skywing@valhallalegends.com)
*/
#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 *****************************************************************/
-VOID
-INIT_FUNCTION
+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
ExpInitializeEventPairImplementation(VOID)
{
- /* 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);
+ 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);
}
-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 = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT1("NtCreateEventPair: %x\n", EventPairHandle);
+ PKEVENT_PAIR EventPair;
+ HANDLE hEventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
- /* Check Output Safety */
- if(PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(EventPairHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode == UserMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(EventPairHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- 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;
- }
- }
-
- /* Return Status */
- return Status;
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ 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;
}
-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 = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ HANDLE hEventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
- /* Check Output Safety */
- if(PreviousMode == UserMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(EventPairHandle,
- sizeof(HANDLE),
- sizeof(ULONG));
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode == UserMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(EventPairHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+ }
+ _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;
- }
+ 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;
+ }
- /* Return status */
- return Status;
+ return Status;
}
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtSetHighEventPair(IN HANDLE EventPairHandle)
{
- PKEVENT_PAIR EventPair;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status;
+ PKEVENT_PAIR EventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
+ EventPairHandle);
- DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
+ PreviousMode = ExGetPreviousMode();
- /* 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);
-
- /* Dereference Object */
- ObDereferenceObject(EventPair);
- }
+ Status = ObReferenceObjectByHandle(EventPairHandle,
+ SYNCHRONIZE,
+ ExEventPairObjectType,
+ PreviousMode,
+ (PVOID*)&EventPair,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ KeSetEvent(&EventPair->HighEvent,
+ EVENT_INCREMENT,
+ FALSE);
+
+ ObDereferenceObject(EventPair);
+ }
- /* Return status */
- return Status;
+ return Status;
}
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
{
- PKEVENT_PAIR EventPair;
- KPROCESSOR_MODE PreviousMode = 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);
- }
+ PKEVENT_PAIR EventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
- /* Return status */
- return Status;
+ 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;
}
-NTSTATUS
-STDCALL
+
+NTSTATUS STDCALL
NtSetLowEventPair(IN HANDLE EventPairHandle)
{
- PKEVENT_PAIR EventPair;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status;
+ PKEVENT_PAIR EventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+
+ PAGED_CODE();
- DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
+ DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
+ EventPairHandle);
+
+ PreviousMode = ExGetPreviousMode();
- /* 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);
-
- /* Dereference Object */
- ObDereferenceObject(EventPair);
- }
-
- /* Return status */
- return Status;
+ Status = ObReferenceObjectByHandle(EventPairHandle,
+ SYNCHRONIZE,
+ ExEventPairObjectType,
+ PreviousMode,
+ (PVOID*)&EventPair,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ KeSetEvent(&EventPair->LowEvent,
+ EVENT_INCREMENT,
+ FALSE);
+
+ ObDereferenceObject(EventPair);
+ }
+
+ return Status;
}
NTSTATUS STDCALL
NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
{
- 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);
- }
+ PKEVENT_PAIR EventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
+ EventPairHandle);
+
+ PreviousMode = ExGetPreviousMode();
- /* Return status */
- return Status;
+ 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;
}
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtWaitLowEventPair(IN HANDLE EventPairHandle)
{
- 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->LowEvent,
- WrEventPair,
- PreviousMode,
- FALSE,
- NULL);
-
- /* Dereference Object */
- ObDereferenceObject(EventPair);
- }
+ PKEVENT_PAIR EventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
+ EventPairHandle);
+
+ PreviousMode = ExGetPreviousMode();
- /* Return status */
- return Status;
+ Status = ObReferenceObjectByHandle(EventPairHandle,
+ SYNCHRONIZE,
+ ExEventPairObjectType,
+ PreviousMode,
+ (PVOID*)&EventPair,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ KeWaitForSingleObject(&EventPair->LowEvent,
+ WrEventPair,
+ PreviousMode,
+ FALSE,
+ NULL);
+
+ ObDereferenceObject(EventPair);
+ }
+
+ return Status;
}
-NTSTATUS
-STDCALL
+
+NTSTATUS STDCALL
NtWaitHighEventPair(IN HANDLE EventPairHandle)
{
- 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);
- }
+ PKEVENT_PAIR EventPair;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
+ EventPairHandle);
+
+ PreviousMode = ExGetPreviousMode();
- /* Return status */
- return Status;
+ Status = ObReferenceObjectByHandle(EventPairHandle,
+ SYNCHRONIZE,
+ ExEventPairObjectType,
+ PreviousMode,
+ (PVOID*)&EventPair,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ KeWaitForSingleObject(&EventPair->HighEvent,
+ WrEventPair,
+ PreviousMode,
+ FALSE,
+ NULL);
+
+ ObDereferenceObject(EventPair);
+ }
+
+ 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 */
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/init.c
* PURPOSE: Executive initalization
*
- * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
- * and optimized/cleaned it.
- * Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * PROGRAMMERS: 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)
{
VOID INIT_FUNCTION
ExInit3 (VOID)
{
- ExpInitializeWorkerThreads();
+ ExInitializeWorkerThreads();
ExpInitializeEventImplementation();
ExpInitializeEventPairImplementation();
ExpInitializeMutantImplementation();
ExpInitializeProfileImplementation();
ExpWin32kInit();
ExpInitUuids();
- ExpInitializeCallbacks();
+}
+
+
+/*
+ * @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 */
}
/* EOF */
-/*
+/* $Id:$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/mutant.c
- * PURPOSE: Executive Management of Mutants
+ * PURPOSE: Synchronization primitives
*
- * PROGRAMMERS:
- * Alex Ionescu - Fix tab/space mismatching, tiny fixes to query function and
- * add more debug output.
- * David Welch (welch@cwcom.net)
+ * PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
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[] = {
-
- /* MutantBasicInformation */
- ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+static const INFORMATION_CLASS_INFO ExMutantInfoClass[] =
+{
+ ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* MutantBasicInformation */
};
/* FUNCTIONS *****************************************************************/
-VOID
-STDCALL
-ExpDeleteMutant(PVOID ObjectBody)
+
+NTSTATUS STDCALL
+ExpCreateMutant(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ POBJECT_ATTRIBUTES ObjectAttributes)
{
+ DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+ ObjectBody, Parent, RemainingPath);
- DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody);
+ if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
+ {
+ return(STATUS_UNSUCCESSFUL);
+ }
- /* Make sure to release the Mutant */
- KeReleaseMutant((PKMUTANT)ObjectBody,
- MUTANT_INCREMENT,
- TRUE,
- FALSE);
+ return(STATUS_SUCCESS);
}
-VOID
-INIT_FUNCTION
-ExpInitializeMutantImplementation(VOID)
+
+VOID STDCALL
+ExpDeleteMutant(PVOID ObjectBody)
{
+ DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
- /* Allocate the Object Type */
- ExMutantObjectType = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), TAG('M', 't', 'n', 't'));
-
- /* 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);
+ KeReleaseMutant((PKMUTANT)ObjectBody,
+ MUTANT_INCREMENT,
+ TRUE,
+ FALSE);
}
+
+VOID INIT_FUNCTION
+ExpInitializeMutantImplementation(VOID)
+{
+ ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(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 = ExpCreateMutant;
+ 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 = ExGetPreviousMode();
- HANDLE hMutant;
- PKMUTANT Mutant;
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("NtCreateMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
+ KPROCESSOR_MODE PreviousMode;
+ HANDLE hMutant;
+ PKMUTEX Mutant;
+ NTSTATUS Status = STATUS_SUCCESS;
- /* 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;
+ 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);
- /* 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);
-
- /* 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;
- }
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *MutantHandle = hMutant;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
+ }
- /* Return Status */
- return Status;
+ return Status;
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtOpenMutant(OUT PHANDLE MutantHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- HANDLE hMutant;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ HANDLE hMutant;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE();
+ PAGED_CODE();
- DPRINT("NtOpenMutant(0x%x, 0x%x, 0x%x)\n", MutantHandle, DesiredAccess, ObjectAttributes);
-
- /* 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;
+ 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));
}
-
- /* Open the Object */
- Status = ObOpenObjectByName(ObjectAttributes,
- ExMutantObjectType,
- NULL,
- PreviousMode,
- DesiredAccess,
- NULL,
- &hMutant);
-
- /* Check for success and return handle */
- if(NT_SUCCESS(Status)) {
-
- _SEH_TRY {
-
- *MutantHandle = hMutant;
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ 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
+NTSTATUS STDCALL
NtQueryMutant(IN HANDLE MutantHandle,
- IN MUTANT_INFORMATION_CLASS MutantInformationClass,
- OUT PVOID MutantInformation,
- IN ULONG MutantInformationLength,
- OUT PULONG ResultLength OPTIONAL)
+ 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;
- }
+ PKMUTANT Mutant;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
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;
+ PreviousMode = ExGetPreviousMode();
+
+ DefaultQueryInfoBufferCheck(MutantInformationClass,
+ ExMutantInfoClass,
+ MutantInformation,
+ MutantInformationLength,
+ ResultLength,
+ PreviousMode,
+ &Status);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
+ return Status;
+ }
+
+ Status = ObReferenceObjectByHandle(MutantHandle,
+ MUTANT_QUERY_STATE,
+ ExMutantObjectType,
+ PreviousMode,
+ (PVOID*)&Mutant,
+ NULL);
+ if(NT_SUCCESS(Status))
+ {
+ switch(MutantInformationClass)
+ {
+ case MutantBasicInformation:
+ {
+ PMUTANT_BASIC_INFORMATION BasicInfo = (PMUTANT_BASIC_INFORMATION)MutantInformation;
+
+ _SEH_TRY
+ {
+ BasicInfo->Count = KeReadStateMutant(Mutant);
+ BasicInfo->Owned = (Mutant->OwnerThread != NULL);
+ BasicInfo->Abandoned = Mutant->Abandoned;
+
+ if(ResultLength != NULL)
+ {
+ *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+ }
+
+ default:
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ ObDereferenceObject(Mutant);
+ }
+
+ return Status;
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtReleaseMutant(IN HANDLE MutantHandle,
- IN PLONG PreviousCount OPTIONAL)
+ IN PLONG PreviousCount OPTIONAL)
{
- PKMUTANT Mutant;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ PKMUTANT Mutant;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
- }
- }
+ PAGED_CODE();
- /* Return Status */
- return Status;
+ 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;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ 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);
+
+ if(PreviousCount != NULL)
+ {
+ _SEH_TRY
+ {
+ *PreviousCount = Prev;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ }
+
+ return Status;
}
/* EOF */
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/rundown.c
* PURPOSE: Rundown Protection Functions
*
- * PROGRAMMERS: Alex Ionescu & Thomas Weidenmueller - Implementation
+ * PROGRAMMERS: No programmer listed.
*/
/* INCLUDES *****************************************************************/
-/*
+/* $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: Alex Ionescu (alex@relsoft.net)- Reformatting, bug fixes.
- * David Welch (welch@mcmail.com)
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
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};
-
-static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = {
-
- /* SemaphoreBasicInformation */
- ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+ 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 */
};
-VOID
-INIT_FUNCTION
+/* 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
ExpInitializeSemaphoreImplementation(VOID)
{
-
- /* 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);
+ 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);
}
/*
* @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 = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ PKSEMAPHORE Semaphore;
+ HANDLE hSemaphore;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
- }
-
- /* Make sure the counts make sense */
- if (!MaximumCount || !InitialCount || InitialCount > MaximumCount) {
-
- DPRINT("Invalid Count Data!\n");
- return STATUS_INVALID_PARAMETER;
- }
+ PAGED_CODE();
- /* 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;
- }
- }
+ 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);
- /* Return Status */
- return Status;
+ ObDereferenceObject(Semaphore);
+
+ if(NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *SemaphoreHandle = hSemaphore;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ }
+
+ return Status;
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- HANDLE hSemaphore;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status = STATUS_SUCCESS;
+ HANDLE hSemaphore;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
- }
+ PAGED_CODE();
- /* Return Status */
- return Status;
+ 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
+NTSTATUS STDCALL
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
- IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
- OUT PVOID SemaphoreInformation,
- IN ULONG SemaphoreInformationLength,
- OUT PULONG ReturnLength OPTIONAL)
+ 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)) {
+ PKSEMAPHORE Semaphore;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
- _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);
+ 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 */
return Status;
}
+
/*
* @implemented
*/
-NTSTATUS
-STDCALL
+NTSTATUS STDCALL
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
- IN LONG ReleaseCount,
- OUT PLONG PreviousCount OPTIONAL)
+ IN LONG ReleaseCount,
+ OUT PLONG PreviousCount OPTIONAL)
{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();;
- PKSEMAPHORE Semaphore;
- NTSTATUS Status = STATUS_SUCCESS;
+ KPROCESSOR_MODE PreviousMode;
+ 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;
- }
+ PAGED_CODE();
- /* 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);
+ 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);
- /* Return it */
- if(PreviousCount) {
-
- _SEH_TRY {
-
- *PreviousCount = PrevCount;
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
- }
- }
+ if(PreviousCount != NULL)
+ {
+ _SEH_TRY
+ {
+ *PreviousCount = PrevCount;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ }
- /* Return Status */
- return Status;
+ return Status;
}
/* EOF */
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,
PreviousMode = ExGetPreviousMode();
DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass);
-
+
/* Check Validity */
DefaultQueryInfoBufferCheck(TimerInformationClass,
ExTimerInfoClass,
/* Check for Success */
if(NT_SUCCESS(Status)) {
+
+ switch(TimerInformationClass) {
+ case TimerBasicInformation: {
+ /* Return the Basic Information */
+ _SEH_TRY {
- /* 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);
+ /* FIXME: Interrupt correction based on Interrupt Time */
+ DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
+ BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
+ BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
- if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
+ if(ReturnLength != NULL) {
+ *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
+ }
- } _SEH_HANDLE {
-
+ } _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
- } _SEH_END;
+ } _SEH_END;
+ }
+ }
- /* Dereference Object */
ObDereferenceObject(Timer);
}
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/work.c
* PURPOSE: Manage system work queues
*
- * PROGRAMMERS: Alex Ionescu - Used correct work queue array and added some fixes and checks.
- * Gunnar Dalsnes - Implemented
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES ******************************************************************/
/*
* PURPOSE: Queue of items waiting to be processed at normal priority
*/
-EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
+KQUEUE EiNormalWorkQueue;
+
+KQUEUE EiCriticalWorkQueue;
+
+KQUEUE EiHyperCriticalWorkQueue;
/* FUNCTIONS ****************************************************************/
+//static NTSTATUS STDCALL
+static VOID STDCALL
+ExWorkerThreadEntryPoint(IN PVOID context)
/*
* FUNCTION: Entry point for a worker thread
* ARGUMENTS:
* 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 WorkItem;
- PLIST_ENTRY QueueEntry;
- WORK_QUEUE_TYPE WorkQueueType;
- PEX_WORK_QUEUE WorkQueue;
+
+ PWORK_QUEUE_ITEM item;
+ PLIST_ENTRY current;
- /* Get Queue Type and Worker Queue */
- WorkQueueType = (WORK_QUEUE_TYPE)Context;
- WorkQueue = &ExWorkerQueue[WorkQueueType];
-
- /* Loop forever */
- while (TRUE) {
-
- /* Wait for Something to Happen on the Queue */
- QueueEntry = KeRemoveQueue(&WorkQueue->WorkerQueue, KernelMode, NULL);
+ while (TRUE)
+ {
+ current = KeRemoveQueue( (PKQUEUE)context, KernelMode, NULL );
- /* Can't happen since we do a KernelMode wait (and we're a system thread) */
- ASSERT((NTSTATUS)QueueEntry != STATUS_USER_APC);
+ /* can't happend since we do a KernelMode wait (and we're a system thread) */
+ ASSERT((NTSTATUS)current != 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);
- }
- }
+ /* 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
-STDCALL
-ExpInitializeWorkQueue(WORK_QUEUE_TYPE WorkQueueType,
- KPRIORITY Priority)
+static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
+ KPRIORITY Priority)
{
- ULONG i;
- PETHREAD Thread;
- HANDLE hThread;
+ 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);
+
+ for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
+ {
- /* Dereference and close handle */
- ObDereferenceObject(Thread);
- ZwClose(hThread);
- }
+ 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);
+ }
}
-VOID
-INIT_FUNCTION
-ExpInitializeWorkerThreads(VOID)
+VOID INIT_FUNCTION
+ExInitializeWorkerThreads(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);
+ KeInitializeQueue( &EiNormalWorkQueue, NUMBER_OF_WORKER_THREADS );
+ KeInitializeQueue( &EiCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
+ KeInitializeQueue( &EiHyperCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
+
+ ExInitializeWorkQueue(&EiNormalWorkQueue,
+ LOW_PRIORITY);
+ ExInitializeWorkQueue(&EiCriticalWorkQueue,
+ LOW_REALTIME_PRIORITY);
+ ExInitializeWorkQueue(&EiHyperCriticalWorkQueue,
+ 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 Queue */
- KeInsertQueue(&ExWorkerQueue[QueueType].WorkerQueue, &WorkItem->List);
+ /*
+ * 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;
+
+ }
}
/* EOF */
VOID
ExpInitTimeZoneInfo(VOID);
VOID
-ExpInitializeWorkerThreads(VOID);
+ExInitializeWorkerThreads(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,
* 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)
/* bootlog.c */
VOID
-IopInitBootLog(BOOLEAN StartBootLog);
+IopInitBootLog(VOID);
VOID
IopStartBootLog(VOID);
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);
VOID STDCALL KiExpireTimers(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
-KIRQL inline FASTCALL KeAcquireDispatcherDatabaseLock(VOID);
-VOID inline FASTCALL KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
-VOID inline FASTCALL KeReleaseDispatcherDatabaseLock(KIRQL Irql);
-VOID inline FASTCALL KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
+KIRQL KeAcquireDispatcherDatabaseLock(VOID);
+VOID KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
+VOID KeReleaseDispatcherDatabaseLock(KIRQL Irql);
+VOID KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment);
VOID STDCALL KeExpireTimers(PKDPC Apc,
PVOID Arg1,
PVOID Arg2,
PVOID Arg3);
-VOID inline FASTCALL KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
+VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
ULONG Size, ULONG SignalState);
VOID KeDumpStackFrames(PULONG Frame);
BOOLEAN KiTestAlert(VOID);
-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);
+BOOLEAN KiAbortWaitThread(struct _KTHREAD* Thread, NTSTATUS WaitStatus);
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 STDCALL KiInitializeUserApc(IN PVOID Reserved,
+VOID KiInitializeUserApc(IN PVOID Reserved,
IN PKTRAP_FRAME TrapFrame,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID NormalContext,
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;
VOID KeInitTimer(VOID);
VOID KeInitDpc(struct _KPCR* Pcr);
VOID KeInitDispatcher(VOID);
-VOID inline FASTCALL KeInitializeDispatcher(VOID);
+VOID KeInitializeDispatcher(VOID);
VOID KiInitializeSystemClock(VOID);
VOID KeInitializeBugCheck(VOID);
VOID Phase1Initialization(PVOID Context);
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);
*/
VOID MmInitSystem(ULONG Phase, PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG LastKernelAddress);
VOID IoInit(VOID);
-VOID IoInit2(BOOLEAN BootLog);
-VOID STDCALL IoInit3(VOID);
+VOID IoInit2(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);
VOID
-STDCALL
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
-
NTSTATUS KeReleaseThread(PKTHREAD Thread);
VOID
ULONG PsEnumThreadsByProcess(PEPROCESS Process);
PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
VOID
-STDCALL
-PsBlockThread(PNTSTATUS Status,
- UCHAR Alertable,
- ULONG WaitMode,
- UCHAR WaitReason);
+PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
+ BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason);
VOID
PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment);
VOID
/* FUNCTIONS ****************************************************************/
VOID INIT_FUNCTION
-IopInitBootLog(BOOLEAN StartBootLog)
+IopInitBootLog(VOID)
{
ExInitializeResourceLite(&IopBootLogResource);
- if (StartBootLog) IopStartBootLog();
}
-VOID INIT_FUNCTION
+VOID
IopStartBootLog(VOID)
{
IopBootLogCreate = TRUE;
FileObject,
DeviceObject);
FileObject->Vpb = DeviceObject->Vpb;
- FileObject->Type = IO_TYPE_FILE;
+ FileObject->Type = InternalFileType;
return(STATUS_SUCCESS);
}
CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
CreatedFileObject->Vpb = DeviceObject->Vpb;
- CreatedFileObject->Type = IO_TYPE_FILE;
+ CreatedFileObject->Type = InternalFileType;
CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
// shouldn't we initialize the lock event, and several other things here too?
RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
- Object->Type = IO_TYPE_DRIVER;
+ Object->Type = InternalDriverType;
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
Object->MajorFunction[i] = IopInvalidDeviceRequest;
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/iocomp.c
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 *****************************************************************/
-VOID
+NTSTATUS
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;
- PLIST_ENTRY FirstEntry;
- PLIST_ENTRY CurrentEntry;
- PIO_COMPLETION_PACKET Packet;
-
- DPRINT("IopDeleteIoCompletion()\n");
-
- /* 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);
- }
+ PKQUEUE Queue = ObjectBody;
+
+ DPRINT("IopDeleteIoCompletion()\n");
+
+ KeRundownQueue(Queue);
}
+
/*
- * @implemented
+ * @unimplemented
*/
NTSTATUS
STDCALL
-IoSetIoCompletion(IN PVOID IoCompletion,
- IN PVOID KeyContext,
- IN PVOID ApcContext,
- IN NTSTATUS IoStatus,
- IN ULONG_PTR IoStatusInformation,
- IN BOOLEAN Quota)
+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
+ )
{
- PKQUEUE Queue = (PKQUEUE)IoCompletion;
- PIO_COMPLETION_PACKET Packet;
-
- /* 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);
-
- /* Return Success */
- return STATUS_SUCCESS;
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
}
/*
- * @unimplemented
+ * @implemented
*/
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)
+IoSetIoCompletion (
+ IN PVOID IoCompletion,
+ IN PVOID KeyContext,
+ IN PVOID ApcContext,
+ IN NTSTATUS IoStatus,
+ IN ULONG_PTR IoStatusInformation,
+ IN BOOLEAN Quota
+ )
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PKQUEUE Queue = (PKQUEUE) IoCompletion;
+ PIO_COMPLETION_PACKET Packet;
+
+ Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
+ if (NULL == Packet)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ Packet->Key = KeyContext;
+ Packet->Context = ApcContext;
+ Packet->IoStatus.Status = IoStatus;
+ Packet->IoStatus.Information = IoStatusInformation;
+
+ KeInsertQueue(Queue, &Packet->ListEntry);
+
+ return STATUS_SUCCESS;
}
VOID
FASTCALL
IopInitIoCompletionImplementation(VOID)
{
- /* 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;
-
- /* Initialize the Lookaside List we'll use for packets */
- ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
- NULL,
- NULL,
- 0,
- sizeof(IO_COMPLETION_PACKET),
- IOC_TAG,
- 0);
+ 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;
+
+ 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;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-
- /* 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);
+ PKQUEUE Queue;
+ NTSTATUS Status;
+
+ Status = ObCreateObject(ExGetPreviousMode(),
+ ExIoCompletionType,
+ ObjectAttributes,
+ ExGetPreviousMode(),
+ NULL,
+ sizeof(KQUEUE),
+ 0,
+ 0,
+ (PVOID*)&Queue);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
}
-
- /* Return Status */
+
+ Status = ObInsertObject ((PVOID)Queue,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ IoCompletionHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Queue);
+ return Status;
+ }
+
+ KeInitializeQueue(Queue, NumberOfConcurrentThreads);
+ ObDereferenceObject(Queue);
+
return STATUS_SUCCESS;
+ /*
+
+ CompletionPort = NULL OR ExistingCompletionPort
+
+ */
+
+
}
+/*
+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)
+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;
+ 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;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PKQUEUE Queue;
+ NTSTATUS Status;
- /* Get the Object */
- Status = ObReferenceObjectByHandle(IoCompletionHandle,
+ if (IoCompletionInformationClass != IoCompletionBasicInformation)
+ {
+ return STATUS_INVALID_INFO_CLASS;
+ }
+ if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION))
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ Status = ObReferenceObjectByHandle( IoCompletionHandle,
IO_COMPLETION_QUERY_STATE,
ExIoCompletionType,
- PreviousMode,
+ UserMode,
(PVOID*)&Queue,
NULL);
-
- /* Check for Success */
- if (NT_SUCCESS(Status)) {
-
- /* Return Info */
- ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = KeReadStateQueue(Queue);
- ObDereferenceObject(Queue);
+ if (NT_SUCCESS(Status))
+ {
+ ((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth =
+ Queue->Header.SignalState;
- /* Return Result Length if needed */
- if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
- }
+ ObDereferenceObject(Queue);
- /* Return Status */
- return Status;
+ if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
+ }
+
+ 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;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-
- /* Open the Object */
- Status = ObReferenceObjectByHandle(IoCompletionHandle,
+ PKQUEUE Queue;
+ NTSTATUS Status;
+ PIO_COMPLETION_PACKET Packet;
+ PLIST_ENTRY ListEntry;
+
+ Status = ObReferenceObjectByHandle( IoCompletionHandle,
IO_COMPLETION_MODIFY_STATE,
ExIoCompletionType,
- PreviousMode,
+ UserMode,
(PVOID*)&Queue,
NULL);
-
- /* Check for success */
- if (NT_SUCCESS(Status)) {
-
- /* Remove queue */
- ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout);
-
- /* 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 (!NT_SUCCESS(Status))
+ {
+ return 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 );
+
+ /* 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 ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
+ {
+ return STATUS_TIMEOUT;
+ }
+
+ ASSERT(ListEntry);
- /* Dereference the Object */
- ObDereferenceObject(Queue);
- }
-
- /* Return status */
- return Status;
+ 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;
}
+
+/*
+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;
-
- /* Get the Object */
- Status = ObReferenceObjectByHandle(IoCompletionPortHandle,
+ NTSTATUS Status;
+ PKQUEUE Queue;
+
+ Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
IO_COMPLETION_MODIFY_STATE,
ExIoCompletionType,
- ExGetPreviousMode(),
+ UserMode,
(PVOID*)&Queue,
NULL);
-
- /* Check for Success */
- if (NT_SUCCESS(Status)) {
-
- /* Set the Completion */
- Status = IoSetIoCompletion(Queue,
- CompletionKey,
- CompletionContext,
- CompletionStatus,
- CompletionInformation,
- TRUE);
- ObDereferenceObject(Queue);
- }
-
- /* Return status */
- return Status;
+ if (NT_SUCCESS(Status))
+ {
+ Status = IoSetIoCompletion(Queue, CompletionKey, CompletionContext,
+ CompletionStatus, CompletionInformation, TRUE);
+ ObDereferenceObject(Queue);
+ }
+
+ return Status;
}
}
-VOID
-INIT_FUNCTION
-IoInit2(BOOLEAN BootLog)
+VOID INIT_FUNCTION
+IoInit2(VOID)
{
PDEVICE_NODE DeviceNode;
PDRIVER_OBJECT DriverObject;
MODULE_OBJECT ModuleObject;
NTSTATUS Status;
- IoCreateDriverList();
-
KeInitializeSpinLock (&IoStatisticsLock);
/* Initialize raw filesystem driver */
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);
}
/*
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*/
--- /dev/null
+/* $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;
+}
+
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/apc.c
VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
-/* FUNCTIONS *****************************************************************/
+#define TAG_KAPC TAG('K', 'A', 'P', 'C')
-/*++
- * KeEnterCriticalRegion
- * @implemented NT4
- *
- * The KeEnterCriticalRegion routine temporarily disables the delivery of
- * normal kernel APCs; special kernel-mode APCs are still delivered.
- *
- * Params:
- * None.
- *
- * Returns:
- * None.
- *
- * Remarks:
- * Highest-level drivers can call this routine while running in the context
- * of the thread that requested the current I/O operation. Any caller of
- * this routine should call KeLeaveCriticalRegion as quickly as possible.
- *
- * Callers of KeEnterCriticalRegion must be running at IRQL <= APC_LEVEL.
- *
- *--*/
-VOID
-STDCALL
-KeEnterCriticalRegion(VOID)
-{
- /* Disable Kernel APCs */
- PKTHREAD Thread = KeGetCurrentThread();
- if (Thread) Thread->KernelApcDisable--;
-}
+/* FUNCTIONS *****************************************************************/
-/*++
- * KeInitializeApc
- * @implemented NT4
- *
- * The The KeInitializeApc routine initializes an APC object, and registers
- * the Kernel, Rundown and Normal routines for that object.
- *
- * Params:
- * Apc - Pointer to a KAPC structure that represents the APC object to
- * initialize. The caller must allocate storage for the structure
- * from resident memory.
- *
- * Thread - Thread to which to deliver the APC.
- *
- * TargetEnvironment - APC Environment to be used.
- *
- * KernelRoutine - Points to the KernelRoutine to associate with the APC.
- * This routine is executed for all APCs.
- *
- * RundownRoutine - Points to the RundownRoutine to associate with the APC.
- * This routine is executed when the Thread exists with
- * the APC executing.
- *
- * NormalRoutine - Points to the NormalRoutine to associate with the APC.
- * This routine is executed at PASSIVE_LEVEL. If this is
- * not specifed, the APC becomes a Special APC and the
- * Mode and Context parameters are ignored.
- *
- * Mode - Specifies the processor mode at which to run the Normal Routine.
- *
- * Context - Specifices the value to pass as Context parameter to the
- * registered routines.
- *
- * Returns:
- * None.
- *
- * Remarks:
- * The caller can queue an initialized APC with KeInsertQueueApc.
- *
- * Storage for the APC object must be resident, such as nonpaged pool
- * allocated by the caller.
- *
- * Callers of this routine must be running at IRQL = PASSIVE_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
VOID
STDCALL
-KeInitializeApc(IN PKAPC Apc,
- IN PKTHREAD Thread,
- IN KAPC_ENVIRONMENT TargetEnvironment,
- IN PKKERNEL_ROUTINE KernelRoutine,
- IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
- IN PKNORMAL_ROUTINE NormalRoutine,
- IN KPROCESSOR_MODE Mode,
- IN PVOID Context)
+KeInitializeApc(
+ IN PKAPC Apc,
+ IN PKTHREAD Thread,
+ IN KAPC_ENVIRONMENT TargetEnvironment,
+ IN PKKERNEL_ROUTINE KernelRoutine,
+ IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
+ IN PKNORMAL_ROUTINE NormalRoutine,
+ IN KPROCESSOR_MODE Mode,
+ IN PVOID Context)
+/*
+ * FUNCTION: Initialize an APC object
+ * ARGUMENTS:
+ * Apc = Pointer to the APC object to initialized
+ * Thread = Thread the APC is to be delivered to
+ * TargetEnvironment = APC environment to use
+ * KernelRoutine = Routine to be called for a kernel-mode APC
+ * RundownRoutine = Routine to be called if the thread has exited with
+ * the APC being executed
+ * NormalRoutine = Routine to be called for a user-mode APC
+ * Mode = APC mode
+ * Context = Parameter to be passed to the APC routine
+ */
{
- DPRINT("KeInitializeApc(Apc %x, Thread %x, Environment %d, "
- "KernelRoutine %x, RundownRoutine %x, NormalRoutine %x, Mode %d, "
- "Context %x)\n",Apc,Thread,TargetEnvironment,KernelRoutine,RundownRoutine,
- NormalRoutine,Mode,Context);
-
- /* Set up the basic APC Structure Data */
- RtlZeroMemory(Apc, sizeof(KAPC));
- Apc->Type = ApcObject;
- Apc->Size = sizeof(KAPC);
-
- /* Set the Environment */
- if (TargetEnvironment == CurrentApcEnvironment) {
-
- Apc->ApcStateIndex = Thread->ApcStateIndex;
-
- } else {
-
- Apc->ApcStateIndex = TargetEnvironment;
- }
-
- /* Set the Thread and Routines */
- Apc->Thread = Thread;
- Apc->KernelRoutine = KernelRoutine;
- Apc->RundownRoutine = RundownRoutine;
- Apc->NormalRoutine = NormalRoutine;
+ DPRINT ("KeInitializeApc(Apc %x, Thread %x, Environment %d, "
+ "KernelRoutine %x, RundownRoutine %x, NormalRoutine %x, Mode %d, "
+ "Context %x)\n",Apc,Thread,TargetEnvironment,KernelRoutine,RundownRoutine,
+ NormalRoutine,Mode,Context);
+
+ /* Set up the basic APC Structure Data */
+ RtlZeroMemory(Apc, sizeof(KAPC));
+ Apc->Type = KApc;
+ Apc->Size = sizeof(KAPC);
+
+ /* Set the Environment */
+ if (TargetEnvironment == CurrentApcEnvironment) {
+ Apc->ApcStateIndex = Thread->ApcStateIndex;
+ } else {
+ Apc->ApcStateIndex = TargetEnvironment;
+ }
+
+ /* Set the Thread and Routines */
+ Apc->Thread = Thread;
+ Apc->KernelRoutine = KernelRoutine;
+ Apc->RundownRoutine = RundownRoutine;
+ Apc->NormalRoutine = NormalRoutine;
- /* Check if this is a Special APC, in which case we use KernelMode and no Context */
- if (ARGUMENT_PRESENT(NormalRoutine)) {
-
- Apc->ApcMode = Mode;
- Apc->NormalContext = Context;
-
- } else {
-
- Apc->ApcMode = KernelMode;
- }
+ /* Check if this is a Special APC, in which case we use KernelMode and no Context */
+ if (ARGUMENT_PRESENT(NormalRoutine)) {
+ Apc->ApcMode = Mode;
+ Apc->NormalContext = Context;
+ } else {
+ Apc->ApcMode = KernelMode;
+ }
}
-/*++
- * KeInsertQueueApc
- * @implemented NT4
- *
- * The KeInsertQueueApc routine queues a APC for execution when the right
- * scheduler environment exists.
- *
- * Params:
- * Apc - Pointer to an initialized control object of type DPC for which the
- * caller provides the storage.
- *
- * SystemArgument[1,2] - Pointer to a set of two parameters that contain
- * untyped data.
- *
- * PriorityBoost - Priority Boost to apply to the Thread.
- *
- * Returns:
- * If the APC is already inserted or APC queueing is disabled, FALSE.
- * Otherwise, TRUE.
- *
- * Remarks:
- * The APC will execute at APC_LEVEL for the KernelRoutine registered, and
- * at PASSIVE_LEVEL for the NormalRoutine registered.
- *
- * Callers of this routine must be running at IRQL = PASSIVE_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
BOOLEAN
STDCALL
-KeInsertQueueApc(PKAPC Apc,
- PVOID SystemArgument1,
- PVOID SystemArgument2,
- KPRIORITY PriorityBoost)
-
+KeInsertQueueApc (PKAPC Apc,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2,
+ KPRIORITY PriorityBoost)
+/*
+ * FUNCTION: Queues an APC for execution
+ * ARGUMENTS:
+ * Apc = APC to be queued
+ * SystemArgument[1-2] = Arguments we ignore and simply pass on.
+ * PriorityBoost = Priority Boost to give to the Thread
+ */
{
- KIRQL OldIrql;
- PKTHREAD Thread;
- PLIST_ENTRY ApcListEntry;
- PKAPC QueuedApc;
+ KIRQL OldIrql;
+ PKTHREAD Thread;
+ PLIST_ENTRY ApcListEntry;
+ PKAPC QueuedApc;
- ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
- DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
- "SystemArgument2 %x)\n",Apc,SystemArgument1,
- SystemArgument2);
-
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Get the Thread specified in the APC */
- Thread = Apc->Thread;
-
- /* Make sure the thread allows APC Queues.
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+ DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
+ "SystemArgument2 %x)\n",Apc,SystemArgument1,
+ SystemArgument2);
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+
+ /* Get the Thread specified in the APC */
+ Thread = Apc->Thread;
+
+ /* Make sure the thread allows APC Queues.
* The thread is not apc queueable, for instance, when it's (about to be) terminated.
*/
- if (Thread->ApcQueueable == FALSE) {
- DPRINT("Thread doesn't allow APC Queues\n");
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return FALSE;
- }
-
- /* Set the System Arguments */
- Apc->SystemArgument1 = SystemArgument1;
- Apc->SystemArgument2 = SystemArgument2;
-
- /* Don't do anything if the APC is already inserted */
- if (Apc->Inserted) {
-
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return FALSE;
- }
-
- /* Three scenarios:
- 1) Kernel APC with Normal Routine or User APC = Put it at the end of the List
- 2) User APC which is PsExitSpecialApc = Put it at the front of the List
- 3) Kernel APC without Normal Routine = Put it at the end of the No-Normal Routine Kernel APC list
- */
- if ((Apc->ApcMode != KernelMode) && (Apc->KernelRoutine == (PKKERNEL_ROUTINE)PsExitSpecialApc)) {
-
- DPRINT ("Inserting the Process Exit APC into the Queue\n");
- Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = TRUE;
- InsertHeadList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
- &Apc->ApcListEntry);
-
- } else if (Apc->NormalRoutine == NULL) {
-
- DPRINT ("Inserting Special APC %x into the Queue\n", Apc);
-
- for (ApcListEntry = Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode].Flink;
- ApcListEntry != &Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode];
- ApcListEntry = ApcListEntry->Flink) {
-
- QueuedApc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
- if (Apc->NormalRoutine != NULL) break;
- }
-
- /* We found the first "Normal" APC, so write right before it */
- ApcListEntry = ApcListEntry->Blink;
- InsertHeadList(ApcListEntry, &Apc->ApcListEntry);
-
- } else {
-
- DPRINT ("Inserting Normal APC %x into the %x Queue\n", Apc, Apc->ApcMode);
- InsertTailList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
- &Apc->ApcListEntry);
- }
-
- /* Confirm Insertion */
- Apc->Inserted = TRUE;
-
- /*
- * Three possibilites here again:
- * 1) Kernel APC, The thread is Running: Request an Interrupt
- * 2) Kernel APC, The Thread is Waiting at PASSIVE_LEVEL and APCs are enabled and not in progress: Unwait the Thread
- * 3) User APC, Unwait the Thread if it is alertable
- */
- if (Apc->ApcMode == KernelMode) {
-
- /* Set Kernel APC pending */
- Thread->ApcState.KernelApcPending = TRUE;
-
- /* Check the Thread State */
- if (Thread->State == THREAD_STATE_RUNNING) {
-
- /* FIXME: Use IPI */
- DPRINT ("Requesting APC Interrupt for Running Thread \n");
- HalRequestSoftwareInterrupt(APC_LEVEL);
-
- } else if ((Thread->State == THREAD_STATE_BLOCKED) &&
+ if (Thread->ApcQueueable == FALSE) {
+ DPRINT("Thread doesn't allow APC Queues\n");
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return FALSE;
+ }
+
+ /* Set the System Arguments */
+ Apc->SystemArgument1 = SystemArgument1;
+ Apc->SystemArgument2 = SystemArgument2;
+
+ /* Don't do anything if the APC is already inserted */
+ if (Apc->Inserted) {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return FALSE;
+ }
+
+ /* Three scenarios:
+ 1) Kernel APC with Normal Routine or User APC = Put it at the end of the List
+ 2) User APC which is PsExitSpecialApc = Put it at the front of the List
+ 3) Kernel APC without Normal Routine = Put it at the end of the No-Normal Routine Kernel APC list
+ */
+ if ((Apc->ApcMode != KernelMode) && (Apc->KernelRoutine == (PKKERNEL_ROUTINE)PsExitSpecialApc)) {
+ DPRINT ("Inserting the Process Exit APC into the Queue\n");
+ Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = TRUE;
+ InsertHeadList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
+ &Apc->ApcListEntry);
+ } else if (Apc->NormalRoutine == NULL) {
+ DPRINT ("Inserting Special APC %x into the Queue\n", Apc);
+ for (ApcListEntry = Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode].Flink;
+ ApcListEntry != &Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode];
+ ApcListEntry = ApcListEntry->Flink) {
+
+ QueuedApc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
+ if (Apc->NormalRoutine != NULL) break;
+ }
+
+ /* We found the first "Normal" APC, so write right before it */
+ ApcListEntry = ApcListEntry->Blink;
+ InsertHeadList(ApcListEntry, &Apc->ApcListEntry);
+ } else {
+ DPRINT ("Inserting Normal APC %x into the %x Queue\n", Apc, Apc->ApcMode);
+ InsertTailList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
+ &Apc->ApcListEntry);
+ }
+
+ /* Confirm Insertion */
+ Apc->Inserted = TRUE;
+
+ /* Three possibilites here again:
+ 1) Kernel APC, The thread is Running: Request an Interrupt
+ 2) Kernel APC, The Thread is Waiting at PASSIVE_LEVEL and APCs are enabled and not in progress: Unwait the Thread
+ 3) User APC, Unwait the Thread if it is alertable
+ */
+ if (Apc->ApcMode == KernelMode) {
+ Thread->ApcState.KernelApcPending = TRUE;
+ if (Thread->State == THREAD_STATE_RUNNING) {
+ /* FIXME: Use IPI */
+ DPRINT ("Requesting APC Interrupt for Running Thread \n");
+ HalRequestSoftwareInterrupt(APC_LEVEL);
+ } else if ((Thread->State == THREAD_STATE_BLOCKED) &&
(Thread->WaitIrql < APC_LEVEL) &&
- (Apc->NormalRoutine == NULL)) {
-
- DPRINT("Waking up Thread for Kernel-Mode APC Delivery \n");
- KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
- }
-
+ (Apc->NormalRoutine == NULL))
+ {
+ DPRINT ("Waking up Thread for Kernel-Mode APC Delivery \n");
+ KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
+ }
} else if ((Thread->State == THREAD_STATE_BLOCKED) &&
(Thread->WaitMode == UserMode) &&
- (Thread->Alertable)) {
-
- DPRINT("Waking up Thread for User-Mode APC Delivery \n");
- Thread->ApcState.UserApcPending = TRUE;
- KiAbortWaitThread(Thread, STATUS_USER_APC);
- }
-
- /* Return Sucess if we are here */
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return TRUE;
+ (Thread->Alertable))
+ {
+ DPRINT ("Waking up Thread for User-Mode APC Delivery \n");
+ Thread->ApcState.UserApcPending = TRUE;
+ KiAbortWaitThread(Thread, STATUS_USER_APC);
+ }
+
+ /* Return Sucess if we are here */
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return TRUE;
}
-/*++
- * KeLeaveCriticalRegion
- * @implemented NT4
- *
- * The KeLeaveCriticalRegion routine reenables the delivery of normal
- * kernel-mode APCs that were disabled by a call to KeEnterCriticalRegion.
- *
- * Params:
- * None.
- *
- * Returns:
- * None.
- *
- * Remarks:
- * Highest-level drivers can call this routine while running in the context
- * of the thread that requested the current I/O operation.
- *
- * Callers of KeLeaveCriticalRegion must be running at IRQL <= DISPATCH_LEVEL.
- *
- *--*/
-VOID
-STDCALL
-KeLeaveCriticalRegion (VOID)
+BOOLEAN STDCALL
+KeRemoveQueueApc (PKAPC Apc)
+/*
+ * FUNCTION: Removes APC object from the apc queue
+ * ARGUMENTS:
+ * Apc = APC to remove
+ * RETURNS: TRUE if the APC was in the queue
+ * FALSE otherwise
+ * NOTE: This function is not exported.
+ */
{
- PKTHREAD Thread = KeGetCurrentThread();
-
- /* Check if Kernel APCs are now enabled */
- if((Thread) && (++Thread->KernelApcDisable == 0)) {
-
- /* Check if we need to request an APC Delivery */
- if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) {
-
- /* Set APC Pending */
- Thread->ApcState.KernelApcPending = TRUE;
- HalRequestSoftwareInterrupt(APC_LEVEL);
- }
- }
+ KIRQL OldIrql;
+ PKTHREAD Thread = Apc->Thread;
+
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+ DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+ KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+
+ /* Remove it from the Queue if it's inserted */
+ if (!Apc->Inserted == FALSE) {
+ RemoveEntryList(&Apc->ApcListEntry);
+ Apc->Inserted = FALSE;
+
+ /* If the Queue is completely empty, then no more APCs are pending */
+ if (IsListEmpty(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode])) {
+ if (Apc->ApcMode == KernelMode) {
+ Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->KernelApcPending = FALSE;
+ } else {
+ Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = FALSE;
+ }
+ }
+ } else {
+ KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return(FALSE);
+ }
+
+ /* Restore IRQL and Return */
+ KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return(TRUE);
}
-/*++
- * KeRemoveQueueApc
- *
- * The KeRemoveQueueApc routine removes a given APC object from the system
- * APC queue.
- *
- * Params:
- * APC - Pointer to an initialized APC object that was queued by calling
- * KeInsertQueueApc.
- *
- * Returns:
- * TRUE if the APC Object is in the APC Queue. If it isn't, no operation is
- * performed and FALSE is returned.
- *
- * Remarks:
- * If the given APC Object is currently queued, it is removed from the queue
- * and any calls to the registered routines are cancelled.
- *
- * Callers of KeLeaveCriticalRegion can be running at any IRQL.
- *
- *--*/
-BOOLEAN
-STDCALL
-KeRemoveQueueApc(PKAPC Apc)
-{
- KIRQL OldIrql;
- PKTHREAD Thread = Apc->Thread;
-
- ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
- DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
-
- OldIrql = KeAcquireDispatcherDatabaseLock();
- KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
-
- /* Check if it's inserted */
- if (Apc->Inserted) {
-
- /* Remove it from the Queue*/
- RemoveEntryList(&Apc->ApcListEntry);
- Apc->Inserted = FALSE;
-
- /* If the Queue is completely empty, then no more APCs are pending */
- if (IsListEmpty(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode])) {
-
- /* Set the correct State based on the Apc Mode */
- if (Apc->ApcMode == KernelMode) {
-
- Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->KernelApcPending = FALSE;
-
- } else {
-
- Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->UserApcPending = FALSE;
- }
- }
-
- } else {
-
- /* It's not inserted, fail */
- KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return(FALSE);
- }
-
- /* Restore IRQL and Return */
- KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return(TRUE);
-}
-/*++
- * KiDeliverApc
- * @implemented @NT4
- *
- * The KiDeliverApc routine is called from IRQL switching code if the
- * thread is returning from an IRQL >= APC_LEVEL and Kernel-Mode APCs are
- * pending.
- *
- * Params:
- * DeliveryMode - Specifies the current processor mode.
- *
- * Reserved - Pointer to the Exception Frame on non-i386 builds.
- *
- * TrapFrame - Pointer to the Trap Frame.
- *
- * Returns:
- * None.
- *
- * Remarks:
- * First, Special APCs are delivered, followed by Kernel-Mode APCs and
- * User-Mode APCs. Note that the TrapFrame is only valid if the previous
- * mode is User.
- *
- * Upon entry, this routine executes at APC_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
VOID
STDCALL
KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame)
+/*
+ * FUNCTION: Deliver an APC to the current thread.
+ * NOTES: This is called from the IRQL switching code if the current thread
+ * is returning from an IRQL greater than or equal to APC_LEVEL to
+ * PASSIVE_LEVEL and there are kernel-mode APCs pending. This means any
+ * pending APCs will be delivered after a thread gets a new quantum and
+ * after it wakes from a wait. Note that the TrapFrame is only valid if
+ * the previous mode is User.
+ */
{
- PKTHREAD Thread = KeGetCurrentThread();
- PLIST_ENTRY ApcListEntry;
- PKAPC Apc;
- KIRQL OldIrql;
- PKKERNEL_ROUTINE KernelRoutine;
- PVOID NormalContext;
- PKNORMAL_ROUTINE NormalRoutine;
- PVOID SystemArgument1;
- PVOID SystemArgument2;
+ PKTHREAD Thread = KeGetCurrentThread();
+ PLIST_ENTRY ApcListEntry;
+ PKAPC Apc;
+ KIRQL OldIrql;
+ PKKERNEL_ROUTINE KernelRoutine;
+ PVOID NormalContext;
+ PKNORMAL_ROUTINE NormalRoutine;
+ PVOID SystemArgument1;
+ PVOID SystemArgument2;
- ASSERT_IRQL_EQUAL(APC_LEVEL);
-
- /* Lock the APC Queue and Raise IRQL to Synch */
- KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
-
- /* Clear APC Pending */
- Thread->ApcState.KernelApcPending = FALSE;
-
- /* Do the Kernel APCs first */
- while (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) {
-
- /* Get the next Entry */
- ApcListEntry = Thread->ApcState.ApcListHead[KernelMode].Flink;
- Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
-
- /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
- NormalRoutine = Apc->NormalRoutine;
- KernelRoutine = Apc->KernelRoutine;
- NormalContext = Apc->NormalContext;
- SystemArgument1 = Apc->SystemArgument1;
- SystemArgument2 = Apc->SystemArgument2;
+ ASSERT_IRQL_EQUAL(APC_LEVEL);
+
+ /* Lock the APC Queue and Raise IRQL to Synch */
+ KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+
+ /* Clear APC Pending */
+ Thread->ApcState.KernelApcPending = FALSE;
+
+ /* Do the Kernel APCs first */
+ while (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) {
+
+ /* Get the next Entry */
+ ApcListEntry = Thread->ApcState.ApcListHead[KernelMode].Flink;
+ Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
+
+ /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
+ NormalRoutine = Apc->NormalRoutine;
+ KernelRoutine = Apc->KernelRoutine;
+ NormalContext = Apc->NormalContext;
+ SystemArgument1 = Apc->SystemArgument1;
+ SystemArgument2 = Apc->SystemArgument2;
- /* Special APC */
- if (NormalRoutine == NULL) {
-
- /* Remove the APC from the list */
- Apc->Inserted = FALSE;
- RemoveEntryList(ApcListEntry);
-
- /* Go back to APC_LEVEL */
- KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-
- /* Call the Special APC */
- DPRINT("Delivering a Special APC: %x\n", Apc);
- KernelRoutine(Apc,
- &NormalRoutine,
- &NormalContext,
- &SystemArgument1,
- &SystemArgument2);
-
- /* Raise IRQL and Lock again */
- KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+ /* Special APC */
+ if (NormalRoutine == NULL) {
+ /* Remove the APC from the list */
+ Apc->Inserted = FALSE;
+ RemoveEntryList(ApcListEntry);
+
+ /* Go back to APC_LEVEL */
+ KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+
+ /* Call the Special APC */
+ DPRINT("Delivering a Special APC: %x\n", Apc);
+ KernelRoutine(Apc,
+ &NormalRoutine,
+ &NormalContext,
+ &SystemArgument1,
+ &SystemArgument2);
+
+ /* Raise IRQL and Lock again */
+ KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+ } else {
+ /* Normal Kernel APC */
+ if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
- } else {
-
- /* Normal Kernel APC */
- if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
-
- /*
- * DeliveryMode must be KernelMode in this case, since one may not
- * return to umode while being inside a critical section or while
- * a regular kmode apc is running (the latter should be impossible btw).
- * -Gunnar
- */
- ASSERT(DeliveryMode == KernelMode);
-
- KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
- return;
- }
-
- /* Dequeue the APC */
- RemoveEntryList(ApcListEntry);
- Apc->Inserted = FALSE;
-
- /* Go back to APC_LEVEL */
- KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
-
- /* Call the Kernel APC */
- DPRINT("Delivering a Normal APC: %x\n", Apc);
- KernelRoutine(Apc,
- &NormalRoutine,
- &NormalContext,
- &SystemArgument1,
- &SystemArgument2);
-
- /* If There still is a Normal Routine, then we need to call this at PASSIVE_LEVEL */
- if (NormalRoutine != NULL) {
-
- /* At Passive Level, this APC can be prempted by a Special APC */
- Thread->ApcState.KernelApcInProgress = TRUE;
- KeLowerIrql(PASSIVE_LEVEL);
-
- /* Call and Raise IRQ back to APC_LEVEL */
- DPRINT("Calling the Normal Routine for a Normal APC: %x\n", Apc);
- NormalRoutine(&NormalContext, &SystemArgument1, &SystemArgument2);
- KeRaiseIrql(APC_LEVEL, &OldIrql);
- }
-
- /* Raise IRQL and Lock again */
- KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
- Thread->ApcState.KernelApcInProgress = FALSE;
- }
- }
-
- /* Now we do the User APCs */
- if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
- (DeliveryMode == UserMode) && (Thread->ApcState.UserApcPending == TRUE)) {
-
- /* It's not pending anymore */
- Thread->ApcState.UserApcPending = FALSE;
-
- /* Get the APC Object */
- ApcListEntry = Thread->ApcState.ApcListHead[UserMode].Flink;
- Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
-
- /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
- NormalRoutine = Apc->NormalRoutine;
- KernelRoutine = Apc->KernelRoutine;
- NormalContext = Apc->NormalContext;
- SystemArgument1 = Apc->SystemArgument1;
- SystemArgument2 = Apc->SystemArgument2;
-
- /* Remove the APC from Queue, restore IRQL and call the APC */
- RemoveEntryList(ApcListEntry);
- Apc->Inserted = FALSE;
+ /*
+ * DeliveryMode must be KernelMode in this case, since one may not
+ * return to umode while being inside a critical section or while
+ * a regular kmode apc is running (the latter should be impossible btw).
+ * -Gunnar
+ */
+ ASSERT(DeliveryMode == KernelMode);
+
+ KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+ return;
+ }
+
+ /* Dequeue the APC */
+ RemoveEntryList(ApcListEntry);
+ Apc->Inserted = FALSE;
+
+ /* Go back to APC_LEVEL */
+ KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+
+ /* Call the Kernel APC */
+ DPRINT("Delivering a Normal APC: %x\n", Apc);
+ KernelRoutine(Apc,
+ &NormalRoutine,
+ &NormalContext,
+ &SystemArgument1,
+ &SystemArgument2);
+
+ /* If There still is a Normal Routine, then we need to call this at PASSIVE_LEVEL */
+ if (NormalRoutine != NULL) {
+ /* At Passive Level, this APC can be prempted by a Special APC */
+ Thread->ApcState.KernelApcInProgress = TRUE;
+ KeLowerIrql(PASSIVE_LEVEL);
+
+ /* Call and Raise IRQ back to APC_LEVEL */
+ DPRINT("Calling the Normal Routine for a Normal APC: %x\n", Apc);
+ NormalRoutine(&NormalContext, &SystemArgument1, &SystemArgument2);
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
+ }
+
+ /* Raise IRQL and Lock again */
+ KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
+ Thread->ApcState.KernelApcInProgress = FALSE;
+ }
+ }
+
+ /* Now we do the User APCs */
+ if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
+ (DeliveryMode == UserMode) &&
+ (Thread->ApcState.UserApcPending == TRUE)) {
+
+ /* It's not pending anymore */
+ Thread->ApcState.UserApcPending = FALSE;
+
+ /* Get the APC Object */
+ ApcListEntry = Thread->ApcState.ApcListHead[UserMode].Flink;
+ Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
+
+ /* Save Parameters so that it's safe to free the Object in Kernel Routine*/
+ NormalRoutine = Apc->NormalRoutine;
+ KernelRoutine = Apc->KernelRoutine;
+ NormalContext = Apc->NormalContext;
+ SystemArgument1 = Apc->SystemArgument1;
+ SystemArgument2 = Apc->SystemArgument2;
+
+ /* Remove the APC from Queue, restore IRQL and call the APC */
+ RemoveEntryList(ApcListEntry);
+ Apc->Inserted = FALSE;
- KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
- DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
- KernelRoutine(Apc,
- &NormalRoutine,
- &NormalContext,
- &SystemArgument1,
- &SystemArgument2);
-
- if (NormalRoutine == NULL) {
-
- /* Check if more User APCs are Pending */
- KeTestAlertThread(UserMode);
-
- } else {
-
- /* Set up the Trap Frame and prepare for Execution in NTDLL.DLL */
- DPRINT("Delivering a User APC: %x\n", Apc);
- KiInitializeUserApc(Reserved,
- TrapFrame,
- NormalRoutine,
- NormalContext,
- SystemArgument1,
- SystemArgument2);
- }
-
- } else {
-
- /* Go back to APC_LEVEL */
- KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
- }
+ KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+ DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
+ KernelRoutine(Apc,
+ &NormalRoutine,
+ &NormalContext,
+ &SystemArgument1,
+ &SystemArgument2);
+
+ if (NormalRoutine == NULL) {
+ /* Check if more User APCs are Pending */
+ KeTestAlertThread(UserMode);
+ } else {
+ /* Set up the Trap Frame and prepare for Execution in NTDLL.DLL */
+ DPRINT("Delivering a User APC: %x\n", Apc);
+ KiInitializeUserApc(Reserved,
+ TrapFrame,
+ NormalRoutine,
+ NormalContext,
+ SystemArgument1,
+ SystemArgument2);
+ }
+ } else {
+ /* Go back to APC_LEVEL */
+ KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
+ }
}
VOID
STDCALL
KiFreeApcRoutine(PKAPC Apc,
- PKNORMAL_ROUTINE* NormalRoutine,
- PVOID* NormalContext,
- PVOID* SystemArgument1,
- PVOID* SystemArgument2)
+ PKNORMAL_ROUTINE* NormalRoutine,
+ PVOID* NormalContext,
+ PVOID* SystemArgument1,
+ PVOID* SystemArgument2)
{
- /* Free the APC and do nothing else */
- ExFreePool(Apc);
+ /* Free the APC and do nothing else */
+ ExFreePool(Apc);
}
-/*++
- * KiInitializeUserApc
- *
- * Prepares the Context for a User-Mode APC called through NTDLL.DLL
- *
- * Params:
- * Reserved - Pointer to the Exception Frame on non-i386 builds.
- *
- * TrapFrame - Pointer to the Trap Frame.
- *
- * NormalRoutine - Pointer to the NormalRoutine to call.
- *
- * NormalContext - Pointer to the context to send to the Normal Routine.
- *
- * SystemArgument[1-2] - Pointer to a set of two parameters that contain
- * untyped data.
- *
- * Returns:
- * None.
- *
- * Remarks:
- * None.
- *
- *--*/
-VOID
-STDCALL
+VOID
KiInitializeUserApc(IN PVOID Reserved,
- IN PKTRAP_FRAME TrapFrame,
- IN PKNORMAL_ROUTINE NormalRoutine,
- IN PVOID NormalContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2)
+ IN PKTRAP_FRAME TrapFrame,
+ IN PKNORMAL_ROUTINE NormalRoutine,
+ IN PVOID NormalContext,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2)
+/*
+ * FUNCTION: Prepares the Context for a user mode APC through ntdll.dll
+ */
{
- PCONTEXT Context;
- PULONG Esp;
+ PCONTEXT Context;
+ PULONG Esp;
- DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame, KeGetCurrentThread()->TrapFrame);
+ DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame, KeGetCurrentThread()->TrapFrame);
- /*
- * Save the thread's current context (in other words the registers
- * that will be restored when it returns to user mode) so the
- * APC dispatcher can restore them later
- */
- Context = (PCONTEXT)(((PUCHAR)TrapFrame->Esp) - sizeof(CONTEXT));
- RtlZeroMemory(Context, sizeof(CONTEXT));
- Context->ContextFlags = CONTEXT_FULL;
- Context->SegGs = TrapFrame->Gs;
- Context->SegFs = TrapFrame->Fs;
- Context->SegEs = TrapFrame->Es;
- Context->SegDs = TrapFrame->Ds;
- Context->Edi = TrapFrame->Edi;
- Context->Esi = TrapFrame->Esi;
- Context->Ebx = TrapFrame->Ebx;
- Context->Edx = TrapFrame->Edx;
- Context->Ecx = TrapFrame->Ecx;
- Context->Eax = TrapFrame->Eax;
- Context->Ebp = TrapFrame->Ebp;
- Context->Eip = TrapFrame->Eip;
- Context->SegCs = TrapFrame->Cs;
- Context->EFlags = TrapFrame->Eflags;
- Context->Esp = TrapFrame->Esp;
- Context->SegSs = TrapFrame->Ss;
+ /*
+ * Save the thread's current context (in other words the registers
+ * that will be restored when it returns to user mode) so the
+ * APC dispatcher can restore them later
+ */
+ Context = (PCONTEXT)(((PUCHAR)TrapFrame->Esp) - sizeof(CONTEXT));
+ RtlZeroMemory(Context, sizeof(CONTEXT));
+ Context->ContextFlags = CONTEXT_FULL;
+ Context->SegGs = TrapFrame->Gs;
+ Context->SegFs = TrapFrame->Fs;
+ Context->SegEs = TrapFrame->Es;
+ Context->SegDs = TrapFrame->Ds;
+ Context->Edi = TrapFrame->Edi;
+ Context->Esi = TrapFrame->Esi;
+ Context->Ebx = TrapFrame->Ebx;
+ Context->Edx = TrapFrame->Edx;
+ Context->Ecx = TrapFrame->Ecx;
+ Context->Eax = TrapFrame->Eax;
+ Context->Ebp = TrapFrame->Ebp;
+ Context->Eip = TrapFrame->Eip;
+ Context->SegCs = TrapFrame->Cs;
+ Context->EFlags = TrapFrame->Eflags;
+ Context->Esp = TrapFrame->Esp;
+ Context->SegSs = TrapFrame->Ss;
- /*
- * Setup the trap frame so the thread will start executing at the
- * APC Dispatcher when it returns to user-mode
- */
- Esp = (PULONG)(((PUCHAR)TrapFrame->Esp) - (sizeof(CONTEXT) + (6 * sizeof(ULONG))));
- Esp[0] = 0xdeadbeef;
- Esp[1] = (ULONG)NormalRoutine;
- Esp[2] = (ULONG)NormalContext;
- Esp[3] = (ULONG)SystemArgument1;
- Esp[4] = (ULONG)SystemArgument2;
- Esp[5] = (ULONG)Context;
- TrapFrame->Eip = (ULONG)LdrpGetSystemDllApcDispatcher();
- TrapFrame->Esp = (ULONG)Esp;
+ /*
+ * Setup the trap frame so the thread will start executing at the
+ * APC Dispatcher when it returns to user-mode
+ */
+ Esp = (PULONG)(((PUCHAR)TrapFrame->Esp) - (sizeof(CONTEXT) + (6 * sizeof(ULONG))));
+ Esp[0] = 0xdeadbeef;
+ Esp[1] = (ULONG)NormalRoutine;
+ Esp[2] = (ULONG)NormalContext;
+ Esp[3] = (ULONG)SystemArgument1;
+ Esp[4] = (ULONG)SystemArgument2;
+ Esp[5] = (ULONG)Context;
+ TrapFrame->Eip = (ULONG)LdrpGetSystemDllApcDispatcher();
+ TrapFrame->Esp = (ULONG)Esp;
}
-/*++
- * KeAreApcsDisabled
- * @implemented NT4
- *
- * Prepares the Context for a User-Mode APC called through NTDLL.DLL
- *
- * Params:
- * None.
- *
- * Returns:
- * KeAreApcsDisabled returns TRUE if the thread is within a critical region
- * or a guarded region, and FALSE otherwise.
- *
- * Remarks:
- * A thread running at IRQL = PASSIVE_LEVEL can use KeAreApcsDisabled to
- * determine if normal kernel APCs are disabled. A thread that is inside a
- * critical region has both user APCs and normal kernel APCs disabled, but
- * not special kernel APCs. A thread that is inside a guarded region has
- * all APCs disabled, including special kernel APCs.
- *
- * Callers of this routine must be running at IRQL <= APC_LEVEL.
- *
- *--*/
+/*
+ * @implemented
+ */
BOOLEAN
STDCALL
-KeAreApcsDisabled(VOID)
+KeAreApcsDisabled(
+ VOID
+ )
{
- /* Return the Kernel APC State */
- return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
+ return KeGetCurrentThread()->KernelApcDisable ? TRUE : FALSE;
}
-/*++
- * NtQueueApcThread
- * NT4
- *
- * This routine is used to queue an APC from user-mode for the specified
- * thread.
- *
- * Params:
- * Thread Handle - Handle to the Thread. This handle must have THREAD_SET_CONTEXT privileges.
- *
- * ApcRoutine - Pointer to the APC Routine to call when the APC executes.
- *
- * NormalContext - Pointer to the context to send to the Normal Routine.
- *
- * SystemArgument[1-2] - Pointer to a set of two parameters that contain
- * untyped data.
- *
- * Returns:
- * STATUS_SUCCESS or failure cute from associated calls.
- *
- * Remarks:
- * The thread must enter an alertable wait before the APC will be
- * delivered.
- *
- *--*/
NTSTATUS
STDCALL
-NtQueueApcThread(HANDLE ThreadHandle,
- PKNORMAL_ROUTINE ApcRoutine,
- PVOID NormalContext,
- PVOID SystemArgument1,
- PVOID SystemArgument2)
+NtQueueApcThread(HANDLE ThreadHandle,
+ PKNORMAL_ROUTINE ApcRoutine,
+ PVOID NormalContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2)
+/*
+ * FUNCTION:
+ * This function is used to queue an APC from user-mode for the specified thread.
+ * The thread must enter an alertable wait before the APC will be delivered.
+ *
+ * ARGUMENTS:
+ * Thread Handle - Handle to the Thread. This handle must have THREAD_SET_CONTEXT privileges.
+ * ApcRoutine - Pointer to the APC Routine to call when the APC executes.
+ * NormalContext - User-defined value to pass to the APC Routine
+ * SystemArgument1 - User-defined value to pass to the APC Routine
+ * SystemArgument2 - User-defined value to pass to the APC Routine
+ *
+ * RETURNS: NTSTATUS SUCCESS or Failure Code from included calls.
+ */
{
- PKAPC Apc;
- PETHREAD Thread;
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- NTSTATUS Status;
-
- /* Get ETHREAD from Handle */
- Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_SET_CONTEXT,
- PsThreadType,
- PreviousMode,
- (PVOID)&Thread,
- NULL);
-
- /* Fail if the Handle is invalid for some reason */
- if (!NT_SUCCESS(Status)) {
-
- return(Status);
- }
-
- /* If this is a Kernel or System Thread, then fail */
- if (Thread->Tcb.Teb == NULL) {
-
- ObDereferenceObject(Thread);
- return STATUS_INVALID_HANDLE;
- }
+
+ PKAPC Apc;
+ PETHREAD Thread;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status;
+
+ PreviousMode = ExGetPreviousMode();
+
+ /* Get ETHREAD from Handle */
+ Status = ObReferenceObjectByHandle(ThreadHandle,
+ THREAD_SET_CONTEXT,
+ PsThreadType,
+ PreviousMode,
+ (PVOID)&Thread,
+ NULL);
+
+ /* Fail if the Handle is invalid for some reason */
+ if (!NT_SUCCESS(Status)) {
+ return(Status);
+ }
+
+ /* If this is a Kernel or System Thread, then fail */
+ if (Thread->Tcb.Teb == NULL) {
+ ObDereferenceObject(Thread);
+ return STATUS_INVALID_HANDLE;
+ }
- /* Allocate an APC */
- Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG('P', 's', 'a', 'p'));
- if (Apc == NULL) {
-
- ObDereferenceObject(Thread);
- return(STATUS_NO_MEMORY);
- }
+ /* Allocate an APC */
+ Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC);
+ if (Apc == NULL) {
+ ObDereferenceObject(Thread);
+ return(STATUS_NO_MEMORY);
+ }
- /* Initialize and Queue a user mode apc (always!) */
- KeInitializeApc(Apc,
- &Thread->Tcb,
- OriginalApcEnvironment,
- KiFreeApcRoutine,
- NULL,
- ApcRoutine,
- UserMode,
- NormalContext);
-
- if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) {
-
- Status = STATUS_UNSUCCESSFUL;
-
- } else {
-
- Status = STATUS_SUCCESS;
- }
+ /* Initialize and Queue a user mode apc (always!) */
+ KeInitializeApc(Apc,
+ &Thread->Tcb,
+ OriginalApcEnvironment,
+ KiFreeApcRoutine,
+ NULL,
+ ApcRoutine,
+ UserMode,
+ NormalContext);
+ if (!KeInsertQueueApc(Apc, SystemArgument1, SystemArgument2, IO_NO_INCREMENT)) {
+ Status = STATUS_UNSUCCESSFUL;
+ } else {
+ Status = STATUS_SUCCESS;
+ }
- /* Dereference Thread and Return */
- ObDereferenceObject(Thread);
- return Status;
+ /* Dereference Thread and Return */
+ ObDereferenceObject(Thread);
+ return Status;
}
-static inline
-VOID RepairList(PLIST_ENTRY Original,
- PLIST_ENTRY Copy,
- KPROCESSOR_MODE Mode)
+
+static inline VOID RepairList(PLIST_ENTRY Original,
+ PLIST_ENTRY Copy,
+ KPROCESSOR_MODE Mode)
{
- /* Copy Source to Desination */
- if (IsListEmpty(&Original[(int)Mode])) {
-
- InitializeListHead(&Copy[(int)Mode]);
-
- } else {
-
- Copy[(int)Mode].Flink = Original[(int)Mode].Flink;
- Copy[(int)Mode].Blink = Original[(int)Mode].Blink;
- Original[(int)Mode].Flink->Blink = &Copy[(int)Mode];
- Original[(int)Mode].Blink->Flink = &Copy[(int)Mode];
- }
+ /* Copy Source to Desination */
+ if (IsListEmpty(&Original[(int)Mode])) {
+ InitializeListHead(&Copy[(int)Mode]);
+ } else {
+ Copy[(int)Mode].Flink = Original[(int)Mode].Flink;
+ Copy[(int)Mode].Blink = Original[(int)Mode].Blink;
+ Original[(int)Mode].Flink->Blink = &Copy[(int)Mode];
+ Original[(int)Mode].Blink->Flink = &Copy[(int)Mode];
+ }
}
VOID
STDCALL
-KiMoveApcState(PKAPC_STATE OldState,
- PKAPC_STATE NewState)
+KiMoveApcState (PKAPC_STATE OldState,
+ PKAPC_STATE NewState)
{
- /* Restore backup of Original Environment */
- *NewState = *OldState;
+ /* Restore backup of Original Environment */
+ *NewState = *OldState;
- /* Repair Lists */
- RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
- RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
+ /* Repair Lists */
+ RepairList(NewState->ApcListHead, OldState->ApcListHead, KernelMode);
+ RepairList(NewState->ApcListHead, OldState->ApcListHead, UserMode);
}
return FALSE;
}
-/*
- * @unimplemented
- */
-BOOLEAN
-STDCALL
-KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
-{
- UNIMPLEMENTED;
- return FALSE;
-}
-
/*
* @implemented
*/
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,
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/catch.c
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
-/*
- * @unimplemented
- */
VOID
-STDCALL
-KiCoprocessorError(VOID)
+KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
+ PCONTEXT Context,
+ PKTRAP_FRAME Tf,
+ KPROCESSOR_MODE PreviousMode,
+ BOOLEAN SearchFrames)
{
- UNIMPLEMENTED;
-}
+ EXCEPTION_DISPOSITION Value;
+ CONTEXT TContext;
+ KD_CONTINUE_TYPE Action = kdHandleException;
-/*
- * @unimplemented
- */
-VOID
-STDCALL
-KiUnexpectedInterrupt(VOID)
-{
- UNIMPLEMENTED;
-}
+ DPRINT("KiDispatchException() called\n");
-VOID
-KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
- PCONTEXT Context,
- PKTRAP_FRAME Tf,
- KPROCESSOR_MODE PreviousMode,
- BOOLEAN SearchFrames)
-{
- EXCEPTION_DISPOSITION Value;
- CONTEXT TContext;
- KD_CONTINUE_TYPE Action = kdHandleException;
-
- DPRINT("KiDispatchException() called\n");
-
- /* Increase number of Exception Dispatches */
- KeGetCurrentKPCR()->PrcbData.KeExceptionDispatchCount++;
-
- 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;
- }
+
+ /* PCR->KeExceptionDispatchCount++; */
+
+ if (Context == NULL)
+ {
+ TContext.ContextFlags = CONTEXT_FULL;
+ if (PreviousMode == UserMode)
+ {
+ TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
+ }
- /* Convert the Trapframe into a Context */
- KeTrapFrameToContext(Tf, &TContext);
+ KeTrapFrameToContext(Tf, &TContext);
- /* Use local stack context */
- Context = &TContext;
+ Context = &TContext;
}
-#if 0 /* FIXME: Isn't this right? With a break after? */
- if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
- Context->Eip--;
+#if 0
+ if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
+ {
+ Context->Eip--;
}
#endif
+
+ if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
+ {
+ Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
+ }
- /* Check if a Debugger is enabled */
- if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) {
-
- /* Break into it */
- Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
+ if (Action == kdContinue)
+ {
+ return;
}
-
- /* 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) {
-
- 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;
+
+ 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;
#ifdef KDBG
- /* Enter KDB if available */
- Action = KdbEnterDebuggerException(ExceptionRecord,
- PreviousMode,
- Context,
- Tf,
- FALSE);
-
- /* Exit if we're continuing */
- if (Action == kdContinue) return;
+ Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+ Context, Tf, FALSE);
+ if (Action == kdContinue)
+ {
+ return;
+ }
#endif
- /* FIXME: Forward exception to user mode debugger */
-
- /* 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 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));
- /* FIXME: Forward the exception to the debugger */
+ 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 process exception port */
+ /* 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;
+ Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+ Context, Tf, TRUE);
+ if (Action == kdContinue)
+ {
+ return;
+ }
#endif
- /* Terminate the offending thread */
- DPRINT1("Unhandled UserMode exception, terminating thread\n");
- ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
-
- } else {
-
- /* This is Kernel Mode */
+ /* Terminate the offending thread */
+ DPRINT1("Unhandled UserMode exception, terminating thread\n");
+ ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
+ }
+ else
+ {
+ /* PreviousMode == KernelMode */
#ifdef KDBG
- /* Enter KDB if available */
- Action = KdbEnterDebuggerException(ExceptionRecord,
- PreviousMode,
- Context,
- Tf,
- FALSE);
-
- /* Exit if we're continuing */
- if (Action == kdContinue) return;
+ Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+ Context, Tf, FALSE);
+ 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);
+ 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
- /* Enter KDB if available */
- Action = KdbEnterDebuggerException(ExceptionRecord,
- PreviousMode,
- Context,
- Tf,
- TRUE);
-
- /* Exit if we're continuing */
- if (Action == kdContinue) return;
+ Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
+ Context, Tf, TRUE);
+ if (Action == kdContinue)
+ {
+ return;
+ }
#endif
- KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
- }
- }
+ 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 */
--- /dev/null
+/* $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 */
/* 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);
*/
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.
* NOTE: Callers can be running at any IRQL.
*/
{
- 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;
+ 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;
}
/*
* @implemented
- *
+ */
+VOID
+STDCALL
+KeInitializeDpc (PKDPC Dpc,
+ PKDEFERRED_ROUTINE DeferredRoutine,
+ PVOID DeferredContext)
+/*
* FUNCTION:
* Initalizes a DPC and registers the DeferredRoutine for it.
* ARGUMENTS:
* 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 = DpcObject;
- 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 = KDpc;
+ 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
* 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;
-
- 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 == ThreadedDpcObject) {
- return FALSE;
- KeLowerIrql(OldIrql);
- }
+ KIRQL OldIrql;
+ PKPCR Pcr;
+
+ 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);
+ //}
#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));
- }
-
- /* 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);
+ 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);
- /* 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;
- }
- }
+ /* 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
- 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:
* 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;
}
/*
* Called when deleting a Driver.
*/
{
- /* Request an interrupt if needed */
- if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+ if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
/*
BOOLEAN
STDCALL
KeIsExecutingDpc(
- VOID
+ VOID
)
{
- /* Return if the Dpc Routine is active */
- return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
+ return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
}
/*
*/
VOID
STDCALL
-KeSetImportanceDpc (IN PKDPC Dpc,
- IN KDPC_IMPORTANCE Importance)
+KeSetImportanceDpc (IN PKDPC Dpc,
+ IN KDPC_IMPORTANCE Importance)
{
- /* Set the DPC Importance */
- Dpc->Importance = 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)
{
- /* 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;
- }
+ if (Number >= MAXIMUM_PROCESSORS)
+ {
+ Dpc->Number = 0;
+ }
+ else
+ {
+ 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
* 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) {
-
- /* 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);
-}
+ 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);
+}
/*
* @implemented
- *
- * 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)
+/*
+ * FUNCTION:
+ * Called whenever a system interrupt is generated at DISPATCH_LEVEL.
+ * It delivers queued DPCs and dispatches a new thread if need be.
+ */
{
- PLIST_ENTRY DpcEntry;
- PKDPC Dpc;
- KIRQL OldIrql;
- PKPCR Pcr;
-
- DPRINT("Dispatching Interrupts\n");
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
-
- /* 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);
+ PLIST_ENTRY DpcEntry;
+ PKDPC Dpc;
+ KIRQL OldIrql;
+ PKPCR Pcr;
+
+ DPRINT("Dispatching Interrupts\n");
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ /* 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);
#endif
- 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--;
+ 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--;
#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 */
--- /dev/null
+/* $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 */
/*
* @implemented
*/
-VOID
-STDCALL
-KeClearEvent(PKEVENT Event)
+VOID STDCALL KeClearEvent (PKEVENT Event)
{
- DPRINT("KeClearEvent(Event %x)\n", Event);
-
- /* Reset Signal State */
- Event->Header.SignalState = FALSE;
+ DPRINT("KeClearEvent(Event %x)\n", Event);
+ 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)
{
- DPRINT("KeInitializeEvent(Event %x)\n", Event);
-
- /* Initialize the Dispatcher Header */
- KeInitializeDispatcherHeader(&Event->Header,
- Type,
- sizeof(Event) / sizeof(ULONG),
- State);
+ ULONG IType;
+
+ if (Type == NotificationEvent)
+ {
+ IType = InternalNotificationEvent;
+ }
+ else if (Type == SynchronizationEvent)
+ {
+ IType = InternalSynchronizationEvent;
+ }
+ else
+ {
+ ASSERT(FALSE);
+ return;
+ }
+
+ KeInitializeDispatcherHeader(&(Event->Header),
+ IType,
+ sizeof(Event)/sizeof(ULONG),State);
+ InitializeListHead(&(Event->Header.WaitListHead));
}
/*
* @implemented
*/
-VOID
-STDCALL
-KeInitializeEventPair(PKEVENT_PAIR EventPair)
+LONG STDCALL KeReadStateEvent (PKEVENT Event)
{
- 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);
+ return(Event->Header.SignalState);
}
/*
* @implemented
*/
-LONG STDCALL
-KePulseEvent(IN PKEVENT Event,
- IN KPRIORITY Increment,
- IN BOOLEAN Wait)
+LONG STDCALL KeResetEvent (PKEVENT Event)
{
- KIRQL OldIrql;
- LONG PreviousState;
-
- DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
-
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Save the Old State */
- PreviousState = Event->Header.SignalState;
-
- /* Check if we are non-signaled and we have stuff in the Wait Queue */
- if (!PreviousState && !IsListEmpty(&Event->Header.WaitListHead)) {
-
- /* Set the Event to Signaled */
- Event->Header.SignalState = 1;
-
- /* Wake the Event */
- KiWaitTest(&Event->Header, Increment);
- }
-
- /* Unsignal it */
- Event->Header.SignalState = 0;
-
- /* Check what wait state was requested */
- if (Wait == FALSE) {
-
- /* Wait not requested, release Dispatcher Database and return */
- KeReleaseDispatcherDatabaseLock(OldIrql);
-
- } else {
-
- /* Return Locked and with a Wait */
- KTHREAD *Thread = KeGetCurrentThread();
- Thread->WaitNext = TRUE;
- Thread->WaitIrql = OldIrql;
- }
-
- /* Return the previous State */
- return PreviousState;
+ /* FIXME: must use interlocked func. everywhere! (wait.c)
+ * or use dispather lock instead
+ * -Gunnar */
+ return(InterlockedExchange(&(Event->Header.SignalState),0));
}
/*
* @implemented
*/
-LONG
-STDCALL
-KeReadStateEvent(PKEVENT Event)
+LONG STDCALL KeSetEvent (PKEVENT Event,
+ KPRIORITY Increment,
+ BOOLEAN Wait)
{
- /* Return the Signal State */
- return Event->Header.SignalState;
-}
+ KIRQL OldIrql;
+ int ret;
-/*
- * @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;
+ DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+
+ ret = InterlockedExchange(&Event->Header.SignalState,1);
+
+ KiDispatcherObjectWake(&Event->Header, Increment);
+
+ if (Wait == FALSE)
+ {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ }
+ else
+ {
+ KTHREAD *Thread = KeGetCurrentThread();
+ Thread->WaitNext = TRUE;
+ Thread->WaitIrql = OldIrql;
+ }
+
+ return(ret);
}
/*
* @implemented
*/
-LONG
-STDCALL
-KeSetEvent(PKEVENT Event,
- KPRIORITY Increment,
- BOOLEAN Wait)
+LONG STDCALL
+KePulseEvent (IN PKEVENT Event,
+ IN KPRIORITY Increment,
+ IN 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);
- }
+ KIRQL OldIrql;
+ LONG Ret;
+
+ DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+ Ret = InterlockedExchange(&Event->Header.SignalState,1);
+ KiDispatcherObjectWake(&Event->Header, Increment);
+ InterlockedExchange(&(Event->Header.SignalState),0);
+
+ if (Wait == FALSE)
+ {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
}
-
- /* 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;
+ else
+ {
+ KTHREAD *Thread = KeGetCurrentThread();
+ Thread->WaitNext = TRUE;
+ Thread->WaitIrql = OldIrql;
}
- /* Return the previous State */
- DPRINT("Done: %d\n", PreviousState);
- return PreviousState;
+ return Ret;
}
/*
*/
VOID
STDCALL
-KeSetEventBoostPriority(IN PKEVENT Event,
- IN PKTHREAD *Thread OPTIONAL)
+KeSetEventBoostPriority(
+ IN PKEVENT Event,
+ IN PKTHREAD *Thread OPTIONAL
+)
{
- 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);
- }
+ PKTHREAD WaitingThread;
+ KIRQL OldIrql;
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+
+ /* 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);
- /* Release the Dispatcher Database Lock */
- KeReleaseDispatcherDatabaseLock(OldIrql);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
}
/* EOF */
*/
sti
- call @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
+ call _KeReleaseDispatcherDatabaseLockFromDpcLevel
cmpl $0, _PiNrThreadsAwaitingReaping
je 5f
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/kthread.c
* PURPOSE: Microkernel thread support
*
- * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Commented, reorganized some stuff, fixed/implemented some functions.
- * David Welch (welch@cwcom.net)
+ * PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
/* FUNCTIONS *****************************************************************/
-ULONG
-STDCALL
-KeAlertResumeThread(IN PKTHREAD Thread)
+VOID
+KiServiceCheck (VOID)
{
- ULONG PreviousCount;
- KIRQL OldIrql;
-
- ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-
- /* Lock the Dispatcher Database and the APC Queue */
- OldIrql = KeAcquireDispatcherDatabaseLock();
- KiAcquireSpinLock(&Thread->ApcQueueLock);
-
- /* Return if Thread is already alerted. */
- if (Thread->Alerted[KernelMode] == FALSE) {
-
- /* If it's Blocked, unblock if it we should */
- if (Thread->State == THREAD_STATE_BLOCKED && Thread->Alertable) {
-
- DPRINT("Aborting Wait\n");
- KiAbortWaitThread(Thread, STATUS_ALERTED);
-
- } else {
-
- /* If not, simply Alert it */
- Thread->Alerted[KernelMode] = TRUE;
- }
- }
-
- /* Save the old Suspend Count */
- PreviousCount = Thread->SuspendCount;
-
- /* If the thread is suspended, decrease one of the suspend counts */
- if (PreviousCount) {
-
- /* Decrease count. If we are now zero, unwait it completely */
- if (--Thread->SuspendCount) {
-
- /* Signal and satisfy */
- Thread->SuspendSemaphore.Header.SignalState++;
- KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
- }
- }
+ PETHREAD Thread;
- /* Release Locks and return the Old State */
- KiReleaseSpinLock(&Thread->ApcQueueLock);
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return PreviousCount;
-}
+ Thread = PsGetCurrentThread();
-BOOLEAN
-STDCALL
-KeAlertThread(PKTHREAD Thread,
- KPROCESSOR_MODE AlertMode)
-{
- KIRQL OldIrql;
- BOOLEAN PreviousState;
+ if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow)
+ {
+ PsInitWin32Thread (Thread);
- /* Acquire the Dispatcher Database Lock */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Save the Previous State */
- PreviousState = Thread->Alerted[AlertMode];
-
- /* Return if Thread is already alerted. */
- if (PreviousState == FALSE) {
-
- /* If it's Blocked, unblock if it we should */
- if (Thread->State == THREAD_STATE_BLOCKED &&
- (AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
- Thread->Alertable) {
-
- DPRINT("Aborting Wait\n");
- KiAbortWaitThread(Thread, STATUS_ALERTED);
-
- } else {
-
- /* If not, simply Alert it */
- Thread->Alerted[AlertMode] = TRUE;
- }
+ Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
}
-
- /* Release the Dispatcher Lock */
- KeReleaseDispatcherDatabaseLock(OldIrql);
-
- /* Return the old state */
- return PreviousState;
}
/*
*/
VOID
STDCALL
-KeCapturePersistentThreadState(IN PVOID CurrentThread,
- IN ULONG Setting1,
- IN ULONG Setting2,
- IN ULONG Setting3,
- IN ULONG Setting4,
- IN ULONG Setting5,
- IN PVOID ThreadState)
+KeCapturePersistentThreadState(
+ IN PVOID CurrentThread,
+ IN ULONG Setting1,
+ IN ULONG Setting2,
+ IN ULONG Setting3,
+ IN ULONG Setting4,
+ IN ULONG Setting5,
+ IN PVOID ThreadState
+)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED;
}
-/*
- * FUNCTION: Initialize the microkernel state of the thread
- */
VOID
-STDCALL
-KeInitializeThread(PKPROCESS Process,
- PKTHREAD Thread,
- BOOLEAN First)
+KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
+ PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
{
- PVOID KernelStack;
- NTSTATUS Status;
- extern unsigned int init_stack_top;
- extern unsigned int init_stack;
- PMEMORY_AREA StackArea;
- ULONG i;
- PHYSICAL_ADDRESS BoundaryAddressMultiple;
-
- /* Initialize the Boundary Address */
- BoundaryAddressMultiple.QuadPart = 0;
-
- /* Initalize the Dispatcher Header */
- KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
- ThreadObject,
- sizeof(KTHREAD),
- FALSE);
- InitializeListHead(&Thread->MutantListHead);
-
- /* If this is isn't the first thread, allocate the Kernel Stack */
- if (!First) {
-
- PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
- KernelStack = NULL;
-
- MmLockAddressSpace(MmGetKernelAddressSpace());
- Status = MmCreateMemoryArea(NULL,
- MmGetKernelAddressSpace(),
- MEMORY_AREA_KERNEL_STACK,
- &KernelStack,
- MM_STACK_SIZE,
- 0,
- &StackArea,
- FALSE,
- FALSE,
- BoundaryAddressMultiple);
- MmUnlockAddressSpace(MmGetKernelAddressSpace());
-
- /* Check for Success */
- if (!NT_SUCCESS(Status)) {
-
- DPRINT1("Failed to create thread stack\n");
- KEBUGCHECK(0);
- }
-
- /* Mark the Stack */
- for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) {
-
- Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
-
- /* Check for success */
- if (!NT_SUCCESS(Status)) {
-
- KEBUGCHECK(0);
- }
- }
-
- /* Create a Virtual Mapping for it */
- Status = MmCreateVirtualMapping(NULL,
- KernelStack,
- PAGE_READWRITE,
- Page,
- MM_STACK_SIZE / PAGE_SIZE);
-
- /* Check for success */
- if (!NT_SUCCESS(Status)) {
-
- KEBUGCHECK(0);
- }
-
- /* Set the Kernel Stack */
- Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
- Thread->StackBase = (PCHAR)KernelStack + MM_STACK_SIZE;
- Thread->StackLimit = (ULONG_PTR)KernelStack;
- Thread->KernelStack = (PCHAR)KernelStack + MM_STACK_SIZE;
-
- } else {
-
- /* Use the Initial Stack */
- Thread->InitialStack = (PCHAR)init_stack_top;
- Thread->StackBase = (PCHAR)init_stack_top;
- Thread->StackLimit = (ULONG_PTR)init_stack;
- Thread->KernelStack = (PCHAR)init_stack_top;
+ ASSERT(SwapEntry == 0);
+ if (Page != 0)
+ {
+ MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
}
-
- /*
- * Establish the pde's for the new stack and the thread structure within the
- * address space of the new process. They are accessed while taskswitching or
- * while handling page faults. At this point it isn't possible to call the
- * page fault handler for the missing pde's.
- */
- MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
- MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
-
- /* Set the Thread to initalized */
- Thread->State = THREAD_STATE_INITIALIZED;
-
- /* The Native API function will initialize the TEB field later */
- Thread->Teb = NULL;
-
- /* Initialize stuff to zero */
- Thread->TlsArray = NULL;
- Thread->DebugActive = 0;
- Thread->Alerted[0] = 0;
- Thread->Alerted[1] = 0;
- Thread->Iopl = 0;
-
- /* FIXME: Think how this might work */
- Thread->NpxState = 0;
- Thread->NpxIrql = 0;
-
- /* Setup APC Fields */
- InitializeListHead(&Thread->ApcState.ApcListHead[0]);
- InitializeListHead(&Thread->ApcState.ApcListHead[1]);
- Thread->ApcState.Process = Process;
- Thread->ApcState.KernelApcInProgress = 0;
- Thread->ApcState.KernelApcPending = 0;
- Thread->ApcState.UserApcPending = 0;
- Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
- Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
- Thread->ApcStateIndex = OriginalApcEnvironment;
- Thread->ApcQueueable = TRUE;
- memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
- KeInitializeSpinLock(&Thread->ApcQueueLock);
-
- /* Setup Wait Fields */
- Thread->WaitStatus = STATUS_SUCCESS;
- Thread->WaitIrql = PASSIVE_LEVEL;
- Thread->WaitMode = 0;
- Thread->WaitNext = FALSE;
- Thread->WaitListEntry.Flink = NULL;
- Thread->WaitListEntry.Blink = NULL;
- Thread->WaitTime = 0;
- Thread->WaitBlockList = NULL;
- memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK) * 4);
- memset(&Thread->Timer, 0, sizeof(KTIMER));
- KeInitializeTimer(&Thread->Timer);
-
- /* Setup scheduler Fields */
- Thread->BasePriority = Process->BasePriority;
- Thread->DecrementCount = 0;
- Thread->PriorityDecrement = 0;
- Thread->Quantum = Process->ThreadQuantum;
- Thread->Saturation = 0;
- Thread->Priority = Process->BasePriority;
- Thread->UserAffinity = Process->Affinity;
- Thread->SystemAffinityActive = 0;
- Thread->Affinity = Process->Affinity;
- Thread->Preempted = 0;
- Thread->ProcessReadyQueue = 0;
- Thread->KernelStackResident = 1;
- Thread->NextProcessor = 0;
- Thread->ContextSwitches = 0;
-
- /* Setup Queue Fields */
- Thread->Queue = NULL;
- Thread->QueueListEntry.Flink = NULL;
- Thread->QueueListEntry.Blink = NULL;
-
- /* Setup Misc Fields */
- Thread->LegoData = 0;
- Thread->PowerState = 0;
- Thread->ServiceTable = KeServiceDescriptorTable;
- Thread->CallbackStack = NULL;
- Thread->Win32Thread = NULL;
- Thread->TrapFrame = NULL;
- Thread->EnableStackSwap = 0;
- Thread->LargeStack = 0;
- Thread->ResourceIndex = 0;
- Thread->PreviousMode = KernelMode;
- Thread->KernelTime = 0;
- Thread->UserTime = 0;
- Thread->AutoAlignment = Process->AutoAlignment;
-
- /* FIXME OPTIMIZATION OF DOOM. DO NOT ENABLE FIXME */
-#if 0
- Thread->WaitBlock[3].Object = (PVOID)&Thread->Timer;
- Thread->WaitBlock[3].Thread = Thread;
- Thread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
- Thread->WaitBlock[3].WaitType = WaitAny;
- Thread->WaitBlock[3].NextWaitBlock = NULL;
- InsertTailList(&Thread->Timer.Header.WaitListHead,
- &Thread->WaitBlock[3].WaitListEntry);
-#endif
-
- /* Initialize the Suspend APC */
- KeInitializeApc(&Thread->SuspendApc,
- Thread,
- OriginalApcEnvironment,
- PiSuspendThreadKernelRoutine,
- PiSuspendThreadRundownRoutine,
- PiSuspendThreadNormalRoutine,
- KernelMode,
- NULL);
-
- /* Initialize the Suspend Semaphore */
- KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
-
- /* Insert the Thread into the Process's Thread List */
- InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
-
- /* Set up the Suspend Counts */
- Thread->FreezeCount = 0;
- Thread->SuspendCount = 0;
-
- /* Do x86 specific part */
}
/*
*/
KPRIORITY
STDCALL
-KeQueryPriorityThread (IN PKTHREAD Thread)
+KeQueryPriorityThread (
+ IN PKTHREAD Thread
+ )
{
- return Thread->Priority;
+ return Thread->Priority;
}
/*
*/
ULONG
STDCALL
-KeQueryRuntimeThread(IN PKTHREAD Thread,
- OUT PULONG UserTime)
-{
- /* Return the User Time */
- *UserTime = Thread->UserTime;
-
- /* Return the Kernel Time */
- return Thread->KernelTime;
-}
-
-VOID
-KeFreeStackPage(PVOID Context,
- MEMORY_AREA* MemoryArea,
- PVOID Address,
- PFN_TYPE Page,
- SWAPENTRY SwapEntry,
- BOOLEAN Dirty)
+KeQueryRuntimeThread(
+ IN PKTHREAD Thread,
+ OUT PULONG UserTime
+ )
{
- ASSERT(SwapEntry == 0);
- if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
+ /* Return the User Time */
+ *UserTime = Thread->UserTime;
+
+ /* Return the Kernel Time */
+ return Thread->KernelTime;
}
-NTSTATUS
+NTSTATUS
KeReleaseThread(PKTHREAD Thread)
/*
* FUNCTION: Releases the resource allocated for a thread by
*/
BOOLEAN
STDCALL
-KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
+KeSetKernelStackSwapEnable(
+ IN BOOLEAN Enable
+ )
{
- PKTHREAD Thread = KeGetCurrentThread();
- BOOLEAN PreviousState;
- KIRQL OldIrql;
-
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Save Old State */
- PreviousState = Thread->EnableStackSwap;
-
- /* Set New State */
- Thread->EnableStackSwap = Enable;
-
- /* No, Release Lock */
- KeReleaseDispatcherDatabaseLock(OldIrql);
-
- /* Return Old State */
- return PreviousState;
+ PKTHREAD Thread;
+ BOOLEAN PreviousState;
+
+ Thread = KeGetCurrentThread();
+
+ /* Save Old State */
+ PreviousState = Thread->EnableStackSwap;
+
+ /* Set New State */
+ Thread->EnableStackSwap = Enable;
+
+ /* Return Old State */
+ return PreviousState;
}
+VOID
+KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
/*
- * @implemented
+ * FUNCTION: Initialize the microkernel state of the thread
*/
-VOID
-STDCALL
-KeRevertToUserAffinityThread(VOID)
{
- PKTHREAD CurrentThread = KeGetCurrentThread();
- KIRQL OldIrql;
-
- ASSERT(CurrentThread->SystemAffinityActive != FALSE);
-
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Return to User Affinity */
- CurrentThread->Affinity = CurrentThread->UserAffinity;
-
- /* Disable System Affinity */
- CurrentThread->SystemAffinityActive = FALSE;
-
- /* Check if we need to Dispatch a New thread */
- if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber())) {
-
- /* No, just release */
- KeReleaseDispatcherDatabaseLock(OldIrql);
-
- } else {
-
- /* We need to dispatch a new thread */
- CurrentThread->WaitIrql = OldIrql;
- PsDispatchThreadNoLock(THREAD_STATE_READY);
- KeLowerIrql(OldIrql);
+ PVOID KernelStack;
+ NTSTATUS Status;
+ extern unsigned int init_stack_top;
+ extern unsigned int init_stack;
+ PMEMORY_AREA StackArea;
+ ULONG i;
+ PHYSICAL_ADDRESS BoundaryAddressMultiple;
+
+ BoundaryAddressMultiple.QuadPart = 0;
+
+ KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
+ InternalThreadType,
+ sizeof(ETHREAD),
+ FALSE);
+ InitializeListHead(&Thread->MutantListHead);
+ if (!First)
+ {
+ PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
+ KernelStack = NULL;
+
+ MmLockAddressSpace(MmGetKernelAddressSpace());
+ Status = MmCreateMemoryArea(NULL,
+ MmGetKernelAddressSpace(),
+ MEMORY_AREA_KERNEL_STACK,
+ &KernelStack,
+ MM_STACK_SIZE,
+ 0,
+ &StackArea,
+ FALSE,
+ FALSE,
+ BoundaryAddressMultiple);
+ MmUnlockAddressSpace(MmGetKernelAddressSpace());
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create thread stack\n");
+ KEBUGCHECK(0);
+ }
+ for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
+ {
+ Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
+ }
+ Status = MmCreateVirtualMapping(NULL,
+ KernelStack,
+ PAGE_READWRITE,
+ Page,
+ MM_STACK_SIZE / PAGE_SIZE);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECK(0);
+ }
+ Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
+ Thread->StackBase = (PCHAR)KernelStack + MM_STACK_SIZE;
+ Thread->StackLimit = (ULONG_PTR)KernelStack;
+ Thread->KernelStack = (PCHAR)KernelStack + MM_STACK_SIZE;
+ }
+ else
+ {
+ Thread->InitialStack = (PCHAR)init_stack_top;
+ Thread->StackBase = (PCHAR)init_stack_top;
+ Thread->StackLimit = (ULONG_PTR)init_stack;
+ Thread->KernelStack = (PCHAR)init_stack_top;
}
+
+ /*
+ * Establish the pde's for the new stack and the thread structure within the
+ * address space of the new process. They are accessed while taskswitching or
+ * while handling page faults. At this point it isn't possible to call the
+ * page fault handler for the missing pde's.
+ */
+
+ MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
+ MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
+
+ /*
+ * The Native API function will initialize the TEB field later
+ */
+ Thread->Teb = NULL;
+ Thread->TlsArray = NULL;
+ Thread->DebugActive = 0;
+ Thread->State = THREAD_STATE_INITIALIZED;
+ Thread->Alerted[0] = 0;
+ Thread->Alerted[1] = 0;
+ Thread->Iopl = 0;
+ /*
+ * FIXME: Think how this might work
+ */
+ Thread->NpxState = 0;
+
+ Thread->Saturation = 0;
+ Thread->Priority = Process->BasePriority;
+ InitializeListHead(&Thread->ApcState.ApcListHead[0]);
+ InitializeListHead(&Thread->ApcState.ApcListHead[1]);
+ Thread->ApcState.Process = Process;
+ Thread->ApcState.KernelApcInProgress = 0;
+ Thread->ApcState.KernelApcPending = 0;
+ Thread->ApcState.UserApcPending = 0;
+ Thread->ContextSwitches = 0;
+ Thread->WaitStatus = STATUS_SUCCESS;
+ Thread->WaitIrql = PASSIVE_LEVEL;
+ Thread->WaitMode = 0;
+ Thread->WaitNext = FALSE;
+ Thread->WaitBlockList = NULL;
+ Thread->WaitListEntry.Flink = NULL;
+ Thread->WaitListEntry.Blink = NULL;
+ Thread->WaitTime = 0;
+ Thread->BasePriority = Process->BasePriority;
+ Thread->DecrementCount = 0;
+ Thread->PriorityDecrement = 0;
+ Thread->Quantum = Process->ThreadQuantum;
+ memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK)*4);
+ Thread->LegoData = 0;
+ Thread->UserAffinity = Process->Affinity;
+ Thread->SystemAffinityActive = 0;
+ Thread->PowerState = 0;
+ Thread->NpxIrql = 0;
+ Thread->ServiceTable = KeServiceDescriptorTable;
+ Thread->Queue = NULL;
+ KeInitializeSpinLock(&Thread->ApcQueueLock);
+ memset(&Thread->Timer, 0, sizeof(KTIMER));
+ KeInitializeTimer(&Thread->Timer);
+ Thread->QueueListEntry.Flink = NULL;
+ Thread->QueueListEntry.Blink = NULL;
+ Thread->Affinity = Process->Affinity;
+ Thread->Preempted = 0;
+ Thread->ProcessReadyQueue = 0;
+ Thread->KernelStackResident = 1;
+ Thread->NextProcessor = 0;
+ Thread->CallbackStack = NULL;
+ Thread->Win32Thread = NULL;
+ Thread->TrapFrame = NULL;
+ Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
+ Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
+ Thread->EnableStackSwap = 0;
+ Thread->LargeStack = 0;
+ Thread->ResourceIndex = 0;
+ Thread->PreviousMode = KernelMode;
+ Thread->KernelTime = 0;
+ Thread->UserTime = 0;
+ memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE));
+
+ Thread->ApcStateIndex = OriginalApcEnvironment;
+ Thread->ApcQueueable = TRUE;
+ Thread->AutoAlignment = Process->AutoAlignment;
+
+ KeInitializeApc(&Thread->SuspendApc,
+ Thread,
+ OriginalApcEnvironment,
+ PiSuspendThreadKernelRoutine,
+ PiSuspendThreadRundownRoutine,
+ PiSuspendThreadNormalRoutine,
+ KernelMode,
+ NULL);
+ KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
+
+ InsertTailList(&Process->ThreadListHead,
+ &Thread->ThreadListEntry);
+ Thread->FreezeCount = 0;
+ Thread->SuspendCount = 0;
+
+ /*
+ * Do x86 specific part
+ */
}
/*
* @implemented
*/
-CCHAR
+VOID
STDCALL
-KeSetIdealProcessorThread(IN PKTHREAD Thread,
- IN CCHAR Processor)
+KeRevertToUserAffinityThread(VOID)
{
- CCHAR PreviousIdealProcessor;
- KIRQL OldIrql;
-
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Save Old Ideal Processor */
- PreviousIdealProcessor = Thread->IdealProcessor;
-
- /* Set New Ideal Processor */
- Thread->IdealProcessor = Processor;
-
- /* Release Lock */
- KeReleaseDispatcherDatabaseLock(OldIrql);
-
- /* Return Old Ideal Processor */
- return PreviousIdealProcessor;
+#ifdef CONFIG_SMP
+ PKTHREAD CurrentThread;
+ KIRQL oldIrql;
+
+ oldIrql = KeAcquireDispatcherDatabaseLock();
+
+ CurrentThread = KeGetCurrentThread();
+
+ ASSERT(CurrentThread->SystemAffinityActive != FALSE);
+
+ /* Return to User Affinity */
+ CurrentThread->Affinity = CurrentThread->UserAffinity;
+
+ /* Disable System Affinity */
+ CurrentThread->SystemAffinityActive = FALSE;
+
+ if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber()))
+ {
+ KeReleaseDispatcherDatabaseLock(oldIrql);
+ }
+ else
+ {
+ CurrentThread->WaitIrql = oldIrql;
+ PsDispatchThreadNoLock(THREAD_STATE_READY);
+ KeLowerIrql(oldIrql);
+ }
+#endif
}
/*
* @implemented
*/
-VOID
+CCHAR
STDCALL
-KeSetSystemAffinityThread(IN KAFFINITY Affinity)
+KeSetIdealProcessorThread (
+ IN PKTHREAD Thread,
+ IN CCHAR Processor)
{
- PKTHREAD CurrentThread = KeGetCurrentThread();
- KIRQL OldIrql;
-
- ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
-
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Set the System Affinity Specified */
- CurrentThread->Affinity = Affinity;
-
- /* Enable System Affinity */
- CurrentThread->SystemAffinityActive = TRUE;
-
- /* Check if we need to Dispatch a New thread */
- if (Affinity & (1 << KeGetCurrentProcessorNumber())) {
-
- /* No, just release */
- KeReleaseDispatcherDatabaseLock(OldIrql);
-
- } else {
-
- /* We need to dispatch a new thread */
- CurrentThread->WaitIrql = OldIrql;
- PsDispatchThreadNoLock(THREAD_STATE_READY);
- KeLowerIrql(OldIrql);
- }
+ CCHAR PreviousIdealProcessor;
+
+ /* Save Old Ideal Processor */
+ PreviousIdealProcessor = Thread->IdealProcessor;
+
+ /* Set New Ideal Processor */
+ Thread->IdealProcessor = Processor;
+
+ /* Return Old Ideal Processor */
+ return PreviousIdealProcessor;
}
/*
* @implemented
*/
- /* The Increment Argument seems to be ignored by NT and always 0 when called */
VOID
STDCALL
-KeTerminateThread(IN KPRIORITY Increment)
+KeSetSystemAffinityThread(IN KAFFINITY Affinity)
{
- /* Call our own internal routine */
- PsTerminateCurrentThread(0);
+#ifdef CONFIG_SMP
+ PKTHREAD CurrentThread;
+ KIRQL oldIrql;
+
+ oldIrql = KeAcquireDispatcherDatabaseLock();
+
+ CurrentThread = KeGetCurrentThread();
+
+ ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
+
+ /* Set the System Affinity Specified */
+ CurrentThread->Affinity = Affinity;
+
+ /* Enable System Affinity */
+ CurrentThread->SystemAffinityActive = TRUE;
+
+ if (Affinity & (1 << KeGetCurrentProcessorNumber()))
+ {
+ KeReleaseDispatcherDatabaseLock(oldIrql);
+ }
+ else
+ {
+ CurrentThread->WaitIrql = oldIrql;
+ PsDispatchThreadNoLock(THREAD_STATE_READY);
+ KeLowerIrql(oldIrql);
+ }
+#endif
}
/*
- * 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
+ * @implemented
*/
-BOOLEAN
-STDCALL
-KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
-{
- KIRQL OldIrql;
- PKTHREAD Thread = KeGetCurrentThread();
- BOOLEAN OldState;
-
- ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
-
- /* Lock the Dispatcher Database and the APC Queue */
- OldIrql = KeAcquireDispatcherDatabaseLock();
- KiAcquireSpinLock(&Thread->ApcQueueLock);
-
- /* Save the old State */
- 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;
- }
-
- /* Release Locks and return the Old State */
- KiReleaseSpinLock(&Thread->ApcQueueLock);
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return OldState;
-}
-
VOID
-KiServiceCheck (VOID)
-{
- PKTHREAD Thread = KeGetCurrentThread();
-
- /* Check if we need to inialize Win32 for this Thread */
- if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
-
- /* We do. Initialize it and save the new table */
- PsInitWin32Thread((PETHREAD)Thread);
- Thread->ServiceTable = KeServiceDescriptorTableShadow;
- }
-}
-
-/*
- *
- * NOT EXPORTED
- */
-NTSTATUS
STDCALL
-NtAlertResumeThread(IN HANDLE ThreadHandle,
- OUT PULONG SuspendCount)
+KeTerminateThread(IN KPRIORITY Increment)
{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- PETHREAD Thread;
- NTSTATUS Status;
- ULONG PreviousState;
-
- /* Check if parameters are valid */
- if(PreviousMode != KernelMode) {
-
- _SEH_TRY {
-
- ProbeForWrite(SuspendCount,
- sizeof(HANDLE),
- sizeof(ULONG));
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
- }
-
- /* Reference the Object */
- Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_SUSPEND_RESUME,
- PsThreadType,
- PreviousMode,
- (PVOID*)&Thread,
- NULL);
-
- /* Check for Success */
- if (NT_SUCCESS(Status)) {
-
- /* Call the Kernel Function */
- PreviousState = KeAlertResumeThread(&Thread->Tcb);
-
- /* Dereference Object */
- ObDereferenceObject(Thread);
-
- if (SuspendCount) {
-
- _SEH_TRY {
-
- *SuspendCount = PreviousState;
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
-
- } _SEH_END;
- }
- }
-
- /* Return status */
- return Status;
+ /* The Increment Argument seems to be ignored by NT and always 0 when called */
+
+ /* Call our own internal routine */
+ PsTerminateCurrentThread(0);
}
-/*
- * @implemented
- *
- * EXPORTED
- */
-NTSTATUS
-STDCALL
-NtAlertThread (IN HANDLE ThreadHandle)
-{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- PETHREAD Thread;
- NTSTATUS Status;
-
- /* Reference the Object */
- Status = ObReferenceObjectByHandle(ThreadHandle,
- THREAD_SUSPEND_RESUME,
- PsThreadType,
- PreviousMode,
- (PVOID*)&Thread,
- NULL);
-
- /* Check for Success */
- if (NT_SUCCESS(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);
-
- /* Dereference Object */
- ObDereferenceObject(Thread);
- }
-
- /* Return status */
- return Status;
-}
NTSTATUS
STDCALL
NtDelayExecution(IN BOOLEAN Alertable,
IN PLARGE_INTEGER DelayInterval)
{
- KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
- LARGE_INTEGER SafeInterval;
- NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
+ LARGE_INTEGER SafeInterval;
- /* Check if parameters are valid */
- if(PreviousMode != KernelMode) {
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ _SEH_TRY
+ {
+ ProbeForRead(DelayInterval,
+ sizeof(LARGE_INTEGER),
+ sizeof(ULONG));
+ /* make a copy on the kernel stack and let DelayInterval point to it so
+ we don't need to wrap KeDelayExecutionThread in SEH! */
+ SafeInterval = *DelayInterval;
+ DelayInterval = &SafeInterval;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
- _SEH_TRY {
-
- ProbeForRead(DelayInterval,
- sizeof(LARGE_INTEGER),
- sizeof(ULONG));
-
- /* make a copy on the kernel stack and let DelayInterval point to it so
- we don't need to wrap KeDelayExecutionThread in SEH! */
- SafeInterval = *DelayInterval;
-
- } _SEH_HANDLE {
-
- Status = _SEH_GetExceptionCode();
- } _SEH_END;
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
}
- /* Call the Kernel Function */
- Status = KeDelayExecutionThread(PreviousMode,
- Alertable,
- &SafeInterval);
-
- /* Return Status */
- return Status;
+ return KeDelayExecutionThread(PreviousMode,
+ Alertable,
+ DelayInterval);
}
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/main.c
* PURPOSE: Initalizes the kernel
*
- * PROGRAMMERS: Alex Ionescu (cleaned up code, moved Executiv stuff to ex/init.c)
- * David Welch (welch@cwcom.net)
+ * PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
+#include "../dbg/kdb.h"
+#include <ntos/bootvid.h>
+#include <napi/core.h>
+
+#ifdef HALDBG
+#include <internal/ntosdbg.h>
+#else
+#if defined(_MSC_VER) && (_MSC_VER <= 1200)
+#define ps
+#else
+#define ps(args...)
+#endif /* HALDBG */
+
+#endif
+
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
#define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
-
-
ULONG NtMajorVersion = 4;
ULONG NtMinorVersion = 0;
ULONG NtOSCSDVersion = BUILD_OSCSDVERSION(6, 0);
EXPORTED ULONG InitSafeBootMode = 0; /* KB83764 */
#endif /* __GNUC__ */
-LOADER_MODULE KeLoaderModules[64];
+static LOADER_MODULE KeLoaderModules[64];
static CHAR KeLoaderModuleStrings[64][256];
static CHAR KeLoaderCommandLine[256];
-ADDRESS_RANGE KeMemoryMap[64];
-ULONG KeMemoryMapRangeCount;
-ULONG_PTR FirstKrnlPhysAddr;
-ULONG_PTR LastKrnlPhysAddr;
-ULONG_PTR LastKernelAddress;
+static ADDRESS_RANGE KeMemoryMap[64];
+static ULONG KeMemoryMapRangeCount;
+static ULONG_PTR FirstKrnlPhysAddr;
+static ULONG_PTR LastKrnlPhysAddr;
+static ULONG_PTR LastKernelAddress;
volatile BOOLEAN Initialized = FALSE;
+extern ULONG MmCoreDumpType;
+extern CHAR KiTimerSystemAuditing;
-ULONG KeLargestCacheLine = 0x40; /* FIXME: Arch-specific */
+extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
/* We allocate 4 pages, but we only use 3. The 4th is to guarantee page alignment */
ULONG kernel_stack[4096];
ULONG trap_stack;
ULONG trap_stack_top;
-/* Cached modules from the loader block */
-PLOADER_MODULE CachedModules[MaximumCachedModuleType];
-
/* 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;
+
+ /*
+ * NOTE:
+ * The shared user page has been zeroed-out right after creation.
+ * There is NO need to do this again.
+ */
+
+ Ki386SetProcessorFeatures();
+
+ SharedUserData->NtProductType = NtProductWinNt;
+ SharedUserData->ProductTypeIsValid = TRUE;
+ SharedUserData->NtMajorVersion = 5;
+ SharedUserData->NtMinorVersion = 0;
+
+ BootDriveFound = FALSE;
+
+ /*
+ * 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));
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ &ArcName,
+ OBJ_OPENLINK,
+ NULL,
+ NULL);
+
+ Status = NtOpenSymbolicLinkObject (&Handle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes);
+ RtlFreeUnicodeString (&ArcName);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeUnicodeString (&BootPath);
+ RtlFreeUnicodeString (&ArcDeviceName);
+ CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
+ Status);
+
+ KEBUGCHECK (0x0);
+ }
+
+ Status = NtQuerySymbolicLinkObject (Handle,
+ &ArcDeviceName,
+ &Length);
+ NtClose (Handle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeUnicodeString (&BootPath);
+ RtlFreeUnicodeString (&ArcDeviceName);
+ CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
+ Status);
+
+ KEBUGCHECK (0x0);
+ }
+ 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));
+
+ for (i = 0; i < 26; i++)
+ {
+ swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
+ RtlInitUnicodeString (&DriveName,
+ DriveNameBuffer);
+
+ InitializeObjectAttributes (&ObjectAttributes,
+ &DriveName,
+ OBJ_OPENLINK,
+ NULL,
+ NULL);
+
+ Status = NtOpenSymbolicLinkObject (&Handle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed to open link %wZ\n",
+ &DriveName);
+ continue;
+ }
+
+ Status = NtQuerySymbolicLinkObject (Handle,
+ &DriveDeviceName,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed query open link %wZ\n",
+ &DriveName);
+ continue;
+ }
+ DPRINT("Opened link: %wZ ==> %wZ\n",
+ &DriveName, &DriveDeviceName);
+
+ 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;
+ }
+
+ NtClose (Handle);
+ }
+
+ RtlFreeUnicodeString (&BootPath);
+ RtlFreeUnicodeString (&DriveDeviceName);
+ RtlFreeUnicodeString (&ArcDeviceName);
+
+ if (BootDriveFound == FALSE)
+ {
+ DbgPrint("No system drive found!\n");
+ KEBUGCHECK (NO_BOOT_DEVICE);
+ }
+}
+
+VOID INIT_FUNCTION
+ExpInitializeExecutive(VOID)
+{
+ LARGE_INTEGER Timeout;
+ HANDLE ProcessHandle;
+ HANDLE ThreadHandle;
+ ULONG i;
+ ULONG start;
+ ULONG length;
+ PCHAR name;
+ CHAR str[50];
+ NTSTATUS Status;
+ BOOLEAN SetupBoot;
+ PCHAR p1, p2;
+ ULONG MaxMem;
+ BOOLEAN NoGuiBoot = FALSE;
+ UNICODE_STRING Name;
+ HANDLE InitDoneEventHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ /*
+ * 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);
+
+ LdrInit1();
+
+ KeLowerIrql(DISPATCH_LEVEL);
+
+ NtEarlyInitVdm();
+
+ p1 = (PCHAR)KeLoaderBlock.CommandLine;
+
+ MaxMem = 0;
+ 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;
+ }
+ }
+ }
+ p1 = p2;
+ }
+
+ MmInit1(FirstKrnlPhysAddr,
+ LastKrnlPhysAddr,
+ LastKernelAddress,
+ (PADDRESS_RANGE)&KeMemoryMap,
+ KeMemoryMapRangeCount,
+ MaxMem > 8 ? MaxMem : 4096);
+
+ /* Import ANSI code page table */
+ for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+ {
+ start = KeLoaderModules[i].ModStart;
+ length = KeLoaderModules[i].ModEnd - start;
+
+ name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+ if (name == NULL)
+ {
+ name = (PCHAR)KeLoaderModules[i].String;
+ }
+ else
+ {
+ name++;
+ }
+
+ if (!_stricmp (name, "ansi.nls"))
+ {
+ RtlpImportAnsiCodePage((PUSHORT)start, length);
+ }
+ }
+
+ /* Import OEM code page table */
+ for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+ {
+ start = KeLoaderModules[i].ModStart;
+ length = KeLoaderModules[i].ModEnd - start;
+
+ name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+ if (name == NULL)
+ {
+ name = (PCHAR)KeLoaderModules[i].String;
+ }
+ else
+ {
+ name++;
+ }
+
+ if (!_stricmp (name, "oem.nls"))
+ {
+ RtlpImportOemCodePage((PUSHORT)start, length);
+ }
+ }
+
+ /* Import Unicode casemap table */
+ for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+ {
+ start = KeLoaderModules[i].ModStart;
+ length = KeLoaderModules[i].ModEnd - start;
+
+ name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+ if (name == NULL)
+ {
+ name = (PCHAR)KeLoaderModules[i].String;
+ }
+ else
+ {
+ name++;
+ }
+
+ if (!_stricmp (name, "casemap.nls"))
+ {
+ RtlpImportUnicodeCasemap((PUSHORT)start, length);
+ }
+ }
+
+ /* Create initial NLS tables */
+ RtlpCreateInitialNlsTables();
+
+ /*
+ * Initialize the kernel debugger
+ */
+ KdInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+ KeInit2();
+
+#if 0
+ if (KeMemoryMapRangeCount > 0)
+ {
+ DPRINT1("MemoryMap:\n");
+ for (i = 0; i < KeMemoryMapRangeCount; i++)
+ {
+ switch(KeMemoryMap[i].Type)
+ {
+ case 1:
+ strcpy(str, "(usable)");
+ break;
+ case 2:
+ strcpy(str, "(reserved)");
+ break;
+ case 3:
+ strcpy(str, "(ACPI data)");
+ break;
+ case 4:
+ strcpy(str, "(ACPI NVS)");
+ break;
+ default:
+ sprintf(str, "type %lu", KeMemoryMap[i].Type);
+ }
+ DPRINT1("%08x - %08x %s\n", KeMemoryMap[i].BaseAddrLow, KeMemoryMap[i].BaseAddrLow + KeMemoryMap[i].LengthLow, str);
+ }
+ }
+#endif
+
+ KeLowerIrql(PASSIVE_LEVEL);
+
+ if (!SeInit1())
+ KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
+
+ ObInit();
+ ExInit2();
+ MmInit2();
+
+ if (!SeInit2())
+ KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
+
+ KeNumberProcessors = 1;
+
+ PiInitProcessManager();
+
+ if (KdPollBreakIn ())
+ {
+ DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
+ }
+
+ /* Initialize all processors */
+ while (!HalAllProcessorsStarted())
+ {
+ PVOID ProcessorStack;
+
+ KePrepareForApplicationProcessorInit(KeNumberProcessors);
+ PsPrepareForApplicationProcessorInit(KeNumberProcessors);
+
+ /* Allocate a stack for use when booting the processor */
+ ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
+
+ HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
+ KeNumberProcessors++;
+ }
+
+ /*
+ * Initialize various critical subsystems
+ */
+ HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+ ExInit3();
+ KdInit1();
+ IoInit();
+ PoInit();
+ CmInitializeRegistry();
+ MmInit3();
+ CcInit();
+ KdInit2();
+ 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");
+
+ if (KeNumberProcessors > 1)
+ {
+ sprintf(str,
+ "Found %d system processors. [%lu MB Memory]\n",
+ KeNumberProcessors,
+ (KeLoaderBlock.MemHigher + 1088)/ 1024);
+ }
+ else
+ {
+ sprintf(str,
+ "Found 1 system processor. [%lu MB Memory]\n",
+ (KeLoaderBlock.MemHigher + 1088)/ 1024);
+ }
+ HalDisplayString(str);
+
+ KdInit3();
+
+
+ /* Create the NLS section */
+ RtlpCreateNlsSection();
+
+ /*
+ * Initalize services loaded at boot time
+ */
+ DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
+ for (i=0; i < KeLoaderBlock.ModsCount; i++)
+ {
+ CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
+ KeLoaderModules[i].String,
+ KeLoaderModules[i].ModStart,
+ KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
+ }
+
+ /* Pass 1: import system hive registry chunk */
+ SetupBoot = TRUE;
+ for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+ {
+ start = KeLoaderModules[i].ModStart;
+ length = KeLoaderModules[i].ModEnd - start;
+
+ DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
+ name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+ if (name == NULL)
+ {
+ name = (PCHAR)KeLoaderModules[i].String;
+ }
+ else
+ {
+ name++;
+ }
+
+ if (!_stricmp (name, "system") ||
+ !_stricmp (name, "system.hiv"))
+ {
+ CPRINT("Process system hive registry chunk at %08lx\n", start);
+ SetupBoot = FALSE;
+ CmImportSystemHive((PCHAR)start, length);
+ }
+ }
+
+ /* Pass 2: import hardware hive registry chunk */
+ for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+ {
+ start = KeLoaderModules[i].ModStart;
+ length = KeLoaderModules[i].ModEnd - start;
+ name = (PCHAR)KeLoaderModules[i].String;
+ if (!_stricmp (name, "hardware") ||
+ !_stricmp (name, "hardware.hiv"))
+ {
+ CPRINT("Process hardware hive registry chunk at %08lx\n", start);
+ CmImportHardwareHive((PCHAR)start, length);
+ }
+ }
+
+ /* Create dummy keys if no hardware hive was found */
+ CmImportHardwareHive (NULL, 0);
+
+ /* Initialize volatile registry settings */
+ if (SetupBoot == FALSE)
+ {
+ CmInit2((PCHAR)KeLoaderBlock.CommandLine);
+ }
+
+ /* Initialize the time zone information from the registry */
+ ExpInitTimeZoneInfo();
+
+ /*
+ * Enter the kernel debugger before starting up the boot drivers
+ */
+#ifdef KDBG
+ KdbEnter();
+#endif /* KDBG */
+
+ IoCreateDriverList();
+
+ IoInit2();
+
+ /* Initialize Callbacks before drivers */
+ ExpInitializeCallbacks();
+
+ /* Start boot logging */
+ IopInitBootLog();
+ p1 = (PCHAR)KeLoaderBlock.CommandLine;
+ while (*p1 && (p2 = strchr(p1, '/')))
+ {
+ p2++;
+ if (!_strnicmp(p2, "BOOTLOG", 7))
+ {
+ p2 += 7;
+ IopStartBootLog();
+ }
+
+ p1 = p2;
+ }
+
+ /*
+ * Load boot start drivers
+ */
+ IopInitializeBootDrivers();
+
+ /* Display the boot screen image if not disabled */
+ if (!NoGuiBoot)
+ {
+ InbvEnableBootDriver(TRUE);
+ }
+
+ /* Create ARC names for boot devices */
+ IoCreateArcNames();
+
+ /* Create the SystemRoot symbolic link */
+ CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
+ DPRINT1("MmSystemRangeStart: 0x%x PageDir: 0x%x\n", MmSystemRangeStart, KeLoaderBlock.PageDirectoryStart);
+ Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint ( "IoCreateSystemRootLink FAILED: (0x%x) - ", Status );
+ DbgPrintErrorMessage ( Status );
+ KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
+ }
+
+#if defined(KDBG) || defined(DBG)
+ KdbInitProfiling2();
+#endif /* KDBG */
+
+ /* On the assumption that we can now access disks start up the debug
+ * logger thread */
+ if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_BOOTLOG))
+ {
+ DebugLogInit2();
+ }
+
+ PiInitDefaultLocale();
+
+ /*
+ * 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);
+
+ /*
+ * Initialize shared user page:
+ * - set dos system path, dos device map, etc.
+ */
+ InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
+
+ /* Create 'ReactOSInitDone' event */
+ RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+ Status = ZwCreateEvent(&InitDoneEventHandle,
+ EVENT_ALL_ACCESS,
+ &ObjectAttributes,
+ SynchronizationEvent,
+ FALSE); /* Not signalled */
+ 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);
+ if (!NT_SUCCESS(Status))
+ {
+ KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
+ }
+
+ if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
+ {
+ HANDLE Handles[2]; /* Init event, Initial process */
+
+ Handles[0] = InitDoneEventHandle;
+ Handles[1] = ProcessHandle;
+
+ /* Wait for the system to be initialized */
+ Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
+ Status = ZwWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
+ Handles,
+ WaitAny,
+ FALSE, /* Non-alertable */
+ &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);
+ }
+
+ if (!NoGuiBoot)
+ {
+ InbvEnableBootDriver(FALSE);
+ }
+
+ 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);
+ if (Status != STATUS_TIMEOUT)
+ {
+ KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
+ }
+ }
/*
- * @implemented
+ * Tell ke/timer.c it's okay to run.
*/
-ULONG
-STDCALL
-KeGetRecommendedSharedDataAlignment(VOID)
-{
- return KeLargestCacheLine;
+
+ KiTimerSystemAuditing = 1;
+
+ ZwClose(ThreadHandle);
+ ZwClose(ProcessHandle);
}
-VOID
-__attribute((noinline))
+VOID __attribute((noinline))
KiSystemStartup(BOOLEAN BootProcessor)
{
- DPRINT("KiSystemStartup(%d)\n", BootProcessor);
-
- /* Initialize the Application Processor */
- if (!BootProcessor) KeApplicationProcessorInit();
-
- /* Initialize the Processor with HAL */
- HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
- /* Load the Kernel if this is the Boot CPU, else inialize the App CPU only */
- if (BootProcessor) {
-
- /* Initialize the Kernel Executive */
- ExpInitializeExecutive();
-
- /* Free Initial Memory */
- MiFreeInitMemory();
-
- /* Never returns */
- PsTerminateSystemThread(STATUS_SUCCESS);
- } else {
-
- /* Do application processor initialization */
- PsApplicationProcessorInit();
-
- /* Lower IRQL and go to Idle Thread */
- KeLowerIrql(PASSIVE_LEVEL);
- PsIdleThreadMain(NULL);
- }
-
- /* Bug Check and loop forever if anything failed */
- KEBUGCHECK(0);
- for(;;);
+ DPRINT1("KiSystemStartup(%d)\n", BootProcessor);
+ if (BootProcessor)
+ {
+ }
+ else
+ {
+ KeApplicationProcessorInit();
+ }
+
+ HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+ if (BootProcessor)
+ {
+ ExpInitializeExecutive();
+ MiFreeInitMemory();
+ /* Never returns */
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ }
+ else
+ {
+ /* Do application processor initialization */
+ PsApplicationProcessorInit();
+ KeLowerIrql(PASSIVE_LEVEL);
+ PsIdleThreadMain(NULL);
+ }
+ KEBUGCHECK(0);
+ for(;;);
}
+VOID INIT_FUNCTION
+_main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
/*
* FUNCTION: Called by the boot loader to start the kernel
* ARGUMENTS:
* NOTE: The boot parameters are stored in low memory which will become
* invalid after the memory managment is initialized so we make a local copy.
*/
-VOID
-INIT_FUNCTION
-_main(ULONG MultiBootMagic,
- PLOADER_PARAMETER_BLOCK _LoaderBlock)
{
- ULONG i;
- ULONG size;
- ULONG HalBase;
- ULONG DriverBase;
- ULONG DriverSize;
- PIMAGE_NT_HEADERS NtHeader;
- PIMAGE_OPTIONAL_HEADER OptHead;
- CHAR* s;
-
- /* Set up the Stacks (Initial Kernel Stack and Double Trap Stack)*/
- trap_stack = PAGE_ROUND_UP(&double_trap_stack);
- trap_stack_top = trap_stack + 3 * PAGE_SIZE;
- init_stack = PAGE_ROUND_UP(&kernel_stack);
- init_stack_top = init_stack + 3 * PAGE_SIZE;
+ ULONG i;
+ ULONG size;
+ ULONG HalBase;
+ ULONG DriverBase;
+ ULONG DriverSize;
+
+ /* Set up the Stacks */
+ trap_stack = PAGE_ROUND_UP(&double_trap_stack);
+ trap_stack_top = trap_stack + 3 * PAGE_SIZE;
+ init_stack = PAGE_ROUND_UP(&kernel_stack);
+ init_stack_top = init_stack + 3 * PAGE_SIZE;
- /* Copy the Loader Block Data locally since Low-Memory will be wiped */
- memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
- memcpy(&KeLoaderModules[1],
- (PVOID)KeLoaderBlock.ModsAddr,
- sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
- KeLoaderBlock.ModsCount++;
- KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
-
- /* Save the Base Address */
- MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
+ /*
+ * Copy the parameters to a local buffer because lowmem will go away
+ */
+ memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+ memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
+ sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
+ KeLoaderBlock.ModsCount++;
+ KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
+
+ /* Save the Base Address */
+ MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
- /* Set the Command Line */
- strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine);
- KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
+ /*
+ * Convert a path specification in the grub format to one understood by the
+ * rest of the kernel.
+ */
+ if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
+ {
+ ULONG DiskNumber = 0, PartNumber = 0;
+ PCH p;
+ CHAR Temp[256];
+ PCH options;
+ PCH s1;
+
+ if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
+ ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
+ {
+ DiskNumber = ((PCHAR)_LoaderBlock->CommandLine)[3] - '0';
+ PartNumber = ((PCHAR)_LoaderBlock->CommandLine)[5] - '0';
+ }
+ strcpy(Temp, &((PCHAR)_LoaderBlock->CommandLine)[7]);
+ if ((options = strchr(Temp, ' ')) != NULL)
+ {
+ *options = 0;
+ options++;
+ }
+ else
+ {
+ options = "";
+ }
+ if ((s1 = strrchr(Temp, '/')) != NULL)
+ {
+ *s1 = 0;
+ if ((s1 = strrchr(Temp, '/')) != NULL)
+ {
+ *s1 = 0;
+ }
+ }
+ sprintf(KeLoaderCommandLine,
+ "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
+ DiskNumber, PartNumber + 1, Temp, options);
+
+ p = KeLoaderCommandLine;
+ while (*p != 0 && *p != ' ')
+ {
+ if ((*p) == '/')
+ {
+ (*p) = '\\';
+ }
+ p++;
+ }
+ DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
+ }
+ else
+ {
+ strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine);
+ }
+ KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
- /* Write the first Module (the Kernel) */
- strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
- KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
- KeLoaderModules[0].ModStart = KERNEL_BASE;
-
- /* Read PE Data */
- NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
- OptHead = &NtHeader->OptionalHeader;
-
- /* Set Kernel Ending */
+ strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
+ KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
+ KeLoaderModules[0].ModStart = KERNEL_BASE;
+ /* Take this value from the PE... */
+ PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
+ PIMAGE_OPTIONAL_HEADER OptHead = &NtHeader->OptionalHeader;
KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
-
- /* Create a block for each module */
- for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
-
- /* Check if we have to copy the path or not */
- if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0) {
-
- strcpy(KeLoaderModuleStrings[i], s + 1);
-
- } else {
-
- strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
- }
-
- /* Substract the base Address in Physical Memory */
- KeLoaderModules[i].ModStart -= 0x200000;
-
- /* Add the Kernel Base Address in Virtual Memory */
- KeLoaderModules[i].ModStart += KERNEL_BASE;
-
- /* Substract the base Address in Physical Memory */
- KeLoaderModules[i].ModEnd -= 0x200000;
-
- /* Add the Kernel Base Address in Virtual Memory */
- KeLoaderModules[i].ModEnd += KERNEL_BASE;
-
- /* Select the proper String */
- KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
+ for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+ {
+ CHAR* s;
+ if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
+ {
+ strcpy(KeLoaderModuleStrings[i], s + 1);
+ }
+ else
+ {
+ strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
+ }
+ KeLoaderModules[i].ModStart -= 0x200000;
+ KeLoaderModules[i].ModStart += KERNEL_BASE;
+ KeLoaderModules[i].ModEnd -= 0x200000;
+ KeLoaderModules[i].ModEnd += KERNEL_BASE;
+ KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
}
- /* Choose last module address as the final kernel address */
- LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
-
- /* Low level architecture specific initialization */
- KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
-
- /* Select the HAL Base */
- HalBase = KeLoaderModules[1].ModStart;
-
- /* Choose Driver Base */
- DriverBase = LastKernelAddress;
- LdrHalBase = (ULONG_PTR)DriverBase;
-
- /* Initialize Module Management */
- LdrInitModuleManagement();
-
- /* Load HAL.DLL with the PE Loader */
- LdrSafePEProcessModule((PVOID)HalBase,
- (PVOID)DriverBase,
- (PVOID)KERNEL_BASE,
- &DriverSize);
-
- /* Increase the last kernel address with the size of HAL */
- LastKernelAddress += PAGE_ROUND_UP(DriverSize);
-
- /* Load the Kernel with the PE Loader */
- LdrSafePEProcessModule((PVOID)KERNEL_BASE,
- (PVOID)KERNEL_BASE,
- (PVOID)DriverBase,
- &DriverSize);
-
- /* Now select the final beginning and ending Kernel Addresses */
- FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
- LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
-
- KeMemoryMapRangeCount = 0;
- if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO) {
-
- /* We have a memory map from the nice BIOS */
- size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
- i = 0;
-
- /* Map it until we run out of size */
- while (i < KeLoaderBlock.MmapLength) {
-
- /* Copy into the Kernel Memory Map */
- memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
- (PVOID)(KeLoaderBlock.MmapAddr + i),
- sizeof(ADDRESS_RANGE));
-
- /* Increase Memory Map Count */
- KeMemoryMapRangeCount++;
-
- /* Increase Size */
- i += size;
+ LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
+
+ /* Low level architecture specific initialization */
+ KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
+
+ HalBase = KeLoaderModules[1].ModStart;
+ DriverBase = LastKernelAddress;
+ LdrHalBase = (ULONG_PTR)DriverBase;
+
+ LdrInitModuleManagement();
+
+ /*
+ * Process hal.dll
+ */
+ LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)KERNEL_BASE, &DriverSize);
+
+ LastKernelAddress += PAGE_ROUND_UP(DriverSize);
+
+ /*
+ * Process ntoskrnl.exe
+ */
+ LdrSafePEProcessModule((PVOID)KERNEL_BASE, (PVOID)KERNEL_BASE, (PVOID)DriverBase, &DriverSize);
+
+ /* Now our imports from HAL are fixed. This is the first */
+ /* time in the boot process that we can use HAL */
+
+ FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
+ LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
+
+ KeMemoryMapRangeCount = 0;
+ if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
+ {
+ /* We have a memory map from the nice BIOS */
+ size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
+ i = 0;
+ while (i < KeLoaderBlock.MmapLength)
+ {
+ memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
+ (PVOID)(KeLoaderBlock.MmapAddr + i),
+ sizeof(ADDRESS_RANGE));
+ KeMemoryMapRangeCount++;
+ i += size;
}
-
- /* Save data */
- KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
- KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
-
- } else {
-
- /* Nothing from BIOS */
- KeLoaderBlock.MmapLength = 0;
- KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
+ KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
+ KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
}
-
- /* Initialize the Debugger */
- KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
- /* Initialize HAL */
- HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-
- /* Do general System Startup */
- KiSystemStartup(1);
+ else
+ {
+ KeLoaderBlock.MmapLength = 0;
+ KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
+ }
+
+ KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+ HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+ DPRINT1("_main (%x, %x)\n", MultiBootMagic, _LoaderBlock);
+
+
+ KiSystemStartup(1);
}
/* EOF */
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/mutex.c
- * PURPOSE: Implements Mutexes and Mutants (that silly davec...)
+ * PURPOSE: Implements mutex
*
- * 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)
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
-#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
-VOID
-STDCALL
-KeInitializeMutant(IN PKMUTANT Mutant,
- IN BOOLEAN InitialOwner)
+VOID STDCALL
+KeInitializeMutex(IN PKMUTEX Mutex,
+ IN ULONG Level)
{
- 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;
- }
-
- /* 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;
+ 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
*/
-VOID
-STDCALL
-KeInitializeMutex(IN PKMUTEX Mutex,
- IN ULONG Level)
+LONG STDCALL
+KeReadStateMutex(IN PKMUTEX Mutex)
{
- 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);
+ return(Mutex->Header.SignalState);
}
/*
* @implemented
*/
-LONG
-STDCALL
-KeReadStateMutant(IN PKMUTANT Mutant)
+LONG STDCALL
+KeReleaseMutex(IN PKMUTEX Mutex,
+ IN BOOLEAN Wait)
{
- /* Return the Signal State */
- return(Mutant->Header.SignalState);
+ 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
*/
-LONG
-STDCALL
-KeReadStateMutex(IN PKMUTEX Mutex)
+NTSTATUS STDCALL
+KeWaitForMutexObject(IN PKMUTEX Mutex,
+ IN KWAIT_REASON WaitReason,
+ IN KPROCESSOR_MODE WaitMode,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Timeout)
{
- /* Return the Signal State */
- return(Mutex->Header.SignalState);
+ return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout));
}
+
/*
* @implemented
*/
-LONG
-STDCALL
-KeReleaseMutant(IN PKMUTANT Mutant,
- IN KPRIORITY Increment,
- IN BOOLEAN Abandon,
- IN BOOLEAN Wait)
+VOID STDCALL
+KeInitializeMutant(IN PKMUTANT Mutant,
+ IN BOOLEAN InitialOwner)
{
- 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;
- }
-
- /* 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 (InitialOwner == TRUE)
+ {
+ KeInitializeDispatcherHeader(&Mutant->Header,
+ InternalMutexType,
+ sizeof(KMUTANT) / sizeof(ULONG),
+ 0);
+ InsertTailList(&KeGetCurrentThread()->MutantListHead,
+ &Mutant->MutantListEntry);
+ Mutant->OwnerThread = KeGetCurrentThread();
}
-
- /* 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;
+ else
+ {
+ KeInitializeDispatcherHeader(&Mutant->Header,
+ InternalMutexType,
+ sizeof(KMUTANT) / sizeof(ULONG),
+ 1);
+ Mutant->MutantListEntry.Flink = NULL;
+ Mutant->MutantListEntry.Blink = NULL;
+ Mutant->OwnerThread = NULL;
}
-
- /* Return the previous state */
- return PreviousState;
+ Mutant->Abandoned = FALSE;
+ Mutant->ApcDisable = 0;
}
/*
* @implemented
*/
-LONG
-STDCALL
-KeReleaseMutex(IN PKMUTEX Mutex,
- IN BOOLEAN Wait)
+LONG STDCALL
+KeReadStateMutant(IN PKMUTANT Mutant)
{
-
- /* There's no difference at this level between the two */
- return KeReleaseMutant(Mutex, IO_NO_INCREMENT, FALSE, Wait);
+ return(Mutant->Header.SignalState);
}
/*
* @implemented
*/
-NTSTATUS
-STDCALL
-KeWaitForMutexObject(IN PKMUTEX Mutex,
- IN KWAIT_REASON WaitReason,
- IN KPROCESSOR_MODE WaitMode,
- IN BOOLEAN Alertable,
- IN PLARGE_INTEGER Timeout)
+LONG STDCALL
+KeReleaseMutant(IN PKMUTANT Mutant,
+ IN KPRIORITY Increment,
+ IN BOOLEAN Abandon,
+ IN BOOLEAN Wait)
{
- /* This is a simple macro. Export the function here though */
- return KeWaitForSingleObject(Mutex,
- WaitReason,
- WaitMode,
- Alertable,
- Timeout);
+ KIRQL OldIrql;
+
+ 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);
+ }
+ else
+ {
+ if (Mutant->OwnerThread != NULL)
+ {
+ Mutant->Header.SignalState = 1;
+ Mutant->Abandoned = TRUE;
+ }
+ }
+
+ if (Mutant->Header.SignalState == 1)
+ {
+ Mutant->OwnerThread = NULL;
+ if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
+ RemoveEntryList(&Mutant->MutantListEntry);
+ KiDispatcherObjectWake(&Mutant->Header, Increment);
+ }
+
+ if (Wait == FALSE)
+ {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ }
+ else
+ {
+ KTHREAD *Thread = KeGetCurrentThread();
+ Thread->WaitNext = TRUE;
+ Thread->WaitIrql = OldIrql;
+ }
+
+ return(0);
}
/* EOF */
/* 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)
{
- 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;
+ 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;
}
+
/*
* @implemented
+ *
+ * Returns number of entries in the queue
*/
-LONG
-STDCALL
-KeInsertHeadQueue(IN PKQUEUE Queue,
- IN PLIST_ENTRY Entry)
+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
+ )
{
- 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);
+ ULONG InitialState;
+
+ DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
- /* Return previous State */
- return PreviousState;
+ 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
-KeInsertQueue(IN PKQUEUE Queue,
- IN PLIST_ENTRY Entry)
+KeInsertHeadQueue(IN PKQUEUE Queue,
+ IN PLIST_ENTRY Entry)
{
- 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);
+ LONG Result;
+ KIRQL OldIrql;
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+ Result = KiInsertQueue(Queue,Entry,TRUE);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
- /* Return previous State */
- return PreviousState;
+ return Result;
}
+
/*
* @implemented
- *
- * Returns number of entries in the queue
*/
-LONG
-STDCALL
-KeReadStateQueue(IN PKQUEUE Queue)
+LONG STDCALL
+KeInsertQueue(IN PKQUEUE Queue,
+ IN PLIST_ENTRY Entry)
{
- /* Returns the Signal State */
- return(Queue->Header.SignalState);
+ LONG Result;
+ KIRQL OldIrql;
+
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+ Result = KiInsertQueue(Queue,Entry,FALSE);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+
+ return Result;
}
+
/*
* @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;
- PKQUEUE PreviousQueue;
- PKWAIT_BLOCK WaitBlock;
- PKWAIT_BLOCK TimerWaitBlock;
- PKTIMER Timer;
-
- 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;
- }
-
- /* This is needed so that we can set the new queue right here, before additional processing */
- PreviousQueue = Thread->Queue;
- Thread->Queue = Queue;
-
- /* 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);
+ PLIST_ENTRY ListEntry;
+ NTSTATUS Status;
+ PKTHREAD Thread = KeGetCurrentThread();
+ KIRQL OldIrql;
+
+ OldIrql = KeAcquireDispatcherDatabaseLock ();
+
+ 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
+ */
+
+ //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);
+ }
}
- /* Insert in this new Queue */
- DPRINT("Inserting new Queue!\n");
- InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
+ // register thread with this queue
+ InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
+ Thread->Queue = Queue;
+ }
+ else /* if (Thread->Queue == Queue) */
+ {
+ //dec. num running threads
+ Queue->CurrentCount--;
+ }
+
+
+
- } 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];
-
- /* 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;
+ 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;
+
+ Status = KeWaitForSingleObject(Queue,
+ WrQueue,
+ WaitMode,
+ TRUE, //bAlertable
+ Timeout);
+
+ if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
+ {
+ return (PVOID)Status;
+ }
+
+ OldIrql = KeAcquireDispatcherDatabaseLock ();
+ }
+ }
}
+
/*
* @implemented
*/
-PLIST_ENTRY
-STDCALL
+PLIST_ENTRY STDCALL
KeRundownQueue(IN PKQUEUE Queue)
{
- PLIST_ENTRY EnumEntry;
- PLIST_ENTRY FirstEntry;
- PKTHREAD Thread;
- KIRQL OldIrql;
-
- DPRINT("KeRundownQueue(Queue %x)\n", Queue);
-
- /* Get the Dispatcher Lock */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* 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;
-
- } 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;
- }
-
- /* Release the lock and return */
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return FirstEntry;
-}
+ PLIST_ENTRY EnumEntry;
+ PKTHREAD Thread;
+ KIRQL 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);
- }
- }
-}
+ DPRINT("KeRundownQueue(Queue %x)\n", Queue);
-/*
- * 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;
+ /* I'm just guessing how this should work:-/
+ * -Gunnar
+ */
- /* 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;
+ OldIrql = KeAcquireDispatcherDatabaseLock ();
+
+ //no thread must wait on queue at rundown
+ ASSERT(IsListEmpty(&Queue->Header.WaitListHead));
+
+ // unlink threads and clear their Thread->Queue
+ while (!IsListEmpty(&Queue->ThreadListHead))
+ {
+ EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
+ Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
+ Thread->Queue = NULL;
+ }
+
+ if (IsListEmpty(&Queue->EntryListHead))
+ {
+ EnumEntry = NULL;
+ }
+ else
+ {
+ EnumEntry = Queue->EntryListHead.Flink;
+ }
+
+ KeReleaseDispatcherDatabaseLock (OldIrql);
+
+ return EnumEntry;
}
/* EOF */
/*
* @implemented
*/
-VOID
-STDCALL
-KeInitializeSemaphore(PKSEMAPHORE Semaphore,
- LONG Count,
- LONG Limit)
+VOID STDCALL
+KeInitializeSemaphore (PKSEMAPHORE Semaphore,
+ LONG Count,
+ LONG 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;
+ KeInitializeDispatcherHeader(&Semaphore->Header,
+ InternalSemaphoreType,
+ sizeof(KSEMAPHORE)/sizeof(ULONG),
+ Count);
+ Semaphore->Limit=Limit;
}
/*
* @implemented
*/
-LONG
-STDCALL
-KeReadStateSemaphore(PKSEMAPHORE Semaphore)
+LONG STDCALL
+KeReadStateSemaphore (PKSEMAPHORE Semaphore)
{
- /* Just return the Signal State */
- return(Semaphore->Header.SignalState);
+ 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
* 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;
- PKTHREAD CurrentThread;
+ ULONG InitialState;
+ KIRQL OldIrql;
- 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);
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
+ OldIrql = KeAcquireDispatcherDatabaseLock();
- /* 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);
+ InitialState = Semaphore->Header.SignalState;
+ if (Semaphore->Limit < (LONG) InitialState + Adjustment ||
+ InitialState > InitialState + Adjustment)
+ {
+ ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
}
- /* 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);
+ Semaphore->Header.SignalState += Adjustment;
+ if (InitialState == 0)
+ {
+ KiDispatcherObjectWake(&Semaphore->Header, SEMAPHORE_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 = KeGetCurrentThread();
- 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 InitialState;
+ return(InitialState);
}
/* EOF */
/* Initialize the Dispatch Header */
KeInitializeDispatcherHeader(&Timer->Header,
- TimerNotificationObject + Type,
+ InternalNotificationTimer + Type,
sizeof(KTIMER) / sizeof(ULONG),
FALSE);
- /* Initalize the Other data */
+ /* Initalize the List Head and other data */
+ InitializeListHead(&Timer->Header.WaitListHead);
Timer->DueTime.QuadPart = 0;
Timer->Period = 0;
}
Timer->Dpc = Dpc;
Timer->Period = Period;
Timer->Header.SignalState = FALSE;
+ Timer->Header.Absolute = FALSE;
/* Insert it */
if (!KiInsertTimer(Timer, DueTime)) {
/* Set it as Signaled */
DPRINT("Setting Timer as Signaled\n");
Timer->Header.SignalState = TRUE;
- KiWaitTest(&Timer->Header, 0);
+ KiDispatcherObjectWake(&Timer->Header, 0);
/* If the Timer is periodic, reinsert the timer with the new due time */
if (Timer->Period) {
if (!KiInsertTimer(Timer, DueTime)) {
/* FIXME: I will think about how to handle this and fix it ASAP -- Alex */
- DPRINT("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n");
+ DPRINT1("CRITICAL UNHANDLED CASE: TIMER ALREADY EXPIRED!!!\n");
};
}
DPRINT("KiInsertTimer(Timer %x DueTime %I64d)\n", Timer, DueTime.QuadPart);
- /* Set default data */
+ /* Set it as Inserted */
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) {
-/*
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS project
* FILE: ntoskrnl/ke/wait.c
* PURPOSE: Manages non-busy waiting
*
- * PROGRAMMERS: Alex Ionescu - Fixes and optimization.
- * Gunnar Dalsnes - Implementation
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
+ * Phillip Susi
+ */
+
+/* NOTES ********************************************************************
+ *
*/
/* INCLUDES ******************************************************************/
static KSPIN_LOCK DispatcherDatabaseLock;
-/* Tells us if the Timer or Event is a Syncronization or Notification Object */
-#define TIMER_OR_EVENT_TYPE 0x7L
+#define KeDispatcherObjectWakeOne(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, FALSE)
+#define KeDispatcherObjectWakeAll(hdr, increment) KeDispatcherObjectWakeOneOrAll(hdr, increment, TRUE)
-/* One of the Reserved Wait Blocks, this one is for the Thread's Timer */
-#define TIMER_WAIT_BLOCK 0x3L
+extern POBJECT_TYPE EXPORTED ExMutantObjectType;
+extern POBJECT_TYPE EXPORTED ExSemaphoreObjectType;
+extern POBJECT_TYPE EXPORTED ExTimerType;
/* FUNCTIONS *****************************************************************/
+VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
+ ULONG Type,
+ ULONG Size,
+ ULONG SignalState)
+{
+ Header->Type = (UCHAR)Type;
+ Header->Absolute = 0;
+ Header->Inserted = 0;
+ Header->Size = (UCHAR)Size;
+ Header->SignalState = SignalState;
+ InitializeListHead(&(Header->WaitListHead));
+}
+
+
+KIRQL
+KeAcquireDispatcherDatabaseLock(VOID)
+/*
+ * PURPOSE: Acquires the dispatcher database lock for the caller
+ */
+{
+ KIRQL OldIrql;
+
+ DPRINT("KeAcquireDispatcherDatabaseLock()\n");
+
+ KeAcquireSpinLock (&DispatcherDatabaseLock, &OldIrql);
+ return OldIrql;
+}
+
+
VOID
-inline
-FASTCALL
-KiCheckAlertability(BOOLEAN Alertable,
- PKTHREAD CurrentThread,
- KPROCESSOR_MODE WaitMode,
- PNTSTATUS Status)
+KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID)
+/*
+ * PURPOSE: Acquires the dispatcher database lock for the caller
+ */
{
- /* At this point, we have to do a wait, so make sure we can make the thread Alertable if requested */
- if (Alertable) {
-
- /* If the Thread is Alerted, set the Wait Status accordingly */
- if (CurrentThread->Alerted[(int)WaitMode]) {
-
- CurrentThread->Alerted[(int)WaitMode] = FALSE;
- DPRINT("Thread was Alerted\n");
- *Status = STATUS_ALERTED;
-
- /* If there are User APCs Pending, then we can't really be alertable */
- } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) &&
- (WaitMode == UserMode)) {
-
- DPRINT("APCs are Pending\n");
- CurrentThread->ApcState.UserApcPending = TRUE;
- *Status = STATUS_USER_APC;
- }
-
- /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */
- } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) {
- DPRINT("APCs are Pending\n");
- *Status = STATUS_USER_APC;
- }
+ DPRINT("KeAcquireDispatcherDatabaseLockAtDpcLevel()\n");
+
+ KeAcquireSpinLockAtDpcLevel (&DispatcherDatabaseLock);
+}
+
+
+VOID
+KeReleaseDispatcherDatabaseLock(KIRQL OldIrql)
+{
+ DPRINT("KeReleaseDispatcherDatabaseLock(OldIrql %x)\n",OldIrql);
+ if (!KeIsExecutingDpc() &&
+ OldIrql < DISPATCH_LEVEL &&
+ KeGetCurrentThread() != NULL &&
+ KeGetCurrentThread() == KeGetCurrentKPCR()->PrcbData.IdleThread)
+ {
+ PsDispatchThreadNoLock(THREAD_STATE_READY);
+ KeLowerIrql(OldIrql);
+ }
+ else
+ {
+ KeReleaseSpinLock(&DispatcherDatabaseLock, OldIrql);
+ }
+}
+
+
+VOID
+KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID)
+{
+ DPRINT("KeReleaseDispatcherDatabaseLock()\n");
+
+ KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
+}
+
+
+static BOOLEAN
+KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
+ PKTHREAD Thread)
+/*
+ * FUNCTION: Perform side effects on object before a wait for a thread is
+ * satisfied
+ */
+{
+ BOOLEAN Abandoned = FALSE;
+
+ switch (hdr->Type)
+ {
+ case InternalSynchronizationEvent:
+ hdr->SignalState = 0;
+ break;
+
+ case InternalQueueType:
+ break;
+
+ case InternalSemaphoreType:
+ hdr->SignalState--;
+ break;
+
+ case InternalProcessType:
+ break;
+
+ case InternalThreadType:
+ break;
+
+ case InternalNotificationEvent:
+ break;
+
+ case InternalSynchronizationTimer:
+ hdr->SignalState = FALSE;
+ break;
+
+ case InternalNotificationTimer:
+ break;
+
+ case InternalMutexType:
+ {
+ PKMUTEX Mutex;
+
+ Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
+ hdr->SignalState--;
+ ASSERT(hdr->SignalState <= 1);
+ if (hdr->SignalState == 0)
+ {
+ if (Thread == NULL)
+ {
+ DPRINT("Thread == NULL!\n");
+ KEBUGCHECK(0);
+ }
+ Abandoned = Mutex->Abandoned;
+ if (Thread != NULL)
+ InsertTailList(&Thread->MutantListHead, &Mutex->MutantListEntry);
+ Mutex->OwnerThread = Thread;
+ Mutex->Abandoned = FALSE;
+ }
+ }
+ break;
+
+ default:
+ DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n", __FILE__, __LINE__, hdr);
+ KEBUGCHECK(0);
+ }
+
+ return Abandoned;
+}
+
+static BOOLEAN
+KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
+ PKTHREAD Thread)
+{
+ if (hdr->Type == InternalMutexType)
+ {
+ PKMUTEX Mutex;
+
+ Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
+
+ ASSERT(hdr->SignalState <= 1);
+
+ if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) || hdr->SignalState == 1)
+ {
+ return (TRUE);
+ }
+ else
+ {
+ return (FALSE);
+ }
+ }
+
+ if (hdr->SignalState <= 0)
+ {
+ return (FALSE);
+ }
+ else
+ {
+ return (TRUE);
+ }
+}
+
+/* Must be called with the dispatcher lock held */
+BOOLEAN KiAbortWaitThread(PKTHREAD Thread, NTSTATUS WaitStatus)
+{
+ PKWAIT_BLOCK WaitBlock;
+ BOOLEAN WasWaiting;
+
+ /* if we are blocked, we must be waiting on something also */
+ ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != NULL));
+
+ WaitBlock = (PKWAIT_BLOCK)Thread->WaitBlockList;
+ WasWaiting = (WaitBlock != NULL);
+
+ while (WaitBlock)
+ {
+ RemoveEntryList(&WaitBlock->WaitListEntry);
+ WaitBlock = WaitBlock->NextWaitBlock;
+ }
+
+ Thread->WaitBlockList = NULL;
+
+ if (WasWaiting)
+ {
+ PsUnblockThread((PETHREAD)Thread, &WaitStatus, 0);
+ }
+ return WasWaiting;
+}
+
+static BOOLEAN
+KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
+ KPRIORITY increment,
+ BOOLEAN WakeAll)
+{
+ PKWAIT_BLOCK Waiter;
+ PKWAIT_BLOCK WaiterHead;
+ PLIST_ENTRY EnumEntry;
+ NTSTATUS Status;
+ BOOLEAN Abandoned;
+ BOOLEAN AllSignaled;
+ BOOLEAN WakedAny = FALSE;
+
+ DPRINT("KeDispatcherObjectWakeOnOrAll(hdr %x)\n", hdr);
+ DPRINT ("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
+ hdr->WaitListHead.Flink, hdr->WaitListHead.Blink);
+
+ if (IsListEmpty(&hdr->WaitListHead))
+ {
+ return (FALSE);
+ }
+
+ //enum waiters for this dispatcher object
+ EnumEntry = hdr->WaitListHead.Flink;
+ while (EnumEntry != &hdr->WaitListHead && (WakeAll || !WakedAny))
+ {
+ WaiterHead = CONTAINING_RECORD(EnumEntry, KWAIT_BLOCK, WaitListEntry);
+ DPRINT("current_entry %x current %x\n", EnumEntry, WaiterHead);
+ EnumEntry = EnumEntry->Flink;
+ ASSERT(WaiterHead->Thread != NULL);
+ ASSERT(WaiterHead->Thread->WaitBlockList != NULL);
+
+ Abandoned = FALSE;
+
+ if (WaiterHead->WaitType == WaitAny)
+ {
+ DPRINT("WaitAny: Remove all wait blocks.\n");
+ for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
+ {
+ RemoveEntryList(&Waiter->WaitListEntry);
+ }
+
+ WaiterHead->Thread->WaitBlockList = NULL;
+
+ /*
+ * If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
+ * but thats ok since WakeAll objects has no sideeffects.
+ */
+ Abandoned |= KiSideEffectsBeforeWake(hdr, WaiterHead->Thread);
+ }
+ else
+ {
+ DPRINT("WaitAll: All WaitAll objects must be signaled.\n");
+
+ AllSignaled = TRUE;
+
+ //all WaitAll obj. for thread need to be signaled to satisfy a wake
+ for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
+ {
+ //no need to check hdr since it has to be signaled
+ if (Waiter->WaitType == WaitAll && Waiter->Object != hdr)
+ {
+ if (!KiIsObjectSignalled(Waiter->Object, Waiter->Thread))
+ {
+ AllSignaled = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (AllSignaled)
+ {
+ for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
+ {
+ RemoveEntryList(&Waiter->WaitListEntry);
+
+ if (Waiter->WaitType == WaitAll)
+ {
+ Abandoned |= KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread);
+ }
+
+ //no WaitAny objects can possibly be signaled since we are here
+ ASSERT(!(Waiter->WaitType == WaitAny
+ && KiIsObjectSignalled(Waiter->Object, Waiter->Thread)));
+ }
+
+ WaiterHead->Thread->WaitBlockList = NULL;
+ }
+ }
+
+ if (WaiterHead->Thread->WaitBlockList == NULL)
+ {
+ Status = WaiterHead->WaitKey;
+ if (Abandoned)
+ {
+ DPRINT("Abandoned mutex among objects");
+ Status += STATUS_ABANDONED_WAIT_0;
+ }
+
+ WakedAny = TRUE;
+ DPRINT("Waking %x status = %x\n", WaiterHead->Thread, Status);
+ PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb),
+ &Status, increment);
+ }
+ }
+
+ return WakedAny;
+}
+
+
+BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
+/*
+ * FUNCTION: Wake threads waiting on a dispatcher object
+ * NOTE: The exact semantics of waking are dependant on the type of object
+ */
+{
+ BOOL Ret;
+
+ DPRINT("Entering KeDispatcherObjectWake(hdr %x)\n",hdr);
+// DPRINT("hdr->WaitListHead %x hdr->WaitListHead.Flink %x\n",
+// &hdr->WaitListHead,hdr->WaitListHead.Flink);
+ DPRINT("hdr->Type %x\n",hdr->Type);
+ switch (hdr->Type)
+ {
+ case InternalNotificationEvent:
+ return(KeDispatcherObjectWakeAll(hdr, increment));
+
+ case InternalNotificationTimer:
+ return(KeDispatcherObjectWakeAll(hdr, increment));
+
+ case InternalSynchronizationEvent:
+ return(KeDispatcherObjectWakeOne(hdr, increment));
+
+ case InternalSynchronizationTimer:
+ return(KeDispatcherObjectWakeOne(hdr, increment));
+
+ case InternalQueueType:
+ return(KeDispatcherObjectWakeOne(hdr, increment));
+
+ case InternalSemaphoreType:
+ DPRINT("hdr->SignalState %d\n", hdr->SignalState);
+ if(hdr->SignalState>0)
+ {
+ do
+ {
+ DPRINT("Waking one semaphore waiter\n");
+ Ret = KeDispatcherObjectWakeOne(hdr, increment);
+ } while(hdr->SignalState > 0 && Ret) ;
+ return(Ret);
+ }
+ else return FALSE;
+
+ case InternalProcessType:
+ return(KeDispatcherObjectWakeAll(hdr, increment));
+
+ case InternalThreadType:
+ return(KeDispatcherObjectWakeAll(hdr, increment));
+
+ case InternalMutexType:
+ return(KeDispatcherObjectWakeOne(hdr, increment));
+ }
+ DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type);
+ KEBUGCHECK(0);
+ return(FALSE);
}
/*
* @implemented
- *
+ */
+NTSTATUS STDCALL
+KeDelayExecutionThread (KPROCESSOR_MODE WaitMode,
+ BOOLEAN Alertable,
+ PLARGE_INTEGER Interval)
+/*
* FUNCTION: Puts the current thread into an alertable or nonalertable
* wait state for a given internal
* ARGUMENTS:
* Interval = Specifies the interval to wait
* RETURNS: Status
*/
-NTSTATUS
-STDCALL
-KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
- BOOLEAN Alertable,
- PLARGE_INTEGER Interval)
{
- PKWAIT_BLOCK TimerWaitBlock;
- PKTIMER ThreadTimer;
- PKTHREAD CurrentThread = KeGetCurrentThread();
- NTSTATUS Status;
+ PKTHREAD Thread = KeGetCurrentThread();
- DPRINT("Entering KeDelayExecutionThread\n");
-
- /* Check if the lock is already held */
- if (CurrentThread->WaitNext) {
-
- /* Lock is held, disable Wait Next */
- DPRINT("Lock is held\n");
- CurrentThread->WaitNext = FALSE;
-
- } else {
-
- /* Lock not held, acquire it */
- DPRINT("Lock is not held, acquiring\n");
- CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
- }
-
- /* Use built-in Wait block */
- TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
-
- /* Start Wait Loop */
- do {
-
- /* We are going to wait no matter what (that's the point), so test Alertability */
- KiCheckAlertability(Alertable, CurrentThread, KernelMode, &Status);
-
- /* Set Timer */
- ThreadTimer = &CurrentThread->Timer;
-
- /* Setup the Wait Block */
- CurrentThread->WaitBlockList = TimerWaitBlock;
- TimerWaitBlock->Object = (PVOID)ThreadTimer;
- TimerWaitBlock->Thread = CurrentThread;
- TimerWaitBlock->WaitKey = (USHORT)STATUS_TIMEOUT;
- TimerWaitBlock->WaitType = WaitAny;
- TimerWaitBlock->NextWaitBlock = NULL;
-
- /* Link the timer to this Wait Block */
- InitializeListHead(&ThreadTimer->Header.WaitListHead);
- InsertTailList(&ThreadTimer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
-
- /* Insert the Timer into the Timer Lists and enable it */
- if (!KiInsertTimer(ThreadTimer, *Interval)) {
-
- /* FIXME: Unhandled case...what should we do? */
- DPRINT1("Could not create timer for KeDelayExecutionThread\n");
- }
-
- /* Handle Kernel Queues */
- if (CurrentThread->Queue) {
-
- DPRINT("Waking Queue\n");
- KiWakeQueue(CurrentThread->Queue);
- }
-
- /* Block the Thread */
- DPRINT("Blocking the Thread: %d, %d, %x\n", Alertable, WaitMode, KeGetCurrentThread());
- PsBlockThread(&Status,
- Alertable,
- WaitMode,
- DelayExecution);
-
- /* Check if we were executing an APC or if we timed out */
- if (Status != STATUS_KERNEL_APC) {
-
- /* This is a good thing */
- if (Status == STATUS_TIMEOUT) Status = STATUS_SUCCESS;
-
- /* Return Status */
- return Status;
- }
-
- DPRINT("Looping Again\n");
- CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-
- } while (TRUE);
-
- /* Release the Lock, we are done */
- DPRINT("Returning from KeDelayExecutionThread(), %x. Status: %d\n", KeGetCurrentThread(), Status);
- KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
- return Status;
+ KeSetTimer(&Thread->Timer, *Interval, NULL);
+ return (KeWaitForSingleObject(&Thread->Timer,
+ (WaitMode == KernelMode) ? Executive : UserRequest, /* TMN: Was unconditionally Executive */
+ WaitMode, /* TMN: Was UserMode */
+ Alertable,
+ NULL));
}
/*
* @implemented
- *
+ */
+NTSTATUS STDCALL
+KeWaitForSingleObject(PVOID Object,
+ KWAIT_REASON WaitReason,
+ KPROCESSOR_MODE WaitMode,
+ BOOLEAN Alertable,
+ PLARGE_INTEGER Timeout)
+/*
* FUNCTION: Puts the current thread into a wait state until the
* given dispatcher object is set to signalled
* ARGUMENTS:
* Timeout = Optional timeout value
* RETURNS: Status
*/
-NTSTATUS
-STDCALL
-KeWaitForSingleObject(PVOID Object,
- KWAIT_REASON WaitReason,
- KPROCESSOR_MODE WaitMode,
- BOOLEAN Alertable,
- PLARGE_INTEGER Timeout)
{
- PDISPATCHER_HEADER CurrentObject;
- PKWAIT_BLOCK WaitBlock;
- PKWAIT_BLOCK TimerWaitBlock;
- PKTIMER ThreadTimer;
- PKTHREAD CurrentThread = KeGetCurrentThread();
- NTSTATUS Status;
- NTSTATUS WaitStatus;
-
- DPRINT("Entering KeWaitForSingleObject\n");
-
- /* Check if the lock is already held */
- if (CurrentThread->WaitNext) {
-
- /* Lock is held, disable Wait Next */
- DPRINT("Lock is held\n");
- CurrentThread->WaitNext = FALSE;
-
- } else {
-
- /* Lock not held, acquire it */
- DPRINT("Lock is not held, acquiring\n");
- CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
- }
-
- /* Start the actual Loop */
- do {
-
- /* Get the current Wait Status */
- WaitStatus = CurrentThread->WaitStatus;
-
- /* Append wait block to the KTHREAD wait block list */
- CurrentThread->WaitBlockList = WaitBlock = &CurrentThread->WaitBlock[0];
-
- /* Get the Current Object */
- CurrentObject = (PDISPATCHER_HEADER)Object;
-
- /* FIXME:
- * Temporary hack until my Object Manager re-write. Basically some objects, like
- * the File Object, but also LPCs and others, are actually waitable on their event.
- * The Object Manager sets this up in The ObjectTypeInformation->DefaultObject member,
- * by using pretty much the same kind of hack as us. Normal objects point to themselves
- * in that pointer. Then, NtWaitForXXX will populate the WaitList that gets sent to us by
- * using ->DefaultObject, so the proper actual objects will be sent to us. Until then however,
- * I will keep this hack here, since there's no need to make an interim hack until the rewrite
- * -- Alex Ionescu 24/02/05
- */
- if (CurrentObject->Type == IO_TYPE_FILE) {
-
- DPRINT1("Hack used: %x\n", &((PFILE_OBJECT)CurrentObject)->Event);
- CurrentObject = (PDISPATCHER_HEADER)(&((PFILE_OBJECT)CurrentObject)->Event);
- }
-
- /* Check if the Object is Signaled */
- if (KiIsObjectSignaled(CurrentObject, CurrentThread)) {
-
- /* Just unwait this guy and exit */
- if (CurrentObject->SignalState != MINLONG) {
-
- /* It has a normal signal state, so unwait it and return */
- KiSatisfyObjectWait(CurrentObject, CurrentThread);
- Status = STATUS_WAIT_0;
- goto WaitDone;
-
- } else {
-
- /* Is this a Mutant? */
- if (CurrentObject->Type == MutantObject) {
-
- /* According to wasm.ru, we must raise this exception (tested and true) */
- KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
- ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
- }
- }
- }
-
- /* Set up the Wait Block */
- WaitBlock->Object = CurrentObject;
- WaitBlock->Thread = CurrentThread;
- WaitBlock->WaitKey = (USHORT)(STATUS_WAIT_0);
- WaitBlock->WaitType = WaitAny;
- WaitBlock->NextWaitBlock = NULL;
-
- /* Make sure we can satisfy the Alertable request */
- KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status);
-
- /* Set the Wait Status */
- CurrentThread->WaitStatus = Status;
-
- /* Enable the Timeout Timer if there was any specified */
- if (Timeout != NULL) {
-
- /* However if 0 timeout was specified, then we must fail since we need to peform a wait */
- if (!Timeout->QuadPart) {
-
- /* Return a timeout */
- Status = STATUS_TIMEOUT;
- goto WaitDone;
- }
-
- /* Point to Timer Wait Block and Thread Timer */
- TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
- ThreadTimer = &CurrentThread->Timer;
+ return KeWaitForMultipleObjects(1,
+ &Object,
+ WaitAny,
+ WaitReason,
+ WaitMode,
+ Alertable,
+ Timeout,
+ NULL);
+}
- /* Connect the Timer Wait Block */
- WaitBlock->NextWaitBlock = TimerWaitBlock;
-
- /* Set up the Timer Wait Block */
- TimerWaitBlock->Object = (PVOID)ThreadTimer;
- TimerWaitBlock->Thread = CurrentThread;
- TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
- TimerWaitBlock->WaitType = WaitAny;
- TimerWaitBlock->NextWaitBlock = NULL;
-
- /* Link the timer to this Wait Block */
- InitializeListHead(&ThreadTimer->Header.WaitListHead);
- InsertTailList(&ThreadTimer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
- /* Insert the Timer into the Timer Lists and enable it */
- if (!KiInsertTimer(ThreadTimer, *Timeout)) {
+inline
+PVOID
+KiGetWaitableObjectFromObject(PVOID Object)
+{
+ //special case when waiting on file objects
+ if ( ((PDISPATCHER_HEADER)Object)->Type == InternalFileType)
+ {
+ return &((PFILE_OBJECT)Object)->Event;
+ }
- /* Return a timeout if we couldn't insert the timer for some reason */
- Status = STATUS_TIMEOUT;
- goto WaitDone;
- }
- }
+ return Object;
+}
- /* Link the Object to this Wait Block */
- InsertTailList(&CurrentObject->WaitListHead, &WaitBlock->WaitListEntry);
-
- /* Handle Kernel Queues */
- if (CurrentThread->Queue) {
-
- DPRINT("Waking Queue\n");
- KiWakeQueue(CurrentThread->Queue);
- }
- /* Block the Thread */
- DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, WaitReason, KeGetCurrentThread());
- PsBlockThread(&Status,
- Alertable,
- WaitMode,
- (UCHAR)WaitReason);
-
- /* Check if we were executing an APC */
- if (Status != STATUS_KERNEL_APC) {
-
- /* Return Status */
- return Status;
- }
-
- DPRINT("Looping Again\n");
- CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-
- } while (TRUE);
-
-WaitDone:
- /* Release the Lock, we are done */
- DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n", KeGetCurrentThread(), Status);
- KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
- return Status;
+inline BOOL
+KiIsObjectWaitable(PVOID Object)
+{
+ POBJECT_HEADER Header;
+ Header = BODY_TO_HEADER(Object);
+ if (Header->ObjectType == ExEventObjectType ||
+ Header->ObjectType == ExIoCompletionType ||
+ Header->ObjectType == ExMutantObjectType ||
+ Header->ObjectType == ExSemaphoreObjectType ||
+ Header->ObjectType == ExTimerType ||
+ Header->ObjectType == PsProcessType ||
+ Header->ObjectType == PsThreadType ||
+ Header->ObjectType == IoFileObjectType)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
/*
PLARGE_INTEGER Timeout,
PKWAIT_BLOCK WaitBlockArray)
{
- PDISPATCHER_HEADER CurrentObject;
- PKWAIT_BLOCK WaitBlock;
- PKWAIT_BLOCK TimerWaitBlock;
- PKTIMER ThreadTimer;
- PKTHREAD CurrentThread = KeGetCurrentThread();
- ULONG AllObjectsSignaled;
- ULONG WaitIndex;
- NTSTATUS Status;
- NTSTATUS WaitStatus;
-
- DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
- "PsGetCurrentThread() %x, Timeout %x\n", Count, Object, PsGetCurrentThread(), Timeout);
-
- /* Set the Current Thread */
- CurrentThread = KeGetCurrentThread();
-
- /* Check if the lock is already held */
- if (CurrentThread->WaitNext) {
-
- /* Lock is held, disable Wait Next */
- DPRINT("Lock is held\n");
- CurrentThread->WaitNext = FALSE;
-
- } else {
-
- /* Lock not held, acquire it */
- DPRINT("Lock is not held, acquiring\n");
- CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
- }
+ DISPATCHER_HEADER *hdr;
+ PKWAIT_BLOCK blk;
+ PKTHREAD CurrentThread;
+ ULONG CountSignaled;
+ ULONG i;
+ NTSTATUS Status;
+ KIRQL OldIrql;
+ BOOLEAN Abandoned;
+ NTSTATUS WaitStatus;
- /* Make sure the Wait Count is valid for the Thread and Maximum Wait Objects */
- if (!WaitBlockArray) {
-
- /* Check in regards to the Thread Object Limit */
- if (Count > THREAD_WAIT_OBJECTS) {
-
- DPRINT1("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
- KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
- }
-
- /* Use the Thread's Wait Block */
- WaitBlockArray = &CurrentThread->WaitBlock[0];
-
- } else {
-
- /* Using our own Block Array. Check in regards to System Object Limit */
- if (Count > MAXIMUM_WAIT_OBJECTS) {
-
- DPRINT1("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
- KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
- }
- }
-
- /* Start the actual Loop */
- do {
-
- /* Get the current Wait Status */
- WaitStatus = CurrentThread->WaitStatus;
-
- /* Append wait block to the KTHREAD wait block list */
- CurrentThread->WaitBlockList = WaitBlock = WaitBlockArray;
-
- /* Check if the wait is (already) satisfied */
- AllObjectsSignaled = TRUE;
-
- /* First, we'll try to satisfy the wait directly */
- for (WaitIndex = 0; WaitIndex < Count; WaitIndex++) {
-
- /* Get the Current Object */
- CurrentObject = (PDISPATCHER_HEADER)Object[WaitIndex];
-
- /* FIXME:
- * Temporary hack until my Object Manager re-write. Basically some objects, like
- * the File Object, but also LPCs and others, are actually waitable on their event.
- * The Object Manager sets this up in The ObjectTypeInformation->DefaultObject member,
- * by using pretty much the same kind of hack as us. Normal objects point to themselves
- * in that pointer. Then, NtWaitForXXX will populate the WaitList that gets sent to us by
- * using ->DefaultObject, so the proper actual objects will be sent to us. Until then however,
- * I will keep this hack here, since there's no need to make an interim hack until the rewrite
- * -- Alex Ionescu 24/02/05
- */
- if (CurrentObject->Type == IO_TYPE_FILE) {
-
- DPRINT1("Hack used: %x\n", &((PFILE_OBJECT)CurrentObject)->Event);
- CurrentObject = (PDISPATCHER_HEADER)(&((PFILE_OBJECT)CurrentObject)->Event);
- }
+ DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
+ "PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread());
- /* Check if the Object is Signaled */
- if (KiIsObjectSignaled(CurrentObject, CurrentThread)) {
-
- /* Check what kind of wait this is */
- if (WaitType == WaitAny) {
-
- /* This is a Wait Any, so just unwait this guy and exit */
- if (CurrentObject->SignalState != MINLONG) {
-
- /* It has a normal signal state, so unwait it and return */
- KiSatisfyObjectWait(CurrentObject, CurrentThread);
- Status = STATUS_WAIT_0 | WaitIndex;
- goto WaitDone;
-
- } else {
-
- /* Is this a Mutant? */
- if (CurrentObject->Type == MutantObject) {
-
- /* According to wasm.ru, we must raise this exception (tested and true) */
- KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
- ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
- }
- }
- }
-
- } else {
-
- /* One of the objects isn't signaled... if this is a WaitAll, we will fail later */
- AllObjectsSignaled = FALSE;
- }
+ ASSERT(0 < Count && Count <= MAXIMUM_WAIT_OBJECTS);
- /* Set up a Wait Block for this Object */
- WaitBlock->Object = CurrentObject;
- WaitBlock->Thread = CurrentThread;
- WaitBlock->WaitKey = (USHORT)(STATUS_WAIT_0 + WaitIndex);
- WaitBlock->WaitType = (USHORT)WaitType;
- WaitBlock->NextWaitBlock = WaitBlock + 1;
-
- /* Move to the next Wait Block */
- WaitBlock = WaitBlock->NextWaitBlock;
- }
-
- /* Return to the Root Wait Block */
- WaitBlock--;
- WaitBlock->NextWaitBlock = NULL;
-
- /* Check if this is a Wait All and all the objects are signaled */
- if ((WaitType == WaitAll) && (AllObjectsSignaled)) {
-
- /* Return to the Root Wait Block */
- WaitBlock = CurrentThread->WaitBlockList;
-
- /* Satisfy their Waits and return to the caller */
- KiSatisifyMultipleObjectWaits(WaitBlock);
- Status = STATUS_WAIT_0;
- goto WaitDone;
- }
-
- /* Make sure we can satisfy the Alertable request */
- KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status);
-
- /* Set the Wait Status */
- CurrentThread->WaitStatus = Status;
-
- /* Enable the Timeout Timer if there was any specified */
- if (Timeout != NULL) {
-
- /* However if 0 timeout was specified, then we must fail since we need to peform a wait */
- if (!Timeout->QuadPart) {
-
- /* Return a timeout */
- Status = STATUS_TIMEOUT;
- goto WaitDone;
- }
-
- /* Point to Timer Wait Block and Thread Timer */
- TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
- ThreadTimer = &CurrentThread->Timer;
+ CurrentThread = KeGetCurrentThread();
- /* Connect the Timer Wait Block */
- WaitBlock->NextWaitBlock = TimerWaitBlock;
-
- /* Set up the Timer Wait Block */
- TimerWaitBlock->Object = (PVOID)ThreadTimer;
- TimerWaitBlock->Thread = CurrentThread;
- TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
- TimerWaitBlock->WaitType = WaitAny;
- TimerWaitBlock->NextWaitBlock = NULL;
-
- /* Link the timer to this Wait Block */
- InitializeListHead(&ThreadTimer->Header.WaitListHead);
+ /*
+ * Work out where we are going to put the wait blocks
+ */
+ if (WaitBlockArray == NULL)
+ {
+ if (Count > THREAD_WAIT_OBJECTS)
+ {
+ DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
+ return (STATUS_UNSUCCESSFUL);
+ }
+ WaitBlockArray = &CurrentThread->WaitBlock[0];
+ }
+ else
+ {
+ if (Count > MAXIMUM_WAIT_OBJECTS)
+ {
+ DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
+ return (STATUS_UNSUCCESSFUL);
+ }
+ }
- /* Insert the Timer into the Timer Lists and enable it */
- if (!KiInsertTimer(ThreadTimer, *Timeout)) {
- /* Return a timeout if we couldn't insert the timer for some reason */
- Status = STATUS_TIMEOUT;
- goto WaitDone;
- }
- }
- /* Insert into Object's Wait List*/
- WaitBlock = CurrentThread->WaitBlockList;
- while (WaitBlock) {
-
- /* Get the Current Object */
- CurrentObject = WaitBlock->Object;
-
- /* Link the Object to this Wait Block */
- InsertTailList(&CurrentObject->WaitListHead, &WaitBlock->WaitListEntry);
-
- /* Move to the next Wait Block */
- WaitBlock = WaitBlock->NextWaitBlock;
- }
-
- /* Handle Kernel Queues */
- if (CurrentThread->Queue) {
-
- DPRINT("Waking Queue\n");
- KiWakeQueue(CurrentThread->Queue);
- }
-
- /* Block the Thread */
- DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, WaitReason, KeGetCurrentThread());
- PsBlockThread(&Status,
- Alertable,
- WaitMode,
- (UCHAR)WaitReason);
-
- /* Check if we were executing an APC */
- if (Status != STATUS_KERNEL_APC) {
-
- /* Return Status */
- return Status;
- }
-
- DPRINT("Looping Again\n");
- CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-
- } while (TRUE);
-
-WaitDone:
- /* Release the Lock, we are done */
- DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n", KeGetCurrentThread(), Status);
- KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
- return Status;
-}
+ /*
+ * Set up the timeout if required
+ */
+ if (Timeout != NULL && Timeout->QuadPart != 0)
+ {
+ KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
+ }
-VOID
-FASTCALL
-KiSatisfyObjectWait(PDISPATCHER_HEADER Object,
- PKTHREAD Thread)
+ do
+ {
+ if (CurrentThread->WaitNext)
+ {
+ CurrentThread->WaitNext = FALSE;
+ OldIrql = CurrentThread->WaitIrql;
+ }
+ else
+ {
+ OldIrql = KeAcquireDispatcherDatabaseLock ();
+ }
-{
- /* Special case for Mutants */
- if (Object->Type == MutantObject) {
-
- /* Decrease the Signal State */
- Object->SignalState--;
-
- /* Check if it's now non-signaled */
- if (Object->SignalState == 0) {
-
- /* Set the Owner Thread */
- ((PKMUTANT)Object)->OwnerThread = Thread;
-
- /* Disable APCs if needed */
- Thread->KernelApcDisable -= ((PKMUTANT)Object)->ApcDisable;
+ /* Get the current Wait Status */
+ WaitStatus = CurrentThread->WaitStatus;
+
+ if (Alertable) {
+
+ /* If the Thread is Alerted, set the Wait Status accordingly */
+ if (CurrentThread->Alerted[(int)WaitMode]) {
- /* Check if it's abandoned */
- if (((PKMUTANT)Object)->Abandoned) {
+ CurrentThread->Alerted[(int)WaitMode] = FALSE;
+ DPRINT("Thread was Alerted\n");
+ WaitStatus = STATUS_ALERTED;
- /* Unabandon it */
- ((PKMUTANT)Object)->Abandoned = FALSE;
-
- /* Return Status */
- Thread->WaitStatus = STATUS_ABANDONED;
- }
+ /* If there are User APCs Pending, then we can't really be alertable */
+ } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) &&
+ (WaitMode == UserMode)) {
- /* Insert it into the Mutant List */
- InsertHeadList(&Thread->MutantListHead, &((PKMUTANT)Object)->MutantListEntry);
+ DPRINT1("APCs are Pending\n");
+ CurrentThread->ApcState.UserApcPending = TRUE;
+ WaitStatus = STATUS_USER_APC;
}
-
- } else if ((Object->Type & TIMER_OR_EVENT_TYPE) == EventSynchronizationObject) {
-
- /* These guys (Syncronization Timers and Events) just get un-signaled */
- Object->SignalState = 0;
- } else if (Object->Type == SemaphoreObject) {
+ /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */
+ } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) {
+ DPRINT1("APCs are Pending\n");
+ WaitStatus = STATUS_USER_APC;
+ }
- /* These ones can have multiple signalings, so we only decrease it */
- Object->SignalState--;
- }
-}
+ /*
+ * Check if the wait is (already) satisfied
+ */
+ CountSignaled = 0;
+ Abandoned = FALSE;
+ for (i = 0; i < Count; i++)
+ {
+ hdr = (DISPATCHER_HEADER *) KiGetWaitableObjectFromObject(Object[i]);
-VOID
-FASTCALL
-KiWaitTest(PDISPATCHER_HEADER Object,
- KPRIORITY Increment)
-{
- PLIST_ENTRY WaitEntry;
- PLIST_ENTRY WaitList;
- PKWAIT_BLOCK CurrentWaitBlock;
- PKWAIT_BLOCK NextWaitBlock;
-
- /* Loop the Wait Entries */
- DPRINT("KiWaitTest for Object: %x\n", Object);
- WaitList = &Object->WaitListHead;
- WaitEntry = WaitList->Flink;
- while ((WaitEntry != WaitList) && (Object->SignalState > 0)) {
-
- /* Get the current wait block */
- CurrentWaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
-
- /* Check the current Wait Mode */
- if (CurrentWaitBlock->WaitType == WaitAny) {
-
- /* Easy case, satisfy only this wait */
- DPRINT("Satisfiying a Wait any\n");
- WaitEntry = WaitEntry->Blink;
- KiSatisfyObjectWait(Object, CurrentWaitBlock->Thread);
-
- } else {
-
- /* Everything must be satisfied */
- DPRINT("Checking for a Wait All\n");
- NextWaitBlock = CurrentWaitBlock->NextWaitBlock;
-
- /* Loop first to make sure they are valid */
- while (NextWaitBlock) {
-
- /* Check if the object is signaled */
- if (!KiIsObjectSignaled(Object, CurrentWaitBlock->Thread)) {
-
- /* It's not, move to the next one */
- DPRINT1("One of the object is non-signaled, sorry.\n");
- goto SkipUnwait;
- }
-
- /* Go to the next Wait block */
- NextWaitBlock = NextWaitBlock->NextWaitBlock;
+ if (KiIsObjectSignalled(hdr, CurrentThread))
+ {
+ CountSignaled++;
+
+ if (WaitType == WaitAny)
+ {
+ Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
+
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+
+ if (Timeout != NULL && Timeout->QuadPart != 0)
+ {
+ KeCancelTimer(&CurrentThread->Timer);
+ }
+
+ DPRINT("One object is (already) signaled!\n");
+ if (Abandoned == TRUE)
+ {
+ return (STATUS_ABANDONED_WAIT_0 + i);
+ }
+
+ return (STATUS_WAIT_0 + i);
}
-
- /* All the objects are signaled, we can satisfy */
- DPRINT("Satisfiying a Wait All\n");
- WaitEntry = WaitEntry->Blink;
- KiSatisifyMultipleObjectWaits(CurrentWaitBlock);
- }
-
- /* All waits satisfied, unwait the thread */
- DPRINT("Unwaiting the Thread\n");
- KiAbortWaitThread(CurrentWaitBlock->Thread, CurrentWaitBlock->WaitKey);
+ }
+ }
-SkipUnwait:
- /* Next entry */
- WaitEntry = WaitEntry->Flink;
- }
-
- DPRINT("Done\n");
-}
+ Abandoned = FALSE;
+ if ((WaitType == WaitAll) && (CountSignaled == Count))
+ {
+ for (i = 0; i < Count; i++)
+ {
+ hdr = (DISPATCHER_HEADER *) KiGetWaitableObjectFromObject(Object[i]);
+ Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
+ }
-/* Must be called with the dispatcher lock held */
-VOID
-FASTCALL
-KiAbortWaitThread(PKTHREAD Thread,
- NTSTATUS WaitStatus)
-{
- PKWAIT_BLOCK WaitBlock;
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+
+ if (Timeout != NULL && Timeout->QuadPart != 0)
+ {
+ KeCancelTimer(&CurrentThread->Timer);
+ }
- /* If we are blocked, we must be waiting on something also */
- DPRINT("KiAbortWaitThread: %x, Status: %x, %x \n", Thread, WaitStatus, Thread->WaitBlockList);
- ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != NULL));
+ DPRINT("All objects are (already) signaled!\n");
- /* Remove the Wait Blocks from the list */
- DPRINT("Removing waits\n");
- WaitBlock = Thread->WaitBlockList;
- while (WaitBlock) {
-
- /* Remove it */
- DPRINT("Removing Waitblock: %x, %x\n", WaitBlock, WaitBlock->NextWaitBlock);
- RemoveEntryList(&WaitBlock->WaitListEntry);
-
- /* Go to the next one */
- WaitBlock = WaitBlock->NextWaitBlock;
- };
-
- /* 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);
- }
-
- /* Increment the Queue's active threads */
- if (Thread->Queue) {
-
- DPRINT("Incrementing Queue's active threads\n");
- Thread->Queue->CurrentCount++;
- }
+ if (Abandoned == TRUE)
+ {
+ return (STATUS_ABANDONED_WAIT_0);
+ }
- /* Reschedule the Thread */
- DPRINT("Unblocking the Thread\n");
- PsUnblockThread((PETHREAD)Thread, &WaitStatus, 0);
-}
+ return (STATUS_WAIT_0);
+ }
-BOOLEAN
-inline
-FASTCALL
-KiIsObjectSignaled(PDISPATCHER_HEADER Object,
- PKTHREAD Thread)
-{
- /* Mutants are...well...mutants! */
- if (Object->Type == MutantObject) {
-
- ASSERT(hdr->SignalState <= 1);
-
- /*
- * Because Cutler hates mutants, they are actually signaled if the Signal State is <= 0
- * Well, only if they are recursivly acquired (i.e if we own it right now).
- * Of course, they are also signaled if their signal state is 1.
- */
- if ((Object->SignalState <= 0 && ((PKMUTANT)Object)->OwnerThread == Thread) ||
- (Object->SignalState == 1)) {
-
- /* Signaled Mutant */
- return (TRUE);
-
- } else {
-
- /* Unsignaled Mutant */
- return (FALSE);
- }
- }
-
- /* Any other object is not a mutated freak, so let's use logic */
- return (!Object->SignalState <= 0);
-}
+ //zero timeout is used for testing if the object(s) can be immediately acquired
+ if (Timeout != NULL && Timeout->QuadPart == 0)
+ {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return STATUS_TIMEOUT;
+ }
-BOOL
-inline
-FASTCALL
-KiIsObjectWaitable(PVOID Object)
-{
- POBJECT_HEADER Header;
- Header = BODY_TO_HEADER(Object);
-
- if (Header->ObjectType == ExEventObjectType ||
- Header->ObjectType == ExIoCompletionType ||
- Header->ObjectType == ExMutantObjectType ||
- Header->ObjectType == ExSemaphoreObjectType ||
- Header->ObjectType == ExTimerType ||
- Header->ObjectType == PsProcessType ||
- Header->ObjectType == PsThreadType ||
- Header->ObjectType == IoFileObjectType) {
-
- return TRUE;
-
- } else {
-
- return FALSE;
- }
-}
+ /*
+ * Check if we have already timed out
+ */
+ if (Timeout != NULL && KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
+ {
+ KiSideEffectsBeforeWake(&CurrentThread->Timer.Header, CurrentThread);
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ KeCancelTimer(&CurrentThread->Timer);
+ return (STATUS_TIMEOUT);
+ }
-VOID
-inline
-FASTCALL
-KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock)
-{
- PKTHREAD WaitThread = WaitBlock->Thread;
-
- /* Loop through all the Wait Blocks, and wake each Object */
- while (WaitBlock) {
+ /* Append wait block to the KTHREAD wait block list */
+ CurrentThread->WaitBlockList = blk = WaitBlockArray;
+
+ /*
+ * Set up the wait
+ */
+ CurrentThread->WaitStatus = WaitStatus;;
+
+ for (i = 0; i < Count; i++)
+ {
+ hdr = (DISPATCHER_HEADER *) KiGetWaitableObjectFromObject(Object[i]);
+
+ blk->Object = KiGetWaitableObjectFromObject(Object[i]);
+ blk->Thread = CurrentThread;
+ blk->WaitKey = (USHORT)(STATUS_WAIT_0 + i);
+ blk->WaitType = (USHORT)WaitType;
+
+ if (i == (Count - 1))
+ {
+ if (Timeout != NULL)
+ {
+ blk->NextWaitBlock = &CurrentThread->WaitBlock[3];
+ }
+ else
+ {
+ blk->NextWaitBlock = NULL;
+ }
+ }
+ else
+ {
+ blk->NextWaitBlock = blk + 1;
+ }
+
+ /*
+ * add wait block to disp. obj. wait list
+ * Use FIFO for all waits except for queues which use LIFO
+ */
+ if (WaitReason == WrQueue)
+ {
+ InsertHeadList(&hdr->WaitListHead, &blk->WaitListEntry);
+ }
+ else
+ {
+ InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry);
+ }
+
+ blk = blk->NextWaitBlock;
+ }
+
+ if (Timeout != NULL)
+ {
+ CurrentThread->WaitBlock[3].Object = (PVOID) & CurrentThread->Timer;
+ CurrentThread->WaitBlock[3].Thread = CurrentThread;
+ CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
+ CurrentThread->WaitBlock[3].WaitType = WaitAny;
+ CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
+
+ InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
+ &CurrentThread->WaitBlock[3].WaitListEntry);
+ }
+
+ //kernel queues
+ if (CurrentThread->Queue && WaitReason != WrQueue)
+ {
+ DPRINT("queue: sleep on something else\n");
+ CurrentThread->Queue->CurrentCount--;
- /* Wake the Object */
- KiSatisfyObjectWait(WaitBlock->Object, WaitThread);
- WaitBlock = WaitBlock->NextWaitBlock;
- }
-}
+ //wake another thread
+ if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
+ !IsListEmpty(&CurrentThread->Queue->EntryListHead))
+ {
+ KiDispatcherObjectWake(&CurrentThread->Queue->Header, IO_NO_INCREMENT);
+ }
+ }
-VOID
-inline
-FASTCALL
-KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
- ULONG Type,
- ULONG Size,
- ULONG SignalState)
-{
- Header->Type = (UCHAR)Type;
- Header->Absolute = 0;
- Header->Inserted = 0;
- Header->Size = (UCHAR)Size;
- Header->SignalState = SignalState;
- InitializeListHead(&(Header->WaitListHead));
-}
+ PsBlockThread(&Status, Alertable, WaitMode, TRUE, OldIrql, (UCHAR)WaitReason);
-KIRQL
-inline
-FASTCALL
-KeAcquireDispatcherDatabaseLock(VOID)
-{
- KIRQL OldIrql;
+ //kernel queues
+ OldIrql = KeAcquireDispatcherDatabaseLock ();
+ if (CurrentThread->Queue && WaitReason != WrQueue)
+ {
+ DPRINT("queue: wake from something else\n");
+ CurrentThread->Queue->CurrentCount++;
+ }
+ if (Status == STATUS_KERNEL_APC)
+ {
+ CurrentThread->WaitNext = TRUE;
+ CurrentThread->WaitIrql = OldIrql;
+ }
+ else
+ {
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ }
+
+ } while (Status == STATUS_KERNEL_APC);
+
- KeAcquireSpinLock (&DispatcherDatabaseLock, &OldIrql);
- return OldIrql;
+ if (Timeout != NULL)
+ {
+ KeCancelTimer(&CurrentThread->Timer);
+ }
+
+ DPRINT("Returning from KeWaitForMultipleObjects()\n");
+ return (Status);
}
-VOID
-inline
-FASTCALL
-KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID)
+VOID KeInitializeDispatcher(VOID)
{
- KeAcquireSpinLockAtDpcLevel (&DispatcherDatabaseLock);
+ KeInitializeSpinLock(&DispatcherDatabaseLock);
}
-VOID
-inline
-FASTCALL
-KeInitializeDispatcher(VOID)
+NTSTATUS STDCALL
+NtWaitForMultipleObjects(IN ULONG ObjectCount,
+ IN PHANDLE ObjectsArray,
+ IN WAIT_TYPE WaitType,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER TimeOut OPTIONAL)
{
- /* Initialize the Dispatcher Lock */
- KeInitializeSpinLock(&DispatcherDatabaseLock);
+ 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);
}
-VOID
-inline
-FASTCALL
-KeReleaseDispatcherDatabaseLock(KIRQL OldIrql)
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtWaitForSingleObject(IN HANDLE ObjectHandle,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER TimeOut OPTIONAL)
{
- /* If it's the idle thread, dispatch */
- if (!KeIsExecutingDpc() && OldIrql < DISPATCH_LEVEL && KeGetCurrentThread() != NULL &&
- KeGetCurrentThread() == KeGetCurrentKPCR()->PrcbData.IdleThread) {
-
- PsDispatchThreadNoLock(THREAD_STATE_READY);
- KeLowerIrql(OldIrql);
-
- } else {
-
- /* Just release the spin lock */
- KeReleaseSpinLock(&DispatcherDatabaseLock, OldIrql);
- }
+ 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);
}
-VOID
-inline
-FASTCALL
-KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID)
+
+NTSTATUS STDCALL
+NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
+ IN HANDLE WaitableObjectHandle,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER TimeOut OPTIONAL)
{
- KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
-}
+ KPROCESSOR_MODE PreviousMode;
+ DISPATCHER_HEADER* hdr;
+ PVOID SignalObj;
+ PVOID WaitObj;
+ LARGE_INTEGER SafeTimeOut;
+ NTSTATUS Status = STATUS_SUCCESS;
-/* EOF */
+ 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 InternalNotificationEvent:
+ case InternalSynchronizationEvent:
+ KeSetEvent(SignalObj,
+ EVENT_INCREMENT,
+ TRUE);
+ break;
+
+ case InternalMutexType:
+ KeReleaseMutex(SignalObj,
+ TRUE);
+ break;
+
+ case InternalSemaphoreType:
+ 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;
+}
ExIsResourceAcquiredSharedLite@4
ExLocalTimeToSystemTime@8
ExNotifyCallback@12
+ExPostSystemEvent@12
ExQueryPoolBlockSize@8
ExQueueWorkItem@8
ExRaiseAccessViolation@0
Ke386QueryIoAccessMap@8
Ke386SetIoAccessMap@8
KeAcquireSpinLockAtDpcLevel@4
-@KeAcquireDispatcherDatabaseLockAtDpcLevel@0
+KeAcquireDispatcherDatabaseLockAtDpcLevel
@KeAcquireInStackQueuedSpinLockAtDpcLevel@8
KeAcquireInterruptSpinLock@4
KeAddSystemServiceTable@20
KeReadStateTimer@4
KeRegisterBugCheckCallback@20
KeRegisterBugCheckReasonCallback@16
-@KeReleaseDispatcherDatabaseLockFromDpcLevel@0
+KeReleaseDispatcherDatabaseLockFromDpcLevel
@KeReleaseInStackQueuedSpinLockFromDpcLevel@4
KeReleaseInterruptSpinLock@8
KeReleaseMutant@16
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
+++ /dev/null
-/*
- * 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 */
oldIrql = KeAcquireDispatcherDatabaseLock();
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
- KiWaitTest(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
+ KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
KeReleaseDispatcherDatabaseLock (oldIrql);
/* The last thread shall close the door on exit */
}
OldIrql = KeAcquireDispatcherDatabaseLock ();
Process->Pcb.DispatcherHeader.SignalState = TRUE;
- KiWaitTest(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
+ KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
KeReleaseDispatcherDatabaseLock (OldIrql);
ObDereferenceObject(Process);
return(STATUS_SUCCESS);
PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
- ProcessObject,
+ InternalProcessType,
sizeof(EPROCESS),
FALSE);
KProcess = &PsInitialSystemProcess->Pcb;
}
KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
- ProcessObject,
+ InternalProcessType,
sizeof(EPROCESS),
FALSE);
OldThread = CurrentThread;
CurrentThread = Candidate;
-
IdleThread = KeGetCurrentKPCR()->PrcbData.IdleThread;
if (&OldThread->Tcb == IdleThread)
}
VOID
-STDCALL
-PsBlockThread(PNTSTATUS Status,
- UCHAR Alertable,
- ULONG WaitMode,
- UCHAR WaitReason)
+PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
+ BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason)
{
- PKTHREAD Thread = KeGetCurrentThread();
- PKWAIT_BLOCK WaitBlock;
+ KIRQL oldIrql;
+ PKTHREAD KThread;
+ PETHREAD Thread;
+ PKWAIT_BLOCK WaitBlock;
- 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;
+ if (!DispatcherLock)
+ {
+ oldIrql = KeAcquireDispatcherDatabaseLock();
}
-
- DPRINT("Releasing Dispatcher Lock\n");
- KfLowerIrql(Thread->WaitIrql);
+
+ 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);
}
VOID
return(STATUS_SUCCESS);
}
-/*
- * NOT EXPORTED
- */
-NTSTATUS
-STDCALL
-NtTestAlert(VOID)
-{
- /* Check and Alert Thread if needed */
- return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
-}
/*
* @implemented
/* 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,
NtSetEvent 2
NtSetHighEventPair 1
NtSetHighWaitLowEventPair 1
+NtSetHighWaitLowThread 0
NtSetInformationFile 5
NtSetInformationKey 4
NtSetInformationJobObject 4
NtSetLdtEntries 6
NtSetLowEventPair 1
NtSetLowWaitHighEventPair 1
+NtSetLowWaitHighThread 0
NtSetQuotaInformationFile 4
NtSetSecurityObject 3
NtSetSystemEnvironmentValue 2