Пример #1
0
static NTSTATUS NTAPI
V4vDispatchWmi(PDEVICE_OBJECT fdo, PIRP irp)
{
    NTSTATUS          status;
    PXENV4V_EXTENSION pde = V4vGetDeviceExtension(fdo);

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    // We don't support WMI, so just pass it on down the stack

    status = IoAcquireRemoveLock(&pde->removeLock, irp);
    if (!NT_SUCCESS(status)) {
        TraceError(("failed to acquire IO lock - error: 0x%x\n", status));        
        return V4vSimpleCompleteIrp(irp, status);
    }

    IoSkipCurrentIrpStackLocation(irp);
    status = IoCallDriver(pde->ldo, irp);

    IoReleaseRemoveLock(&pde->removeLock, irp);

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));
 
    return status;
}
Пример #2
0
static VOID
V4vStopDevice(PDEVICE_OBJECT fdo, PXENV4V_EXTENSION pde)
{
    PIRP pendingIrp;
    XENV4V_QPEEK peek;

    // Go to the stopped state to prevent IO, stop the timer and
    // interrupt (ec).
    InterlockedExchange(&pde->state, XENV4V_DEV_STOPPED);
    V4vUninitializeEventChannel(fdo);
    KeCancelTimer(&pde->timer);

    peek.types = XENV4V_PEEK_STREAM;              // process for stream types
    peek.ops   = XENV4V_PEEK_SYN|XENV4V_PEEK_ACK; // all SYN/ACK ops
    peek.pfo   = NULL;                            // not using file object search
    peek.dst.domain = DOMID_INVALID;              // not using destination search
    peek.dst.port   = V4V_PORT_NONE;

    pendingIrp = IoCsqRemoveNextIrp(&pde->csqObject, &peek);
    while (pendingIrp != NULL) {
        V4vSimpleCompleteIrp(pendingIrp, STATUS_CANCELLED);
        pendingIrp = IoCsqRemoveNextIrp(&pde->csqObject, &peek);
    }
}
Пример #3
0
VOID
V4vDoAccepts(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx)
{
    NTSTATUS            status;
    KLOCK_QUEUE_HANDLE  lqh;
    PIO_STACK_LOCATION  isl;
    PIRP                nextIrp = NULL;
    XENV4V_QPEEK        peek;
    ULONG               ioControlCode;
    PVOID               ioBuffer;
    struct v4v_addr    *peer;
    ULONG               size;
    XENV4V_CONTEXT     *actx;
    XENV4V_SYN         *sptr;
    V4V_ACCEPT_PRIVATE *priv;

    peek.types = XENV4V_PEEK_STREAM; // process for stream types
    peek.ops   = XENV4V_PEEK_ACCEPT; // accept ops
    peek.pfo   = ctx->pfoParent;     // for a specific file object

    // Lock the SYN list state and process SYN entries. For each,
    // try to locate an accept IRP in the queue for this listener.
    KeAcquireInStackQueuedSpinLock(&ctx->u.listener.synLock, &lqh);

    do {
        if (ctx->u.listener.synCount == 0) {
            // No data so clear any events indicating pending accepts.
            KeClearEvent(ctx->kevReceive);
            break; // no more to read
        }

        // SYNs, any pending accepts?
        nextIrp = IoCsqRemoveNextIrp(&pde->csqObject, &peek);
        if (nextIrp == NULL) {
            // Nobody to accept it so tell the listener there are SYNs waiting.
            // Set the data ready event for clients who use it.
            KeSetEvent(ctx->kevReceive, EVENT_INCREMENT, FALSE);
            break;
        }

        // Now there is a SYN and an accept IRP to take it.
        isl           = IoGetCurrentIrpStackLocation(nextIrp);
        ioControlCode = isl->Parameters.DeviceIoControl.IoControlCode;
        ioBuffer      = nextIrp->AssociatedIrp.SystemBuffer;

        // Gather the private accept information
        size = V4vGetAcceptPrivate(ioControlCode, ioBuffer, &priv, &peer);

        // Get the stashed referenced context pointer for the new accepter
#if defined(_WIN64)
        actx = (XENV4V_CONTEXT*)priv->q.a;
#else
        actx = (XENV4V_CONTEXT*)priv->d.a;
#endif

        // Pop the next in order from the head of the list
        ASSERT(ctx->u.listener.synHead != NULL);
        ASSERT(ctx->u.listener.synTail != NULL);
        sptr = ctx->u.listener.synHead;
        if (ctx->u.listener.synHead != ctx->u.listener.synTail) {
            // More than one on the list
            ctx->u.listener.synHead = sptr->next;
        }
        else {
            // Only one on the list, reset pointers
            ctx->u.listener.synHead = NULL;
            ctx->u.listener.synTail = NULL;
        }

        ctx->u.listener.synCount--;
        ASSERT(ctx->u.listener.synCount >= 0);

        // Finish the accept, clear the SYN entry and drop the ref count on the context
        actx->sdst   = sptr->sdst;
        actx->connId = sptr->connId;
        (*peer)      = sptr->sdst;
        RtlZeroMemory(sptr, sizeof(XENV4V_SYN));
        V4vReleaseContext(pde, actx);
        InterlockedExchange(&actx->state, XENV4V_STATE_ACCEPTED);

        // Send the ACK to our peer
        status = V4vSendAcknowledge(pde, actx);
        if (!NT_SUCCESS(status)) {
            // Fail the IRP and go to the disconnected state for the new context
            V4vSimpleCompleteIrp(nextIrp, status);
            InterlockedExchange(&actx->state, XENV4V_STATE_DISCONNECTED);
            continue;
        }

        // Complete the IRP - this will finish the accept call. Set the IOCTL output
        // buffer to the size appropriate for the user mode caller (32b vs 64b).
        nextIrp->IoStatus.Information = size;
        nextIrp->IoStatus.Status = STATUS_SUCCESS;
        IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
    } while (TRUE);

    KeReleaseInStackQueuedSpinLock(&lqh);
}
Пример #4
0
static NTSTATUS NTAPI
V4vDispatchPower(PDEVICE_OBJECT fdo, PIRP irp)
{
    NTSTATUS           status;
    PXENV4V_EXTENSION  pde = V4vGetDeviceExtension(fdo);
    PIO_STACK_LOCATION isl = IoGetCurrentIrpStackLocation(irp);

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    switch (isl->MinorFunction) {
    case IRP_MN_SET_POWER:
        if (isl->Parameters.Power.Type == SystemPowerState) {
            TraceNotice(("SET system power: %d %d\n",
                          isl->Parameters.Power.State.SystemState,
                          isl->Parameters.Power.ShutdownType));

            // If we are transitioning from the working (S0) power state to a lower state,
            // disconnect the VIRQ. If we are resuming to the working power state, re-connect.           
            if (isl->Parameters.Power.State.SystemState == PowerSystemWorking) {
                // When resuming from hibernation w/ multi-vCPUs, the pv drivers
                // may be initialized in parallel causing problems with xenbus being
                // initialized before we try to bind our VIRQ. Kick the job off to a 
                // work item and wait for initialization there.
                if (pde->lastPoState == PowerSystemHibernate) {
                    V4vStartDehibernateWorkItem(fdo);
                }
                else {
                    (VOID)V4vInitializeEventChannel(fdo);
                }
            }
            else if (isl->Parameters.Power.State.SystemState >= PowerSystemSleeping1) {
                V4vUninitializeEventChannel(fdo);               
            }

            // If the last state was S4, flush all connections
            if (pde->lastPoState == PowerSystemHibernate) {
                V4vDisconnectAllStreams(pde);
            }

            // Reset the last state to what we just saw
            pde->lastPoState = isl->Parameters.Power.State.SystemState;
        }
        else if (isl->Parameters.Power.Type == DevicePowerState) {
            TraceNotice(("SET device power: %d %d\n",
                         isl->Parameters.Power.State.SystemState,
                         isl->Parameters.Power.ShutdownType));
        }
        break;
    case IRP_MN_QUERY_POWER:
        if (isl->Parameters.Power.Type == SystemPowerState) {
            TraceNotice(("QUERY system power: %d %d\n",
                          isl->Parameters.Power.State.SystemState,
                          isl->Parameters.Power.ShutdownType));
        }
        else if (isl->Parameters.Power.Type == DevicePowerState) {
            TraceNotice(("QUERY device power: %d %d\n",
                         isl->Parameters.Power.State.SystemState,
                         isl->Parameters.Power.ShutdownType));
        }
        break;
    };    

    status = IoAcquireRemoveLock(&pde->removeLock, irp);
    if (!NT_SUCCESS(status)) {
        TraceError(("failed to acquire IO lock - error: 0x%x\n", status));
        PoStartNextPowerIrp(irp); // for xp and 2k3
        return V4vSimpleCompleteIrp(irp, status);
    }

    PoStartNextPowerIrp(irp); // for xp and 2k3
    IoSkipCurrentIrpStackLocation(irp);
    status = PoCallDriver(pde->ldo, irp);

    IoReleaseRemoveLock(&pde->removeLock, irp);

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return status;
}
Пример #5
0
static NTSTATUS NTAPI
V4vDispatchPnP(PDEVICE_OBJECT fdo, PIRP irp)
{
    NTSTATUS           status = STATUS_SUCCESS;
    PIO_STACK_LOCATION isl = IoGetCurrentIrpStackLocation(irp);
    PXENV4V_EXTENSION  pde = V4vGetDeviceExtension(fdo);
    KEVENT             kev;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    TraceVerbose((" =PnP= 0x%x\n", isl->MinorFunction));

    status = IoAcquireRemoveLock(&pde->removeLock, irp);
    if (!NT_SUCCESS(status)) {
        TraceError(("failed to acquire IO lock - error: 0x%x\n", status));
        return V4vSimpleCompleteIrp(irp, status);
    }

    switch (isl->MinorFunction) {
    case IRP_MN_START_DEVICE:
        KeInitializeEvent(&kev, NotificationEvent, FALSE);
        // Send the start down and wait for it to complete
        IoCopyCurrentIrpStackLocationToNext(irp);
        IoSetCompletionRoutine(irp, V4vStartDeviceIoCompletion, &kev, TRUE, TRUE, TRUE);
        status = IoCallDriver(pde->ldo, irp);
        if (status == STATUS_PENDING) {
            // Wait for everything underneath us to complete
            TraceVerbose(("Device start waiting for lower device.\n"));
            KeWaitForSingleObject(&kev, Executive, KernelMode, FALSE, NULL);
            TraceVerbose(("Device start wait finished.\n"));
        }

        status = irp->IoStatus.Status;
        if (!NT_SUCCESS(status)) {
            TraceError(("Failed to start lower drivers: %x.\n", status));
            IoCompleteRequest(irp, IO_NO_INCREMENT);
            break;
        }

        status = STATUS_SUCCESS;

        // Connect our interrupt (ec).
        status = V4vInitializeEventChannel(fdo);
        if (NT_SUCCESS(status)) {
            InterlockedExchange(&pde->state, XENV4V_DEV_STARTED);
        }
        else {
            TraceError(("failed to initialize event channel - error: 0x%x\n", status));
        }

        irp->IoStatus.Status = status;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        break;
    case IRP_MN_STOP_DEVICE:
        // Stop our device's IO processing
        V4vStopDevice(fdo, pde);

        // Pass it down
        irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);
        break;        
    case IRP_MN_REMOVE_DEVICE:
        // Stop our device's IO processing
        V4vStopDevice(fdo, pde);

        // Cleanup anything here that locks for IO
        IoReleaseRemoveLockAndWait(&pde->removeLock, irp);

        // Pass it down first
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);

        // Then detach and cleanup our device
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CLOSED);
        IoDetachDevice(pde->ldo);
        ExDeleteNPagedLookasideList(&pde->destLookasideList);
        XmFreeMemory(pde->frontendPath);
        IoDeleteSymbolicLink(&pde->symbolicLink);
        IoDeleteDevice(fdo);
        InterlockedAnd(&g_deviceCreated, 0);
        return status;
    default:
        // Pass it down
        TraceVerbose(("IRP_MJ_PNP MinorFunction %d passed down\n", isl->MinorFunction));
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);
    };

    // Everybody but REMOVE
    IoReleaseRemoveLock(&pde->removeLock, irp); 

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return status;
}