Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}