/*
- * ReactOS kernel
- * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
+ * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/nt/event.c
* PURPOSE: Named event support
- * PROGRAMMER: Philip Susi and David Welch
- * UPDATE HISTORY:
- * Created 22/05/98
+ *
+ * PROGRAMMERS: Alex Ionescu(alex@relsoft.net) - Fixed bugs/commented
+ * Philip Susi and David Welch
*/
/* INCLUDES *****************************************************************/
POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
static GENERIC_MAPPING ExpEventMapping = {
- STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
- STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
- STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
- EVENT_ALL_ACCESS};
+ STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
+ STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
+ STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
+ EVENT_ALL_ACCESS};
+
+static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
+ /* EventBasicInformation */
+ ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
+};
/* FUNCTIONS *****************************************************************/
-NTSTATUS STDCALL
-NtpCreateEvent(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes)
+VOID
+INIT_FUNCTION
+STDCALL
+ExpInitializeEventImplementation(VOID)
{
- DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
- ObjectBody, Parent, RemainingPath);
+ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+ UNICODE_STRING Name;
+
+ DPRINT("Creating Event Object Type\n");
+
+ /* Create the Event Object Type */
+ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+ RtlInitUnicodeString(&Name, L"Event");
+ ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+ ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT);
+ ObjectTypeInitializer.GenericMapping = ExpEventMapping;
+ ObjectTypeInitializer.PoolType = NonPagedPool;
+ ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS;
+ ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExEventObjectType);
+}
- if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
- {
- return(STATUS_UNSUCCESSFUL);
- }
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
+NtClearEvent(IN HANDLE EventHandle)
+{
+ PKEVENT Event;
+ NTSTATUS Status;
- return(STATUS_SUCCESS);
-}
+ PAGED_CODE();
+ /* Reference the Object */
+ Status = ObReferenceObjectByHandle(EventHandle,
+ EVENT_MODIFY_STATE,
+ ExEventObjectType,
+ ExGetPreviousMode(),
+ (PVOID*)&Event,
+ NULL);
-VOID INIT_FUNCTION
-ExpInitializeEventImplementation(VOID)
-{
- ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
-
- RtlCreateUnicodeString(&ExEventObjectType->TypeName, L"Event");
-
- 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);
-}
+ /* Check for Success */
+ if(NT_SUCCESS(Status)) {
+ /* Clear the Event and Dereference */
+ KeClearEvent(Event);
+ ObDereferenceObject(Event);
+ }
-NTSTATUS STDCALL
-NtClearEvent(IN HANDLE EventHandle)
-{
- PKEVENT Event;
- NTSTATUS Status;
-
- Status = ObReferenceObjectByHandle(EventHandle,
- EVENT_MODIFY_STATE,
- ExEventObjectType,
- UserMode,
- (PVOID*)&Event,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- KeClearEvent(Event);
- ObDereferenceObject(Event);
- return(STATUS_SUCCESS);
+ /* Return Status */
+ return Status;
}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+STDCALL
NtCreateEvent(OUT PHANDLE EventHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
- IN EVENT_TYPE EventType,
- IN BOOLEAN InitialState)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN EVENT_TYPE EventType,
+ IN BOOLEAN InitialState)
{
- PKEVENT Event;
- HANDLE hEvent;
- NTSTATUS Status;
- OBJECT_ATTRIBUTES SafeObjectAttributes;
-
- if (ObjectAttributes != NULL)
- {
- Status = MmCopyFromCaller(&SafeObjectAttributes, ObjectAttributes,
- sizeof(OBJECT_ATTRIBUTES));
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- ObjectAttributes = &SafeObjectAttributes;
- }
-
- Status = ObCreateObject(ExGetPreviousMode(),
- ExEventObjectType,
- ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(KEVENT),
- 0,
- 0,
- (PVOID*)&Event);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- KeInitializeEvent(Event,
- EventType,
- InitialState);
-
- Status = ObInsertObject ((PVOID)Event,
- NULL,
- DesiredAccess,
- 0,
- NULL,
- &hEvent);
- ObDereferenceObject(Event);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Status = MmCopyToCaller(EventHandle, &hEvent, sizeof(HANDLE));
- if (!NT_SUCCESS(Status))
- {
- ZwClose(hEvent);
- return(Status);
- }
- return(STATUS_SUCCESS);
-}
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PKEVENT Event;
+ HANDLE hEvent;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+ DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n", EventHandle, DesiredAccess, ObjectAttributes);
+
+ /* Check Output Safety */
+ if(PreviousMode != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWriteHandle(EventHandle);
+ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ 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);
-NTSTATUS STDCALL
+ /* Check for success and return handle */
+ if(NT_SUCCESS(Status)) {
+
+ _SEH_TRY {
+
+ *EventHandle = hEvent;
+
+ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ Status = _SEH_GetExceptionCode();
+
+ } _SEH_END;
+ }
+ }
+
+ /* Return Status */
+ return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
NtOpenEvent(OUT PHANDLE EventHandle,
- IN ACCESS_MASK DesiredAccess,
- IN POBJECT_ATTRIBUTES ObjectAttributes)
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
{
- NTSTATUS Status;
- HANDLE hEvent;
-
- DPRINT("ObjectName '%wZ'\n", ObjectAttributes->ObjectName);
-
- Status = ObOpenObjectByName(ObjectAttributes,
- ExEventObjectType,
- NULL,
- UserMode,
- DesiredAccess,
- NULL,
- &hEvent);
-
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- Status = MmCopyToCaller(EventHandle, &hEvent, sizeof(HANDLE));
- if (!NT_SUCCESS(Status))
- {
- ZwClose(EventHandle);
- return(Status);
- }
-
- return(Status);
-}
+ HANDLE hEvent;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+ DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n", EventHandle, DesiredAccess, ObjectAttributes);
+
+ /* Check Output Safety */
+ if(PreviousMode != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWriteHandle(EventHandle);
+ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ Status = _SEH_GetExceptionCode();
+ } _SEH_END;
-NTSTATUS STDCALL
+ 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_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ Status = _SEH_GetExceptionCode();
+
+ } _SEH_END;
+ }
+
+ /* Return status */
+ return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
NtPulseEvent(IN HANDLE EventHandle,
- OUT PLONG PreviousState OPTIONAL)
+ OUT PLONG PreviousState OPTIONAL)
{
- PKEVENT Event;
- NTSTATUS Status;
-
- DPRINT("NtPulseEvent(EventHandle %x PreviousState %x)\n",
- EventHandle, PreviousState);
-
- Status = ObReferenceObjectByHandle(EventHandle,
- EVENT_MODIFY_STATE,
- ExEventObjectType,
- UserMode,
- (PVOID*)&Event,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- KePulseEvent(Event, EVENT_INCREMENT, FALSE);
-
- ObDereferenceObject(Event);
- return(STATUS_SUCCESS);
+ 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 != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWriteLong(PreviousState);
+ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ 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_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ Status = _SEH_GetExceptionCode();
+
+ } _SEH_END;
+ }
+ }
+
+ /* Return Status */
+ return Status;
}
-NTSTATUS STDCALL
+/*
+ * @implemented
+ */
+NTSTATUS
+STDCALL
NtQueryEvent(IN HANDLE EventHandle,
- IN EVENT_INFORMATION_CLASS EventInformationClass,
- OUT PVOID EventInformation,
- IN ULONG EventInformationLength,
- OUT PULONG ReturnLength OPTIONAL)
+ IN EVENT_INFORMATION_CLASS EventInformationClass,
+ OUT PVOID EventInformation,
+ IN ULONG EventInformationLength,
+ OUT PULONG ReturnLength OPTIONAL)
{
- EVENT_BASIC_INFORMATION Info;
- PKEVENT Event;
- NTSTATUS Status;
- ULONG RetLen;
-
- if (EventInformationClass > EventBasicInformation)
- return STATUS_INVALID_INFO_CLASS;
-
- if (EventInformationLength < sizeof(EVENT_BASIC_INFORMATION))
- return STATUS_INFO_LENGTH_MISMATCH;
-
- Status = ObReferenceObjectByHandle(EventHandle,
- EVENT_QUERY_STATE,
- ExEventObjectType,
- UserMode,
- (PVOID*)&Event,
- NULL);
- if (!NT_SUCCESS(Status))
- return Status;
-
- if (Event->Header.Type == InternalNotificationEvent)
- Info.EventType = NotificationEvent;
- else
- Info.EventType = SynchronizationEvent;
- Info.EventState = KeReadStateEvent(Event);
-
- Status = MmCopyToCaller(EventInformation, &Event,
- sizeof(EVENT_BASIC_INFORMATION));
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Event);
- return(Status);
- }
-
- if (ReturnLength != NULL)
- {
- RetLen = sizeof(EVENT_BASIC_INFORMATION);
- Status = MmCopyToCaller(ReturnLength, &RetLen, sizeof(ULONG));
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Event);
- return(Status);
- }
- }
-
- ObDereferenceObject(Event);
- return(STATUS_SUCCESS);
-}
+ PKEVENT Event;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+ PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
+
+ PAGED_CODE();
+ DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle, EventInformationClass);
+
+ /* Check buffers and class validity */
+ Status = DefaultQueryInfoBufferCheck(EventInformationClass,
+ ExEventInfoClass,
+ sizeof(ExEventInfoClass) / sizeof(ExEventInfoClass[0]),
+ EventInformation,
+ EventInformationLength,
+ ReturnLength,
+ PreviousMode);
+ 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);
-NTSTATUS STDCALL
-NtResetEvent(IN HANDLE EventHandle,
- OUT PLONG PreviousState OPTIONAL)
-{
- PKEVENT Event;
- NTSTATUS Status;
-
- DPRINT("NtResetEvent(EventHandle %x)\n", EventHandle);
-
- Status = ObReferenceObjectByHandle(EventHandle,
- EVENT_MODIFY_STATE,
- ExEventObjectType,
- UserMode,
- (PVOID*)&Event,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- KeResetEvent(Event);
- ObDereferenceObject(Event);
- return(STATUS_SUCCESS);
-}
+ /* 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_EXCEPT(_SEH_ExSystemExceptionFilter) {
+ Status = _SEH_GetExceptionCode();
+
+ } _SEH_END;
+
+ /* Dereference the Object */
+ ObDereferenceObject(Event);
+ }
+
+ /* Return status */
+ return Status;
+}
/*
* @implemented
*/
-NTSTATUS STDCALL
-NtSetEvent(IN HANDLE EventHandle,
- OUT PLONG PreviousState OPTIONAL)
+NTSTATUS
+STDCALL
+NtResetEvent(IN HANDLE EventHandle,
+ OUT PLONG PreviousState OPTIONAL)
{
- PKEVENT Event;
- NTSTATUS Status;
-
- DPRINT("NtSetEvent(EventHandle %x)\n", EventHandle);
-
- Status = ObReferenceObjectByHandle(EventHandle,
- EVENT_MODIFY_STATE,
- ExEventObjectType,
- UserMode,
- (PVOID*)&Event,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- KeSetEvent(Event,EVENT_INCREMENT,FALSE);
- ObDereferenceObject(Event);
- return(STATUS_SUCCESS);
+ 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 != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWriteLong(PreviousState);
+ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ 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_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ Status = _SEH_GetExceptionCode();
+
+ } _SEH_END;
+ }
+ }
+
+ /* Return Status */
+ return Status;
}
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
STDCALL
-NtTraceEvent(
- IN ULONG TraceHandle,
- IN ULONG Flags,
- IN ULONG TraceHeaderLength,
- IN struct _EVENT_TRACE_HEADER* TraceHeader
- )
+NtSetEvent(IN HANDLE EventHandle,
+ OUT PLONG PreviousState OPTIONAL)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
+ PKEVENT Event;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+ DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
+ EventHandle, PreviousState);
+
+ /* Check buffer validity */
+ if(PreviousState != NULL && PreviousMode != KernelMode) {
+
+ _SEH_TRY {
+
+ ProbeForWriteLong(PreviousState);
+ } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ 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_EXCEPT(_SEH_ExSystemExceptionFilter) {
+
+ Status = _SEH_GetExceptionCode();
+
+ } _SEH_END;
+ }
+ }
+
+ /* Return Status */
+ return Status;
+}
/* EOF */