Reverting to 13775. Sorry for the mess. This is dedicated to Jane! 19934415.

svn path=/trunk/; revision=13777
This commit is contained in:
Alex Ionescu
2005-02-28 17:40:15 +00:00
parent ecfad8ec74
commit db4c78ea86
56 changed files with 6256 additions and 6860 deletions
+2 -2
View File
@@ -15,7 +15,7 @@ ARCH := i386
# be optimze for.
#
OARCH := pentium2
OARCH := i486
#
# Whether to compile in the kernel debugger
@@ -30,7 +30,7 @@ DBG := 0
#
# Whether to compile with optimizations
#
OPTIMIZED := 1
OPTIMIZED := 0
#
# Whether to compile a multiprocessor or single processor version
+4 -4
View File
@@ -58,7 +58,7 @@ static ULONG gNumberOfControllers = 0;
/* Queue thread management */
static KEVENT QueueThreadTerminate;
static PVOID QueueThreadObject;
static PVOID ThreadObject;
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
@@ -378,8 +378,8 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
KdPrint(("floppy: unloading\n"));
KeSetEvent(&QueueThreadTerminate, 0, FALSE);
KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0);
ObDereferenceObject(QueueThreadObject);
KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0);
ObDereferenceObject(ThreadObject);
for(i = 0; i < gNumberOfControllers; i++)
{
@@ -1152,7 +1152,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject,
return STATUS_INSUFFICIENT_RESOURCES;
}
if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &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;
-21
View File
@@ -30,23 +30,6 @@ typedef enum _WORK_QUEUE_TYPE {
MaximumWorkQueue
} WORK_QUEUE_TYPE;
typedef struct _EX_QUEUE_WORKER_INFO {
UCHAR QueueDisabled:1;
UCHAR MakeThreadsAsNecessary:1;
UCHAR WaitMode:1;
ULONG WorkerCount:29;
} EX_QUEUE_WORKER_INFO, *PEX_QUEUE_WORKER_INFO;
typedef struct _EX_WORK_QUEUE {
KQUEUE WorkerQueue;
ULONG DynamicThreadCount;
ULONG WorkItemsProcessed;
ULONG WorkItemsProcessedLastPass;
ULONG QueueDepthLastPass;
EX_QUEUE_WORKER_INFO Info;
} EX_WORK_QUEUE, *PEX_WORK_QUEUE;
typedef ULONG_PTR ERESOURCE_THREAD, *PERESOURCE_THREAD;
typedef struct _OWNER_ENTRY
@@ -257,10 +240,6 @@ typedef VOID STDCALL_FUNC
PVOID Argument1,
PVOID Argument2);
extern struct _OBJECT_TYPE EXPORTED *ExMutantObjectType;
extern struct _OBJECT_TYPE EXPORTED *ExSemaphoreObjectType;
extern struct _OBJECT_TYPE EXPORTED *ExTimerType;
#endif /* __INCLUDE_DDK_EXTYPES_H */
/* EOF */
-2
View File
@@ -886,8 +886,6 @@ struct _FAST_IO_DISPATCH_TABLE
#endif
#define IO_TYPE_DRIVER 4L
#define IO_TYPE_FILE 0x0F5L
#define DRVO_UNLOAD_INVOKED 0x1L
#define DRVO_LEGACY_DRIVER 0x2L
#define DRVO_BUILTIN_DRIVER 0x4L
+17 -28
View File
@@ -36,34 +36,23 @@ typedef VOID STDCALL_FUNC
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>
+3 -3
View File
@@ -1262,9 +1262,9 @@ typedef enum _MUTANT_INFORMATION_CLASS
typedef struct _MUTANT_BASIC_INFORMATION
{
LONG CurrentCount;
BOOLEAN OwnedByCaller;
BOOLEAN AbandonedState;
LONG Count;
BOOLEAN Owned;
BOOLEAN Abandoned;
} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
+4
View File
@@ -225,6 +225,7 @@ NtSetEaFile@16
NtSetEvent@8
NtSetHighEventPair@4
NtSetHighWaitLowEventPair@4
NtSetHighWaitLowThread@0
NtSetInformationFile@20
NtSetInformationJobObject@16
NtSetInformationKey@16
@@ -237,6 +238,7 @@ NtSetIoCompletion@20
NtSetLdtEntries@24
NtSetLowEventPair@4
NtSetLowWaitHighEventPair@4
NtSetLowWaitHighThread@0
NtSetSecurityObject@12
NtSetSystemEnvironmentValue@8
NtSetSystemInformation@12
@@ -847,6 +849,7 @@ ZwSetEaFile@16
ZwSetEvent@8
ZwSetHighEventPair@4
ZwSetHighWaitLowEventPair@4
ZwSetHighWaitLowThread@0
ZwSetInformationFile@20
ZwSetInformationKey@16
ZwSetInformationObject@16
@@ -858,6 +861,7 @@ ZwSetIoCompletion@20
ZwSetLdtEntries@24
ZwSetLowEventPair@4
ZwSetLowWaitHighEventPair@4
ZwSetLowWaitHighThread@0
ZwSetSecurityObject@12
ZwSetSystemEnvironmentValue@8
ZwSetSystemInformation@12
+4 -3
View File
@@ -101,8 +101,10 @@ OBJECTS_KE = \
ke/bug.o \
ke/catch.o \
ke/clock.o \
ke/critical.o \
ke/dpc.o \
ke/device.o \
ke/error.o \
ke/event.o \
ke/kqueue.o \
ke/kthread.o \
@@ -116,6 +118,7 @@ OBJECTS_KE = \
ke/spinlock.o \
ke/timer.o \
ke/wait.o \
ke/alert.o
# Memory Manager (Mm)
OBJECTS_MM = \
@@ -216,8 +219,7 @@ OBJECTS_OB = \
ob/object.o \
ob/sdcache.o \
ob/security.o \
ob/symlink.o \
ob/wait.o
ob/symlink.o
# Process Manager (Ps)
OBJECTS_PS = \
@@ -240,7 +242,6 @@ OBJECTS_PS = \
OBJECTS_EX = \
ex/btree.o \
ex/callback.o \
ex/error.o \
ex/event.o \
ex/evtpair.o \
ex/fmutex.o \
-23
View File
@@ -241,29 +241,6 @@ CmiCheckRegistry(BOOLEAN Verbose)
CmiCheckByName(Verbose, L"User");
}
VOID
INIT_FUNCTION
STDCALL
CmInitHives(BOOLEAN SetupBoot)
{
PCHAR BaseAddress;
/* Load Registry Hives */
BaseAddress = (PCHAR)CachedModules[SystemRegistry]->ModStart;
CmImportSystemHive(BaseAddress,
CachedModules[SystemRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
BaseAddress = (PCHAR)CachedModules[HardwareRegistry]->ModStart;
CmImportHardwareHive(BaseAddress,
CachedModules[HardwareRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
/* Create dummy keys if no hardware hive was found */
CmImportHardwareHive (NULL, 0);
/* Initialize volatile registry settings */
if (SetupBoot == FALSE) CmInit2((PCHAR)KeLoaderBlock.CommandLine);
}
VOID INIT_FUNCTION
CmInitializeRegistry(VOID)
-163
View File
@@ -1,163 +0,0 @@
/*
* 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 ([email protected]) - 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 */
+430 -388
View File
@@ -19,286 +19,300 @@
POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
static GENERIC_MAPPING ExpEventMapping = {
STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
EVENT_ALL_ACCESS};
STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
EVENT_ALL_ACCESS};
static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
/* EventBasicInformation */
ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
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;
PAGED_CODE();
/* Reference the Object */
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
ExGetPreviousMode(),
(PVOID*)&Event,
NULL);
EVENT_MODIFY_STATE,
ExEventObjectType,
ExGetPreviousMode(),
(PVOID*)&Event,
NULL);
if(NT_SUCCESS(Status))
{
KeClearEvent(Event);
ObDereferenceObject(Event);
}
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Clear the Event and Dereference */
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);
PAGED_CODE();
DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(EventHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExEventObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hEvent);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*EventHandle = hEvent;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
PreviousMode = ExGetPreviousMode();
/* Return status */
return Status;
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(EventHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObOpenObjectByName(ObjectAttributes,
ExEventObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hEvent);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*EventHandle = hEvent;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
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);
PAGED_CODE();
/* Check buffer validity */
if(PreviousState && PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
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);
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;
}
@@ -306,202 +320,230 @@ NtPulseEvent(IN HANDLE EventHandle,
/*
* @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)) {
PAGED_CODE();
_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);
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();
PAGED_CODE();
DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
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;
PreviousMode = ExGetPreviousMode();
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);
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 = KeResetEvent(Event);
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
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();
PAGED_CODE();
DPRINT1("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
DPRINT("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;
PreviousMode = ExGetPreviousMode();
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;
}
if(PreviousState != NULL && PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
if(NT_SUCCESS(Status))
{
LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
ObDereferenceObject(Event);
if(PreviousState != NULL)
{
_SEH_TRY
{
*PreviousState = Prev;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
/* Return Status */
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 */
+522 -328
View File
@@ -1,11 +1,11 @@
/*
/* $Id: evtpair.c 12779 2005-01-04 04:45:00Z gdalsnes $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/evtpair.c
* PURPOSE: Support for event pairs
*
* PROGRAMMERS: Alex Ionescu (Commented, reorganized, removed Thread Pair, used KeInitializeEventPair, added SEH)
* David Welch ([email protected])
* PROGRAMMERS: David Welch ([email protected])
* Skywing ([email protected])
*/
@@ -15,394 +15,588 @@
#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;
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(EventPairHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* 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;
}
}
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
/* Return Status */
return Status;
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(EventPairHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = 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;
DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
/* 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);
PAGED_CODE();
/* Dereference Object */
ObDereferenceObject(EventPair);
}
DPRINT("NtSetHighEventPair(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->HighEvent,
EVENT_INCREMENT,
FALSE);
ObDereferenceObject(EventPair);
}
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;
DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
PKEVENT_PAIR EventPair;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
/* 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);
PAGED_CODE();
/* Dereference Object */
ObDereferenceObject(EventPair);
}
/* Return status */
return Status;
DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
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;
/* Return status */
return Status;
PAGED_CODE();
DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeSetEvent(&EventPair->LowEvent,
EVENT_INCREMENT,
TRUE);
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
}
return Status;
}
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;
/* Return status */
return Status;
PAGED_CODE();
DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
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;
/* Return status */
return Status;
PAGED_CODE();
DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
EventPairHandle);
PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(EventPairHandle,
SYNCHRONIZE,
ExEventPairObjectType,
PreviousMode,
(PVOID*)&EventPair,
NULL);
if(NT_SUCCESS(Status))
{
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
PreviousMode,
FALSE,
NULL);
ObDereferenceObject(EventPair);
}
return Status;
}
#ifdef _ENABLE_THRDEVTPAIR
/*
* Author: Skywing ([email protected]), 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 ([email protected]), 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 ([email protected]), 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 */
+26 -614
View File
@@ -1,630 +1,21 @@
/*
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/init.c
* PURPOSE: Executive initalization
*
* PROGRAMMERS: Alex Ionescu ([email protected]) - Added ExpInitializeExecutive
* and optimized/cleaned it.
* Eric Kohl ([email protected])
* PROGRAMMERS: Eric Kohl ([email protected])
*/
#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)
{
@@ -634,7 +25,7 @@ ExInit2(VOID)
VOID INIT_FUNCTION
ExInit3 (VOID)
{
ExpInitializeWorkerThreads();
ExInitializeWorkerThreads();
ExpInitializeEventImplementation();
ExpInitializeEventPairImplementation();
ExpInitializeMutantImplementation();
@@ -644,7 +35,28 @@ ExInit3 (VOID)
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 */
+290 -274
View File
@@ -1,13 +1,11 @@
/*
/* $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 ([email protected])
* PROGRAMMERS: David Welch ([email protected])
*/
/* INCLUDES *****************************************************************/
@@ -19,342 +17,360 @@
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
NTSTATUS STDCALL
ExpCreateMutant(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
}
VOID STDCALL
ExpDeleteMutant(PVOID ObjectBody)
{
DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody);
DPRINT("ExpDeleteMutant(ObjectBody %x)\n", ObjectBody);
/* Make sure to release the Mutant */
KeReleaseMutant((PKMUTANT)ObjectBody,
MUTANT_INCREMENT,
TRUE,
FALSE);
KeReleaseMutant((PKMUTANT)ObjectBody,
MUTANT_INCREMENT,
TRUE,
FALSE);
}
VOID
INIT_FUNCTION
VOID INIT_FUNCTION
ExpInitializeMutantImplementation(VOID)
{
ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
/* Allocate the Object Type */
ExMutantObjectType = ExAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), TAG('M', 't', 'n', 't'));
RtlpCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant", NonPagedPool);
/* 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);
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;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(!NT_SUCCESS(Status)) return Status;
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(MutantHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
/* 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;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
/* Return 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);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*MutantHandle = hMutant;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
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);
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;
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;
/* Return Status */
return Status;
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;
}
/*
* @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)) {
PreviousMode = ExGetPreviousMode();
_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;
DefaultQueryInfoBufferCheck(MutantInformationClass,
ExMutantInfoClass,
MutantInformation,
MutantInformationLength,
ResultLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtQueryMutant() failed, Status: 0x%x\n", Status);
return Status;
}
/* Return the Result Length if requested */
if(ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
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;
/* Release the Object */
ObDereferenceObject(Mutant);
}
/* Return Status */
return Status;
_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();
PAGED_CODE();
DPRINT("NtReleaseMutant(MutantHandle 0%x PreviousCount 0%x)\n",
MutantHandle,
PreviousCount);
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;
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;
}
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);
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);
/* Return it */
if(PreviousCount) {
_SEH_TRY {
*PreviousCount = Prev;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
if(PreviousCount != NULL)
{
_SEH_TRY
{
*PreviousCount = Prev;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
/* Return Status */
return Status;
return Status;
}
/* EOF */
+3 -2
View File
@@ -1,10 +1,11 @@
/*
/* $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 *****************************************************************/
+311 -302
View File
@@ -1,11 +1,11 @@
/*
/* $Id: ntsem.c 12779 2005-01-04 04:45:00Z gdalsnes $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/sem.c
* PURPOSE: Synchronization primitives
*
* PROGRAMMERS: Alex Ionescu ([email protected])- Reformatting, bug fixes.
* David Welch ([email protected])
* PROGRAMMERS: David Welch ([email protected])
*/
/* INCLUDES *****************************************************************/
@@ -19,336 +19,345 @@
POBJECT_TYPE ExSemaphoreObjectType;
static GENERIC_MAPPING ExSemaphoreMapping = {
STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
SEMAPHORE_ALL_ACCESS};
STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE,
SEMAPHORE_ALL_ACCESS};
static const INFORMATION_CLASS_INFO ExSemaphoreInfoClass[] = {
/* SemaphoreBasicInformation */
ICI_SQ_SAME( sizeof(SEMAPHORE_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
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();
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;
}
PreviousMode = ExGetPreviousMode();
/* 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);
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(SemaphoreHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*SemaphoreHandle = hSemaphore;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(SemaphoreHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExSemaphoreObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hSemaphore);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*SemaphoreHandle = hSemaphore;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
OUT PVOID SemaphoreInformation,
IN ULONG SemaphoreInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
PKSEMAPHORE Semaphore;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check buffers and class validity */
DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
ExSemaphoreInfoClass,
SemaphoreInformation,
SemaphoreInformationLength,
ReturnLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status)) {
/* Invalid buffers */
DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
return Status;
}
/* Get the Object */
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_QUERY_STATE,
ExSemaphoreObjectType,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
/* Check for success */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
/* Return the basic information */
BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
BasicInfo->MaximumCount = Semaphore->Limit;
/* Return length */
if(ReturnLength) *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* Dereference the Object */
ObDereferenceObject(Semaphore);
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObCreateObject(PreviousMode,
ExSemaphoreObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KSEMAPHORE),
0,
0,
(PVOID*)&Semaphore);
if (NT_SUCCESS(Status))
{
KeInitializeSemaphore(Semaphore,
InitialCount,
MaximumCount);
Status = ObInsertObject ((PVOID)Semaphore,
NULL,
DesiredAccess,
0,
NULL,
&hSemaphore);
ObDereferenceObject(Semaphore);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*SemaphoreHandle = hSemaphore;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
/* Return status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
IN LONG ReleaseCount,
OUT PLONG PreviousCount OPTIONAL)
NTSTATUS STDCALL
NtOpenSemaphore(OUT PHANDLE SemaphoreHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();;
PKSEMAPHORE Semaphore;
NTSTATUS Status = STATUS_SUCCESS;
HANDLE hSemaphore;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
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;
PreviousMode = ExGetPreviousMode();
if(!NT_SUCCESS(Status)) return Status;
}
/* Make sure count makes sense */
if (!ReleaseCount) {
DPRINT("Invalid Release Count\n");
return STATUS_INVALID_PARAMETER;
}
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(SemaphoreHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
/* 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);
Status = ObOpenObjectByName(ObjectAttributes,
ExSemaphoreObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hSemaphore);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*SemaphoreHandle = hSemaphore;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtQuerySemaphore(IN HANDLE SemaphoreHandle,
IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
OUT PVOID SemaphoreInformation,
IN ULONG SemaphoreInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
PKSEMAPHORE Semaphore;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DefaultQueryInfoBufferCheck(SemaphoreInformationClass,
ExSemaphoreInfoClass,
SemaphoreInformation,
SemaphoreInformationLength,
ReturnLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
return Status;
}
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_QUERY_STATE,
ExSemaphoreObjectType,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
if(NT_SUCCESS(Status))
{
switch(SemaphoreInformationClass)
{
case SemaphoreBasicInformation:
{
PSEMAPHORE_BASIC_INFORMATION BasicInfo = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation;
_SEH_TRY
{
BasicInfo->CurrentCount = KeReadStateSemaphore(Semaphore);
BasicInfo->MaximumCount = Semaphore->Limit;
if(ReturnLength != NULL)
{
*ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
}
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
ObDereferenceObject(Semaphore);
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtReleaseSemaphore(IN HANDLE SemaphoreHandle,
IN LONG ReleaseCount,
OUT PLONG PreviousCount OPTIONAL)
{
KPROCESSOR_MODE PreviousMode;
PKSEMAPHORE Semaphore;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousCount != NULL && PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(PreviousCount,
sizeof(LONG),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(SemaphoreHandle,
SEMAPHORE_MODIFY_STATE,
ExSemaphoreObjectType,
PreviousMode,
(PVOID*)&Semaphore,
NULL);
if (NT_SUCCESS(Status))
{
LONG PrevCount = KeReleaseSemaphore(Semaphore,
IO_NO_INCREMENT,
ReleaseCount,
FALSE);
ObDereferenceObject(Semaphore);
/* 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 */
-14
View File
@@ -86,20 +86,6 @@ ExGetCurrentProcessorCounts (
ProcessorNumber = &ProcNumber;
}
/*
* @implemented
*/
BOOLEAN
STDCALL
ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
{
/* Quick check to see if it exists at all */
if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
/* Return our support for it */
return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
}
NTSTATUS STDCALL
NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
OUT PWCHAR ValueBuffer,
+21 -17
View File
@@ -473,7 +473,7 @@ NtQueryTimer(IN HANDLE TimerHandle,
PreviousMode = ExGetPreviousMode();
DPRINT("NtQueryTimer(TimerHandle: %x, Class: %d)\n", TimerHandle, TimerInformationClass);
/* Check Validity */
DefaultQueryInfoBufferCheck(TimerInformationClass,
ExTimerInfoClass,
@@ -498,23 +498,27 @@ NtQueryTimer(IN HANDLE TimerHandle,
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Return the Basic Information */
_SEH_TRY {
/* FIXME: Interrupt correction based on Interrupt Time */
DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* Dereference Object */
switch(TimerInformationClass) {
case TimerBasicInformation: {
/* Return the Basic Information */
_SEH_TRY {
/* FIXME: Interrupt correction based on Interrupt Time */
DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
if(ReturnLength != NULL) {
*ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
}
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
ObDereferenceObject(Timer);
}
+119 -112
View File
@@ -1,11 +1,11 @@
/*
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/work.c
* PURPOSE: Manage system work queues
*
* PROGRAMMERS: Alex Ionescu - Used correct work queue array and added some fixes and checks.
* Gunnar Dalsnes - Implemented
* PROGRAMMERS: David Welch ([email protected])
*/
/* INCLUDES ******************************************************************/
@@ -25,10 +25,17 @@
/*
* 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:
@@ -37,138 +44,138 @@ EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
* 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;
/* 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);
/* Can't happen since we do a KernelMode wait (and we're a system thread) */
ASSERT((NTSTATUS)QueueEntry != STATUS_USER_APC);
/* this should never happen either, since we wait with NULL timeout,
* but there's a slight possibility that STATUS_TIMEOUT is returned
* at queue rundown in NT (unlikely) -Gunnar
*/
ASSERT((NTSTATUS)QueueEntry != STATUS_TIMEOUT);
/* Increment Processed Work Items */
InterlockedIncrement(&WorkQueue->WorkItemsProcessed);
/* Get the Work Item */
WorkItem = CONTAINING_RECORD(QueueEntry, WORK_QUEUE_ITEM, List);
/* Call the Worker Routine */
WorkItem->WorkerRoutine(WorkItem->Parameter);
/* Make sure it returned at right IRQL */
if (KeGetCurrentIrql() != PASSIVE_LEVEL) {
/* FIXME: Make this an Ex */
KEBUGCHECK(WORKER_THREAD_RETURNED_AT_BAD_IRQL);
}
/* Make sure it returned with Impersionation Disabled */
if (PsGetCurrentThread()->ActiveImpersonationInfo) {
/* FIXME: Make this an Ex */
KEBUGCHECK(IMPERSONATING_WORKER_THREAD);
}
}
PWORK_QUEUE_ITEM item;
PLIST_ENTRY current;
while (TRUE)
{
current = KeRemoveQueue( (PKQUEUE)context, KernelMode, NULL );
/* can't happend since we do a KernelMode wait (and we're a system thread) */
ASSERT((NTSTATUS)current != STATUS_USER_APC);
/* this should never happend either, since we wait with NULL timeout,
* but there's a slight possibility that STATUS_TIMEOUT is returned
* at queue rundown in NT (unlikely) -Gunnar
*/
ASSERT((NTSTATUS)current != STATUS_TIMEOUT);
/* based on INVALID_WORK_QUEUE_ITEM bugcheck desc. */
if (current->Flink == NULL || current->Blink == NULL)
{
KeBugCheck(INVALID_WORK_QUEUE_ITEM);
}
/* "reinitialize" item (same as done in ExInitializeWorkItem) */
current->Flink = NULL;
item = CONTAINING_RECORD( current, WORK_QUEUE_ITEM, List);
item->WorkerRoutine(item->Parameter);
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
}
}
}
static
VOID
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++) {
for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
{
/* Create the System Thread */
PsCreateSystemThread(&hThread,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
ExpWorkerThreadEntryPoint,
(PVOID)WorkQueueType);
/* Get the Thread */
ObReferenceObjectByHandle(hThread,
THREAD_SET_INFORMATION,
PsThreadType,
KernelMode,
(PVOID*)&Thread,
NULL);
/* Set the Priority */
KeSetPriorityThread(&Thread->Tcb, Priority);
/* Dereference and close handle */
ObDereferenceObject(Thread);
ZwClose(hThread);
}
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 */
+9 -4
View File
@@ -98,19 +98,24 @@ ExInit3(VOID);
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,
+13
View File
@@ -2,5 +2,18 @@
* 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)
+1 -1
View File
@@ -412,7 +412,7 @@ IoDestroyDriverList(VOID);
/* bootlog.c */
VOID
IopInitBootLog(BOOLEAN StartBootLog);
IopInitBootLog(VOID);
VOID
IopStartBootLog(VOID);
+8 -32
View File
@@ -115,17 +115,6 @@ typedef struct _KPROFILE
struct _EPROCESS *Process;
} KPROFILE, *PKPROFILE;
/* Cached modules from the loader block */
typedef enum _CACHED_MODULE_TYPE {
AnsiCodepage,
OemCodepage,
UnicodeCasemap,
SystemRegistry,
HardwareRegistry,
MaximumCachedModuleType,
} CACHED_MODULE_TYPE, *PCACHED_MODULE_TYPE;
extern PLOADER_MODULE CachedModules[MaximumCachedModuleType];
VOID STDCALL
DbgBreakPointNoBugCheck(VOID);
@@ -155,42 +144,30 @@ VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
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,
@@ -206,7 +183,6 @@ STDCALL
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
VOID FASTCALL KiWakeQueue(IN PKQUEUE Queue);
PLIST_ENTRY STDCALL KeRundownQueue(IN PKQUEUE Queue);
extern LARGE_INTEGER SystemBootTime;
@@ -218,7 +194,7 @@ VOID KeInitInterrupts(VOID);
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);
-1
View File
@@ -29,7 +29,6 @@ extern ULONG NlsUnicodeTableOffset;
extern PUSHORT NlsUnicodeUpcaseTable;
extern PUSHORT NlsUnicodeLowercaseTable;
VOID STDCALL RtlpInitNls(VOID);
VOID RtlpImportAnsiCodePage(PUSHORT TableBase, ULONG Size);
VOID RtlpImportOemCodePage(PUSHORT TableBase, ULONG Size);
VOID RtlpImportUnicodeCasemap(PUSHORT TableBase, ULONG Size);
+1 -3
View File
@@ -49,12 +49,10 @@ VOID ExpInitializeProfileImplementation(VOID);
*/
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);
+2 -7
View File
@@ -498,9 +498,7 @@ VOID STDCALL PsExitSpecialApc(PKAPC Apc,
VOID
STDCALL
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
NTSTATUS KeReleaseThread(PKTHREAD Thread);
VOID
@@ -527,11 +525,8 @@ VOID PsUnfreezeProcessThreads(PEPROCESS Process);
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
+2 -3
View File
@@ -27,14 +27,13 @@ static ERESOURCE IopBootLogResource;
/* FUNCTIONS ****************************************************************/
VOID INIT_FUNCTION
IopInitBootLog(BOOLEAN StartBootLog)
IopInitBootLog(VOID)
{
ExInitializeResourceLite(&IopBootLogResource);
if (StartBootLog) IopStartBootLog();
}
VOID INIT_FUNCTION
VOID
IopStartBootLog(VOID)
{
IopBootLogCreate = TRUE;
+2 -2
View File
@@ -176,7 +176,7 @@ IopCreateFile(PVOID ObjectBody,
FileObject,
DeviceObject);
FileObject->Vpb = DeviceObject->Vpb;
FileObject->Type = IO_TYPE_FILE;
FileObject->Type = InternalFileType;
return(STATUS_SUCCESS);
}
@@ -240,7 +240,7 @@ IoCreateStreamFileObject(PFILE_OBJECT FileObject,
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?
+1 -1
View File
@@ -160,7 +160,7 @@ IopCreateDriver(
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;
+291 -245
View File
@@ -1,4 +1,5 @@
/*
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/iocomp.c
@@ -17,48 +18,66 @@
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;
PKQUEUE Queue = ObjectBody;
DPRINT("IopDeleteIoCompletion()\n");
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);
}
KeRundownQueue(Queue);
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
IoSetCompletionRoutineEx(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PIO_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context,
IN BOOLEAN InvokeOnSuccess,
IN BOOLEAN InvokeOnError,
IN BOOLEAN InvokeOnCancel
)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
@@ -66,278 +85,305 @@ IopDeleteIoCompletion(PVOID ObjectBody)
*/
NTSTATUS
STDCALL
IoSetIoCompletion(IN PVOID IoCompletion,
IN PVOID KeyContext,
IN PVOID ApcContext,
IN NTSTATUS IoStatus,
IN ULONG_PTR IoStatusInformation,
IN BOOLEAN Quota)
IoSetIoCompletion (
IN PVOID IoCompletion,
IN PVOID KeyContext,
IN PVOID ApcContext,
IN NTSTATUS IoStatus,
IN ULONG_PTR IoStatusInformation,
IN BOOLEAN Quota
)
{
PKQUEUE Queue = (PKQUEUE)IoCompletion;
PIO_COMPLETION_PACKET Packet;
PKQUEUE Queue = (PKQUEUE) IoCompletion;
PIO_COMPLETION_PACKET Packet;
/* Allocate the Packet */
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
if (NULL == Packet) return STATUS_NO_MEMORY;
/* Set up the Packet */
Packet->Key = KeyContext;
Packet->Context = ApcContext;
Packet->IoStatus.Status = IoStatus;
Packet->IoStatus.Information = IoStatusInformation;
/* Insert the Queue */
KeInsertQueue(Queue, &Packet->ListEntry);
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
if (NULL == Packet)
{
return STATUS_NO_MEMORY;
}
/* Return Success */
return STATUS_SUCCESS;
}
Packet->Key = KeyContext;
Packet->Context = ApcContext;
Packet->IoStatus.Status = IoStatus;
Packet->IoStatus.Information = IoStatusInformation;
KeInsertQueue(Queue, &Packet->ListEntry);
/*
* @unimplemented
*/
NTSTATUS
STDCALL
IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PIO_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context,
IN BOOLEAN InvokeOnSuccess,
IN BOOLEAN InvokeOnError,
IN BOOLEAN InvokeOnCancel)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
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;
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;
/* Initialize the Lookaside List we'll use for packets */
ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
NULL,
NULL,
0,
sizeof(IO_COMPLETION_PACKET),
IOC_TAG,
0);
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();
PKQUEUE Queue;
NTSTATUS Status;
/* Create the Object */
Status = ObCreateObject(PreviousMode,
ExIoCompletionType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KQUEUE),
0,
0,
(PVOID*)&Queue);
/* Check for success */
if (!NT_SUCCESS(Status)) {
/* Initialize the Queue */
KeInitializeQueue(Queue, NumberOfConcurrentThreads);
/* Insert it */
Status = ObInsertObject(Queue,
NULL,
DesiredAccess,
0,
NULL,
IoCompletionHandle);
ObDereferenceObject(Queue);
Status = 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;
}
/*
NTSTATUS
STDCALL
NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExIoCompletionType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
IoCompletionHandle);
CompletionPort = NULL OR ExistingCompletionPort
*/
/* Return Status */
return Status;
}
/*
DesiredAccess:
ZERO
IO_COMPLETION_QUERY_STATE Query access
IO_COMPLETION_MODIFY_STATE Modify access
IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL
ObjectAttributes
OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes
Return Value
STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or
STATUS_OBJECT_NAME_NOT_FOUND.
*/
NTSTATUS
STDCALL
NtOpenIoCompletion(
OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
)
{
NTSTATUS Status;
Status = ObOpenObjectByName(ObjectAttributes,
ExIoCompletionType,
NULL,
UserMode,
DesiredAccess,
NULL,
IoCompletionHandle); //<- ???
return Status;
}
NTSTATUS
STDCALL
NtQueryIoCompletion(IN HANDLE IoCompletionHandle,
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
OUT PVOID IoCompletionInformation,
IN ULONG IoCompletionInformationLength,
OUT PULONG ResultLength OPTIONAL)
NtQueryIoCompletion(
IN HANDLE IoCompletionHandle,
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
OUT PVOID IoCompletionInformation,
IN ULONG IoCompletionInformationLength,
OUT PULONG ResultLength OPTIONAL
)
{
PKQUEUE Queue;
NTSTATUS Status;
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)) {
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Remove queue */
ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout);
/*
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 );
/* 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);
}
/* 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);
/* Dereference the Object */
ObDereferenceObject(Queue);
}
/* Return status */
return Status;
if ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
{
return STATUS_TIMEOUT;
}
ASSERT(ListEntry);
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
if (CompletionKey) *CompletionKey = Packet->Key;
if (CompletionContext) *CompletionContext = Packet->Context;
if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
return STATUS_SUCCESS;
}
/*
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;
}
+2 -55
View File
@@ -553,17 +553,14 @@ IoInit (VOID)
}
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 */
@@ -608,56 +605,6 @@ IoInit2(BOOLEAN BootLog)
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);
}
/*
-14
View File
@@ -249,18 +249,4 @@ IoWMIDeviceObjectToInstanceName(
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
NtTraceEvent(IN ULONG TraceHandle,
IN ULONG Flags,
IN ULONG TraceHeaderLength,
IN struct _EVENT_TRACE_HEADER* TraceHeader)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*Eof*/
+150
View File
@@ -0,0 +1,150 @@
/* $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;
}
+495 -733
View File
File diff suppressed because it is too large Load Diff
-25
View File
@@ -47,17 +47,6 @@ KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
return FALSE;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @implemented
*/
@@ -85,20 +74,6 @@ KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
return(FALSE);
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
IN KBUGCHECK_CALLBACK_REASON Reason,
IN PUCHAR Component)
{
UNIMPLEMENTED;
return FALSE;
}
VOID STDCALL
KeBugCheckWithTf(ULONG BugCheckCode,
ULONG BugCheckParameter1,
+253 -176
View File
@@ -1,4 +1,5 @@
/*
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/catch.c
@@ -20,206 +21,282 @@ ULONG
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
/*
* @unimplemented
*/
VOID
STDCALL
KiCoprocessorError(VOID)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID
STDCALL
KiUnexpectedInterrupt(VOID)
{
UNIMPLEMENTED;
}
VOID
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
{
EXCEPTION_DISPOSITION Value;
CONTEXT TContext;
KD_CONTINUE_TYPE Action = kdHandleException;
EXCEPTION_DISPOSITION Value;
CONTEXT TContext;
KD_CONTINUE_TYPE Action = kdHandleException;
DPRINT("KiDispatchException() called\n");
DPRINT("KiDispatchException() called\n");
/* Increase number of Exception Dispatches */
KeGetCurrentKPCR()->PrcbData.KeExceptionDispatchCount++;
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
/* Check if a Debugger is enabled */
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) {
/* Break into it */
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
{
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
}
/* If the debugger said continue, then continue */
if (Action == kdContinue) return;
/* If the Debugger couldn't handle it... */
if (Action != kdDoNotHandleException) {
/* See what kind of Exception this is */
if (PreviousMode == UserMode) {
/* User mode exception, search the frames if we have to */
if (SearchFrames) {
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 == kdContinue)
{
return;
}
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: 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");
/* FIXME: Check user mode stack for enough space */
/*
* Let usermode try and handle the exception
*/
Stack = (PULONG)temp_space;
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
/* Return address */
Stack[0] = 0;
/* Pointer to EXCEPTION_RECORD structure */
Stack[1] = (ULONG)&pNewUserStack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&pNewUserStack[CDest];
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
StatusOfCopy = MmCopyToCaller(pNewUserStack,
temp_space,
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
if (NT_SUCCESS(StatusOfCopy))
{
Tf->Esp = (ULONG)pNewUserStack;
}
else
{
/* Now it really hit the ventilation device. Sorry,
* can do nothing but kill the sucker.
*/
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
DPRINT1("User-mode stack was invalid. Terminating target thread\n");
}
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, TRUE);
if (Action == kdContinue)
{
return;
}
/* Set EIP to the User-mode Dispathcer */
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
/* Terminate the offending thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
} else {
/* 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;
#endif
/* Dispatch the Exception */
Value = RtlpDispatchException (ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
/* If RtlpDispatchException() did not handle the exception then bugcheck */
if (Value != ExceptionContinueExecution ||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)) {
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n", ExceptionRecord->ExceptionAddress);
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, FALSE);
if (Action == kdContinue)
{
return;
}
}
#endif
Value = RtlpDispatchException (ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
/*
* If RtlpDispatchException() does not handle the exception then
* bugcheck
*/
if (Value != ExceptionContinueExecution ||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
{
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
ExceptionRecord->ExceptionAddress );
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, TRUE);
if (Action == kdContinue)
{
return;
}
#endif
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
}
}
}
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseAccessViolation (VOID)
{
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseDatatypeMisalignment (VOID)
{
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseStatus (IN NTSTATUS Status)
{
EXCEPTION_RECORD ExceptionRecord;
DPRINT("ExRaiseStatus(%x)\n", Status);
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionFlags = 0;
RtlRaiseException(&ExceptionRecord);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseException (
PEXCEPTION_RECORD ExceptionRecord
)
{
RtlRaiseException(ExceptionRecord);
}
/*
* @implemented
*/
BOOLEAN
STDCALL
ExSystemExceptionFilter(VOID)
{
return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
/*
* @unimplemented
*/
VOID
STDCALL
ExRaiseHardError (
IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response
)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeDeregisterBugCheckReasonCallback(
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
ULONG
STDCALL
KeGetRecommendedSharedDataAlignment(
VOID
)
{
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeRegisterBugCheckReasonCallback(
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
IN KBUGCHECK_CALLBACK_REASON Reason,
IN PUCHAR Component
)
{
UNIMPLEMENTED;
return FALSE;
}
/* EOF */
+56
View File
@@ -0,0 +1,56 @@
/* $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 */
+298 -337
View File
@@ -24,15 +24,15 @@
/* TYPES *******************************************************************/
#define MAX_QUANTUM 0x7F
/* GLOBALS ******************************************************************/
/* FUNCTIONS ****************************************************************/
VOID INIT_FUNCTION
KeInitDpc(PKPCR Pcr)
/*
* FUNCTION: Initialize DPC handling
*/
VOID
INIT_FUNCTION
KeInitDpc(PKPCR Pcr)
{
InitializeListHead(&Pcr->PrcbData.DpcData[0].DpcListHead);
KeInitializeEvent(Pcr->PrcbData.DpcEvent, 0, 0);
@@ -47,9 +47,9 @@ KeInitDpc(PKPCR Pcr)
*/
VOID
STDCALL
KeInitializeThreadedDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
KeInitializeThreadedDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
/*
* FUNCTION:
* Initalizes a Threaded DPC and registers the DeferredRoutine for it.
@@ -60,18 +60,24 @@ KeInitializeThreadedDpc(PKDPC Dpc,
* 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:
@@ -80,24 +86,24 @@ KeInitializeThreadedDpc(PKDPC Dpc,
* DeferredContext = Parameter to be passed to the callback routine.
* NOTE: Callers can be running at any IRQL.
*/
VOID
STDCALL
KeInitializeDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
{
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
Dpc->Type = 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
@@ -149,141 +155,124 @@ KeInitializeDpc(PKDPC Dpc,
* is greater that the target depth or the minimum DPC rate is less than the
* target rate.
*/
BOOLEAN
STDCALL
KeInsertQueueDpc(PKDPC Dpc,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
KIRQL OldIrql;
PKPCR Pcr;
KIRQL OldIrql;
PKPCR Pcr;
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
Dpc, SystemArgument1, SystemArgument2);
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
Dpc, SystemArgument1, SystemArgument2);
/* Check IRQL and Raise it to HIGH_LEVEL */
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Check if this is a Thread DPC, which we don't support (yet) */
if (Dpc->Type == ThreadedDpcObject) {
return FALSE;
KeLowerIrql(OldIrql);
}
/* Check IRQL and Raise it to HIGH_LEVEL */
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Check if this is a Thread DPC, which we don't support (yet) */
//if (Dpc->Type == 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));
}
KeLowerIrql(OldIrql);
return(FALSE);
}
/* Make sure the lists are free if the Queue is 0 */
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
} else {
ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
}
/* Now we can play with the DPC safely */
Dpc->SystemArgument1=SystemArgument1;
Dpc->SystemArgument2=SystemArgument2;
Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
Pcr->PrcbData.DpcData[0].DpcCount++;
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
if (Dpc->Importance == HighImportance) {
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
} else {
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
}
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
/* Now we can play with the DPC safely */
Dpc->SystemArgument1=SystemArgument1;
Dpc->SystemArgument2=SystemArgument2;
Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
Pcr->PrcbData.DpcData[0].DpcCount++;
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
if (Dpc->Importance == HighImportance) {
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
} else {
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
}
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
/* Make sure a DPC isn't executing already and respect rules outlined above. */
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
#ifdef CONFIG_SMP
/* Check if this is the same CPU */
if (Pcr != KeGetCurrentKPCR()) {
/* Send IPI if High Importance */
if ((Dpc->Importance == HighImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
} else {
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
}
/* Make sure a DPC isn't executing already and respect rules outlined above. */
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
#ifdef CONFIG_SMP
/* Check if this is the same CPU */
if (Pcr != KeGetCurrentKPCR()) {
/* Send IPI if High Importance */
if ((Dpc->Importance == HighImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
} else {
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
}
}
} else {
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
}
}
} else {
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
}
#else
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
DPRINT("Requesting Interrupt\n");
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
DPRINT("Requesting Interrupt\n");
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
#endif
}
}
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
/* Lower IRQL */
KeLowerIrql(OldIrql);
return(TRUE);
/* Lower IRQL */
KeLowerIrql(OldIrql);
return(TRUE);
}
/*
* @implemented
*
*/
BOOLEAN STDCALL
KeRemoveQueueDpc (PKDPC Dpc)
/*
* FUNCTION:
* Removes DPC object from the system dpc queue
* ARGUMENTS:
@@ -292,36 +281,33 @@ KeInsertQueueDpc(PKDPC Dpc,
* TRUE if the DPC was in the queue
* FALSE otherwise
*/
BOOLEAN
STDCALL
KeRemoveQueueDpc(PKDPC Dpc)
{
BOOLEAN WasInQueue;
KIRQL OldIrql;
/* Raise IRQL */
DPRINT("Removing DPC: %x\n", Dpc);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
BOOLEAN WasInQueue;
KIRQL OldIrql;
/* Raise IRQL */
DPRINT("Removing DPC: %x\n", Dpc);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif
/* First make sure the DPC lock isn't being held */
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
if (Dpc->DpcData) {
/* Remove the DPC */
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
RemoveEntryList(&Dpc->DpcListEntry);
/* First make sure the DPC lock isn't being held */
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
if (Dpc->DpcData) {
/* Remove the DPC */
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
RemoveEntryList(&Dpc->DpcListEntry);
}
}
#ifdef CONFIG_SMP
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif
/* Return if the DPC was in the queue or not */
KeLowerIrql(OldIrql);
return WasInQueue;
/* Return if the DPC was in the queue or not */
KeLowerIrql(OldIrql);
return WasInQueue;
}
/*
@@ -337,8 +323,7 @@ KeFlushQueuedDpcs(VOID)
* 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);
}
/*
@@ -347,11 +332,10 @@ KeFlushQueuedDpcs(VOID)
BOOLEAN
STDCALL
KeIsExecutingDpc(
VOID
VOID
)
{
/* Return if the Dpc Routine is active */
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
}
/*
@@ -365,41 +349,39 @@ KeIsExecutingDpc(
*/
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
@@ -407,173 +389,152 @@ KeSetTargetProcessorDpc(IN PKDPC Dpc,
* 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;
PLIST_ENTRY DpcEntry;
PKDPC Dpc;
KIRQL OldIrql;
PKPCR Pcr;
DPRINT("Dispatching Interrupts\n");
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
DPRINT("Dispatching Interrupts\n");
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Set DPC Deliver to Active */
Pcr = KeGetCurrentKPCR();
/* Set DPC Deliver to Active */
Pcr = KeGetCurrentKPCR();
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
/* Raise IRQL */
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
/* Raise IRQL */
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
Pcr->PrcbData.DpcRoutineActive = TRUE;
Pcr->PrcbData.DpcRoutineActive = TRUE;
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
/* Loop while we have entries */
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
/* Get the DPC call it */
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
Dpc->DpcData = NULL;
Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
/* Loop while we have entries */
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
/* Get the DPC call it */
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
Dpc->DpcData = NULL;
Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
/* Disable/Enabled Interrupts and Call the DPC */
KeLowerIrql(OldIrql);
DPRINT("Calling DPC: %x\n", Dpc);
Dpc->DeferredRoutine(Dpc,
Dpc->DeferredContext,
Dpc->SystemArgument1,
Dpc->SystemArgument2);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Disable/Enabled Interrupts and Call the DPC */
KeLowerIrql(OldIrql);
DPRINT("Calling DPC: %x\n", Dpc);
Dpc->DeferredRoutine(Dpc,
Dpc->DeferredContext,
Dpc->SystemArgument1,
Dpc->SystemArgument2);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
/*
* If the dpc routine drops the irql below DISPATCH_LEVEL,
* a thread switch can occur and after the next thread switch
* the execution may start on an other processor.
*/
if (Pcr != KeGetCurrentKPCR()) {
Pcr->PrcbData.DpcRoutineActive = FALSE;
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr = KeGetCurrentKPCR();
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr->PrcbData.DpcRoutineActive = TRUE;
}
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
/*
* If the dpc routine drops the irql below DISPATCH_LEVEL,
* a thread switch can occur and after the next thread switch
* the execution may start on an other processor.
*/
if (Pcr != KeGetCurrentKPCR()) {
Pcr->PrcbData.DpcRoutineActive = FALSE;
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr = KeGetCurrentKPCR();
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr->PrcbData.DpcRoutineActive = TRUE;
}
#endif
}
/* Clear DPC Flags */
Pcr->PrcbData.DpcRoutineActive = FALSE;
Pcr->PrcbData.DpcInterruptRequested = FALSE;
}
/* Clear DPC Flags */
Pcr->PrcbData.DpcRoutineActive = FALSE;
Pcr->PrcbData.DpcInterruptRequested = FALSE;
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
/* DPC Dispatching Ended, re-enable interrupts */
KeLowerIrql(OldIrql);
}
DPRINT("Checking for Quantum End\n");
/* If we have Quantum End, call the function */
if (Pcr->PrcbData.QuantumEnd) {
Pcr->PrcbData.QuantumEnd = FALSE;
KiQuantumEnd();
}
/* DPC Dispatching Ended, re-enable interrupts */
KeLowerIrql(OldIrql);
}
DPRINT("Checking for Quantum End\n");
/* If we have Quantum End, call the function */
if (Pcr->PrcbData.QuantumEnd) {
Pcr->PrcbData.QuantumEnd = FALSE;
KiQuantumEnd();
}
}
/* EOF */
+98
View File
@@ -0,0 +1,98 @@
/* $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 */
+110 -212
View File
@@ -19,211 +19,121 @@
/*
* @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 KeResetEvent (PKEVENT Event)
{
/* FIXME: must use interlocked func. everywhere! (wait.c)
* or use dispather lock instead
* -Gunnar */
return(InterlockedExchange(&(Event->Header.SignalState),0));
}
/*
* @implemented
*/
LONG STDCALL KeSetEvent (PKEVENT Event,
KPRIORITY Increment,
BOOLEAN Wait)
{
KIRQL OldIrql;
int ret;
DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
OldIrql = KeAcquireDispatcherDatabaseLock();
ret = InterlockedExchange(&Event->Header.SignalState,1);
KiDispatcherObjectWake(&Event->Header, Increment);
if (Wait == FALSE)
{
KeReleaseDispatcherDatabaseLock(OldIrql);
}
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
return(ret);
}
/*
* @implemented
*/
LONG STDCALL
KePulseEvent(IN PKEVENT Event,
IN KPRIORITY Increment,
IN BOOLEAN Wait)
KePulseEvent (IN PKEVENT Event,
IN KPRIORITY Increment,
IN BOOLEAN Wait)
{
KIRQL OldIrql;
LONG PreviousState;
KIRQL OldIrql;
LONG Ret;
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);
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);
}
/* 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;
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
/* Return the previous State */
return PreviousState;
}
/*
* @implemented
*/
LONG
STDCALL
KeReadStateEvent(PKEVENT Event)
{
/* Return the Signal State */
return Event->Header.SignalState;
}
/*
* @implemented
*/
LONG
STDCALL
KeResetEvent(PKEVENT Event)
{
KIRQL OldIrql;
LONG PreviousState;
DPRINT("KeResetEvent(Event %x)\n",Event);
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the Previous State */
PreviousState = Event->Header.SignalState;
/* Set it to zero */
Event->Header.SignalState = 0;
/* Release Dispatcher Database and return previous state */
KeReleaseDispatcherDatabaseLock(OldIrql);
return PreviousState;
}
/*
* @implemented
*/
LONG
STDCALL
KeSetEvent(PKEVENT Event,
KPRIORITY Increment,
BOOLEAN Wait)
{
KIRQL OldIrql;
LONG PreviousState;
PKWAIT_BLOCK WaitBlock;
DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait);
/* Lock the Dispathcer Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the Previous State */
PreviousState = Event->Header.SignalState;
/* Check if we have stuff in the Wait Queue */
if (IsListEmpty(&Event->Header.WaitListHead)) {
/* Set the Event to Signaled */
DPRINT("Empty Wait Queue, Signal the Event\n");
Event->Header.SignalState = 1;
} else {
/* Get the Wait Block */
WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink,
KWAIT_BLOCK,
WaitListEntry);
/* Check the type of event */
if (Event->Header.Type == NotificationEvent || WaitBlock->WaitType == WaitAll) {
if (PreviousState == 0) {
/* We must do a full wait satisfaction */
DPRINT("Notification Event or WaitAll, Wait on the Event and Signal\n");
Event->Header.SignalState = 1;
KiWaitTest(&Event->Header, Increment);
}
} else {
/* We can satisfy wait simply by waking the thread, since our signal state is 0 now */
DPRINT("WaitAny or Sync Event, just unwait the thread\n");
KiAbortWaitThread(WaitBlock->Thread, WaitBlock->WaitKey);
}
}
/* Check what wait state was requested */
if (Wait == FALSE) {
/* Wait not requested, release Dispatcher Database and return */
KeReleaseDispatcherDatabaseLock(OldIrql);
} else {
/* Return Locked and with a Wait */
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
/* Return the previous State */
DPRINT("Done: %d\n", PreviousState);
return PreviousState;
return Ret;
}
/*
@@ -231,39 +141,27 @@ KeSetEvent(PKEVENT Event,
*/
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();
/* Release the Dispatcher Database Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
/* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
/* Return it to caller if requested */
if ARGUMENT_PRESENT(Thread) *Thread = WaitingThread;
/* Reset the Quantum and Unwait the Thread */
WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
KeReleaseDispatcherDatabaseLock(OldIrql);
}
/* EOF */
+1 -1
View File
@@ -200,7 +200,7 @@ _Ki386ContextSwitch:
*/
sti
call @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
call _KeReleaseDispatcherDatabaseLockFromDpcLevel
cmpl $0, _PiNrThreadsAwaitingReaping
je 5f
File diff suppressed because it is too large Load Diff
+954 -191
View File
File diff suppressed because it is too large Load Diff
+148 -189
View File
@@ -3,19 +3,14 @@
* 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 *****************************************************************/
@@ -23,212 +18,176 @@
/*
* @implemented
*/
VOID
STDCALL
KeInitializeMutant(IN PKMUTANT Mutant,
IN BOOLEAN InitialOwner)
{
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;
}
/*
* @implemented
*/
VOID
STDCALL
VOID STDCALL
KeInitializeMutex(IN PKMUTEX Mutex,
IN ULONG Level)
IN ULONG Level)
{
DPRINT("KeInitializeMutex: %x\n", Mutex);
/* Set up the Dispatcher Header */
KeInitializeDispatcherHeader(&Mutex->Header,
MutantObject,
sizeof(KMUTEX) / sizeof(ULONG),
1);
/* Initialize the default data */
Mutex->OwnerThread = NULL;
Mutex->Abandoned = FALSE;
Mutex->ApcDisable = 1;
InitializeListHead(&Mutex->Header.WaitListHead);
KeInitializeDispatcherHeader(&Mutex->Header,
InternalMutexType,
sizeof(KMUTEX) / sizeof(ULONG),
1);
Mutex->MutantListEntry.Flink = NULL;
Mutex->MutantListEntry.Blink = NULL;
Mutex->OwnerThread = NULL;
Mutex->Abandoned = FALSE;
Mutex->ApcDisable = 1;
}
/*
* @implemented
*/
LONG
STDCALL
KeReadStateMutant(IN PKMUTANT Mutant)
{
/* Return the Signal State */
return(Mutant->Header.SignalState);
}
/*
* @implemented
*/
LONG
STDCALL
LONG STDCALL
KeReadStateMutex(IN PKMUTEX Mutex)
{
/* Return the Signal State */
return(Mutex->Header.SignalState);
return(Mutex->Header.SignalState);
}
/*
* @implemented
*/
LONG
STDCALL
KeReleaseMutant(IN PKMUTANT Mutant,
IN KPRIORITY Increment,
IN BOOLEAN Abandon,
IN BOOLEAN Wait)
{
KIRQL OldIrql;
LONG PreviousState;
PKTHREAD CurrentThread = KeGetCurrentThread();
DPRINT("KeReleaseMutant: %x\n", Mutant);
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the Previous State */
PreviousState = Mutant->Header.SignalState;
/* Check if it is to be abandonned */
if (Abandon == FALSE) {
/* Make sure that the Owner Thread is the current Thread */
if (Mutant->OwnerThread != CurrentThread) {
DPRINT1("Trying to touch a Mutant that the caller doesn't own!\n");
ExRaiseStatus(STATUS_MUTANT_NOT_OWNED);
}
/* If the thread owns it, then increase the signal state */
Mutant->Header.SignalState++;
} else {
/* It's going to be abandonned */
DPRINT("Abandonning the Mutant\n");
Mutant->Header.SignalState = 1;
Mutant->Abandoned = TRUE;
}
/* 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 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;
}
/* Return the previous state */
return PreviousState;
}
/*
* @implemented
*/
LONG
STDCALL
LONG STDCALL
KeReleaseMutex(IN PKMUTEX Mutex,
IN BOOLEAN Wait)
IN BOOLEAN Wait)
{
KIRQL OldIrql;
/* There's no difference at this level between the two */
return KeReleaseMutant(Mutex, IO_NO_INCREMENT, FALSE, Wait);
OldIrql = KeAcquireDispatcherDatabaseLock();
if (Mutex->OwnerThread != KeGetCurrentThread())
{
DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutex %p\n", Mutex);
KEBUGCHECK(THREAD_NOT_MUTEX_OWNER);
}
Mutex->Header.SignalState++;
ASSERT(Mutex->Header.SignalState <= 1);
if (Mutex->Header.SignalState == 1)
{
Mutex->OwnerThread = NULL;
if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
RemoveEntryList(&Mutex->MutantListEntry);
KiDispatcherObjectWake(&Mutex->Header, IO_NO_INCREMENT);
}
if (Wait == FALSE)
{
KeReleaseDispatcherDatabaseLock(OldIrql);
}
else
{
KTHREAD *Thread = KeGetCurrentThread();
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
}
return(0);
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NTSTATUS STDCALL
KeWaitForMutexObject(IN PKMUTEX Mutex,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout)
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout)
{
/* This is a simple macro. Export the function here though */
return KeWaitForSingleObject(Mutex,
WaitReason,
WaitMode,
Alertable,
Timeout);
return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout));
}
/*
* @implemented
*/
VOID STDCALL
KeInitializeMutant(IN PKMUTANT Mutant,
IN BOOLEAN InitialOwner)
{
if (InitialOwner == TRUE)
{
KeInitializeDispatcherHeader(&Mutant->Header,
InternalMutexType,
sizeof(KMUTANT) / sizeof(ULONG),
0);
InsertTailList(&KeGetCurrentThread()->MutantListHead,
&Mutant->MutantListEntry);
Mutant->OwnerThread = KeGetCurrentThread();
}
else
{
KeInitializeDispatcherHeader(&Mutant->Header,
InternalMutexType,
sizeof(KMUTANT) / sizeof(ULONG),
1);
Mutant->MutantListEntry.Flink = NULL;
Mutant->MutantListEntry.Blink = NULL;
Mutant->OwnerThread = NULL;
}
Mutant->Abandoned = FALSE;
Mutant->ApcDisable = 0;
}
/*
* @implemented
*/
LONG STDCALL
KeReadStateMutant(IN PKMUTANT Mutant)
{
return(Mutant->Header.SignalState);
}
/*
* @implemented
*/
LONG STDCALL
KeReleaseMutant(IN PKMUTANT Mutant,
IN KPRIORITY Increment,
IN BOOLEAN Abandon,
IN BOOLEAN Wait)
{
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 */
+215 -452
View File
@@ -16,482 +16,245 @@
/* 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
*/
LONG
STDCALL
KeInsertHeadQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
{
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);
/* Return previous State */
return PreviousState;
}
/*
* @implemented
*/
LONG STDCALL
KeInsertQueue(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);
/* Return previous State */
return PreviousState;
}
/*
* @implemented
*
* Returns number of entries in the queue
*/
LONG
STDCALL
LONG STDCALL
KeReadStateQueue(IN PKQUEUE Queue)
{
/* Returns the Signal State */
return(Queue->Header.SignalState);
}
/*
* @implemented
*/
PLIST_ENTRY
STDCALL
KeRemoveQueue(IN PKQUEUE Queue,
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);
}
/* Insert in this new Queue */
DPRINT("Inserting new Queue!\n");
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
} 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;
}
/*
* @implemented
*/
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;
}
/*
* Called when a thread which has a queue entry is entering a wait state
*/
VOID
FASTCALL
KiWakeQueue(IN PKQUEUE Queue)
{
PLIST_ENTRY QueueEntry;
PLIST_ENTRY WaitEntry;
PKWAIT_BLOCK WaitBlock;
/* Decrement the number of active threads */
DPRINT("KiWakeQueue: %x. Thread: %x\n", Queue, KeGetCurrentThread());
Queue->CurrentCount--;
/* Make sure the counts are OK */
if (Queue->CurrentCount < Queue->MaximumCount) {
/* Get the Queue Entry */
QueueEntry = Queue->EntryListHead.Flink;
/* Get the Wait Entry */
WaitEntry = Queue->Header.WaitListHead.Blink;
DPRINT("Queue Count is ok, Queue entries: %x, %x\n", QueueEntry, WaitEntry);
/* Make sure that the Queue List isn't empty and that this entry is valid */
if (!IsListEmpty(&Queue->Header.WaitListHead) &&
(QueueEntry != &Queue->EntryListHead)) {
/* Remove this entry */
DPRINT("Queue in List, removing it\n");
RemoveEntryList(QueueEntry);
QueueEntry->Flink = NULL;
/* Decrease the Signal State */
Queue->Header.SignalState--;
/* Unwait the Thread */
DPRINT("Unwaiting Thread\n");
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
KiAbortWaitThread(WaitBlock->Thread, (NTSTATUS)QueueEntry);
}
}
return(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 STDCALL
KiInsertQueue(
IN PKQUEUE Queue,
IN PLIST_ENTRY Entry,
BOOLEAN Head
)
{
ULONG InitialState;
PKTHREAD Thread = KeGetCurrentThread();
PKWAIT_BLOCK WaitBlock;
PLIST_ENTRY WaitEntry;
ULONG InitialState;
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
/* Save the old state */
InitialState = Queue->Header.SignalState;
/* Get the Entry */
WaitEntry = Queue->Header.WaitListHead.Blink;
DPRINT("Initial State, WaitEntry: %d, %x\n", InitialState, WaitEntry);
/*
* Why the KeGetCurrentThread()->Queue != Queue?
* KiInsertQueue might be called from an APC for the current thread.
* -Gunnar
*/
if ((Queue->CurrentCount < Queue->MaximumCount) &&
(WaitEntry != &Queue->Header.WaitListHead) &&
((Thread->Queue != Queue) || (Thread->WaitReason != WrQueue))) {
/* Remove the wait entry */
DPRINT("Removing Entry\n");
RemoveEntryList(WaitEntry);
/* Get the Wait Block and Thread */
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
DPRINT("Got wait block: %x\n", WaitBlock);
Thread = WaitBlock->Thread;
/* Reset the wait reason */
Thread->WaitReason = 0;
/* Increase the waiting threads */
Queue->CurrentCount++;
/* Check if there's a Thread Timer */
if (Thread->Timer.Header.Inserted) {
/* Cancel the Thread Timer with the no-lock fastpath */
DPRINT("Removing the Thread's Timer\n");
Thread->Timer.Header.Inserted = FALSE;
RemoveEntryList(&Thread->Timer.TimerListEntry);
}
/* Reschedule the Thread */
DPRINT("Unblocking the Thread\n");
PsUnblockThread((PETHREAD)Thread, (PNTSTATUS)&Entry, 0);
} else {
/* Increase the Entries */
DPRINT("Adding new Queue Entry: %d %d\n", Head, Queue->Header.SignalState);
Queue->Header.SignalState++;
if (Head) {
InsertHeadList(&Queue->EntryListHead, Entry);
} else {
InsertTailList(&Queue->EntryListHead, Entry);
}
}
InitialState = Queue->Header.SignalState;
/* Return the previous state */
DPRINT("Returning\n");
return InitialState;
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
KeInsertHeadQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
{
LONG Result;
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock();
Result = KiInsertQueue(Queue,Entry,TRUE);
KeReleaseDispatcherDatabaseLock(OldIrql);
return Result;
}
/*
* @implemented
*/
LONG STDCALL
KeInsertQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
{
LONG Result;
KIRQL OldIrql;
OldIrql = KeAcquireDispatcherDatabaseLock();
Result = KiInsertQueue(Queue,Entry,FALSE);
KeReleaseDispatcherDatabaseLock(OldIrql);
return Result;
}
/*
* @implemented
*/
PLIST_ENTRY STDCALL
KeRemoveQueue(IN PKQUEUE Queue,
IN KPROCESSOR_MODE WaitMode,
IN PLARGE_INTEGER Timeout OPTIONAL)
{
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);
}
}
// register thread with this queue
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
Thread->Queue = Queue;
}
else /* if (Thread->Queue == Queue) */
{
//dec. num running threads
Queue->CurrentCount--;
}
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
KeRundownQueue(IN PKQUEUE Queue)
{
PLIST_ENTRY EnumEntry;
PKTHREAD Thread;
KIRQL OldIrql;
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
/* I'm just guessing how this should work:-/
* -Gunnar
*/
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 */
+43 -71
View File
@@ -19,39 +19,36 @@
/*
* @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
@@ -71,65 +68,40 @@ KeReadStateSemaphore(PKSEMAPHORE Semaphore)
* RETURNS: If the return value is zero, the previous state of the semaphore
* object is Not-Signaled.
*/
LONG
STDCALL
KeReleaseSemaphore(PKSEMAPHORE Semaphore,
KPRIORITY Increment,
LONG Adjustment,
BOOLEAN Wait)
{
ULONG InitialState;
KIRQL OldIrql;
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 */
+7 -7
View File
@@ -107,11 +107,12 @@ KeInitializeTimerEx (PKTIMER Timer,
/* 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;
}
@@ -195,6 +196,7 @@ KeSetTimerEx (PKTIMER Timer,
Timer->Dpc = Dpc;
Timer->Period = Period;
Timer->Header.SignalState = FALSE;
Timer->Header.Absolute = FALSE;
/* Insert it */
if (!KiInsertTimer(Timer, DueTime)) {
@@ -294,7 +296,7 @@ KiHandleExpiredTimer(PKTIMER Timer)
/* 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) {
@@ -304,7 +306,7 @@ KiHandleExpiredTimer(PKTIMER Timer)
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");
};
}
@@ -336,10 +338,8 @@ KiInsertTimer(PKTIMER Timer,
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) {
+966 -808
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -122,6 +122,7 @@ ExIsResourceAcquiredExclusiveLite@4
ExIsResourceAcquiredSharedLite@4
ExLocalTimeToSystemTime@8
ExNotifyCallback@12
ExPostSystemEvent@12
ExQueryPoolBlockSize@8
ExQueueWorkItem@8
ExRaiseAccessViolation@0
@@ -529,7 +530,7 @@ Ke386IoSetAccessProcess@8
Ke386QueryIoAccessMap@8
Ke386SetIoAccessMap@8
KeAcquireSpinLockAtDpcLevel@4
@KeAcquireDispatcherDatabaseLockAtDpcLevel@0
KeAcquireDispatcherDatabaseLockAtDpcLevel
@KeAcquireInStackQueuedSpinLockAtDpcLevel@8
KeAcquireInterruptSpinLock@4
KeAddSystemServiceTable@20
@@ -610,7 +611,7 @@ KeReadStateSemaphore@4
KeReadStateTimer@4
KeRegisterBugCheckCallback@20
KeRegisterBugCheckReasonCallback@16
@KeReleaseDispatcherDatabaseLockFromDpcLevel@0
KeReleaseDispatcherDatabaseLockFromDpcLevel
@KeReleaseInStackQueuedSpinLockFromDpcLevel@4
KeReleaseInterruptSpinLock@8
KeReleaseMutant@16
-16
View File
@@ -987,22 +987,6 @@ Language=English
INVALID_WORK_QUEUE_ITEM
.
MessageId=0xE1
Severity=Success
Facility=System
SymbolicName=WORKER_THREAD_RETURNED_AT_BAD_IRQL
Language=English
WORKER_THREAD_RETURNED_AT_BAD_IRQL
.
MessageId=0xFA
Severity=Success
Facility=System
SymbolicName=IMPERSONATING_WORKER_THREAD
Language=English
IMPERSONATING_WORKER_THREAD
.
MessageId=0x9A
Severity=Informational
Facility=System
-300
View File
@@ -1,300 +0,0 @@
/*
* 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 */
+2 -2
View File
@@ -204,7 +204,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
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 */
@@ -331,7 +331,7 @@ PiTerminateProcess(PEPROCESS Process,
}
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);
+2 -2
View File
@@ -374,7 +374,7 @@ PsInitProcessManagment(VOID)
PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
ProcessObject,
InternalProcessType,
sizeof(EPROCESS),
FALSE);
KProcess = &PsInitialSystemProcess->Pcb;
@@ -823,7 +823,7 @@ exitdereferenceobjects:
}
KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
ProcessObject,
InternalProcessType,
sizeof(EPROCESS),
FALSE);
+40 -48
View File
@@ -437,7 +437,6 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
OldThread = CurrentThread;
CurrentThread = Candidate;
IdleThread = KeGetCurrentKPCR()->PrcbData.IdleThread;
if (&OldThread->Tcb == IdleThread)
@@ -546,46 +545,49 @@ PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment)
}
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
@@ -1052,16 +1054,6 @@ NtYieldExecution(VOID)
return(STATUS_SUCCESS);
}
/*
* NOT EXPORTED
*/
NTSTATUS
STDCALL
NtTestAlert(VOID)
{
/* Check and Alert Thread if needed */
return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
}
/*
* @implemented
+1 -26
View File
@@ -36,32 +36,7 @@ ULONG NlsUnicodeTableOffset = 0;
/* FUNCTIONS *****************************************************************/
VOID
INIT_FUNCTION
STDCALL
RtlpInitNls(VOID)
{
ULONG_PTR BaseAddress;
/* Import NLS Data */
BaseAddress = CachedModules[AnsiCodepage]->ModStart;
RtlpImportAnsiCodePage((PUSHORT)BaseAddress,
CachedModules[AnsiCodepage]->ModEnd - BaseAddress);
BaseAddress = CachedModules[OemCodepage]->ModStart;
RtlpImportOemCodePage((PUSHORT)BaseAddress,
CachedModules[OemCodepage]->ModEnd - BaseAddress);
BaseAddress = CachedModules[UnicodeCasemap]->ModStart;
RtlpImportUnicodeCasemap((PUSHORT)BaseAddress,
CachedModules[UnicodeCasemap]->ModEnd - BaseAddress);
/* Create initial NLS tables */
RtlpCreateInitialNlsTables();
/* Create the NLS section */
RtlpCreateNlsSection();
}
VOID INIT_FUNCTION
RtlpImportAnsiCodePage(PUSHORT TableBase,
+2
View File
@@ -180,6 +180,7 @@ NtSetEaFile 4
NtSetEvent 2
NtSetHighEventPair 1
NtSetHighWaitLowEventPair 1
NtSetHighWaitLowThread 0
NtSetInformationFile 5
NtSetInformationKey 4
NtSetInformationJobObject 4
@@ -191,6 +192,7 @@ NtSetIntervalProfile 2
NtSetLdtEntries 6
NtSetLowEventPair 1
NtSetLowWaitHighEventPair 1
NtSetLowWaitHighThread 0
NtSetQuotaInformationFile 4
NtSetSecurityObject 3
NtSetSystemEnvironmentValue 2