/*++ Copyright (c) 1989 Microsoft Corporation Module Name: eventpr.c Abstract: This module implements the executive event pair object. Functions are provided to create, open, waitlow, waithi, setlow, sethi, sethiwaitlo, setlowaithi. Author: Mark Lucovsky (markl) 18-Oct-1990 Environment: Kernel mode only. Revision History: --*/ #include "exp.h" // // Define performance counters. // ULONG EvPrSetHigh = 0; ULONG EvPrSetLow = 0; // // Address of event pair object type descriptor. // POBJECT_TYPE ExEventPairObjectType; // // Structure that describes the mapping of generic access rights to object // specific access rights for event pair objects. // #ifdef ALLOC_DATA_PRAGMA #pragma const_seg("INITCONST") #endif const GENERIC_MAPPING ExpEventPairMapping = { STANDARD_RIGHTS_READ | SYNCHRONIZE, STANDARD_RIGHTS_WRITE | SYNCHRONIZE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, EVENT_PAIR_ALL_ACCESS }; #ifdef ALLOC_DATA_PRAGMA #pragma const_seg() #endif #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, ExpEventPairInitialization) #pragma alloc_text(PAGE, NtCreateEventPair) #pragma alloc_text(PAGE, NtOpenEventPair) #pragma alloc_text(PAGE, NtWaitLowEventPair) #pragma alloc_text(PAGE, NtWaitHighEventPair) #pragma alloc_text(PAGE, NtSetLowWaitHighEventPair) #pragma alloc_text(PAGE, NtSetHighWaitLowEventPair) #pragma alloc_text(PAGE, NtSetHighEventPair) #pragma alloc_text(PAGE, NtSetLowEventPair) #endif BOOLEAN ExpEventPairInitialization ( ) /*++ Routine Description: This function creates the event pair object type descriptor at system initialization and stores the address of the object type descriptor in global storage. Arguments: None. Return Value: A value of TRUE is returned if the event pair object type descriptor is successfully initialized. Otherwise a value of FALSE is returned. --*/ { OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; NTSTATUS Status; UNICODE_STRING TypeName; // // Initialize string descriptor. // RtlInitUnicodeString(&TypeName, L"EventPair"); // // Create event object type descriptor. // RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; ObjectTypeInitializer.GenericMapping = ExpEventPairMapping; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EEVENT_PAIR); ObjectTypeInitializer.ValidAccessMask = EVENT_PAIR_ALL_ACCESS; ObjectTypeInitializer.UseDefaultObject = TRUE; Status = ObCreateObjectType(&TypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ExEventPairObjectType); // // If the event pair object type descriptor was successfully created, then // return a value of TRUE. Otherwise return a value of FALSE. // return (BOOLEAN)(NT_SUCCESS(Status)); } NTSTATUS NtCreateEventPair ( OUT PHANDLE EventPairHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL ) /*++ Routine Description: This function creates an event pair object, sets it initial state, and opens a handle to the object with the specified desired access. Arguments: EventPairHandle - Supplies a pointer to a variable that will receive the event pair object handle. DesiredAccess - Supplies the desired types of access for the event pair object. ObjectAttributes - Supplies a pointer to an object attributes structure. Return Value: NTSTATUS. --*/ { PEEVENT_PAIR EventPair; HANDLE Handle; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Establish an exception handler, probe the output handle address, and // attempt to create an event object. If the probe fails, then return the // exception code as the service status. Otherwise return the status value // returned by the object insertion routine. // // // Get previous processor mode and probe output handle address if // necessary. // PreviousMode = KeGetPreviousMode(); if (PreviousMode != KernelMode) { try { ProbeForWriteHandle(EventPairHandle); } except (ExSystemExceptionFilter()) { return GetExceptionCode(); } } // // Allocate event object. // Status = ObCreateObject(PreviousMode, ExEventPairObjectType, ObjectAttributes, PreviousMode, NULL, sizeof(EEVENT_PAIR), 0, 0, (PVOID *)&EventPair); // // If the event pair object was successfully allocated, then // initialize the event pair object and attempt to insert the // event pair object in the current process' handle table. // if (NT_SUCCESS(Status)) { KeInitializeEventPair(&EventPair->KernelEventPair); Status = ObInsertObject((PVOID)EventPair, NULL, DesiredAccess, 0, (PVOID *)NULL, &Handle); // // If the event pair object was successfully inserted in the // current process' handle table, then attempt to write the // event pair object handle value. If the write attempt // fails, then do not report an error. When the caller // attempts to access the handle value, an access violation // will occur. if (NT_SUCCESS(Status)) { if (PreviousMode != KernelMode) { try { *EventPairHandle = Handle; } except(ExSystemExceptionFilter()) { NOTHING; } } else { *EventPairHandle = Handle; } } } // // Return service status. // return Status; } NTSTATUS NtOpenEventPair( OUT PHANDLE EventPairHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ) /*++ Routine Description: This function opens a handle to an event pair object with the specified desired access. Arguments: EventPairHandle - Supplies a pointer to a variable that will receive the event pair object handle. DesiredAccess - Supplies the desired types of access for the event pair object. ObjectAttributes - Supplies a pointer to an object attributes structure. Return Value: NTSTATUS. --*/ { HANDLE Handle; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Establish an exception handler, probe the output handle address, and // attempt to open the event object. If the probe fails, then return the // exception code as the service status. Otherwise return the status value // returned by the object open routine. // // // Get previous processor mode and probe output handle address // if necessary. // PreviousMode = KeGetPreviousMode(); if (PreviousMode != KernelMode) { try { ProbeForWriteHandle(EventPairHandle); } except (ExSystemExceptionFilter()) { return GetExceptionCode(); } } // // Open handle to the event pair object with the specified // desired access. // Status = ObOpenObjectByName(ObjectAttributes, ExEventPairObjectType, PreviousMode, NULL, DesiredAccess, NULL, &Handle); // // If the open was successful, then attempt to write the event // pair object handle value. If the write attempt fails, then do // not report an error. When the caller attempts to access the // handle value, an access violation will occur. // if (NT_SUCCESS(Status)) { if (PreviousMode != KernelMode) { try { *EventPairHandle = Handle; } except(ExSystemExceptionFilter()) { NOTHING; } } else { *EventPairHandle = Handle; } } // // Return service status. // return Status; } NTSTATUS NtWaitLowEventPair( IN HANDLE EventPairHandle ) /*++ Routine Description: This function waits on the low event of an event pair object. Arguments: EventPairHandle - Supplies a handle to an event pair object. Return Value: NTSTATUS. --*/ { PEEVENT_PAIR EventPair; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Reference event pair object by handle. // PreviousMode = KeGetPreviousMode(); Status = ObReferenceObjectByHandle(EventPairHandle, SYNCHRONIZE, ExEventPairObjectType, PreviousMode, (PVOID *)&EventPair, NULL); // // If the reference was successful, then wait on the Low event // of the event pair. // if (NT_SUCCESS(Status)) { Status = KeWaitForLowEventPair(&EventPair->KernelEventPair, PreviousMode, FALSE, NULL); ObDereferenceObject(EventPair); } // // Return service status. // return Status; } NTSTATUS NtWaitHighEventPair( IN HANDLE EventPairHandle ) /*++ Routine Description: This function waits on the high event of an event pair object. Arguments: EventPairHandle - Supplies a handle to an event pair object. Return Value: NTSTATUS. --*/ { PEEVENT_PAIR EventPair; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Reference event pair object by handle. // PreviousMode = KeGetPreviousMode(); Status = ObReferenceObjectByHandle(EventPairHandle, SYNCHRONIZE, ExEventPairObjectType, PreviousMode, (PVOID *)&EventPair, NULL); // // If the reference was successful, then wait on the Low event // of the event pair. // if (NT_SUCCESS(Status)) { Status = KeWaitForHighEventPair(&EventPair->KernelEventPair, PreviousMode, FALSE, NULL); ObDereferenceObject(EventPair); } // // Return service status. // return Status; } NTSTATUS NtSetLowWaitHighEventPair( IN HANDLE EventPairHandle ) /*++ Routine Description: This function sets the low event of an event pair and then waits on the high event of an event pair object. Arguments: EventPairHandle - Supplies a handle to an event pair object. Return Value: NTSTATUS. --*/ { PEEVENT_PAIR EventPair; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Reference event pair object by handle. // PreviousMode = KeGetPreviousMode(); Status = ObReferenceObjectByHandle(EventPairHandle, SYNCHRONIZE, ExEventPairObjectType, PreviousMode, (PVOID *)&EventPair, NULL); // // If the reference was successful, then wait on the Low event // of the event pair. // if (NT_SUCCESS(Status)) { EvPrSetLow += 1; Status = KeSetLowWaitHighEventPair(&EventPair->KernelEventPair, PreviousMode); ObDereferenceObject(EventPair); } // // Return service status. // return Status; } NTSTATUS NtSetHighWaitLowEventPair( IN HANDLE EventPairHandle ) /*++ Routine Description: This function sets the high event of an event pair and then waits on the low event of an event pair object. Arguments: EventPairHandle - Supplies a handle to an event pair object. Return Value: NTSTATUS. --*/ { PEEVENT_PAIR EventPair; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Reference event pair object by handle. // PreviousMode = KeGetPreviousMode(); Status = ObReferenceObjectByHandle(EventPairHandle, SYNCHRONIZE, ExEventPairObjectType, PreviousMode, (PVOID *)&EventPair, NULL); // // If the reference was successful, then wait on the Low event // of the event pair. // if (NT_SUCCESS(Status)) { EvPrSetHigh += 1; Status = KeSetHighWaitLowEventPair(&EventPair->KernelEventPair, PreviousMode); ObDereferenceObject(EventPair); } // // Return service status. // return Status; } NTSTATUS NtSetLowEventPair( IN HANDLE EventPairHandle ) /*++ Routine Description: This function sets the low event of an event pair object. Arguments: EventPairHandle - Supplies a handle to an event pair object. Return Value: NTSTATUS. --*/ { PEEVENT_PAIR EventPair; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Reference event pair object by handle. // PreviousMode = KeGetPreviousMode(); Status = ObReferenceObjectByHandle(EventPairHandle, SYNCHRONIZE, ExEventPairObjectType, PreviousMode, (PVOID *)&EventPair, NULL); // // If the reference was successful, then wait on the Low event // of the event pair. // if (NT_SUCCESS(Status)) { EvPrSetLow += 1; KeSetLowEventPair(&EventPair->KernelEventPair, EVENT_PAIR_INCREMENT,FALSE); ObDereferenceObject(EventPair); } // // Return service status. // return Status; } NTSTATUS NtSetHighEventPair( IN HANDLE EventPairHandle ) /*++ Routine Description: This function sets the high event of an event pair object. Arguments: EventPairHandle - Supplies a handle to an event pair object. Return Value: NTSTATUS. --*/ { PEEVENT_PAIR EventPair; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; // // Reference event pair object by handle. // PreviousMode = KeGetPreviousMode(); Status = ObReferenceObjectByHandle(EventPairHandle, SYNCHRONIZE, ExEventPairObjectType, PreviousMode, (PVOID *)&EventPair, NULL); // // If the reference was successful, then wait on the Low event // of the event pair. // if (NT_SUCCESS(Status)) { EvPrSetHigh += 1; KeSetHighEventPair(&EventPair->KernelEventPair, EVENT_PAIR_INCREMENT,FALSE); ObDereferenceObject(EventPair); } // // Return service status. // return Status; }