Test commit. Not official branch release -- it will follow shortly in 15 minutes. If this ends up in HEAD i will revert immediately (i have svn switched so it shouldn't)

svn path=/trunk/; revision=13776
This commit is contained in:
Alex Ionescu 2005-02-28 16:44:38 +00:00
parent 24fd581490
commit ecfad8ec74
56 changed files with 6939 additions and 6335 deletions

View file

@ -15,7 +15,7 @@ ARCH := i386
# be optimze for.
#
OARCH := i486
OARCH := pentium2
#
# Whether to compile in the kernel debugger
@ -30,7 +30,7 @@ DBG := 0
#
# Whether to compile with optimizations
#
OPTIMIZED := 0
OPTIMIZED := 1
#
# Whether to compile a multiprocessor or single processor version

View file

@ -58,7 +58,7 @@ static ULONG gNumberOfControllers = 0;
/* Queue thread management */
static KEVENT QueueThreadTerminate;
static PVOID ThreadObject;
static PVOID QueueThreadObject;
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
@ -378,8 +378,8 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
KdPrint(("floppy: unloading\n"));
KeSetEvent(&QueueThreadTerminate, 0, FALSE);
KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0);
ObDereferenceObject(ThreadObject);
KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0);
ObDereferenceObject(QueueThreadObject);
for(i = 0; i < gNumberOfControllers; i++)
{
@ -1152,7 +1152,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject,
return STATUS_INSUFFICIENT_RESOURCES;
}
if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ThreadObject, NULL) != STATUS_SUCCESS)
if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
{
KdPrint(("floppy: Unable to reference returned thread handle; failing init\n"));
return STATUS_UNSUCCESSFUL;

View file

@ -30,6 +30,23 @@ typedef enum _WORK_QUEUE_TYPE {
MaximumWorkQueue
} WORK_QUEUE_TYPE;
typedef struct _EX_QUEUE_WORKER_INFO {
UCHAR QueueDisabled:1;
UCHAR MakeThreadsAsNecessary:1;
UCHAR WaitMode:1;
ULONG WorkerCount:29;
} EX_QUEUE_WORKER_INFO, *PEX_QUEUE_WORKER_INFO;
typedef struct _EX_WORK_QUEUE {
KQUEUE WorkerQueue;
ULONG DynamicThreadCount;
ULONG WorkItemsProcessed;
ULONG WorkItemsProcessedLastPass;
ULONG QueueDepthLastPass;
EX_QUEUE_WORKER_INFO Info;
} EX_WORK_QUEUE, *PEX_WORK_QUEUE;
typedef ULONG_PTR ERESOURCE_THREAD, *PERESOURCE_THREAD;
typedef struct _OWNER_ENTRY
@ -240,6 +257,10 @@ typedef VOID STDCALL_FUNC
PVOID Argument1,
PVOID Argument2);
extern struct _OBJECT_TYPE EXPORTED *ExMutantObjectType;
extern struct _OBJECT_TYPE EXPORTED *ExSemaphoreObjectType;
extern struct _OBJECT_TYPE EXPORTED *ExTimerType;
#endif /* __INCLUDE_DDK_EXTYPES_H */
/* EOF */

View file

@ -886,6 +886,8 @@ struct _FAST_IO_DISPATCH_TABLE
#endif
#define IO_TYPE_DRIVER 4L
#define IO_TYPE_FILE 0x0F5L
#define DRVO_UNLOAD_INVOKED 0x1L
#define DRVO_LEGACY_DRIVER 0x2L
#define DRVO_BUILTIN_DRIVER 0x4L

View file

@ -36,23 +36,34 @@ typedef VOID STDCALL_FUNC
struct _DISPATCHER_HEADER;
typedef enum _KERNEL_OBJECTS {
KNotificationEvent = 0,
KSynchronizationEvent = 1,
KMutant = 2,
KProcess = 3,
KQueue = 4,
KSemaphore = 5,
KThread = 6,
KNotificationTimer = 8,
KSynchronizationTimer = 9,
KApc = 18,
KDpc = 19,
KDeviceQueue = 20,
KEventPair = 21,
KInterrupt = 22,
KProfile = 23
} KERNEL_OBJECTS;
typedef enum _KOBJECTS {
EventNotificationObject = 0,
EventSynchronizationObject = 1,
MutantObject = 2,
ProcessObject = 3,
QueueObject = 4,
SemaphoreObject = 5,
ThreadObject = 6,
GateObject = 7,
TimerNotificationObject = 8,
TimerSynchronizationObject = 9,
Spare2Object = 10,
Spare3Object = 11,
Spare4Object = 12,
Spare5Object = 13,
Spare6Object = 14,
Spare7Object = 15,
Spare8Object = 16,
Spare9Object = 17,
ApcObject = 18,
DpcObject = 19,
DeviceQueueObject = 20,
EventPairObject = 21,
InterruptObject = 22,
ProfileObject = 23,
ThreadedDpcObject = 24,
MaximumKernelObject = 25
} KOBJECTS;
#include <pshpack1.h>

View file

@ -1262,9 +1262,9 @@ typedef enum _MUTANT_INFORMATION_CLASS
typedef struct _MUTANT_BASIC_INFORMATION
{
LONG Count;
BOOLEAN Owned;
BOOLEAN Abandoned;
LONG CurrentCount;
BOOLEAN OwnedByCaller;
BOOLEAN AbandonedState;
} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;

View file

@ -225,7 +225,6 @@ NtSetEaFile@16
NtSetEvent@8
NtSetHighEventPair@4
NtSetHighWaitLowEventPair@4
NtSetHighWaitLowThread@0
NtSetInformationFile@20
NtSetInformationJobObject@16
NtSetInformationKey@16
@ -238,7 +237,6 @@ NtSetIoCompletion@20
NtSetLdtEntries@24
NtSetLowEventPair@4
NtSetLowWaitHighEventPair@4
NtSetLowWaitHighThread@0
NtSetSecurityObject@12
NtSetSystemEnvironmentValue@8
NtSetSystemInformation@12
@ -849,7 +847,6 @@ ZwSetEaFile@16
ZwSetEvent@8
ZwSetHighEventPair@4
ZwSetHighWaitLowEventPair@4
ZwSetHighWaitLowThread@0
ZwSetInformationFile@20
ZwSetInformationKey@16
ZwSetInformationObject@16
@ -861,7 +858,6 @@ ZwSetIoCompletion@20
ZwSetLdtEntries@24
ZwSetLowEventPair@4
ZwSetLowWaitHighEventPair@4
ZwSetLowWaitHighThread@0
ZwSetSecurityObject@12
ZwSetSystemEnvironmentValue@8
ZwSetSystemInformation@12

View file

@ -101,10 +101,8 @@ OBJECTS_KE = \
ke/bug.o \
ke/catch.o \
ke/clock.o \
ke/critical.o \
ke/dpc.o \
ke/device.o \
ke/error.o \
ke/event.o \
ke/kqueue.o \
ke/kthread.o \
@ -118,7 +116,6 @@ OBJECTS_KE = \
ke/spinlock.o \
ke/timer.o \
ke/wait.o \
ke/alert.o
# Memory Manager (Mm)
OBJECTS_MM = \
@ -219,7 +216,8 @@ OBJECTS_OB = \
ob/object.o \
ob/sdcache.o \
ob/security.o \
ob/symlink.o
ob/symlink.o \
ob/wait.o
# Process Manager (Ps)
OBJECTS_PS = \
@ -242,6 +240,7 @@ OBJECTS_PS = \
OBJECTS_EX = \
ex/btree.o \
ex/callback.o \
ex/error.o \
ex/event.o \
ex/evtpair.o \
ex/fmutex.o \

View file

@ -241,6 +241,29 @@ CmiCheckRegistry(BOOLEAN Verbose)
CmiCheckByName(Verbose, L"User");
}
VOID
INIT_FUNCTION
STDCALL
CmInitHives(BOOLEAN SetupBoot)
{
PCHAR BaseAddress;
/* Load Registry Hives */
BaseAddress = (PCHAR)CachedModules[SystemRegistry]->ModStart;
CmImportSystemHive(BaseAddress,
CachedModules[SystemRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
BaseAddress = (PCHAR)CachedModules[HardwareRegistry]->ModStart;
CmImportHardwareHive(BaseAddress,
CachedModules[HardwareRegistry]->ModEnd - (ULONG_PTR)BaseAddress);
/* Create dummy keys if no hardware hive was found */
CmImportHardwareHive (NULL, 0);
/* Initialize volatile registry settings */
if (SetupBoot == FALSE) CmInit2((PCHAR)KeLoaderBlock.CommandLine);
}
VOID INIT_FUNCTION
CmInitializeRegistry(VOID)

163
reactos/ntoskrnl/ex/error.c Normal file
View file

@ -0,0 +1,163 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/error.c
* PURPOSE: Error Functions and Status/Exception Dispatching/Raising
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created File
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ****************************************************************/
BOOLEAN ExReadyForErrors = FALSE;
PEPORT ExpDefaultErrorPort = NULL;
PEPROCESS ExpDefaultErrorPortProcess = NULL;
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
VOID
STDCALL
ExRaiseAccessViolation(VOID)
{
/* Raise the Right Status */
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseDatatypeMisalignment (VOID)
{
/* Raise the Right Status */
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseStatus(IN NTSTATUS Status)
{
EXCEPTION_RECORD ExceptionRecord;
DPRINT("ExRaiseStatus(%x)\n", Status);
/* Set up an Exception Record */
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionFlags = 0;
/* Call the Rtl Function */
RtlRaiseException(&ExceptionRecord);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseException (PEXCEPTION_RECORD ExceptionRecord)
{
/* Call the Rtl function */
RtlRaiseException(ExceptionRecord);
}
/*
* @implemented
*/
BOOLEAN
STDCALL
ExSystemExceptionFilter(VOID)
{
return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
/*
* @unimplemented
*/
VOID
STDCALL
ExRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response)
{
UNIMPLEMENTED;
}
NTSTATUS
STDCALL
NtRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response)
{
DPRINT1("Hard error %x\n", ErrorStatus);
/* Call the Executive Function (WE SHOULD PUT SEH HERE/CAPTURE!) */
ExRaiseHardError(ErrorStatus,
NumberOfParameters,
UnicodeStringParameterMask,
Parameters,
ResponseOption,
Response);
/* Return Success */
return STATUS_SUCCESS;
}
NTSTATUS
STDCALL
NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_UNSUCCESSFUL;
/* Check if we have the Privilege */
if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) {
DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
/* Only called once during bootup, make sure we weren't called yet */
if(!ExReadyForErrors) {
Status = ObReferenceObjectByHandle(PortHandle,
0,
LpcPortObjectType,
PreviousMode,
(PVOID*)&ExpDefaultErrorPort,
NULL);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Save the data */
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
ExReadyForErrors = TRUE;
}
}
return Status;
}
/* EOF */

View file

@ -19,531 +19,489 @@
POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
static GENERIC_MAPPING ExpEventMapping = {
STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
EVENT_ALL_ACCESS};
STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
EVENT_ALL_ACCESS};
static const INFORMATION_CLASS_INFO ExEventInfoClass[] =
{
ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* EventBasicInformation */
static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
/* EventBasicInformation */
ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
};
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
NtpCreateEvent(PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes)
{
DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
}
VOID INIT_FUNCTION
VOID
INIT_FUNCTION
ExpInitializeEventImplementation(VOID)
{
ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
ExEventObjectType->PeakObjects = 0;
ExEventObjectType->PeakHandles = 0;
ExEventObjectType->TotalObjects = 0;
ExEventObjectType->TotalHandles = 0;
ExEventObjectType->PagedPoolCharge = 0;
ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
ExEventObjectType->Mapping = &ExpEventMapping;
ExEventObjectType->Dump = NULL;
ExEventObjectType->Open = NULL;
ExEventObjectType->Close = NULL;
ExEventObjectType->Delete = NULL;
ExEventObjectType->Parse = NULL;
ExEventObjectType->Security = NULL;
ExEventObjectType->QueryName = NULL;
ExEventObjectType->OkayToClose = NULL;
ExEventObjectType->Create = NtpCreateEvent;
ExEventObjectType->DuplicationNotify = NULL;
ObpCreateTypeObject(ExEventObjectType);
/* Create the Event Object Type */
ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
ExEventObjectType->PeakObjects = 0;
ExEventObjectType->PeakHandles = 0;
ExEventObjectType->TotalObjects = 0;
ExEventObjectType->TotalHandles = 0;
ExEventObjectType->PagedPoolCharge = 0;
ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
ExEventObjectType->Mapping = &ExpEventMapping;
ExEventObjectType->Dump = NULL;
ExEventObjectType->Open = NULL;
ExEventObjectType->Close = NULL;
ExEventObjectType->Delete = NULL;
ExEventObjectType->Parse = NULL;
ExEventObjectType->Security = NULL;
ExEventObjectType->QueryName = NULL;
ExEventObjectType->OkayToClose = NULL;
ExEventObjectType->Create = NULL;
ExEventObjectType->DuplicationNotify = NULL;
ObpCreateTypeObject(ExEventObjectType);
}
/*
* @implemented
*/
NTSTATUS STDCALL
NTSTATUS
STDCALL
NtClearEvent(IN HANDLE EventHandle)
{
PKEVENT Event;
NTSTATUS Status;
PAGED_CODE();
PKEVENT Event;
NTSTATUS Status;
PAGED_CODE();
/* Reference the Object */
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
ExGetPreviousMode(),
(PVOID*)&Event,
NULL);
if(NT_SUCCESS(Status))
{
KeClearEvent(Event);
ObDereferenceObject(Event);
}
EVENT_MODIFY_STATE,
ExEventObjectType,
ExGetPreviousMode(),
(PVOID*)&Event,
NULL);
return Status;
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Clear the Event and Dereference */
KeClearEvent(Event);
ObDereferenceObject(Event);
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtCreateEvent(OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN EVENT_TYPE EventType,
IN BOOLEAN InitialState)
{
KPROCESSOR_MODE PreviousMode;
PKEVENT Event;
HANDLE hEvent;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(EventHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObCreateObject(PreviousMode,
ExEventObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KEVENT),
0,
0,
(PVOID*)&Event);
if(NT_SUCCESS(Status))
{
KeInitializeEvent(Event,
EventType,
InitialState);
Status = ObInsertObject((PVOID)Event,
NULL,
DesiredAccess,
0,
NULL,
&hEvent);
ObDereferenceObject(Event);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*EventHandle = hEvent;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtOpenEvent(OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hEvent;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
PreviousMode = ExGetPreviousMode();
if(PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(EventHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObOpenObjectByName(ObjectAttributes,
ExEventObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hEvent);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*EventHandle = hEvent;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtPulseEvent(IN HANDLE EventHandle,
OUT PLONG PreviousState OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
PreviousMode = ExGetPreviousMode();
if(PreviousState != NULL && PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
if(NT_SUCCESS(Status))
{
LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
ObDereferenceObject(Event);
if(PreviousState != NULL)
{
_SEH_TRY
{
*PreviousState = Prev;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtQueryEvent(IN HANDLE EventHandle,
IN EVENT_INFORMATION_CLASS EventInformationClass,
OUT PVOID EventInformation,
IN ULONG EventInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
DefaultQueryInfoBufferCheck(EventInformationClass,
ExEventInfoClass,
EventInformation,
EventInformationLength,
ReturnLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status);
return Status;
}
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_QUERY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
if(NT_SUCCESS(Status))
{
switch(EventInformationClass)
{
case EventBasicInformation:
{
PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
_SEH_TRY
{
if (Event->Header.Type == InternalNotificationEvent)
BasicInfo->EventType = NotificationEvent;
else
BasicInfo->EventType = SynchronizationEvent;
BasicInfo->EventState = KeReadStateEvent(Event);
if(ReturnLength != NULL)
{
*ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
break;
}
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
ObDereferenceObject(Event);
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtResetEvent(IN HANDLE EventHandle,
OUT PLONG PreviousState OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
PreviousMode = ExGetPreviousMode();
if(PreviousState != NULL && PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
if(NT_SUCCESS(Status))
{
LONG Prev = KeResetEvent(Event);
ObDereferenceObject(Event);
if(PreviousState != NULL)
{
_SEH_TRY
{
*PreviousState = Prev;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status;
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtSetEvent(IN HANDLE EventHandle,
OUT PLONG PreviousState OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
PreviousMode = ExGetPreviousMode();
if(PreviousState != NULL && PreviousMode == UserMode)
{
_SEH_TRY
{
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
if(NT_SUCCESS(Status))
{
LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
ObDereferenceObject(Event);
if(PreviousState != NULL)
{
_SEH_TRY
{
*PreviousState = Prev;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status;
}
/*
* @unimplemented
*/
NTSTATUS
NTSTATUS
STDCALL
NtTraceEvent(
IN ULONG TraceHandle,
IN ULONG Flags,
IN ULONG TraceHeaderLength,
IN struct _EVENT_TRACE_HEADER* TraceHeader
)
NtCreateEvent(OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN EVENT_TYPE EventType,
IN BOOLEAN InitialState)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PKEVENT Event;
HANDLE hEvent;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(EventHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Create the Object */
Status = ObCreateObject(PreviousMode,
ExEventObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KEVENT),
0,
0,
(PVOID*)&Event);
/* Check for Success */
if(NT_SUCCESS(Status)) {
/* Initalize the Event */
KeInitializeEvent(Event,
EventType,
InitialState);
/* Insert it */
Status = ObInsertObject((PVOID)Event,
NULL,
DesiredAccess,
0,
NULL,
&hEvent);
ObDereferenceObject(Event);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*EventHandle = hEvent;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtOpenEvent(OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
HANDLE hEvent;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
/* Check Output Safety */
if(PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(EventHandle,
sizeof(HANDLE),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExEventObjectType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
&hEvent);
/* Check for success and return handle */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
*EventHandle = hEvent;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
/* Return status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtPulseEvent(IN HANDLE EventHandle,
OUT PLONG PreviousState OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
/* Check buffer validity */
if(PreviousState && PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
/* Check for success */
if(NT_SUCCESS(Status)) {
/* Pulse the Event */
LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
ObDereferenceObject(Event);
/* Return it */
if(PreviousState) {
_SEH_TRY {
*PreviousState = Prev;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtQueryEvent(IN HANDLE EventHandle,
IN EVENT_INFORMATION_CLASS EventInformationClass,
OUT PVOID EventInformation,
IN ULONG EventInformationLength,
OUT PULONG ReturnLength OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
/* Check buffers and class validity */
DefaultQueryInfoBufferCheck(EventInformationClass,
ExEventInfoClass,
EventInformation,
EventInformationLength,
ReturnLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status)) {
/* Invalid buffers */
DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
return Status;
}
/* Get the Object */
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_QUERY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
/* Check for success */
if(NT_SUCCESS(Status)) {
_SEH_TRY {
/* Return Event Type and State */
BasicInfo->EventType = Event->Header.Type;
BasicInfo->EventState = KeReadStateEvent(Event);
/* Return length */
if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* Dereference the Object */
ObDereferenceObject(Event);
}
/* Return status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtResetEvent(IN HANDLE EventHandle,
OUT PLONG PreviousState OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
/* Check buffer validity */
if(PreviousState && PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
/* Check for success */
if(NT_SUCCESS(Status)) {
/* Reset the Event */
LONG Prev = KeResetEvent(Event);
ObDereferenceObject(Event);
/* Return it */
if(PreviousState) {
_SEH_TRY {
*PreviousState = Prev;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NtSetEvent(IN HANDLE EventHandle,
OUT PLONG PreviousState OPTIONAL)
{
PKEVENT Event;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT1("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
EventHandle, PreviousState);
/* Check buffer validity */
if(PreviousState != NULL && PreviousMode == UserMode) {
_SEH_TRY {
ProbeForWrite(PreviousState,
sizeof(LONG),
sizeof(ULONG));
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
if(!NT_SUCCESS(Status)) return Status;
}
/* Open the Object */
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID*)&Event,
NULL);
/* Check for success */
if(NT_SUCCESS(Status)) {
/* Set the Event */
LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
ObDereferenceObject(Event);
/* Return it */
if(PreviousState) {
_SEH_TRY {
*PreviousState = Prev;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
/* Return Status */
return Status;
}
/* EOF */

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

View file

@ -1,21 +1,630 @@
/* $Id:$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/init.c
* PURPOSE: Executive initalization
*
* PROGRAMMERS: Eric Kohl (ekohl@abo.rhein-zeitung.de)
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
* and optimized/cleaned it.
* Eric Kohl (ekohl@abo.rhein-zeitung.de)
*/
#include <ntoskrnl.h>
#include <ntos/bootvid.h>
#define NDEBUG
#include <internal/debug.h>
/* DATA **********************************************************************/
extern ULONG MmCoreDumpType;
extern CHAR KiTimerSystemAuditing;
extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
extern ADDRESS_RANGE KeMemoryMap[64];
extern ULONG KeMemoryMapRangeCount;
extern ULONG_PTR FirstKrnlPhysAddr;
extern ULONG_PTR LastKrnlPhysAddr;
extern ULONG_PTR LastKernelAddress;
extern LOADER_MODULE KeLoaderModules[64];
/* FUNCTIONS ****************************************************************/
static
VOID
INIT_FUNCTION
InitSystemSharedUserPage (PCSZ ParameterLine)
{
UNICODE_STRING ArcDeviceName;
UNICODE_STRING ArcName;
UNICODE_STRING BootPath;
UNICODE_STRING DriveDeviceName;
UNICODE_STRING DriveName;
WCHAR DriveNameBuffer[20];
PCHAR ParamBuffer;
PWCHAR ArcNameBuffer;
PCHAR p;
NTSTATUS Status;
ULONG Length;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE Handle;
ULONG i;
BOOLEAN BootDriveFound = FALSE;
/*
* NOTE:
* The shared user page has been zeroed-out right after creation.
* There is NO need to do this again.
*/
Ki386SetProcessorFeatures();
/* Set the Version Data */
SharedUserData->NtProductType = NtProductWinNt;
SharedUserData->ProductTypeIsValid = TRUE;
SharedUserData->NtMajorVersion = 5;
SharedUserData->NtMinorVersion = 0;
/*
* Retrieve the current dos system path
* (e.g.: C:\reactos) from the given arc path
* (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
* Format: "<arc_name>\<path> [options...]"
*/
/* Create local parameter line copy */
ParamBuffer = ExAllocatePool(PagedPool, 256);
strcpy (ParamBuffer, (char *)ParameterLine);
DPRINT("%s\n", ParamBuffer);
/* Cut options off */
p = strchr (ParamBuffer, ' ');
if (p) *p = 0;
DPRINT("%s\n", ParamBuffer);
/* Extract path */
p = strchr (ParamBuffer, '\\');
if (p) {
DPRINT("Boot path: %s\n", p);
RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
*p = 0;
} else {
DPRINT("Boot path: %s\n", "\\");
RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
}
DPRINT("Arc name: %s\n", ParamBuffer);
/* Only ARC Name left - Build full ARC Name */
ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
RtlInitUnicodeString (&ArcName, ArcNameBuffer);
DPRINT("Arc name: %wZ\n", &ArcName);
/* Free ParamBuffer */
ExFreePool (ParamBuffer);
/* Allocate ARC Device Name string */
ArcDeviceName.Length = 0;
ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
/* Open the Symbolic Link */
InitializeObjectAttributes(&ObjectAttributes,
&ArcName,
OBJ_OPENLINK,
NULL,
NULL);
Status = NtOpenSymbolicLinkObject(&Handle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes);
/* Free the String */
RtlFreeUnicodeString (&ArcName);
/* Check for Success */
if (!NT_SUCCESS(Status)) {
/* Free the Strings */
RtlFreeUnicodeString(&BootPath);
RtlFreeUnicodeString(&ArcDeviceName);
CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
KEBUGCHECK(0);
}
/* Query the Link */
Status = NtQuerySymbolicLinkObject(Handle,
&ArcDeviceName,
&Length);
NtClose (Handle);
/* Check for Success */
if (!NT_SUCCESS(Status)) {
/* Free the Strings */
RtlFreeUnicodeString(&BootPath);
RtlFreeUnicodeString(&ArcDeviceName);
CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
KEBUGCHECK(0);
}
DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
/* Allocate Device Name string */
DriveDeviceName.Length = 0;
DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
/* Loop Drives */
for (i = 0; i < 26; i++) {
/* Setup the String */
swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
RtlInitUnicodeString(&DriveName,
DriveNameBuffer);
/* Open the Symbolic Link */
InitializeObjectAttributes(&ObjectAttributes,
&DriveName,
OBJ_OPENLINK,
NULL,
NULL);
Status = NtOpenSymbolicLinkObject(&Handle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes);
/* If it failed, skip to the next drive */
if (!NT_SUCCESS(Status)) {
DPRINT("Failed to open link %wZ\n", &DriveName);
continue;
}
/* Query it */
Status = NtQuerySymbolicLinkObject(Handle,
&DriveDeviceName,
&Length);
/* If it failed, skip to the next drive */
if (!NT_SUCCESS(Status)) {
DPRINT("Failed to query link %wZ\n", &DriveName);
continue;
}
DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
/* See if we've found the boot drive */
if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
BootDriveFound = TRUE;
}
/* Close this Link */
NtClose (Handle);
}
/* Free all the Strings we have in memory */
RtlFreeUnicodeString (&BootPath);
RtlFreeUnicodeString (&DriveDeviceName);
RtlFreeUnicodeString (&ArcDeviceName);
/* Make sure we found the Boot Drive */
if (BootDriveFound == FALSE) {
DbgPrint("No system drive found!\n");
KEBUGCHECK (NO_BOOT_DEVICE);
}
}
inline
VOID
STDCALL
ExecuteRuntimeAsserts(VOID)
{
/*
* Fail at runtime if someone has changed various structures without
* updating the offsets used for the assembler code.
*/
ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
}
inline
VOID
STDCALL
ParseAndCacheLoadedModules(PBOOLEAN SetupBoot)
{
ULONG i;
PCHAR Name;
/* Loop the Module List and get the modules we want */
for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
/* Get the Name of this Module */
if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\'))) {
/* Save the name */
Name = (PCHAR)KeLoaderModules[i].String;
} else {
/* No name, skip */
Name++;
}
/* Now check for any of the modules we will need later */
if (!_stricmp(Name, "ansi.nls")) {
CachedModules[AnsiCodepage] = &KeLoaderModules[i];
} else if (!_stricmp(Name, "oem.nls")) {
CachedModules[OemCodepage] = &KeLoaderModules[i];
} else if (!_stricmp(Name, "casemap.nls")) {
CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
} else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv")) {
CachedModules[SystemRegistry] = &KeLoaderModules[i];
*SetupBoot = FALSE;
} else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
CachedModules[HardwareRegistry] = &KeLoaderModules[i];
}
}
}
inline
VOID
STDCALL
ParseCommandLine(PULONG MaxMem, PBOOLEAN NoGuiBoot, PBOOLEAN BootLog)
{
PCHAR p1, p2;
p1 = (PCHAR)KeLoaderBlock.CommandLine;
while(*p1 && (p2 = strchr(p1, '/'))) {
p2++;
if (!_strnicmp(p2, "MAXMEM", 6)) {
p2 += 6;
while (isspace(*p2)) p2++;
if (*p2 == '=') {
p2++;
while(isspace(*p2)) p2++;
if (isdigit(*p2)) {
while (isdigit(*p2)) {
*MaxMem = *MaxMem * 10 + *p2 - '0';
p2++;
}
break;
}
}
} else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
p2 += 9;
*NoGuiBoot = TRUE;
} else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
p2 += 9;
if (*p2 == ':') {
p2++;
if (!_strnicmp(p2, "FULL", 4)) {
MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
} else {
MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
}
}
} else if (!_strnicmp(p2, "BOOTLOG", 7)) {
p2 += 7;
*BootLog = TRUE;
}
p1 = p2;
}
}
VOID
INIT_FUNCTION
STDCALL
ExpInitializeExecutive(VOID)
{
CHAR str[50];
UNICODE_STRING EventName;
HANDLE InitDoneEventHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
BOOLEAN NoGuiBoot = FALSE;
BOOLEAN BootLog = FALSE;
ULONG MaxMem = 0;
BOOLEAN SetupBoot = TRUE;
LARGE_INTEGER Timeout;
HANDLE ProcessHandle;
HANDLE ThreadHandle;
NTSTATUS Status;
/* Check if the structures match the ASM offset constants */
ExecuteRuntimeAsserts();
/* Sets up the Text Sections of the Kernel and HAL for debugging */
LdrInit1();
/* Lower the IRQL to Dispatch Level */
KeLowerIrql(DISPATCH_LEVEL);
/* Sets up the VDM Data */
NtEarlyInitVdm();
/* Parse Command Line Settings */
ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog);
/* Initialize Kernel Memory Address Space */
MmInit1(FirstKrnlPhysAddr,
LastKrnlPhysAddr,
LastKernelAddress,
(PADDRESS_RANGE)&KeMemoryMap,
KeMemoryMapRangeCount,
MaxMem > 8 ? MaxMem : 4096);
/* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
ParseAndCacheLoadedModules(&SetupBoot);
/* Initialize the kernel debugger */
KdInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
/* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
KeInit2();
/* Bring back the IRQL to Passive */
KeLowerIrql(PASSIVE_LEVEL);
/* Load basic Security for other Managers */
if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
/* Create the Basic Object Manager Types to allow new Object Types */
ObInit();
/* Initialize Lookaside Lists */
ExInit2();
/* Set up Region Maps, Sections and the Paging File */
MmInit2();
/* Initialize Tokens now that the Object Manager is ready */
if (!SeInit2()) KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
/* Set 1 CPU for now, we'll increment this later */
KeNumberProcessors = 1;
/* Initalize the Process Manager */
PiInitProcessManager();
/* Break into the Debugger if requested */
if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
/* Initialize all processors */
while (!HalAllProcessorsStarted()) {
PVOID ProcessorStack;
/* Set up the Kernel and Process Manager for this CPU */
KePrepareForApplicationProcessorInit(KeNumberProcessors);
PsPrepareForApplicationProcessorInit(KeNumberProcessors);
/* Allocate a stack for use when booting the processor */
ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
/* Tell HAL a new CPU is being started */
HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
KeNumberProcessors++;
}
/* Do Phase 1 HAL Initalization */
HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
/* Initialize Basic System Objects and Worker Threads */
ExInit3();
/* Initialize the GDB Stub and break */
KdInit1();
/* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
IoInit();
/* TBD */
PoInit();
/* Initialize the Registry (Hives are NOT yet loaded!) */
CmInitializeRegistry();
/* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
MmInit3();
/* Initialize Cache Views */
CcInit();
/* Hook System Interrupt for the Debugger */
KdInit2();
/* Initialize File Locking */
FsRtlpInitFileLockingImplementation();
/* Report all resources used by hal */
HalReportResourceUsage();
/* Clear the screen to blue */
HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
/* Display version number and copyright/warranty message */
HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
KERNEL_VERSION_BUILD_STR")\n");
HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
"Public License, and you\n");
HalDisplayString("are welcome to change it and/or distribute copies of it "
"under certain\n");
HalDisplayString("conditions. There is absolutely no warranty for "
"ReactOS.\n\n");
/* Display number of Processors */
sprintf(str,
"Found %d system processor(s). [%lu MB Memory]\n",
KeNumberProcessors,
(KeLoaderBlock.MemHigher + 1088)/ 1024);
HalDisplayString(str);
/* Print which Debugger is being used */
KdInit3();
/* Import and create NLS Data and Sections */
RtlpInitNls();
/* Import and Load Registry Hives */
CmInitHives(SetupBoot);
/* Initialize the time zone information from the registry */
ExpInitTimeZoneInfo();
/* Enter the kernel debugger before starting up the boot drivers */
#ifdef KDBG
KdbEnter();
#endif /* KDBG */
/* Setup Drivers and Root Device Node */
IoInit2(BootLog);
/* Display the boot screen image if not disabled */
if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
/* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
IoInit3();
/* Initialize the Default Locale */
PiInitDefaultLocale();
/* Initialize shared user page. Set dos system path, dos device map, etc. */
InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
/* Create 'ReactOSInitDone' event */
RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
InitializeObjectAttributes(&ObjectAttributes,
&EventName,
0,
NULL,
NULL);
Status = ZwCreateEvent(&InitDoneEventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
SynchronizationEvent,
FALSE);
/* Check for Success */
if (!NT_SUCCESS(Status)) {
DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
InitDoneEventHandle = INVALID_HANDLE_VALUE;
}
/* Launch initial process */
Status = LdrLoadInitialProcess(&ProcessHandle,
&ThreadHandle);
/* Check for success, Bugcheck if we failed */
if (!NT_SUCCESS(Status)) {
KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
}
/* Wait on the Completion Event */
if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
HANDLE Handles[2]; /* Init event, Initial process */
/* Setup the Handles to wait on */
Handles[0] = InitDoneEventHandle;
Handles[1] = ProcessHandle;
/* Wait for the system to be initialized */
Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
Status = ZwWaitForMultipleObjects(2,
Handles,
WaitAny,
FALSE,
&Timeout);
if (!NT_SUCCESS(Status)) {
DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
} else if (Status == STATUS_TIMEOUT) {
DPRINT1("WARNING: System not initialized after 120 seconds.\n");
} else if (Status == STATUS_WAIT_0 + 1) {
/* Crash the system if the initial process was terminated. */
KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
}
/* Disable the Boot Logo */
if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
/* Signal the Event and close the handle */
ZwSetEvent(InitDoneEventHandle, NULL);
ZwClose(InitDoneEventHandle);
} else {
/* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
/* Crash the system if the initial process terminates within 5 seconds. */
Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
Status = ZwWaitForSingleObject(ProcessHandle,
FALSE,
&Timeout);
/* Check for timeout, crash if the initial process didn't initalize */
if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
}
/* Enable the Clock, close remaining handles */
KiTimerSystemAuditing = 1;
ZwClose(ThreadHandle);
ZwClose(ProcessHandle);
}
VOID INIT_FUNCTION
ExInit2(VOID)
{
@ -25,7 +634,7 @@ ExInit2(VOID)
VOID INIT_FUNCTION
ExInit3 (VOID)
{
ExInitializeWorkerThreads();
ExpInitializeWorkerThreads();
ExpInitializeEventImplementation();
ExpInitializeEventPairImplementation();
ExpInitializeMutantImplementation();
@ -35,28 +644,7 @@ ExInit3 (VOID)
ExpInitializeProfileImplementation();
ExpWin32kInit();
ExpInitUuids();
}
/*
* @implemented
*/
BOOLEAN STDCALL
ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
{
if (ProcessorFeature >= PROCESSOR_FEATURE_MAX)
return(FALSE);
return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
}
VOID STDCALL
ExPostSystemEvent (ULONG Unknown1,
ULONG Unknown2,
ULONG Unknown3)
{
/* doesn't do anything */
ExpInitializeCallbacks();
}
/* EOF */

View file

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

View file

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

View file

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

View file

@ -86,6 +86,20 @@ ExGetCurrentProcessorCounts (
ProcessorNumber = &ProcNumber;
}
/*
* @implemented
*/
BOOLEAN
STDCALL
ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature)
{
/* Quick check to see if it exists at all */
if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE);
/* Return our support for it */
return(SharedUserData->ProcessorFeatures[ProcessorFeature]);
}
NTSTATUS STDCALL
NtQuerySystemEnvironmentValue (IN PUNICODE_STRING VariableName,
OUT PWCHAR ValueBuffer,

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,27 +498,23 @@ NtQueryTimer(IN HANDLE TimerHandle,
/* Check for Success */
if(NT_SUCCESS(Status)) {
switch(TimerInformationClass) {
case TimerBasicInformation: {
/* Return the Basic Information */
_SEH_TRY {
/* FIXME: Interrupt correction based on Interrupt Time */
DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
/* Return the Basic Information */
_SEH_TRY {
if(ReturnLength != NULL) {
*ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
}
/* FIXME: Interrupt correction based on Interrupt Time */
DPRINT("Returning Information for Timer: %x. Time Remaining: %d\n", Timer, Timer->KeTimer.DueTime.QuadPart);
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart;
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
} _SEH_HANDLE {
if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
}
} _SEH_END;
/* Dereference Object */
ObDereferenceObject(Timer);
}

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: David Welch (welch@mcmail.com)
* PROGRAMMERS: Alex Ionescu - Used correct work queue array and added some fixes and checks.
* Gunnar Dalsnes - Implemented
*/
/* INCLUDES ******************************************************************/
@ -25,17 +25,10 @@
/*
* PURPOSE: Queue of items waiting to be processed at normal priority
*/
KQUEUE EiNormalWorkQueue;
KQUEUE EiCriticalWorkQueue;
KQUEUE EiHyperCriticalWorkQueue;
EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
/* FUNCTIONS ****************************************************************/
//static NTSTATUS STDCALL
static VOID STDCALL
ExWorkerThreadEntryPoint(IN PVOID context)
/*
* FUNCTION: Entry point for a worker thread
* ARGUMENTS:
@ -44,138 +37,138 @@ ExWorkerThreadEntryPoint(IN PVOID context)
* NOTE: To kill a worker thread you must queue an item whose callback
* calls PsTerminateSystemThread
*/
static
VOID
STDCALL
ExpWorkerThreadEntryPoint(IN PVOID Context)
{
PWORK_QUEUE_ITEM item;
PLIST_ENTRY current;
PWORK_QUEUE_ITEM WorkItem;
PLIST_ENTRY QueueEntry;
WORK_QUEUE_TYPE WorkQueueType;
PEX_WORK_QUEUE WorkQueue;
while (TRUE)
{
current = KeRemoveQueue( (PKQUEUE)context, KernelMode, NULL );
/* can't happend since we do a KernelMode wait (and we're a system thread) */
ASSERT((NTSTATUS)current != STATUS_USER_APC);
/* this should never happend either, since we wait with NULL timeout,
* but there's a slight possibility that STATUS_TIMEOUT is returned
* at queue rundown in NT (unlikely) -Gunnar
*/
ASSERT((NTSTATUS)current != STATUS_TIMEOUT);
/* based on INVALID_WORK_QUEUE_ITEM bugcheck desc. */
if (current->Flink == NULL || current->Blink == NULL)
{
KeBugCheck(INVALID_WORK_QUEUE_ITEM);
}
/* "reinitialize" item (same as done in ExInitializeWorkItem) */
current->Flink = NULL;
item = CONTAINING_RECORD( current, WORK_QUEUE_ITEM, List);
item->WorkerRoutine(item->Parameter);
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
}
}
}
static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
KPRIORITY Priority)
{
ULONG i;
PETHREAD Thread;
HANDLE hThread;
for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
{
/* Get Queue Type and Worker Queue */
WorkQueueType = (WORK_QUEUE_TYPE)Context;
WorkQueue = &ExWorkerQueue[WorkQueueType];
/* Loop forever */
while (TRUE) {
PsCreateSystemThread(&hThread,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
ExWorkerThreadEntryPoint,
WorkQueue);
ObReferenceObjectByHandle(hThread,
THREAD_ALL_ACCESS,
PsThreadType,
KernelMode,
(PVOID*)&Thread,
NULL);
KeSetPriorityThread(&Thread->Tcb,
Priority);
ObDereferenceObject(Thread);
ZwClose(hThread);
}
/* Wait for Something to Happen on the Queue */
QueueEntry = KeRemoveQueue(&WorkQueue->WorkerQueue, KernelMode, NULL);
/* Can't happen since we do a KernelMode wait (and we're a system thread) */
ASSERT((NTSTATUS)QueueEntry != STATUS_USER_APC);
/* this should never happen either, since we wait with NULL timeout,
* but there's a slight possibility that STATUS_TIMEOUT is returned
* at queue rundown in NT (unlikely) -Gunnar
*/
ASSERT((NTSTATUS)QueueEntry != STATUS_TIMEOUT);
/* Increment Processed Work Items */
InterlockedIncrement(&WorkQueue->WorkItemsProcessed);
/* Get the Work Item */
WorkItem = CONTAINING_RECORD(QueueEntry, WORK_QUEUE_ITEM, List);
/* Call the Worker Routine */
WorkItem->WorkerRoutine(WorkItem->Parameter);
/* Make sure it returned at right IRQL */
if (KeGetCurrentIrql() != PASSIVE_LEVEL) {
/* FIXME: Make this an Ex */
KEBUGCHECK(WORKER_THREAD_RETURNED_AT_BAD_IRQL);
}
/* Make sure it returned with Impersionation Disabled */
if (PsGetCurrentThread()->ActiveImpersonationInfo) {
/* FIXME: Make this an Ex */
KEBUGCHECK(IMPERSONATING_WORKER_THREAD);
}
}
}
VOID INIT_FUNCTION
ExInitializeWorkerThreads(VOID)
static
VOID
STDCALL
ExpInitializeWorkQueue(WORK_QUEUE_TYPE WorkQueueType,
KPRIORITY Priority)
{
KeInitializeQueue( &EiNormalWorkQueue, NUMBER_OF_WORKER_THREADS );
KeInitializeQueue( &EiCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
KeInitializeQueue( &EiHyperCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
ULONG i;
PETHREAD Thread;
HANDLE hThread;
/* Loop through how many threads we need to create */
for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) {
/* Create the System Thread */
PsCreateSystemThread(&hThread,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
ExpWorkerThreadEntryPoint,
(PVOID)WorkQueueType);
/* Get the Thread */
ObReferenceObjectByHandle(hThread,
THREAD_SET_INFORMATION,
PsThreadType,
KernelMode,
(PVOID*)&Thread,
NULL);
/* Set the Priority */
KeSetPriorityThread(&Thread->Tcb, Priority);
/* Dereference and close handle */
ObDereferenceObject(Thread);
ZwClose(hThread);
}
}
ExInitializeWorkQueue(&EiNormalWorkQueue,
LOW_PRIORITY);
ExInitializeWorkQueue(&EiCriticalWorkQueue,
LOW_REALTIME_PRIORITY);
ExInitializeWorkQueue(&EiHyperCriticalWorkQueue,
HIGH_PRIORITY);
VOID
INIT_FUNCTION
ExpInitializeWorkerThreads(VOID)
{
ULONG WorkQueueType;
/* Initialize the Array */
for (WorkQueueType = 0; WorkQueueType < MaximumWorkQueue; WorkQueueType++) {
RtlZeroMemory(&ExWorkerQueue[WorkQueueType], sizeof(EX_WORK_QUEUE));
KeInitializeQueue(&ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
}
/* Create the built-in worker threads for each work queue */
ExpInitializeWorkQueue(CriticalWorkQueue, LOW_REALTIME_PRIORITY);
ExpInitializeWorkQueue(DelayedWorkQueue, LOW_PRIORITY);
ExpInitializeWorkQueue(HyperCriticalWorkQueue, HIGH_PRIORITY);
}
/*
* @implemented
*/
VOID STDCALL
ExQueueWorkItem (PWORK_QUEUE_ITEM WorkItem,
WORK_QUEUE_TYPE QueueType)
/*
*
* FUNCTION: Inserts a work item in a queue for one of the system worker
* threads to process
* ARGUMENTS:
* WorkItem = Item to insert
* QueueType = Queue to insert it in
*/
VOID
STDCALL
ExQueueWorkItem(PWORK_QUEUE_ITEM WorkItem,
WORK_QUEUE_TYPE QueueType)
{
ASSERT(WorkItem!=NULL);
ASSERT_IRQL(DISPATCH_LEVEL);
ASSERT(WorkItem->List.Flink == NULL);
/*
* Insert the item in the appropiate queue and wake up any thread
* waiting for something to do
*/
switch(QueueType)
{
case DelayedWorkQueue:
KeInsertQueue (
&EiNormalWorkQueue,
&WorkItem->List
);
break;
case CriticalWorkQueue:
KeInsertQueue (
&EiCriticalWorkQueue,
&WorkItem->List
);
break;
case HyperCriticalWorkQueue:
KeInsertQueue (
&EiHyperCriticalWorkQueue,
&WorkItem->List
);
break;
default:
break;
}
/* Insert the Queue */
KeInsertQueue(&ExWorkerQueue[QueueType].WorkerQueue, &WorkItem->List);
}
/* EOF */

View file

@ -98,24 +98,19 @@ ExInit3(VOID);
VOID
ExpInitTimeZoneInfo(VOID);
VOID
ExInitializeWorkerThreads(VOID);
ExpInitializeWorkerThreads(VOID);
VOID
ExpInitLookasideLists(VOID);
VOID
ExpInitializeCallbacks(VOID);
VOID
ExpInitUuids(VOID);
VOID
STDCALL
ExpInitializeExecutive(VOID);
/* OTHER FUNCTIONS **********************************************************/
#ifdef _ENABLE_THRDEVTPAIR
VOID
ExpSwapThreadEventPair(
IN struct _ETHREAD* Thread,
IN struct _KEVENT_PAIR* EventPair
);
#endif /* _ENABLE_THRDEVTPAIR */
LONGLONG
FASTCALL
ExfpInterlockedExchange64(LONGLONG volatile * Destination,

View file

@ -2,18 +2,5 @@
* Structure ids
*/
#define InternalBaseType (0xcc)
#define InternalNotificationEvent (InternalBaseType + 1)
#define InternalSynchronizationEvent (InternalBaseType + 2)
#define InternalSemaphoreType (InternalBaseType + 3)
#define InternalProcessType (InternalBaseType + 4)
#define InternalThreadType (InternalBaseType + 5)
#define InternalFileType (InternalBaseType + 6)
#define InternalDriverType (InternalBaseType + 7)
#define InternalDeviceType (InternalBaseType + 8)
#define InternalMutexType (InternalBaseType + 9)
#define InternalNotificationTimer (InternalBaseType + 10)
#define InternalSynchronizationTimer (InternalBaseType + 11)
#define InternalQueueType (InternalBaseType + 12)

View file

@ -412,7 +412,7 @@ IoDestroyDriverList(VOID);
/* bootlog.c */
VOID
IopInitBootLog(VOID);
IopInitBootLog(BOOLEAN StartBootLog);
VOID
IopStartBootLog(VOID);

View file

@ -115,6 +115,17 @@ typedef struct _KPROFILE
struct _EPROCESS *Process;
} KPROFILE, *PKPROFILE;
/* Cached modules from the loader block */
typedef enum _CACHED_MODULE_TYPE {
AnsiCodepage,
OemCodepage,
UnicodeCasemap,
SystemRegistry,
HardwareRegistry,
MaximumCachedModuleType,
} CACHED_MODULE_TYPE, *PCACHED_MODULE_TYPE;
extern PLOADER_MODULE CachedModules[MaximumCachedModuleType];
VOID STDCALL
DbgBreakPointNoBugCheck(VOID);
@ -144,30 +155,42 @@ VOID STDCALL KeUpdateRunTime(PKTRAP_FRAME TrapFrame, KIRQL Irql);
VOID STDCALL KiExpireTimers(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2);
KIRQL KeAcquireDispatcherDatabaseLock(VOID);
VOID KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
VOID KeReleaseDispatcherDatabaseLock(KIRQL Irql);
VOID KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
KIRQL inline FASTCALL KeAcquireDispatcherDatabaseLock(VOID);
VOID inline FASTCALL KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
VOID inline FASTCALL KeReleaseDispatcherDatabaseLock(KIRQL Irql);
VOID inline FASTCALL KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment);
VOID STDCALL KeExpireTimers(PKDPC Apc,
PVOID Arg1,
PVOID Arg2,
PVOID Arg3);
VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
VOID inline FASTCALL KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type,
ULONG Size, ULONG SignalState);
VOID KeDumpStackFrames(PULONG Frame);
BOOLEAN KiTestAlert(VOID);
BOOLEAN KiAbortWaitThread(struct _KTHREAD* Thread, NTSTATUS WaitStatus);
VOID FASTCALL KiAbortWaitThread(struct _KTHREAD* Thread, NTSTATUS WaitStatus);
BOOLEAN STDCALL KiInsertTimer(PKTIMER Timer, LARGE_INTEGER DueTime);
VOID inline FASTCALL KiSatisfyObjectWait(PDISPATCHER_HEADER Object, PKTHREAD Thread);
BOOLEAN inline FASTCALL KiIsObjectSignaled(PDISPATCHER_HEADER Object, PKTHREAD Thread);
VOID inline FASTCALL KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
VOID KeContextToTrapFrame(PCONTEXT Context, PKTRAP_FRAME TrapFrame);
VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame);
VOID STDCALL KeInitializeEventPair(PKEVENT_PAIR EventPair);
VOID KiInitializeUserApc(IN PVOID Reserved,
VOID STDCALL KiInitializeUserApc(IN PVOID Reserved,
IN PKTRAP_FRAME TrapFrame,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID NormalContext,
@ -183,6 +206,7 @@ STDCALL
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode);
BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);
VOID FASTCALL KiWakeQueue(IN PKQUEUE Queue);
PLIST_ENTRY STDCALL KeRundownQueue(IN PKQUEUE Queue);
extern LARGE_INTEGER SystemBootTime;
@ -194,7 +218,7 @@ VOID KeInitInterrupts(VOID);
VOID KeInitTimer(VOID);
VOID KeInitDpc(struct _KPCR* Pcr);
VOID KeInitDispatcher(VOID);
VOID KeInitializeDispatcher(VOID);
VOID inline FASTCALL KeInitializeDispatcher(VOID);
VOID KiInitializeSystemClock(VOID);
VOID KeInitializeBugCheck(VOID);
VOID Phase1Initialization(PVOID Context);

View file

@ -29,6 +29,7 @@ extern ULONG NlsUnicodeTableOffset;
extern PUSHORT NlsUnicodeUpcaseTable;
extern PUSHORT NlsUnicodeLowercaseTable;
VOID STDCALL RtlpInitNls(VOID);
VOID RtlpImportAnsiCodePage(PUSHORT TableBase, ULONG Size);
VOID RtlpImportOemCodePage(PUSHORT TableBase, ULONG Size);
VOID RtlpImportUnicodeCasemap(PUSHORT TableBase, ULONG Size);

View file

@ -49,10 +49,12 @@ VOID ExpInitializeProfileImplementation(VOID);
*/
VOID MmInitSystem(ULONG Phase, PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG LastKernelAddress);
VOID IoInit(VOID);
VOID IoInit2(VOID);
VOID IoInit2(BOOLEAN BootLog);
VOID STDCALL IoInit3(VOID);
VOID ObInit(VOID);
VOID PsInit(VOID);
VOID CmInitializeRegistry(VOID);
VOID STDCALL CmInitHives(BOOLEAN SetupBoot);
VOID CmInit2(PCHAR CommandLine);
VOID CmShutdownRegistry(VOID);
BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);

View file

@ -498,7 +498,9 @@ VOID STDCALL PsExitSpecialApc(PKAPC Apc,
VOID
STDCALL
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
NTSTATUS KeReleaseThread(PKTHREAD Thread);
VOID
@ -525,8 +527,11 @@ VOID PsUnfreezeProcessThreads(PEPROCESS Process);
ULONG PsEnumThreadsByProcess(PEPROCESS Process);
PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
VOID
PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason);
STDCALL
PsBlockThread(PNTSTATUS Status,
UCHAR Alertable,
ULONG WaitMode,
UCHAR WaitReason);
VOID
PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment);
VOID

View file

@ -27,13 +27,14 @@ static ERESOURCE IopBootLogResource;
/* FUNCTIONS ****************************************************************/
VOID INIT_FUNCTION
IopInitBootLog(VOID)
IopInitBootLog(BOOLEAN StartBootLog)
{
ExInitializeResourceLite(&IopBootLogResource);
if (StartBootLog) IopStartBootLog();
}
VOID
VOID INIT_FUNCTION
IopStartBootLog(VOID)
{
IopBootLogCreate = TRUE;

View file

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

View file

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

View file

@ -1,5 +1,4 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/iocomp.c
@ -18,66 +17,48 @@
POBJECT_TYPE ExIoCompletionType;
NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
static GENERIC_MAPPING ExIoCompletionMapping =
{
STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
IO_COMPLETION_ALL_ACCESS
STANDARD_RIGHTS_READ | IO_COMPLETION_QUERY_STATE,
STANDARD_RIGHTS_WRITE | IO_COMPLETION_MODIFY_STATE,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
IO_COMPLETION_ALL_ACCESS
};
/* FUNCTIONS *****************************************************************/
NTSTATUS
VOID
STDCALL
IopCreateIoCompletion(
PVOID ObjectBody,
PVOID Parent,
PWSTR RemainingPath,
POBJECT_ATTRIBUTES ObjectAttributes
)
{
DPRINT("IopCreateIoCompletion(ObjectBody %x, Parent %x, RemainingPath %S)\n",
ObjectBody, Parent, RemainingPath);
if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
{
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
VOID STDCALL
IopDeleteIoCompletion(PVOID ObjectBody)
{
PKQUEUE Queue = ObjectBody;
PKQUEUE Queue = ObjectBody;
PLIST_ENTRY FirstEntry;
PLIST_ENTRY CurrentEntry;
PIO_COMPLETION_PACKET Packet;
DPRINT("IopDeleteIoCompletion()\n");
DPRINT("IopDeleteIoCompletion()\n");
KeRundownQueue(Queue);
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
IoSetCompletionRoutineEx(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PIO_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context,
IN BOOLEAN InvokeOnSuccess,
IN BOOLEAN InvokeOnError,
IN BOOLEAN InvokeOnCancel
)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
/* Rundown the Queue */
FirstEntry = KeRundownQueue(Queue);
/* Clean up the IRPs */
if (FirstEntry) {
CurrentEntry = FirstEntry;
do {
/* Get the Packet */
Packet = CONTAINING_RECORD(CurrentEntry, IO_COMPLETION_PACKET, ListEntry);
/* Go to next Entry */
CurrentEntry = CurrentEntry->Flink;
/* Free it */
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
} while (FirstEntry != CurrentEntry);
}
}
/*
@ -85,305 +66,278 @@ IoSetCompletionRoutineEx(
*/
NTSTATUS
STDCALL
IoSetIoCompletion (
IN PVOID IoCompletion,
IN PVOID KeyContext,
IN PVOID ApcContext,
IN NTSTATUS IoStatus,
IN ULONG_PTR IoStatusInformation,
IN BOOLEAN Quota
)
IoSetIoCompletion(IN PVOID IoCompletion,
IN PVOID KeyContext,
IN PVOID ApcContext,
IN NTSTATUS IoStatus,
IN ULONG_PTR IoStatusInformation,
IN BOOLEAN Quota)
{
PKQUEUE Queue = (PKQUEUE) IoCompletion;
PIO_COMPLETION_PACKET Packet;
PKQUEUE Queue = (PKQUEUE)IoCompletion;
PIO_COMPLETION_PACKET Packet;
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
if (NULL == Packet)
{
return STATUS_NO_MEMORY;
}
/* Allocate the Packet */
Packet = ExAllocateFromNPagedLookasideList(&IoCompletionPacketLookaside);
if (NULL == Packet) return STATUS_NO_MEMORY;
/* Set up the Packet */
Packet->Key = KeyContext;
Packet->Context = ApcContext;
Packet->IoStatus.Status = IoStatus;
Packet->IoStatus.Information = IoStatusInformation;
/* Insert the Queue */
KeInsertQueue(Queue, &Packet->ListEntry);
Packet->Key = KeyContext;
Packet->Context = ApcContext;
Packet->IoStatus.Status = IoStatus;
Packet->IoStatus.Information = IoStatusInformation;
KeInsertQueue(Queue, &Packet->ListEntry);
/* Return Success */
return STATUS_SUCCESS;
}
return STATUS_SUCCESS;
/*
* @unimplemented
*/
NTSTATUS
STDCALL
IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PIO_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context,
IN BOOLEAN InvokeOnSuccess,
IN BOOLEAN InvokeOnError,
IN BOOLEAN InvokeOnCancel)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
VOID
FASTCALL
IopInitIoCompletionImplementation(VOID)
{
ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
RtlpCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion", NonPagedPool);
ExIoCompletionType->Tag = IOC_TAG;
ExIoCompletionType->PeakObjects = 0;
ExIoCompletionType->PeakHandles = 0;
ExIoCompletionType->TotalObjects = 0;
ExIoCompletionType->TotalHandles = 0;
ExIoCompletionType->PagedPoolCharge = 0;
ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
ExIoCompletionType->Mapping = &ExIoCompletionMapping;
ExIoCompletionType->Dump = NULL;
ExIoCompletionType->Open = NULL;
ExIoCompletionType->Close = NULL;
ExIoCompletionType->Delete = IopDeleteIoCompletion;
ExIoCompletionType->Parse = NULL;
ExIoCompletionType->Security = NULL;
ExIoCompletionType->QueryName = NULL;
ExIoCompletionType->OkayToClose = NULL;
ExIoCompletionType->Create = IopCreateIoCompletion;
ExIoCompletionType->DuplicationNotify = NULL;
/* Create the IO Completion Type */
ExIoCompletionType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
RtlpCreateUnicodeString(&ExIoCompletionType->TypeName, L"IoCompletion", NonPagedPool);
ExIoCompletionType->Tag = IOC_TAG;
ExIoCompletionType->PeakObjects = 0;
ExIoCompletionType->PeakHandles = 0;
ExIoCompletionType->TotalObjects = 0;
ExIoCompletionType->TotalHandles = 0;
ExIoCompletionType->PagedPoolCharge = 0;
ExIoCompletionType->NonpagedPoolCharge = sizeof(KQUEUE);
ExIoCompletionType->Mapping = &ExIoCompletionMapping;
ExIoCompletionType->Dump = NULL;
ExIoCompletionType->Open = NULL;
ExIoCompletionType->Close = NULL;
ExIoCompletionType->Delete = IopDeleteIoCompletion;
ExIoCompletionType->Parse = NULL;
ExIoCompletionType->Security = NULL;
ExIoCompletionType->QueryName = NULL;
ExIoCompletionType->OkayToClose = NULL;
ExIoCompletionType->Create = NULL;
ExIoCompletionType->DuplicationNotify = NULL;
ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
NULL,
NULL,
0,
sizeof(IO_COMPLETION_PACKET),
IOC_TAG,
0);
/* Initialize the Lookaside List we'll use for packets */
ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
NULL,
NULL,
0,
sizeof(IO_COMPLETION_PACKET),
IOC_TAG,
0);
}
NTSTATUS
STDCALL
NtCreateIoCompletion(
OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG NumberOfConcurrentThreads
)
NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG NumberOfConcurrentThreads)
{
PKQUEUE Queue;
NTSTATUS Status;
PKQUEUE Queue;
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
Status = ObCreateObject(ExGetPreviousMode(),
ExIoCompletionType,
ObjectAttributes,
ExGetPreviousMode(),
NULL,
sizeof(KQUEUE),
0,
0,
(PVOID*)&Queue);
if (!NT_SUCCESS(Status))
{
return Status;
/* Create the Object */
Status = ObCreateObject(PreviousMode,
ExIoCompletionType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(KQUEUE),
0,
0,
(PVOID*)&Queue);
/* Check for success */
if (!NT_SUCCESS(Status)) {
/* Initialize the Queue */
KeInitializeQueue(Queue, NumberOfConcurrentThreads);
/* Insert it */
Status = ObInsertObject(Queue,
NULL,
DesiredAccess,
0,
NULL,
IoCompletionHandle);
ObDereferenceObject(Queue);
}
Status = ObInsertObject ((PVOID)Queue,
NULL,
DesiredAccess,
0,
NULL,
IoCompletionHandle);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Queue);
return Status;
}
KeInitializeQueue(Queue, NumberOfConcurrentThreads);
ObDereferenceObject(Queue);
/* Return Status */
return STATUS_SUCCESS;
/*
}
CompletionPort = NULL OR ExistingCompletionPort
*/
NTSTATUS
STDCALL
NtOpenIoCompletion(OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
/* Open the Object */
Status = ObOpenObjectByName(ObjectAttributes,
ExIoCompletionType,
NULL,
PreviousMode,
DesiredAccess,
NULL,
IoCompletionHandle);
/* Return Status */
return Status;
}
/*
DesiredAccess:
ZERO
IO_COMPLETION_QUERY_STATE Query access
IO_COMPLETION_MODIFY_STATE Modify access
IO_COMPLETION_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_ALL
ObjectAttributes
OBJ_OPENLINK and OBJ_PERMANENT are not valid attributes
Return Value
STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or
STATUS_OBJECT_NAME_NOT_FOUND.
*/
NTSTATUS
STDCALL
NtOpenIoCompletion(
OUT PHANDLE IoCompletionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
)
{
NTSTATUS Status;
Status = ObOpenObjectByName(ObjectAttributes,
ExIoCompletionType,
NULL,
UserMode,
DesiredAccess,
NULL,
IoCompletionHandle); //<- ???
return Status;
}
NTSTATUS
STDCALL
NtQueryIoCompletion(
IN HANDLE IoCompletionHandle,
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
OUT PVOID IoCompletionInformation,
IN ULONG IoCompletionInformationLength,
OUT PULONG ResultLength OPTIONAL
)
NtQueryIoCompletion(IN HANDLE IoCompletionHandle,
IN IO_COMPLETION_INFORMATION_CLASS IoCompletionInformationClass,
OUT PVOID IoCompletionInformation,
IN ULONG IoCompletionInformationLength,
OUT PULONG ResultLength OPTIONAL)
{
PKQUEUE Queue;
NTSTATUS Status;
PKQUEUE Queue;
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
if (IoCompletionInformationClass != IoCompletionBasicInformation)
{
return STATUS_INVALID_INFO_CLASS;
}
if (IoCompletionInformationLength < sizeof(IO_COMPLETION_BASIC_INFORMATION))
{
return STATUS_INFO_LENGTH_MISMATCH;
}
Status = ObReferenceObjectByHandle( IoCompletionHandle,
/* Get the Object */
Status = ObReferenceObjectByHandle(IoCompletionHandle,
IO_COMPLETION_QUERY_STATE,
ExIoCompletionType,
UserMode,
PreviousMode,
(PVOID*)&Queue,
NULL);
if (NT_SUCCESS(Status))
{
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth =
Queue->Header.SignalState;
/* Check for Success */
if (NT_SUCCESS(Status)) {
/* Return Info */
((PIO_COMPLETION_BASIC_INFORMATION)IoCompletionInformation)->Depth = KeReadStateQueue(Queue);
ObDereferenceObject(Queue);
ObDereferenceObject(Queue);
/* Return Result Length if needed */
if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
}
if (ResultLength) *ResultLength = sizeof(IO_COMPLETION_BASIC_INFORMATION);
}
return Status;
/* Return Status */
return Status;
}
/*
* Dequeues an I/O completion message from an I/O completion object
*/
NTSTATUS
STDCALL
NtRemoveIoCompletion(
IN HANDLE IoCompletionHandle,
OUT PVOID *CompletionKey,
OUT PVOID *CompletionContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER Timeout OPTIONAL
)
NtRemoveIoCompletion(IN HANDLE IoCompletionHandle,
OUT PVOID *CompletionKey,
OUT PVOID *CompletionContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER Timeout OPTIONAL)
{
PKQUEUE Queue;
NTSTATUS Status;
PIO_COMPLETION_PACKET Packet;
PLIST_ENTRY ListEntry;
Status = ObReferenceObjectByHandle( IoCompletionHandle,
PKQUEUE Queue;
NTSTATUS Status;
PIO_COMPLETION_PACKET Packet;
PLIST_ENTRY ListEntry;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
/* Open the Object */
Status = ObReferenceObjectByHandle(IoCompletionHandle,
IO_COMPLETION_MODIFY_STATE,
ExIoCompletionType,
UserMode,
PreviousMode,
(PVOID*)&Queue,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Check for success */
if (NT_SUCCESS(Status)) {
/*
Try 2 remove packet from queue. Wait (optionaly) if
no packet in queue or max num of threads allready running.
*/
do {
ListEntry = KeRemoveQueue(Queue, UserMode, Timeout );
/* Remove queue */
ListEntry = KeRemoveQueue(Queue, PreviousMode, Timeout);
/* Nebbets book says nothing about NtRemoveIoCompletion returning STATUS_USER_APC,
and the umode equivalent GetQueuedCompletionStatus says nothing about this either,
so my guess it we should restart the operation. Need further investigation. -Gunnar
*/
} while((NTSTATUS)ListEntry == STATUS_USER_APC);
ObDereferenceObject(Queue);
/* If we got a timeout or user_apc back, return the status */
if ((NTSTATUS)ListEntry == STATUS_TIMEOUT || (NTSTATUS)ListEntry == STATUS_USER_APC) {
Status = (NTSTATUS)ListEntry;
} else {
/* Get the Packet Data */
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
/* Return it */
if (CompletionKey) *CompletionKey = Packet->Key;
if (CompletionContext) *CompletionContext = Packet->Context;
if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
/* Free packet */
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
}
if ((NTSTATUS)ListEntry == STATUS_TIMEOUT)
{
return STATUS_TIMEOUT;
}
ASSERT(ListEntry);
Packet = CONTAINING_RECORD(ListEntry, IO_COMPLETION_PACKET, ListEntry);
if (CompletionKey) *CompletionKey = Packet->Key;
if (CompletionContext) *CompletionContext = Packet->Context;
if (IoStatusBlock) *IoStatusBlock = Packet->IoStatus;
ExFreeToNPagedLookasideList(&IoCompletionPacketLookaside, Packet);
return STATUS_SUCCESS;
/* Dereference the Object */
ObDereferenceObject(Queue);
}
/* Return status */
return Status;
}
/*
ASSOSIERT MED FOB's IoCompletionContext
typedef struct _IO_COMPLETION_CONTEXT {
PVOID Port;
ULONG Key;
} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;
*/
/*
* Queues an I/O completion message to an I/O completion object
*/
NTSTATUS
STDCALL
NtSetIoCompletion(
IN HANDLE IoCompletionPortHandle,
IN PVOID CompletionKey,
IN PVOID CompletionContext,
IN NTSTATUS CompletionStatus,
IN ULONG CompletionInformation
)
NtSetIoCompletion(IN HANDLE IoCompletionPortHandle,
IN PVOID CompletionKey,
IN PVOID CompletionContext,
IN NTSTATUS CompletionStatus,
IN ULONG CompletionInformation)
{
NTSTATUS Status;
PKQUEUE Queue;
Status = ObReferenceObjectByHandle( IoCompletionPortHandle,
NTSTATUS Status;
PKQUEUE Queue;
/* Get the Object */
Status = ObReferenceObjectByHandle(IoCompletionPortHandle,
IO_COMPLETION_MODIFY_STATE,
ExIoCompletionType,
UserMode,
ExGetPreviousMode(),
(PVOID*)&Queue,
NULL);
if (NT_SUCCESS(Status))
{
Status = IoSetIoCompletion(Queue, CompletionKey, CompletionContext,
CompletionStatus, CompletionInformation, TRUE);
ObDereferenceObject(Queue);
}
return Status;
/* Check for Success */
if (NT_SUCCESS(Status)) {
/* Set the Completion */
Status = IoSetIoCompletion(Queue,
CompletionKey,
CompletionContext,
CompletionStatus,
CompletionInformation,
TRUE);
ObDereferenceObject(Queue);
}
/* Return status */
return Status;
}

View file

@ -553,14 +553,17 @@ IoInit (VOID)
}
VOID INIT_FUNCTION
IoInit2(VOID)
VOID
INIT_FUNCTION
IoInit2(BOOLEAN BootLog)
{
PDEVICE_NODE DeviceNode;
PDRIVER_OBJECT DriverObject;
MODULE_OBJECT ModuleObject;
NTSTATUS Status;
IoCreateDriverList();
KeInitializeSpinLock (&IoStatisticsLock);
/* Initialize raw filesystem driver */
@ -605,6 +608,56 @@ IoInit2(VOID)
IopInvalidateDeviceRelations(
IopRootDeviceNode,
BusRelations);
/* Start boot logging */
IopInitBootLog(BootLog);
/* Load boot start drivers */
IopInitializeBootDrivers();
}
VOID
STDCALL
INIT_FUNCTION
IoInit3(VOID)
{
NTSTATUS Status;
/* Create ARC names for boot devices */
IoCreateArcNames();
/* Create the SystemRoot symbolic link */
CPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
if (!NT_SUCCESS(Status)) {
DbgPrint("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
DbgPrintErrorMessage (Status);
KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
}
/* Start Profiling on a Debug Build */
#if defined(KDBG) || defined(DBG)
KdbInitProfiling2();
#endif /* KDBG */
/* I/O is now setup for disk access, so start the debugging logger thread. */
if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_BOOTLOG)) DebugLogInit2();
/* Load services for devices found by PnP manager */
IopInitializePnpServices(IopRootDeviceNode, FALSE);
/* Load system start drivers */
IopInitializeSystemDrivers();
IoDestroyDriverList();
/* Stop boot logging */
IopStopBootLog();
/* Assign drive letters */
IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
NULL,
NULL,
NULL);
}
/*

View file

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

View file

@ -1,150 +0,0 @@
/* $Id:$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/alert.c
* PURPOSE: Alerts
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
BOOLEAN
STDCALL
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
/*
* FUNCTION: Tests whether there are any pending APCs for the current thread
* and if so the APCs will be delivered on exit from kernel mode
*/
{
KIRQL OldIrql;
PKTHREAD Thread = KeGetCurrentThread();
BOOLEAN OldState;
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
OldIrql = KeAcquireDispatcherDatabaseLock();
KiAcquireSpinLock(&Thread->ApcQueueLock);
OldState = Thread->Alerted[AlertMode];
/* If the Thread is Alerted, Clear it */
if (OldState) {
Thread->Alerted[AlertMode] = FALSE;
} else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) {
/* If the mode is User and the Queue isn't empty, set Pending */
Thread->ApcState.UserApcPending = TRUE;
}
KiReleaseSpinLock(&Thread->ApcQueueLock);
KeReleaseDispatcherDatabaseLock(OldIrql);
return OldState;
}
VOID
KeAlertThread(PKTHREAD Thread, KPROCESSOR_MODE AlertMode)
{
KIRQL oldIrql;
oldIrql = KeAcquireDispatcherDatabaseLock();
/* Return if thread is already alerted. */
if (Thread->Alerted[AlertMode] == FALSE)
{
if (Thread->State == THREAD_STATE_BLOCKED &&
(AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
Thread->Alertable)
{
KiAbortWaitThread(Thread, STATUS_ALERTED);
}
else
{
Thread->Alerted[AlertMode] = TRUE;
}
}
KeReleaseDispatcherDatabaseLock(oldIrql);
}
/*
*
* NOT EXPORTED
*/
NTSTATUS STDCALL
NtAlertResumeThread(IN HANDLE ThreadHandle,
OUT PULONG SuspendCount)
{
UNIMPLEMENTED;
return(STATUS_NOT_IMPLEMENTED);
}
/*
* @implemented
*
* EXPORTED
*/
NTSTATUS STDCALL
NtAlertThread (IN HANDLE ThreadHandle)
{
KPROCESSOR_MODE PreviousMode;
PETHREAD Thread;
NTSTATUS Status;
PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME,
PsThreadType,
PreviousMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/* do an alert depending on the processor mode. If some kmode code wants to
enforce a umode alert it should call KeAlertThread() directly. If kmode
code wants to do a kmode alert it's sufficient to call it with Zw or just
use KeAlertThread() directly */
KeAlertThread(&Thread->Tcb, PreviousMode);
ObDereferenceObject(Thread);
return(STATUS_SUCCESS);
}
/*
* NOT EXPORTED
*/
NTSTATUS
STDCALL
NtTestAlert(VOID)
{
KPROCESSOR_MODE PreviousMode;
PreviousMode = ExGetPreviousMode();
/* Check and Alert Thread if needed */
return KeTestAlertThread(PreviousMode) ? STATUS_ALERTED : STATUS_SUCCESS;
}

File diff suppressed because it is too large Load diff

View file

@ -47,6 +47,17 @@ KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
return FALSE;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeDeregisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @implemented
*/
@ -74,6 +85,20 @@ KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
return(FALSE);
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeRegisterBugCheckReasonCallback(IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
IN KBUGCHECK_CALLBACK_REASON Reason,
IN PUCHAR Component)
{
UNIMPLEMENTED;
return FALSE;
}
VOID STDCALL
KeBugCheckWithTf(ULONG BugCheckCode,
ULONG BugCheckParameter1,

View file

@ -1,5 +1,4 @@
/* $Id$
*
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/catch.c
@ -21,282 +20,206 @@ ULONG
RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
/*
* @unimplemented
*/
VOID
STDCALL
KiCoprocessorError(VOID)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID
STDCALL
KiUnexpectedInterrupt(VOID)
{
UNIMPLEMENTED;
}
VOID
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
{
EXCEPTION_DISPOSITION Value;
CONTEXT TContext;
KD_CONTINUE_TYPE Action = kdHandleException;
EXCEPTION_DISPOSITION Value;
CONTEXT TContext;
KD_CONTINUE_TYPE Action = kdHandleException;
DPRINT("KiDispatchException() called\n");
DPRINT("KiDispatchException() called\n");
/* Increase number of Exception Dispatches */
KeGetCurrentKPCR()->PrcbData.KeExceptionDispatchCount++;
/* PCR->KeExceptionDispatchCount++; */
if (Context == NULL)
{
TContext.ContextFlags = CONTEXT_FULL;
if (PreviousMode == UserMode)
{
TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
}
if (!Context) {
/* Assume Full context */
TContext.ContextFlags = CONTEXT_FULL;
/* Check the mode */
if (PreviousMode == UserMode) {
/* Add Debugger Registers if this is User Mode */
TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
}
KeTrapFrameToContext(Tf, &TContext);
/* Convert the Trapframe into a Context */
KeTrapFrameToContext(Tf, &TContext);
Context = &TContext;
/* Use local stack context */
Context = &TContext;
}
#if 0
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
{
Context->Eip--;
#if 0 /* FIXME: Isn't this right? With a break after? */
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
Context->Eip--;
}
#endif
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
{
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
}
if (Action == kdContinue)
{
return;
/* Check if a Debugger is enabled */
if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) {
/* Break into it */
Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
}
/* If the debugger said continue, then continue */
if (Action == kdContinue) return;
/* If the Debugger couldn't handle it... */
if (Action != kdDoNotHandleException) {
/* See what kind of Exception this is */
if (PreviousMode == UserMode) {
/* User mode exception, search the frames if we have to */
if (SearchFrames) {
if (Action != kdDoNotHandleException)
{
if (PreviousMode == UserMode)
{
if (SearchFrames)
{
PULONG Stack;
ULONG CDest;
char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
NTSTATUS StatusOfCopy;
PULONG Stack;
ULONG CDest;
char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
NTSTATUS StatusOfCopy;
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, FALSE);
if (Action == kdContinue)
{
return;
}
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
FALSE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
/* FIXME: Forward exception to user mode debugger */
/* FIXME: Forward exception to user mode debugger */
/* FIXME: Check user mode stack for enough space */
/*
* Let usermode try and handle the exception
*/
Stack = (PULONG)temp_space;
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
/* Return address */
Stack[0] = 0;
/* Pointer to EXCEPTION_RECORD structure */
Stack[1] = (ULONG)&pNewUserStack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&pNewUserStack[CDest];
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
StatusOfCopy = MmCopyToCaller(pNewUserStack,
temp_space,
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
if (NT_SUCCESS(StatusOfCopy))
{
Tf->Esp = (ULONG)pNewUserStack;
}
else
{
/* Now it really hit the ventilation device. Sorry,
* can do nothing but kill the sucker.
*/
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
DPRINT1("User-mode stack was invalid. Terminating target thread\n");
}
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, TRUE);
if (Action == kdContinue)
{
return;
/* FIXME: Check user mode stack for enough space */
/* Let usermode try and handle the exception. Setup Stack */
Stack = (PULONG)temp_space;
CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
/* Return Address */
Stack[0] = 0;
/* Pointer to EXCEPTION_RECORD structure */
Stack[1] = (ULONG)&pNewUserStack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&pNewUserStack[CDest];
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
/* Copy Stack */
StatusOfCopy = MmCopyToCaller(pNewUserStack,
temp_space,
(12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
/* Check for success */
if (NT_SUCCESS(StatusOfCopy)) {
/* Set new Stack Pointer */
Tf->Esp = (ULONG)pNewUserStack;
} else {
/*
* Now it really hit the ventilation device. Sorry,
* can do nothing but kill the sucker.
*/
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
DPRINT1("User-mode stack was invalid. Terminating target thread\n");
}
/* Set EIP to the User-mode Dispathcer */
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
return;
}
/* FIXME: Forward the exception to the debugger */
/* FIXME: Forward the exception to the process exception port */
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
/* Terminate the offending thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
}
else
{
/* PreviousMode == KernelMode */
/* Terminate the offending thread */
DPRINT1("Unhandled UserMode exception, terminating thread\n");
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
} else {
/* This is Kernel Mode */
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, FALSE);
if (Action == kdContinue)
{
return;
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
FALSE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
/* Dispatch the Exception */
Value = RtlpDispatchException (ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
/* If RtlpDispatchException() did not handle the exception then bugcheck */
if (Value != ExceptionContinueExecution ||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)) {
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n", ExceptionRecord->ExceptionAddress);
#ifdef KDBG
/* Enter KDB if available */
Action = KdbEnterDebuggerException(ExceptionRecord,
PreviousMode,
Context,
Tf,
TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) return;
#endif
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
}
#endif
Value = RtlpDispatchException (ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
/*
* If RtlpDispatchException() does not handle the exception then
* bugcheck
*/
if (Value != ExceptionContinueExecution ||
0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
{
DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
ExceptionRecord->ExceptionAddress );
#ifdef KDBG
Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
Context, Tf, TRUE);
if (Action == kdContinue)
{
return;
}
#endif
KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
}
}
}
}
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseAccessViolation (VOID)
{
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseDatatypeMisalignment (VOID)
{
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
/*
* @implemented
*/
VOID STDCALL
ExRaiseStatus (IN NTSTATUS Status)
{
EXCEPTION_RECORD ExceptionRecord;
DPRINT("ExRaiseStatus(%x)\n", Status);
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionFlags = 0;
RtlRaiseException(&ExceptionRecord);
}
/*
* @implemented
*/
VOID
STDCALL
ExRaiseException (
PEXCEPTION_RECORD ExceptionRecord
)
{
RtlRaiseException(ExceptionRecord);
}
/*
* @implemented
*/
BOOLEAN
STDCALL
ExSystemExceptionFilter(VOID)
{
return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
/*
* @unimplemented
*/
VOID
STDCALL
ExRaiseHardError (
IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response
)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeDeregisterBugCheckReasonCallback(
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
ULONG
STDCALL
KeGetRecommendedSharedDataAlignment(
VOID
)
{
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/
BOOLEAN
STDCALL
KeRegisterBugCheckReasonCallback(
IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
IN KBUGCHECK_CALLBACK_REASON Reason,
IN PUCHAR Component
)
{
UNIMPLEMENTED;
return FALSE;
}
/* EOF */

View file

@ -1,56 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/critical.c
* PURPOSE: Implement critical regions
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
VOID STDCALL KeEnterCriticalRegion (VOID)
{
PKTHREAD Thread = KeGetCurrentThread();
DPRINT("KeEnterCriticalRegion()\n");
if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
Thread->KernelApcDisable--;
}
/*
* @implemented
*/
VOID STDCALL KeLeaveCriticalRegion (VOID)
{
PKTHREAD Thread = KeGetCurrentThread();
DPRINT("KeLeaveCriticalRegion()\n");
if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
/* Reference: http://www.ntfsd.org/archive/ntfsd0104/msg0203.html */
if(++Thread->KernelApcDisable == 0)
{
if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]))
{
Thread->ApcState.KernelApcPending = TRUE;
HalRequestSoftwareInterrupt(APC_LEVEL);
}
}
}
/* EOF */

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,24 +60,18 @@ KeInitializeThreadedDpc(PKDPC Dpc,
* NOTE: Callers can be running at any IRQL.
*/
{
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
//Dpc->Type = KThreadedDpc;
Dpc->Number= 0;
Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine;
Dpc->DeferredContext = DeferredContext;
Dpc->DpcData = NULL;
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
Dpc->Type = ThreadedDpcObject;
Dpc->Number= 0;
Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine;
Dpc->DeferredContext = DeferredContext;
Dpc->DpcData = NULL;
}
/*
* @implemented
*/
VOID
STDCALL
KeInitializeDpc (PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
/*
*
* FUNCTION:
* Initalizes a DPC and registers the DeferredRoutine for it.
* ARGUMENTS:
@ -86,24 +80,24 @@ KeInitializeDpc (PKDPC Dpc,
* DeferredContext = Parameter to be passed to the callback routine.
* NOTE: Callers can be running at any IRQL.
*/
VOID
STDCALL
KeInitializeDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
{
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
Dpc->Type = KDpc;
Dpc->Number= 0;
Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine;
Dpc->DeferredContext = DeferredContext;
Dpc->DpcData = NULL;
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
Dpc->Type = DpcObject;
Dpc->Number= 0;
Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine;
Dpc->DeferredContext = DeferredContext;
Dpc->DpcData = NULL;
}
/*
* @implemented
*/
BOOLEAN STDCALL
KeInsertQueueDpc (PKDPC Dpc,
PVOID SystemArgument1,
PVOID SystemArgument2)
/*
*
* FUNCTION:
* Queues a DPC for execution when the IRQL of a processor
* drops below DISPATCH_LEVEL
@ -155,124 +149,141 @@ KeInsertQueueDpc (PKDPC Dpc,
* is greater that the target depth or the minimum DPC rate is less than the
* target rate.
*/
BOOLEAN
STDCALL
KeInsertQueueDpc(PKDPC Dpc,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
KIRQL OldIrql;
PKPCR Pcr;
KIRQL OldIrql;
PKPCR Pcr;
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
Dpc, SystemArgument1, SystemArgument2);
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
Dpc, SystemArgument1, SystemArgument2);
/* Check IRQL and Raise it to HIGH_LEVEL */
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Check if this is a Thread DPC, which we don't support (yet) */
//if (Dpc->Type == KThreadedDpc) {
// return FALSE;
// KeLowerIrql(OldIrql);
//}
/* Check IRQL and Raise it to HIGH_LEVEL */
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Check if this is a Thread DPC, which we don't support (yet) */
if (Dpc->Type == ThreadedDpcObject) {
return FALSE;
KeLowerIrql(OldIrql);
}
#ifdef CONFIG_SMP
/* Get the right PCR for this CPU */
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE);
} else {
ASSERT (Dpc->Number < KeNumberProcessors);
Pcr = KeGetCurrentKPCR();
Dpc->Number = KeGetCurrentProcessorNumber();
}
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
/* Get the right PCR for this CPU */
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE);
} else {
ASSERT (Dpc->Number < KeNumberProcessors);
Pcr = KeGetCurrentKPCR();
Dpc->Number = KeGetCurrentProcessorNumber();
}
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#else
Pcr = (PKPCR)KPCR_BASE;
Pcr = (PKPCR)KPCR_BASE;
#endif
/* Get the DPC Data */
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
DPRINT("DPC Already Inserted");
/* Get the DPC Data */
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) {
DPRINT("DPC Already Inserted");
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
KeLowerIrql(OldIrql);
return(FALSE);
}
/* Make sure the lists are free if the Queue is 0 */
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
} else {
ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
}
KeLowerIrql(OldIrql);
return(FALSE);
}
/* Make sure the lists are free if the Queue is 0 */
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) {
ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
} else {
ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
}
/* Now we can play with the DPC safely */
Dpc->SystemArgument1=SystemArgument1;
Dpc->SystemArgument2=SystemArgument2;
Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
Pcr->PrcbData.DpcData[0].DpcCount++;
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
if (Dpc->Importance == HighImportance) {
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
} else {
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
}
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
/* Now we can play with the DPC safely */
Dpc->SystemArgument1=SystemArgument1;
Dpc->SystemArgument2=SystemArgument2;
Pcr->PrcbData.DpcData[0].DpcQueueDepth++;
Pcr->PrcbData.DpcData[0].DpcCount++;
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */
if (Dpc->Importance == HighImportance) {
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
} else {
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
}
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
/* Make sure a DPC isn't executing already and respect rules outlined above. */
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
#ifdef CONFIG_SMP
/* Check if this is the same CPU */
if (Pcr != KeGetCurrentKPCR()) {
/* Send IPI if High Importance */
if ((Dpc->Importance == HighImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
} else {
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
}
/* Make sure a DPC isn't executing already and respect rules outlined above. */
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) {
#ifdef CONFIG_SMP
/* Check if this is the same CPU */
if (Pcr != KeGetCurrentKPCR()) {
/* Send IPI if High Importance */
if ((Dpc->Importance == HighImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) {
if (Dpc->Number >= MAXIMUM_PROCESSORS) {
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
} else {
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
}
}
} else {
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
}
}
} else {
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
}
#else
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
DPRINT("Requesting Interrupt\n");
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate);
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) {
/* Request Interrupt */
DPRINT("Requesting Interrupt\n");
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
Pcr->PrcbData.DpcInterruptRequested = TRUE;
}
#endif
}
}
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
/* Lower IRQL */
KeLowerIrql(OldIrql);
return(TRUE);
/* Lower IRQL */
KeLowerIrql(OldIrql);
return(TRUE);
}
/*
* @implemented
*/
BOOLEAN STDCALL
KeRemoveQueueDpc (PKDPC Dpc)
/*
*
* FUNCTION:
* Removes DPC object from the system dpc queue
* ARGUMENTS:
@ -281,33 +292,36 @@ KeRemoveQueueDpc (PKDPC Dpc)
* TRUE if the DPC was in the queue
* FALSE otherwise
*/
BOOLEAN
STDCALL
KeRemoveQueueDpc(PKDPC Dpc)
{
BOOLEAN WasInQueue;
KIRQL OldIrql;
/* Raise IRQL */
DPRINT("Removing DPC: %x\n", Dpc);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
BOOLEAN WasInQueue;
KIRQL OldIrql;
/* Raise IRQL */
DPRINT("Removing DPC: %x\n", Dpc);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif
/* First make sure the DPC lock isn't being held */
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
if (Dpc->DpcData) {
/* Remove the DPC */
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
RemoveEntryList(&Dpc->DpcListEntry);
/* First make sure the DPC lock isn't being held */
WasInQueue = Dpc->DpcData ? TRUE : FALSE;
if (Dpc->DpcData) {
/* Remove the DPC */
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
RemoveEntryList(&Dpc->DpcListEntry);
}
}
#ifdef CONFIG_SMP
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif
/* Return if the DPC was in the queue or not */
KeLowerIrql(OldIrql);
return WasInQueue;
/* Return if the DPC was in the queue or not */
KeLowerIrql(OldIrql);
return WasInQueue;
}
/*
@ -323,7 +337,8 @@ KeFlushQueuedDpcs(VOID)
* Called when deleting a Driver.
*/
{
if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
/* Request an interrupt if needed */
if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
/*
@ -332,10 +347,11 @@ KeFlushQueuedDpcs(VOID)
BOOLEAN
STDCALL
KeIsExecutingDpc(
VOID
VOID
)
{
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
/* Return if the Dpc Routine is active */
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive;
}
/*
@ -349,39 +365,41 @@ KeIsExecutingDpc(
*/
VOID
STDCALL
KeSetImportanceDpc (IN PKDPC Dpc,
IN KDPC_IMPORTANCE Importance)
KeSetImportanceDpc (IN PKDPC Dpc,
IN KDPC_IMPORTANCE Importance)
{
Dpc->Importance = Importance;
/* Set the DPC Importance */
Dpc->Importance = Importance;
}
/*
* @implemented
*
* FUNCTION: Specifies on which processor the DPC will run
* ARGUMENTS:
* Dpc = Initalizes DPC
* Number = Processor number
* RETURNS: None
*
* @implemented
*/
VOID STDCALL
KeSetTargetProcessorDpc (IN PKDPC Dpc,
IN CCHAR Number)
VOID
STDCALL
KeSetTargetProcessorDpc(IN PKDPC Dpc,
IN CCHAR Number)
{
if (Number >= MAXIMUM_PROCESSORS)
{
Dpc->Number = 0;
}
else
{
ASSERT(Number < KeNumberProcessors);
Dpc->Number = Number + MAXIMUM_PROCESSORS;
}
/* Check how many CPUs are on the system */
if (Number >= MAXIMUM_PROCESSORS) {
/* No CPU Number */
Dpc->Number = 0;
} else {
/* Set the Number Specified */
ASSERT(Number < KeNumberProcessors);
Dpc->Number = Number + MAXIMUM_PROCESSORS;
}
}
VOID
STDCALL
KiQuantumEnd(VOID)
/*
* FUNCTION:
* Called when a quantum end occurs to check if priority should be changed
@ -389,152 +407,173 @@ KiQuantumEnd(VOID)
* NOTES:
* Called when deleting a Driver.
*/
VOID
STDCALL
KiQuantumEnd(VOID)
{
PKPRCB Prcb;
PKTHREAD CurrentThread;
KIRQL OldIrql;
PKPROCESS Process;
KPRIORITY OldPriority;
KPRIORITY NewPriority;
/* Lock dispatcher, get current thread */
Prcb = &KeGetCurrentKPCR()->PrcbData;
CurrentThread = KeGetCurrentThread();
OldIrql = KeRaiseIrqlToSynchLevel();
/* Get the Thread's Process */
Process = CurrentThread->ApcState.Process;
/* Set DPC Event if requested */
if (Prcb->DpcSetEventRequest) {
KeSetEvent(Prcb->DpcEvent, 0, 0);
}
/* Check if Quantum expired */
if (CurrentThread->Quantum <= 0) {
/* Set the new Quantum */
CurrentThread->Quantum = Process->ThreadQuantum;
/* Calculate new priority */
OldPriority = CurrentThread->Priority;
if (OldPriority < LOW_REALTIME_PRIORITY) {
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
if (NewPriority < CurrentThread->BasePriority) {
NewPriority = CurrentThread->BasePriority;
}
CurrentThread->PriorityDecrement = 0;
if (OldPriority != NewPriority) {
/* Set new Priority */
CurrentThread->Priority = NewPriority;
} else {
/* Queue new thread if none is already */
if (Prcb->NextThread == NULL) {
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
} else {
/* Make the current thread non-premeptive if a new thread is queued */
CurrentThread->Preempted = FALSE;
}
}
} else {
/* Set the Quantum back to Maximum */
//if (CurrentThread->DisableQuantum) {
// CurrentThread->Quantum = MAX_QUANTUM;
//}
}
}
/* Dispatch the Thread */
KeLowerIrql(DISPATCH_LEVEL);
PsDispatchThread(THREAD_STATE_READY);
}
PKPRCB Prcb;
PKTHREAD CurrentThread;
KIRQL OldIrql;
PKPROCESS Process;
KPRIORITY OldPriority;
KPRIORITY NewPriority;
/* Lock dispatcher, get current thread */
Prcb = &KeGetCurrentKPCR()->PrcbData;
CurrentThread = KeGetCurrentThread();
OldIrql = KeRaiseIrqlToSynchLevel();
/* Get the Thread's Process */
Process = CurrentThread->ApcState.Process;
/* Set DPC Event if requested */
if (Prcb->DpcSetEventRequest) {
KeSetEvent(Prcb->DpcEvent, 0, 0);
}
/* Check if Quantum expired */
if (CurrentThread->Quantum <= 0) {
/* Set the new Quantum */
CurrentThread->Quantum = Process->ThreadQuantum;
/* Calculate new priority */
OldPriority = CurrentThread->Priority;
if (OldPriority < LOW_REALTIME_PRIORITY) {
/* Set the New Priority and add the Priority Decrement */
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
/* Don't go out of bounds */
if (NewPriority < CurrentThread->BasePriority) NewPriority = CurrentThread->BasePriority;
/* Reset the priority decrement */
CurrentThread->PriorityDecrement = 0;
/* Set a new priority if needed */
if (OldPriority != NewPriority) {
/* Set new Priority */
CurrentThread->Priority = NewPriority;
} else {
/* Queue new thread if none is already */
if (Prcb->NextThread == NULL) {
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
} else {
/* Make the current thread non-premeptive if a new thread is queued */
CurrentThread->Preempted = FALSE;
}
}
} else {
/* Set the Quantum back to Maximum */
//if (CurrentThread->DisableQuantum) {
// CurrentThread->Quantum = MAX_QUANTUM;
//}
}
}
/* Dispatch the Thread */
KeLowerIrql(DISPATCH_LEVEL);
PsDispatchThread(THREAD_STATE_READY);
}
/*
* @implemented
*/
VOID
STDCALL
KiDispatchInterrupt(VOID)
/*
*
* FUNCTION:
* Called whenever a system interrupt is generated at DISPATCH_LEVEL.
* It delivers queued DPCs and dispatches a new thread if need be.
*/
VOID
STDCALL
KiDispatchInterrupt(VOID)
{
PLIST_ENTRY DpcEntry;
PKDPC Dpc;
KIRQL OldIrql;
PKPCR Pcr;
PLIST_ENTRY DpcEntry;
PKDPC Dpc;
KIRQL OldIrql;
PKPCR Pcr;
DPRINT("Dispatching Interrupts\n");
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
DPRINT("Dispatching Interrupts\n");
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Set DPC Deliver to Active */
Pcr = KeGetCurrentKPCR();
/* Set DPC Deliver to Active */
Pcr = KeGetCurrentKPCR();
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
/* Raise IRQL */
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) {
/* Raise IRQL */
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
Pcr->PrcbData.DpcRoutineActive = TRUE;
Pcr->PrcbData.DpcRoutineActive = TRUE;
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
/* Loop while we have entries */
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
/* Get the DPC call it */
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
Dpc->DpcData = NULL;
Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead);
/* Loop while we have entries */
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) {
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth);
/* Get the DPC call it */
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead);
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
Dpc->DpcData = NULL;
Pcr->PrcbData.DpcData[0].DpcQueueDepth--;
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
/* Disable/Enabled Interrupts and Call the DPC */
KeLowerIrql(OldIrql);
DPRINT("Calling DPC: %x\n", Dpc);
Dpc->DeferredRoutine(Dpc,
Dpc->DeferredContext,
Dpc->SystemArgument1,
Dpc->SystemArgument2);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Disable/Enabled Interrupts and Call the DPC */
KeLowerIrql(OldIrql);
DPRINT("Calling DPC: %x\n", Dpc);
Dpc->DeferredRoutine(Dpc,
Dpc->DeferredContext,
Dpc->SystemArgument1,
Dpc->SystemArgument2);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
/*
* If the dpc routine drops the irql below DISPATCH_LEVEL,
* a thread switch can occur and after the next thread switch
* the execution may start on an other processor.
*/
if (Pcr != KeGetCurrentKPCR()) {
Pcr->PrcbData.DpcRoutineActive = FALSE;
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr = KeGetCurrentKPCR();
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr->PrcbData.DpcRoutineActive = TRUE;
}
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
/*
* If the dpc routine drops the irql below DISPATCH_LEVEL,
* a thread switch can occur and after the next thread switch
* the execution may start on an other processor.
*/
if (Pcr != KeGetCurrentKPCR()) {
Pcr->PrcbData.DpcRoutineActive = FALSE;
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr = KeGetCurrentKPCR();
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
Pcr->PrcbData.DpcRoutineActive = TRUE;
}
#endif
}
/* Clear DPC Flags */
Pcr->PrcbData.DpcRoutineActive = FALSE;
Pcr->PrcbData.DpcInterruptRequested = FALSE;
}
/* Clear DPC Flags */
Pcr->PrcbData.DpcRoutineActive = FALSE;
Pcr->PrcbData.DpcInterruptRequested = FALSE;
#ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock);
#endif
/* DPC Dispatching Ended, re-enable interrupts */
KeLowerIrql(OldIrql);
}
DPRINT("Checking for Quantum End\n");
/* If we have Quantum End, call the function */
if (Pcr->PrcbData.QuantumEnd) {
Pcr->PrcbData.QuantumEnd = FALSE;
KiQuantumEnd();
}
/* DPC Dispatching Ended, re-enable interrupts */
KeLowerIrql(OldIrql);
}
DPRINT("Checking for Quantum End\n");
/* If we have Quantum End, call the function */
if (Pcr->PrcbData.QuantumEnd) {
Pcr->PrcbData.QuantumEnd = FALSE;
KiQuantumEnd();
}
}
/* EOF */

View file

@ -1,98 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/error.c
* PURPOSE: Error reason setting/getting
*
* PROGRAMMERS: David Welch
*/
/* INCLUDE *****************************************************************/
#include <ntoskrnl.h>
#include <internal/debug.h>
/* FUNCTIONS ***************************************************************/
BOOLEAN ExReadyForErrors = FALSE;
PEPORT ExpDefaultErrorPort = NULL;
PEPROCESS ExpDefaultErrorPortProcess = NULL;
/*
* @unimplemented
*/
VOID
STDCALL
KiCoprocessorError(
VOID
)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID
STDCALL
KiUnexpectedInterrupt(
VOID
)
{
UNIMPLEMENTED;
}
NTSTATUS STDCALL
NtRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
IN PVOID *Parameters,
IN HARDERROR_RESPONSE_OPTION ResponseOption,
OUT PHARDERROR_RESPONSE Response)
{
DPRINT1("Hard error %x\n", ErrorStatus);
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
{
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PreviousMode = ExGetPreviousMode();
if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
PreviousMode))
{
DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
/* serialization shouldn't be required here as it usually is just called once
during startup */
if(!ExReadyForErrors)
{
Status = ObReferenceObjectByHandle(PortHandle,
0,
LpcPortObjectType,
PreviousMode,
(PVOID*)&ExpDefaultErrorPort,
NULL);
if(NT_SUCCESS(Status))
{
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
ExReadyForErrors = TRUE;
}
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
return Status;
}
/* EOF */

View file

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

View file

@ -200,7 +200,7 @@ _Ki386ContextSwitch:
*/
sti
call _KeReleaseDispatcherDatabaseLockFromDpcLevel
call @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
cmpl $0, _PiNrThreadsAwaitingReaping
je 5f

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

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

View file

@ -16,245 +16,482 @@
/* FUNCTIONS *****************************************************************/
LONG STDCALL KiInsertQueue(IN PKQUEUE Queue, IN PLIST_ENTRY Entry, BOOLEAN Head);
/*
* @implemented
*/
VOID STDCALL
VOID
STDCALL
KeInitializeQueue(IN PKQUEUE Queue,
IN ULONG Count OPTIONAL)
IN ULONG Count OPTIONAL)
{
KeInitializeDispatcherHeader(&Queue->Header,
InternalQueueType,
sizeof(KQUEUE)/sizeof(ULONG),
0);
InitializeListHead(&Queue->EntryListHead);
InitializeListHead(&Queue->ThreadListHead);
Queue->CurrentCount = 0;
Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
DPRINT("KeInitializeQueue %x\n", Queue);
/* Initialize the Header */
KeInitializeDispatcherHeader(&Queue->Header,
QueueObject,
sizeof(KQUEUE)/sizeof(ULONG),
0);
/* Initialize the Lists */
InitializeListHead(&Queue->EntryListHead);
InitializeListHead(&Queue->ThreadListHead);
/* Set the Current and Maximum Count */
Queue->CurrentCount = 0;
Queue->MaximumCount = (Count == 0) ? (ULONG) KeNumberProcessors : Count;
}
/*
* @implemented
*
* Returns number of entries in the queue
*/
LONG STDCALL
KeReadStateQueue(IN PKQUEUE Queue)
{
return(Queue->Header.SignalState);
}
/*
* Returns the previous number of entries in the queue
*/
LONG STDCALL
KiInsertQueue(
IN PKQUEUE Queue,
IN PLIST_ENTRY Entry,
BOOLEAN Head
)
{
ULONG InitialState;
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
InitialState = Queue->Header.SignalState;
if (Head)
{
InsertHeadList(&Queue->EntryListHead, Entry);
}
else
{
InsertTailList(&Queue->EntryListHead, Entry);
}
//inc. num entries in queue
Queue->Header.SignalState++;
/* Why the KeGetCurrentThread()->Queue != Queue?
* KiInsertQueue might be called from an APC for the current thread.
* -Gunnar
*/
if (Queue->CurrentCount < Queue->MaximumCount &&
!IsListEmpty(&Queue->Header.WaitListHead) &&
KeGetCurrentThread()->Queue != Queue)
{
KiDispatcherObjectWake(&Queue->Header, IO_NO_INCREMENT);
}
return InitialState;
}
/*
* @implemented
*/
LONG STDCALL
LONG
STDCALL
KeInsertHeadQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
IN PLIST_ENTRY Entry)
{
LONG Result;
KIRQL OldIrql;
LONG PreviousState;
KIRQL OldIrql;
DPRINT("KeInsertHeadQueue %x\n", Queue);
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Insert the Queue */
PreviousState = KiInsertQueue(Queue, Entry, TRUE);
/* Release the Dispatcher Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
OldIrql = KeAcquireDispatcherDatabaseLock();
Result = KiInsertQueue(Queue,Entry,TRUE);
KeReleaseDispatcherDatabaseLock(OldIrql);
return Result;
/* Return previous State */
return PreviousState;
}
/*
* @implemented
*/
LONG STDCALL
KeInsertQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry)
IN PLIST_ENTRY Entry)
{
LONG Result;
KIRQL OldIrql;
LONG PreviousState;
KIRQL OldIrql;
DPRINT("KeInsertQueue %x\n", Queue);
/* Lock the Dispatcher Database */
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Insert the Queue */
PreviousState = KiInsertQueue(Queue, Entry, FALSE);
/* Release the Dispatcher Lock */
KeReleaseDispatcherDatabaseLock(OldIrql);
OldIrql = KeAcquireDispatcherDatabaseLock();
Result = KiInsertQueue(Queue,Entry,FALSE);
KeReleaseDispatcherDatabaseLock(OldIrql);
return Result;
/* Return previous State */
return PreviousState;
}
/*
* @implemented
*
* Returns number of entries in the queue
*/
LONG
STDCALL
KeReadStateQueue(IN PKQUEUE Queue)
{
/* Returns the Signal State */
return(Queue->Header.SignalState);
}
/*
* @implemented
*/
PLIST_ENTRY STDCALL
PLIST_ENTRY
STDCALL
KeRemoveQueue(IN PKQUEUE Queue,
IN KPROCESSOR_MODE WaitMode,
IN PLARGE_INTEGER Timeout OPTIONAL)
IN KPROCESSOR_MODE WaitMode,
IN PLARGE_INTEGER Timeout OPTIONAL)
{
PLIST_ENTRY ListEntry;
NTSTATUS Status;
PKTHREAD Thread = KeGetCurrentThread();
KIRQL OldIrql;
PLIST_ENTRY ListEntry;
NTSTATUS Status;
PKTHREAD Thread = KeGetCurrentThread();
KIRQL OldIrql;
PKQUEUE PreviousQueue;
PKWAIT_BLOCK WaitBlock;
PKWAIT_BLOCK TimerWaitBlock;
PKTIMER Timer;
OldIrql = KeAcquireDispatcherDatabaseLock ();
DPRINT("KeRemoveQueue %x\n", Queue);
/* Check if the Lock is already held */
if (Thread->WaitNext) {
DPRINT("Lock is already held\n");
} else {
/* Lock the Dispatcher Database */
DPRINT("Lock not held, acquiring\n");
OldIrql = KeAcquireDispatcherDatabaseLock();
Thread->WaitIrql = OldIrql;
}
if (Thread->Queue != Queue)
{
/*
* INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
* Queue->ThreadListHead when the thread registers with the queue and unlinked when
* the thread registers with a new queue. The Thread->Queue already tells us what
* queue the thread is registered with.
* -Gunnar
*/
/* This is needed so that we can set the new queue right here, before additional processing */
PreviousQueue = Thread->Queue;
Thread->Queue = Queue;
//unregister thread from previous queue (if any)
if (Thread->Queue)
{
RemoveEntryList(&Thread->QueueListEntry);
Thread->Queue->CurrentCount--;
if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount &&
!IsListEmpty(&Thread->Queue->EntryListHead))
{
KiDispatcherObjectWake(&Thread->Queue->Header, 0);
}
/* Check if this is a different queue */
if (Queue != PreviousQueue) {
/*
* INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
* Queue->ThreadListHead when the thread registers with the queue and unlinked when
* the thread registers with a new queue. The Thread->Queue already tells us what
* queue the thread is registered with.
* -Gunnar
*/
DPRINT("Different Queue\n");
if (PreviousQueue) {
/* Remove from this list */
DPRINT("Removing Old Queue\n");
RemoveEntryList(&Thread->QueueListEntry);
/* Wake the queue */
DPRINT("Activating new thread\n");
KiWakeQueue(PreviousQueue);
}
// register thread with this queue
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
Thread->Queue = Queue;
}
else /* if (Thread->Queue == Queue) */
{
//dec. num running threads
Queue->CurrentCount--;
}
/* Insert in this new Queue */
DPRINT("Inserting new Queue!\n");
InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
while (TRUE)
{
if (Queue->CurrentCount < Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
{
ListEntry = RemoveHeadList(&Queue->EntryListHead);
//dec. num entries in queue
Queue->Header.SignalState--;
//inc. num running threads
Queue->CurrentCount++;
KeReleaseDispatcherDatabaseLock(OldIrql);
return ListEntry;
}
else
{
//inform KeWaitXxx that we are holding disp. lock
Thread->WaitNext = TRUE;
Thread->WaitIrql = OldIrql;
} else {
/* Same queue, decrement waiting threads */
DPRINT("Same Queue!\n");
Queue->CurrentCount--;
}
/* Loop until the queue is processed */
while (TRUE) {
/* Get the Entry */
ListEntry = Queue->EntryListHead.Flink;
/* Check if the counts are valid and if there is still a queued entry */
if ((Queue->CurrentCount < Queue->MaximumCount) &&
(ListEntry != &Queue->EntryListHead)) {
/* Remove the Entry and Save it */
DPRINT("Removing Queue Entry. CurrentCount: %d, Maximum Count: %d\n",
Queue->CurrentCount, Queue->MaximumCount);
ListEntry = RemoveHeadList(&Queue->EntryListHead);
/* Decrease the number of entries */
Queue->Header.SignalState--;
/* Increase numbef of running threads */
Queue->CurrentCount++;
/* Check if the entry is valid. If not, bugcheck */
if (!ListEntry->Flink || !ListEntry->Blink) {
KEBUGCHECK(INVALID_WORK_QUEUE_ITEM);
}
/* Remove the Entry */
RemoveEntryList(ListEntry);
/* Nothing to wait on */
break;
} else {
/* Do the wait */
DPRINT("Waiting on Queue Entry. CurrentCount: %d, Maximum Count: %d\n",
Queue->CurrentCount, Queue->MaximumCount);
/* Use the Thread's Wait Block, it's big enough */
Thread->WaitBlockList = &Thread->WaitBlock[0];
/* Fail if there's an APC Pending */
if (WaitMode == UserMode && Thread->ApcState.UserApcPending) {
/* Return the status and increase the pending threads */
ListEntry = (PLIST_ENTRY)STATUS_USER_APC;
Queue->CurrentCount++;
/* Nothing to wait on */
break;
}
/* Build the Wait Block */
WaitBlock = &Thread->WaitBlock[0];
WaitBlock->Object = (PVOID)Queue;
WaitBlock->WaitKey = STATUS_SUCCESS;
WaitBlock->WaitType = WaitAny;
WaitBlock->Thread = Thread;
WaitBlock->NextWaitBlock = NULL;
Thread->WaitStatus = STATUS_SUCCESS;
/* We need to wait for the object... check if we have a timeout */
if (Timeout) {
/* If it's zero, then don't do any waiting */
if (!Timeout->QuadPart) {
/* Instant Timeout, return the status and increase the pending threads */
DPRINT("Queue Wait has timed out\n");
ListEntry = (PLIST_ENTRY)STATUS_TIMEOUT;
Queue->CurrentCount++;
/* Nothing to wait on */
break;
}
/*
* Set up the Timer. We'll use the internal function so that we can
* hold on to the dispatcher lock.
*/
Timer = &Thread->Timer;
TimerWaitBlock = &Thread->WaitBlock[1];
Status = KeWaitForSingleObject(Queue,
WrQueue,
WaitMode,
TRUE, //bAlertable
Timeout);
if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
{
return (PVOID)Status;
}
OldIrql = KeAcquireDispatcherDatabaseLock ();
}
}
/* Set up the Timer Wait Block */
TimerWaitBlock->Object = (PVOID)Timer;
TimerWaitBlock->Thread = Thread;
TimerWaitBlock->WaitKey = STATUS_TIMEOUT;
TimerWaitBlock->WaitType = WaitAny;
TimerWaitBlock->NextWaitBlock = NULL;
/* Link the timer to this Wait Block */
InitializeListHead(&Timer->Header.WaitListHead);
InsertTailList(&Timer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
/* Create Timer */
DPRINT("Creating Timer with timeout %I64d\n", *Timeout);
KiInsertTimer(Timer, *Timeout);
}
/* Insert the wait block into the Queues's wait list */
WaitBlock = Thread->WaitBlockList;
InsertTailList(&Queue->Header.WaitListHead, &WaitBlock->WaitListEntry);
/* Block the Thread */
DPRINT("Blocking the Thread: %x %x!\n", KeGetCurrentThread(), Thread);
PsBlockThread(&Status,
FALSE,
WaitMode,
WrQueue);
/* Reset the wait reason */
Thread->WaitReason = 0;
/* Check if we were executing an APC */
if (Status != STATUS_KERNEL_APC) {
/* Done Waiting */
DPRINT("Done waking queue. Thread: %x %x!\n", KeGetCurrentThread(), Thread);
return (PLIST_ENTRY)Status;
}
/* Acquire again the lock */
DPRINT("Looping again\n");
OldIrql = KeAcquireDispatcherDatabaseLock();
/* Save the new IRQL and decrease number of waiting threads */
Thread->WaitIrql = OldIrql;
Queue->CurrentCount--;
}
}
/* Unlock Database and return */
KeReleaseDispatcherDatabaseLock(Thread->WaitIrql);
DPRINT("Returning. CurrentCount: %d, Maximum Count: %d\n",
Queue->CurrentCount, Queue->MaximumCount);
return ListEntry;
}
/*
* @implemented
*/
PLIST_ENTRY STDCALL
PLIST_ENTRY
STDCALL
KeRundownQueue(IN PKQUEUE Queue)
{
PLIST_ENTRY EnumEntry;
PKTHREAD Thread;
KIRQL OldIrql;
PLIST_ENTRY EnumEntry;
PLIST_ENTRY FirstEntry;
PKTHREAD Thread;
KIRQL OldIrql;
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
DPRINT("KeRundownQueue(Queue %x)\n", Queue);
/* I'm just guessing how this should work:-/
* -Gunnar
*/
OldIrql = KeAcquireDispatcherDatabaseLock ();
/* Get the Dispatcher Lock */
OldIrql = KeAcquireDispatcherDatabaseLock();
//no thread must wait on queue at rundown
ASSERT(IsListEmpty(&Queue->Header.WaitListHead));
/* Get the First Empty Entry */
FirstEntry = Queue->EntryListHead.Flink;
/* Make sure the list is not empty */
if (FirstEntry == &Queue->EntryListHead) {
/* It is, so don't return anything */
EnumEntry = NULL;
// unlink threads and clear their Thread->Queue
while (!IsListEmpty(&Queue->ThreadListHead))
{
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
Thread->Queue = NULL;
}
} else {
/* Remove it */
RemoveEntryList(&Queue->EntryListHead);
}
/* Unlink threads and clear their Thread->Queue */
while (!IsListEmpty(&Queue->ThreadListHead)) {
/* Get the Entry and Remove it */
EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
/* Get the Entry's Thread */
Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
/* Kill its Queue */
Thread->Queue = NULL;
}
if (IsListEmpty(&Queue->EntryListHead))
{
EnumEntry = NULL;
}
else
{
EnumEntry = Queue->EntryListHead.Flink;
}
/* Release the lock and return */
KeReleaseDispatcherDatabaseLock(OldIrql);
return FirstEntry;
}
KeReleaseDispatcherDatabaseLock (OldIrql);
/*
* Called when a thread which has a queue entry is entering a wait state
*/
VOID
FASTCALL
KiWakeQueue(IN PKQUEUE Queue)
{
PLIST_ENTRY QueueEntry;
PLIST_ENTRY WaitEntry;
PKWAIT_BLOCK WaitBlock;
/* Decrement the number of active threads */
DPRINT("KiWakeQueue: %x. Thread: %x\n", Queue, KeGetCurrentThread());
Queue->CurrentCount--;
/* Make sure the counts are OK */
if (Queue->CurrentCount < Queue->MaximumCount) {
/* Get the Queue Entry */
QueueEntry = Queue->EntryListHead.Flink;
/* Get the Wait Entry */
WaitEntry = Queue->Header.WaitListHead.Blink;
DPRINT("Queue Count is ok, Queue entries: %x, %x\n", QueueEntry, WaitEntry);
/* Make sure that the Queue List isn't empty and that this entry is valid */
if (!IsListEmpty(&Queue->Header.WaitListHead) &&
(QueueEntry != &Queue->EntryListHead)) {
/* Remove this entry */
DPRINT("Queue in List, removing it\n");
RemoveEntryList(QueueEntry);
QueueEntry->Flink = NULL;
/* Decrease the Signal State */
Queue->Header.SignalState--;
/* Unwait the Thread */
DPRINT("Unwaiting Thread\n");
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
KiAbortWaitThread(WaitBlock->Thread, (NTSTATUS)QueueEntry);
}
}
}
return EnumEntry;
/*
* Returns the previous number of entries in the queue
*/
LONG
STDCALL
KiInsertQueue(IN PKQUEUE Queue,
IN PLIST_ENTRY Entry,
BOOLEAN Head)
{
ULONG InitialState;
PKTHREAD Thread = KeGetCurrentThread();
PKWAIT_BLOCK WaitBlock;
PLIST_ENTRY WaitEntry;
DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
/* Save the old state */
InitialState = Queue->Header.SignalState;
/* Get the Entry */
WaitEntry = Queue->Header.WaitListHead.Blink;
DPRINT("Initial State, WaitEntry: %d, %x\n", InitialState, WaitEntry);
/*
* Why the KeGetCurrentThread()->Queue != Queue?
* KiInsertQueue might be called from an APC for the current thread.
* -Gunnar
*/
if ((Queue->CurrentCount < Queue->MaximumCount) &&
(WaitEntry != &Queue->Header.WaitListHead) &&
((Thread->Queue != Queue) || (Thread->WaitReason != WrQueue))) {
/* Remove the wait entry */
DPRINT("Removing Entry\n");
RemoveEntryList(WaitEntry);
/* Get the Wait Block and Thread */
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
DPRINT("Got wait block: %x\n", WaitBlock);
Thread = WaitBlock->Thread;
/* Reset the wait reason */
Thread->WaitReason = 0;
/* Increase the waiting threads */
Queue->CurrentCount++;
/* Check if there's a Thread Timer */
if (Thread->Timer.Header.Inserted) {
/* Cancel the Thread Timer with the no-lock fastpath */
DPRINT("Removing the Thread's Timer\n");
Thread->Timer.Header.Inserted = FALSE;
RemoveEntryList(&Thread->Timer.TimerListEntry);
}
/* Reschedule the Thread */
DPRINT("Unblocking the Thread\n");
PsUnblockThread((PETHREAD)Thread, (PNTSTATUS)&Entry, 0);
} else {
/* Increase the Entries */
DPRINT("Adding new Queue Entry: %d %d\n", Head, Queue->Header.SignalState);
Queue->Header.SignalState++;
if (Head) {
InsertHeadList(&Queue->EntryListHead, Entry);
} else {
InsertTailList(&Queue->EntryListHead, Entry);
}
}
/* Return the previous state */
DPRINT("Returning\n");
return InitialState;
}
/* EOF */

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -122,7 +122,6 @@ ExIsResourceAcquiredExclusiveLite@4
ExIsResourceAcquiredSharedLite@4
ExLocalTimeToSystemTime@8
ExNotifyCallback@12
ExPostSystemEvent@12
ExQueryPoolBlockSize@8
ExQueueWorkItem@8
ExRaiseAccessViolation@0
@ -530,7 +529,7 @@ Ke386IoSetAccessProcess@8
Ke386QueryIoAccessMap@8
Ke386SetIoAccessMap@8
KeAcquireSpinLockAtDpcLevel@4
KeAcquireDispatcherDatabaseLockAtDpcLevel
@KeAcquireDispatcherDatabaseLockAtDpcLevel@0
@KeAcquireInStackQueuedSpinLockAtDpcLevel@8
KeAcquireInterruptSpinLock@4
KeAddSystemServiceTable@20
@ -611,7 +610,7 @@ KeReadStateSemaphore@4
KeReadStateTimer@4
KeRegisterBugCheckCallback@20
KeRegisterBugCheckReasonCallback@16
KeReleaseDispatcherDatabaseLockFromDpcLevel
@KeReleaseDispatcherDatabaseLockFromDpcLevel@0
@KeReleaseInStackQueuedSpinLockFromDpcLevel@4
KeReleaseInterruptSpinLock@8
KeReleaseMutant@16

View file

@ -987,6 +987,22 @@ Language=English
INVALID_WORK_QUEUE_ITEM
.
MessageId=0xE1
Severity=Success
Facility=System
SymbolicName=WORKER_THREAD_RETURNED_AT_BAD_IRQL
Language=English
WORKER_THREAD_RETURNED_AT_BAD_IRQL
.
MessageId=0xFA
Severity=Success
Facility=System
SymbolicName=IMPERSONATING_WORKER_THREAD
Language=English
IMPERSONATING_WORKER_THREAD
.
MessageId=0x9A
Severity=Informational
Facility=System

300
reactos/ntoskrnl/ob/wait.c Normal file
View file

@ -0,0 +1,300 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ob/wait.c
* PURPOSE: Handles Waiting on Objects
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created file
* David Welch (welch@mcmail.com)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS *****************************************************************/
BOOL inline FASTCALL KiIsObjectWaitable(PVOID Object);
NTSTATUS STDCALL
NtWaitForMultipleObjects(IN ULONG ObjectCount,
IN PHANDLE ObjectsArray,
IN WAIT_TYPE WaitType,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER TimeOut OPTIONAL)
{
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
HANDLE SafeObjectsArray[MAXIMUM_WAIT_OBJECTS];
PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
ULONG i, j;
KPROCESSOR_MODE PreviousMode;
LARGE_INTEGER SafeTimeOut;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
"TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
PreviousMode = ExGetPreviousMode();
if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
return STATUS_UNSUCCESSFUL;
if (0 == ObjectCount)
return STATUS_INVALID_PARAMETER;
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForRead(ObjectsArray,
ObjectCount * sizeof(ObjectsArray[0]),
sizeof(ULONG));
/* make a copy so we don't have to guard with SEH later and keep track of
what objects we referenced in case dereferencing pointers suddenly fails */
RtlCopyMemory(SafeObjectsArray, ObjectsArray, ObjectCount * sizeof(ObjectsArray[0]));
ObjectsArray = SafeObjectsArray;
if(TimeOut != NULL)
{
ProbeForRead(TimeOut,
sizeof(LARGE_INTEGER),
sizeof(ULONG));
/* make a local copy of the timeout on the stack */
SafeTimeOut = *TimeOut;
TimeOut = &SafeTimeOut;
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
/* reference all objects */
for (i = 0; i < ObjectCount; i++)
{
Status = ObReferenceObjectByHandle(ObjectsArray[i],
SYNCHRONIZE,
NULL,
PreviousMode,
&ObjectPtrArray[i],
NULL);
if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i]))
{
if (NT_SUCCESS(Status))
{
DPRINT1("Waiting for object type '%wZ' is not supported\n",
&BODY_TO_HEADER(ObjectPtrArray[i])->ObjectType->TypeName);
Status = STATUS_HANDLE_NOT_WAITABLE;
i++;
}
/* dereference all referenced objects */
for (j = 0; j < i; j++)
{
ObDereferenceObject(ObjectPtrArray[j]);
}
return(Status);
}
}
Status = KeWaitForMultipleObjects(ObjectCount,
ObjectPtrArray,
WaitType,
UserRequest,
PreviousMode,
Alertable,
TimeOut,
WaitBlockArray);
/* dereference all objects */
for (i = 0; i < ObjectCount; i++)
{
ObDereferenceObject(ObjectPtrArray[i]);
}
return(Status);
}
/*
* @implemented
*/
NTSTATUS STDCALL
NtWaitForSingleObject(IN HANDLE ObjectHandle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER TimeOut OPTIONAL)
{
PVOID ObjectPtr;
KPROCESSOR_MODE PreviousMode;
LARGE_INTEGER SafeTimeOut;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
ObjectHandle,Alertable,TimeOut);
PreviousMode = ExGetPreviousMode();
if(TimeOut != NULL && PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForRead(TimeOut,
sizeof(LARGE_INTEGER),
sizeof(ULONG));
/* make a copy on the stack */
SafeTimeOut = *TimeOut;
TimeOut = &SafeTimeOut;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(ObjectHandle,
SYNCHRONIZE,
NULL,
PreviousMode,
&ObjectPtr,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
if (!KiIsObjectWaitable(ObjectPtr))
{
DPRINT1("Waiting for object type '%wZ' is not supported\n",
&BODY_TO_HEADER(ObjectPtr)->ObjectType->TypeName);
Status = STATUS_HANDLE_NOT_WAITABLE;
}
else
{
Status = KeWaitForSingleObject(ObjectPtr,
UserRequest,
PreviousMode,
Alertable,
TimeOut);
}
ObDereferenceObject(ObjectPtr);
return(Status);
}
NTSTATUS STDCALL
NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
IN HANDLE WaitableObjectHandle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER TimeOut OPTIONAL)
{
KPROCESSOR_MODE PreviousMode;
DISPATCHER_HEADER* hdr;
PVOID SignalObj;
PVOID WaitObj;
LARGE_INTEGER SafeTimeOut;
NTSTATUS Status = STATUS_SUCCESS;
PreviousMode = ExGetPreviousMode();
if(TimeOut != NULL && PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForRead(TimeOut,
sizeof(LARGE_INTEGER),
sizeof(ULONG));
/* make a copy on the stack */
SafeTimeOut = *TimeOut;
TimeOut = &SafeTimeOut;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
0,
NULL,
PreviousMode,
&SignalObj,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = ObReferenceObjectByHandle(WaitableObjectHandle,
SYNCHRONIZE,
NULL,
PreviousMode,
&WaitObj,
NULL);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(SignalObj);
return Status;
}
hdr = (DISPATCHER_HEADER *)SignalObj;
switch (hdr->Type)
{
case EventNotificationObject:
case EventSynchronizationObject:
KeSetEvent(SignalObj,
EVENT_INCREMENT,
TRUE);
break;
case MutantObject:
KeReleaseMutex(SignalObj,
TRUE);
break;
case SemaphoreObject:
KeReleaseSemaphore(SignalObj,
SEMAPHORE_INCREMENT,
1,
TRUE);
break;
default:
ObDereferenceObject(SignalObj);
ObDereferenceObject(WaitObj);
return STATUS_OBJECT_TYPE_MISMATCH;
}
Status = KeWaitForSingleObject(WaitObj,
UserRequest,
PreviousMode,
Alertable,
TimeOut);
ObDereferenceObject(SignalObj);
ObDereferenceObject(WaitObj);
return Status;
}
/* EOF */

View file

@ -204,7 +204,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
oldIrql = KeAcquireDispatcherDatabaseLock();
CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
KiDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
KiWaitTest(&CurrentThread->Tcb.DispatcherHeader, IO_NO_INCREMENT);
KeReleaseDispatcherDatabaseLock (oldIrql);
/* The last thread shall close the door on exit */
@ -331,7 +331,7 @@ PiTerminateProcess(PEPROCESS Process,
}
OldIrql = KeAcquireDispatcherDatabaseLock ();
Process->Pcb.DispatcherHeader.SignalState = TRUE;
KiDispatcherObjectWake(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
KiWaitTest(&Process->Pcb.DispatcherHeader, IO_NO_INCREMENT);
KeReleaseDispatcherDatabaseLock (OldIrql);
ObDereferenceObject(Process);
return(STATUS_SUCCESS);

View file

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

View file

@ -437,6 +437,7 @@ VOID PsDispatchThreadNoLock (ULONG NewThreadStatus)
OldThread = CurrentThread;
CurrentThread = Candidate;
IdleThread = KeGetCurrentKPCR()->PrcbData.IdleThread;
if (&OldThread->Tcb == IdleThread)
@ -545,49 +546,46 @@ PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment)
}
VOID
PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode,
BOOLEAN DispatcherLock, KIRQL WaitIrql, UCHAR WaitReason)
STDCALL
PsBlockThread(PNTSTATUS Status,
UCHAR Alertable,
ULONG WaitMode,
UCHAR WaitReason)
{
KIRQL oldIrql;
PKTHREAD KThread;
PETHREAD Thread;
PKWAIT_BLOCK WaitBlock;
PKTHREAD Thread = KeGetCurrentThread();
PKWAIT_BLOCK WaitBlock;
if (!DispatcherLock)
{
oldIrql = KeAcquireDispatcherDatabaseLock();
if (Thread->ApcState.KernelApcPending) {
DPRINT("Dispatching Thread as ready (APC!)\n");
/* Remove Waits */
WaitBlock = Thread->WaitBlockList;
while (WaitBlock) {
RemoveEntryList (&WaitBlock->WaitListEntry);
WaitBlock = WaitBlock->NextWaitBlock;
}
Thread->WaitBlockList = NULL;
/* Dispatch it and return status */
PsDispatchThreadNoLock (THREAD_STATE_READY);
if (Status != NULL) *Status = STATUS_KERNEL_APC;
} else {
/* Set the Thread Data as Requested */
DPRINT("Dispatching Thread as blocked\n");
Thread->Alertable = Alertable;
Thread->WaitMode = (UCHAR)WaitMode;
Thread->WaitReason = WaitReason;
/* Dispatch it and return status */
PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
if (Status != NULL) *Status = Thread->WaitStatus;
}
KThread = KeGetCurrentThread();
Thread = CONTAINING_RECORD (KThread, ETHREAD, Tcb);
if (KThread->ApcState.KernelApcPending)
{
WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
while (WaitBlock)
{
RemoveEntryList (&WaitBlock->WaitListEntry);
WaitBlock = WaitBlock->NextWaitBlock;
}
Thread->Tcb.WaitBlockList = NULL;
PsDispatchThreadNoLock (THREAD_STATE_READY);
if (Status != NULL)
{
*Status = STATUS_KERNEL_APC;
}
}
else
{
Thread->Tcb.Alertable = Alertable;
Thread->Tcb.WaitMode = (UCHAR)WaitMode;
Thread->Tcb.WaitReason = WaitReason;
PsDispatchThreadNoLock(THREAD_STATE_BLOCKED);
if (Status != NULL)
{
*Status = Thread->Tcb.WaitStatus;
}
}
KeLowerIrql(WaitIrql);
DPRINT("Releasing Dispatcher Lock\n");
KfLowerIrql(Thread->WaitIrql);
}
VOID
@ -1054,6 +1052,16 @@ NtYieldExecution(VOID)
return(STATUS_SUCCESS);
}
/*
* NOT EXPORTED
*/
NTSTATUS
STDCALL
NtTestAlert(VOID)
{
/* Check and Alert Thread if needed */
return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
}
/*
* @implemented

View file

@ -36,7 +36,32 @@ ULONG NlsUnicodeTableOffset = 0;
/* FUNCTIONS *****************************************************************/
VOID
INIT_FUNCTION
STDCALL
RtlpInitNls(VOID)
{
ULONG_PTR BaseAddress;
/* Import NLS Data */
BaseAddress = CachedModules[AnsiCodepage]->ModStart;
RtlpImportAnsiCodePage((PUSHORT)BaseAddress,
CachedModules[AnsiCodepage]->ModEnd - BaseAddress);
BaseAddress = CachedModules[OemCodepage]->ModStart;
RtlpImportOemCodePage((PUSHORT)BaseAddress,
CachedModules[OemCodepage]->ModEnd - BaseAddress);
BaseAddress = CachedModules[UnicodeCasemap]->ModStart;
RtlpImportUnicodeCasemap((PUSHORT)BaseAddress,
CachedModules[UnicodeCasemap]->ModEnd - BaseAddress);
/* Create initial NLS tables */
RtlpCreateInitialNlsTables();
/* Create the NLS section */
RtlpCreateNlsSection();
}
VOID INIT_FUNCTION
RtlpImportAnsiCodePage(PUSHORT TableBase,

View file

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