NTSTATUS NtPulseEvent ( IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL ) /*++ Routine Description: This function sets an event object to a Signaled state, attempts to satisfy as many waits as possible, and then resets the state of the event object to Not-Signaled. Arguments: EventHandle - Supplies a handle to an event object. PreviousState - Supplies an optional pointer to a variable that will receive the previous state of the event object. Return Value: TBS --*/ { PVOID Event; KPROCESSOR_MODE PreviousMode; LONG State; NTSTATUS Status; // // Establish an exception handler, probe the previous state address if // specified, reference the event object, and pulse the event object. If // the probe fails, then return the exception code as the service status. // Otherwise return the status value returned by the reference object by // handle routine. // try { // // Get previous processor mode and probe previous state address // if necessary. // PreviousMode = KeGetPreviousMode(); if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousState))) { ProbeForWriteLong(PreviousState); } // // Reference event object by handle. // Status = ObReferenceObjectByHandle(EventHandle, EVENT_MODIFY_STATE, ExEventObjectType, PreviousMode, &Event, NULL); // // If the reference was successful, then pulse the event object, // dereference event object, and write the previous state value if // specified. If the write of the previous state fails, then do not // report an error. When the caller attempts to access the previous // state value, an access violation will occur. // if (NT_SUCCESS(Status)) { State = KePulseEvent((PKEVENT)Event, ExpEventBoost, FALSE); ObDereferenceObject(Event); if (ARGUMENT_PRESENT(PreviousState)) { try { *PreviousState = State; } except(ExSystemExceptionFilter()) { } } } // // If an exception occurs during the probe of the previous state, then // always handle the exception and return the exception code as the status // value. // } except(ExSystemExceptionFilter()) { return GetExceptionCode(); } // // Return service status. // return Status; }
NTSTATUS ImDiskReadWriteLowerDevice(PIRP Irp, PDEVICE_EXTENSION DeviceExtension) { PIO_STACK_LOCATION io_stack = IoGetCurrentIrpStackLocation(Irp); PIO_STACK_LOCATION lower_io_stack; PIRP lower_irp; PLOWER_DEVICE_WORK_ITEM item; // If image file is a direct I/O device, we simply forward the IRP with // correct FILE_OBJECT and adjusted offset if needed. if ((DeviceExtension->dev_object->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) { IoCopyCurrentIrpStackLocationToNext(Irp); lower_io_stack = IoGetNextIrpStackLocation(Irp); lower_io_stack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->image_offset.QuadPart; lower_io_stack->FileObject = DeviceExtension->file_object; if ((io_stack->MajorFunction == IRP_MJ_WRITE) && !DeviceExtension->image_modified) { DeviceExtension->image_modified = TRUE; // Fire refresh event if (RefreshEvent != NULL) KePulseEvent(RefreshEvent, 0, FALSE); } return IoCallDriver(DeviceExtension->dev_object, Irp); } // This goes for image files with DO_BUFFERED_IO or DO_NEITHER_IO. // We allocate NP pool as buffer for a request to send down. A completion // routine takes care of copying read operation data back to original IRP. item = (PLOWER_DEVICE_WORK_ITEM) ExAllocatePoolWithTag(NonPagedPool, sizeof(*item), POOL_TAG); if (item == NULL) { Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(item, sizeof(*item)); item->OriginalIrp = Irp; item->DeviceExtension = DeviceExtension; item->OriginalOffset = io_stack->Parameters.Read.ByteOffset.QuadPart; if ((io_stack->MajorFunction == IRP_MJ_READ) || (io_stack->MajorFunction == IRP_MJ_WRITE)) { item->SystemBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if (item->SystemBuffer == NULL) { ExFreePoolWithTag(item, POOL_TAG); Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INSUFFICIENT_RESOURCES; } } lower_irp = IoAllocateIrp(DeviceExtension->dev_object->StackSize, FALSE); if (lower_irp == NULL) { ExFreePoolWithTag(item, POOL_TAG); Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INSUFFICIENT_RESOURCES; } lower_io_stack = IoGetNextIrpStackLocation(lower_irp); lower_io_stack->MajorFunction = io_stack->MajorFunction; lower_io_stack->Parameters = io_stack->Parameters; if ((io_stack->MajorFunction == IRP_MJ_READ) || (io_stack->MajorFunction == IRP_MJ_WRITE)) { lower_irp->AssociatedIrp.SystemBuffer = lower_irp->UserBuffer = item->AllocatedBuffer = (PUCHAR) ExAllocatePoolWithTag(NonPagedPool, io_stack->Parameters.Read.Length, POOL_TAG); if (item->AllocatedBuffer == NULL) { ImDiskFreeIrpWithMdls(lower_irp); ExFreePoolWithTag(item, POOL_TAG); Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_INSUFFICIENT_RESOURCES; } if (io_stack->MajorFunction == IRP_MJ_WRITE) { RtlCopyMemory(item->AllocatedBuffer, item->SystemBuffer, io_stack->Parameters.Write.Length); } else if (io_stack->MajorFunction == IRP_MJ_READ) { item->CopyBack = TRUE; } } lower_irp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread; if (io_stack->MajorFunction == IRP_MJ_READ) { lower_irp->Flags |= IRP_READ_OPERATION; } else if (io_stack->MajorFunction == IRP_MJ_WRITE) { lower_irp->Flags |= IRP_WRITE_OPERATION; lower_io_stack->Flags |= SL_WRITE_THROUGH; } lower_irp->Flags |= IRP_NOCACHE; lower_io_stack->Parameters.Read = io_stack->Parameters.Read; lower_io_stack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->image_offset.QuadPart; lower_io_stack->FileObject = DeviceExtension->file_object; if ((io_stack->MajorFunction == IRP_MJ_WRITE) && (!DeviceExtension->image_modified)) { DeviceExtension->image_modified = TRUE; // Fire refresh event if (RefreshEvent != NULL) KePulseEvent(RefreshEvent, 0, FALSE); } IoSetCompletionRoutine(lower_irp, ImDiskReadWriteLowerDeviceCompletion, item, TRUE, TRUE, TRUE); IoMarkIrpPending(Irp); (void)IoCallDriver(DeviceExtension->dev_object, lower_irp); return STATUS_PENDING; }
static VOID TestEventFunctional( IN PKEVENT Event, IN EVENT_TYPE Type, IN KIRQL OriginalIrql) { LONG State; PKTHREAD Thread = KeGetCurrentThread(); memset(Event, 0x55, sizeof *Event); KeInitializeEvent(Event, Type, FALSE); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); memset(Event, 0x55, sizeof *Event); KeInitializeEvent(Event, Type, TRUE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); Event->Header.SignalState = 0x12345678L; CheckEvent(Event, Type, 0x12345678L, FALSE, OriginalIrql, (PVOID *)NULL, 0); State = KePulseEvent(Event, 0, FALSE); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x12345678L); Event->Header.SignalState = 0x12345678L; KeClearEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); State = KeSetEvent(Event, 0, FALSE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0L); State = KeResetEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 1L); Event->Header.SignalState = 0x23456789L; State = KeSetEvent(Event, 0, FALSE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x23456789L); Event->Header.SignalState = 0x3456789AL; State = KeResetEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x3456789AL); /* Irql is raised to DISPATCH_LEVEL here, which kills checked build, * a spinlock is acquired and never released, which kills MP build */ if ((OriginalIrql <= DISPATCH_LEVEL || !KmtIsCheckedBuild) && !KmtIsMultiProcessorBuild) { Event->Header.SignalState = 0x456789ABL; State = KeSetEvent(Event, 0, TRUE); CheckEvent(Event, Type, 1L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0); ok_eq_long(State, 0x456789ABL); ok_eq_uint(Thread->WaitIrql, OriginalIrql); /* repair the "damage" */ Thread->WaitNext = FALSE; KmtSetIrql(OriginalIrql); Event->Header.SignalState = 0x56789ABCL; State = KePulseEvent(Event, 0, TRUE); CheckEvent(Event, Type, 0L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0); ok_eq_long(State, 0x56789ABCL); ok_eq_uint(Thread->WaitIrql, OriginalIrql); /* repair the "damage" */ Thread->WaitNext = FALSE; KmtSetIrql(OriginalIrql); } ok_irql(OriginalIrql); KmtSetIrql(OriginalIrql); }