예제 #1
0
파일: driver.c 프로젝트: Moteesh/reactos
NTSTATUS
NTAPI
StreamClassAddDevice(
    IN PDRIVER_OBJECT  DriverObject,
    IN PDEVICE_OBJECT  PhysicalDeviceObject)
{
    PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension;
    PDEVICE_OBJECT DeviceObject, LowerDeviceObject;
    PSTREAM_DEVICE_EXTENSION DeviceExtension;
    PKSOBJECT_CREATE_ITEM ItemList;
    NTSTATUS Status;

    /* Fetch driver object extension */
    DriverObjectExtension = IoGetDriverObjectExtension(DriverObject, (PVOID)StreamClassAddDevice);
    if (!DriverObjectExtension)
    {
        /* Failed to get driver extension */
        return STATUS_DEVICE_DOES_NOT_EXIST;
    }
    /* Allocate Create Item */
    ItemList = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
    if (!ItemList)
    {
        /* Failed to allocated Create Item */
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Create the FDO */
    Status = IoCreateDevice(DriverObject, DriverObjectExtension->Data.DeviceExtensionSize + sizeof(STREAM_DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, 0, &DeviceObject);
    if (!NT_SUCCESS(Status))
    {
        /* Failed to create the FDO */
        ExFreePool(ItemList);
        return Status;
    }

    /* Attach to device stack */
    LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
    if (!LowerDeviceObject)
    {
        /* Failed to attach */
        IoDeleteDevice(DeviceObject);
        ExFreePool(ItemList);
        return STATUS_UNSUCCESSFUL;
    }

    /* Zero Create item */
    RtlZeroMemory(ItemList, sizeof(KSOBJECT_CREATE_ITEM));
    /* Setup object class */
    RtlInitUnicodeString(&ItemList->ObjectClass, L"GLOBAL");
    /* Setup CreateDispatch routine */
    ItemList->Create = StreamClassCreateFilter;

    /* Get device extension */
    DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    /* Zero device extension */
    RtlZeroMemory(DeviceExtension, sizeof(STREAM_DEVICE_EXTENSION));
    /* Initialize Ks streaming */
    Status = KsAllocateDeviceHeader(&DeviceExtension->Header, 1, ItemList);
    if (!NT_SUCCESS(Status))
    {
        /* Cleanup resources */
        IoDetachDevice(LowerDeviceObject);
        IoDeleteDevice(DeviceObject);
        ExFreePool(ItemList);
        return Status;
    }

    /* Store lower device object */
    DeviceExtension->LowerDeviceObject = LowerDeviceObject;

    /* Store physical device object */
    DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
    /* Store driver object extension */
    DeviceExtension->DriverExtension = DriverObjectExtension;
    /* Initialize memory list */
    InitializeListHead(&DeviceExtension->MemoryResourceList);
    /* Setup device extension */
    DeviceExtension->DeviceExtension = (PVOID) (DeviceExtension + 1);
    /* Init interrupt dpc */
    KeInitializeDpc(&DeviceExtension->InterruptDpc, StreamClassInterruptDpc, (PVOID)DeviceExtension);

    /* Set device transfer method */
    DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
    /* Clear init flag */
    DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;

    return Status;
}
예제 #2
0
파일: pnp.c 프로젝트: imahmoodz/ScpToolkit
NTSTATUS Bus_FDO_PnP(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PIO_STACK_LOCATION IrpStack, __in PFDO_DEVICE_DATA DeviceData)
{
    NTSTATUS            status;
    ULONG               length, prevcount, numPdosPresent, numPdosMissing;
    PLIST_ENTRY         entry, listHead, nextEntry;
    PPDO_DEVICE_DATA    pdoData;
    PDEVICE_RELATIONS   relations, oldRelations;

    PAGED_CODE();

    Bus_IncIoCount(DeviceData);

    switch (IrpStack->MinorFunction)
	{
    case IRP_MN_START_DEVICE:

        status = Bus_SendIrpSynchronously(DeviceData->NextLowerDriver, Irp);

        if (NT_SUCCESS(status))
		{
            status = Bus_StartFdo (DeviceData, Irp);
        }

        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        Bus_DecIoCount(DeviceData);
        return status;

    case IRP_MN_QUERY_STOP_DEVICE:

        SET_NEW_PNP_STATE(DeviceData, StopPending);

		Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        if (StopPending == DeviceData->DevicePnPState)
        {
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
            ASSERT(DeviceData->DevicePnPState == Started);
        }

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_STOP_DEVICE:

        Bus_DecIoCount(DeviceData);

        KeWaitForSingleObject(&DeviceData->StopEvent, Executive, KernelMode, FALSE, NULL);

        Bus_IncIoCount(DeviceData);

        SET_NEW_PNP_STATE(DeviceData, Stopped);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        SET_NEW_PNP_STATE(DeviceData, RemovePending);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        if (DeviceData->DevicePnPState == RemovePending)
        {
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_SURPRISE_REMOVAL:

        SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
        Bus_RemoveFdo(DeviceData);

        ExAcquireFastMutex(&DeviceData->Mutex);
		{
			listHead = &DeviceData->ListOfPDOs;

			for(entry = listHead->Flink,nextEntry = entry->Flink; entry != listHead; entry = nextEntry, nextEntry = entry->Flink)
			{
				pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);

				RemoveEntryList(&pdoData->Link);
				InitializeListHead(&pdoData->Link);

				pdoData->ParentFdo       = NULL;
				pdoData->ReportedMissing = TRUE;
			}
		}
        ExReleaseFastMutex(&DeviceData->Mutex);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_REMOVE_DEVICE:

        if (DeviceData->DevicePnPState != SurpriseRemovePending)
        {
            Bus_RemoveFdo(DeviceData);
        }

        SET_NEW_PNP_STATE(DeviceData, Deleted);

        Bus_DecIoCount(DeviceData);
        Bus_DecIoCount(DeviceData);

        KeWaitForSingleObject(&DeviceData->RemoveEvent, Executive, KernelMode, FALSE, NULL);

        ExAcquireFastMutex(&DeviceData->Mutex);
		{
			listHead = &DeviceData->ListOfPDOs;

			for(entry = listHead->Flink,nextEntry = entry->Flink; entry != listHead; entry = nextEntry, nextEntry = entry->Flink)
			{
				pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);

				RemoveEntryList(&pdoData->Link);

				if (pdoData->DevicePnPState == SurpriseRemovePending)
				{
					Bus_KdPrint(("\tFound a surprise removed device: 0x%p\n", pdoData->Self));

					InitializeListHead(&pdoData->Link);

					pdoData->ParentFdo       = NULL;
					pdoData->ReportedMissing = TRUE;

					continue;
				}

				Bus_DestroyPdo(pdoData->Self, pdoData);
			}
		}
        ExReleaseFastMutex(&DeviceData->Mutex);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);

        status = IoCallDriver(DeviceData->NextLowerDriver, Irp);

        IoDetachDevice(DeviceData->NextLowerDriver);

        Bus_KdPrint(("\tDeleting FDO: 0x%p\n", DeviceObject));

        IoDeleteDevice(DeviceObject);
        return status;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        Bus_KdPrint(("\tQueryDeviceRelation Type: %s\n", DbgDeviceRelationString(IrpStack->Parameters.QueryDeviceRelations.Type)));

        if (IrpStack->Parameters.QueryDeviceRelations.Type != BusRelations)
		{
            break;
        }

        ExAcquireFastMutex(&DeviceData->Mutex);

        oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;

        if (oldRelations)
		{
            prevcount = oldRelations->Count;

            if (!DeviceData->NumPDOs)
			{
                ExReleaseFastMutex(&DeviceData->Mutex);
                break;
            }
        }
        else
		{
            prevcount = 0;
        }

        numPdosPresent = 0;
		numPdosMissing = 0;

        for (entry = DeviceData->ListOfPDOs.Flink; entry != &DeviceData->ListOfPDOs; entry = entry->Flink)
		{
            pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);

            if (pdoData->Present) numPdosPresent++;
        }

        length = sizeof(DEVICE_RELATIONS) + ((numPdosPresent + prevcount) * sizeof (PDEVICE_OBJECT)) - 1;

        relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag(PagedPool, length, BUSENUM_POOL_TAG);

        if (relations == NULL)
		{
            ExReleaseFastMutex(&DeviceData->Mutex);

            Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            Bus_DecIoCount(DeviceData);
            return status;
        }

        if (prevcount)
		{
            RtlCopyMemory(relations->Objects, oldRelations->Objects, prevcount * sizeof (PDEVICE_OBJECT));
        }

        relations->Count = prevcount + numPdosPresent;

        for (entry = DeviceData->ListOfPDOs.Flink; entry != &DeviceData->ListOfPDOs; entry = entry->Flink)
		{
            pdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);

            if (pdoData->Present)
			{
                relations->Objects[prevcount] = pdoData->Self;
                ObReferenceObject(pdoData->Self);

                prevcount++;
            }
			else
			{
                pdoData->ReportedMissing = TRUE;
				numPdosMissing++;
            }
        }

		Bus_KdPrint(("#PDOS Present = %d, Reported = %d, Missing = %d, Listed = %d", numPdosPresent, relations->Count, numPdosMissing, DeviceData->NumPDOs));

        if (oldRelations)
		{
            ExFreePool(oldRelations);
        }

        Irp->IoStatus.Information = (ULONG_PTR) relations;

        ExReleaseFastMutex(&DeviceData->Mutex);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    default:

        break;
    }

    IoSkipCurrentIrpStackLocation(Irp);
    status = IoCallDriver(DeviceData->NextLowerDriver, Irp);

    Bus_DecIoCount(DeviceData);
    return status;
}
예제 #3
0
파일: pnp.c 프로젝트: Shmuma/usbip
NTSTATUS
Bus_AddDevice(
    __in PDRIVER_OBJECT DriverObject,
    __in PDEVICE_OBJECT PhysicalDeviceObject
    )
/*++
Routine Description.

    Our Toaster bus has been found.  Attach our FDO to it.
    Allocate any required resources.  Set things up.
    And be prepared for the ``start device''

Arguments:

    DriverObject - pointer to driver object.

    PhysicalDeviceObject  - Device object representing the bus to which we
                            will attach a new FDO.

--*/
{
    NTSTATUS            status;
    PDEVICE_OBJECT      deviceObject = NULL;
    PFDO_DEVICE_DATA    deviceData = NULL;
    PWCHAR              deviceName = NULL;
    ULONG               nameLength;
    PKTIMER		timer;
    PKDPC		dpc;

    PAGED_CODE ();

    Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Add Device: 0x%p\n",
                                          PhysicalDeviceObject));

    status = IoCreateDevice (
                    DriverObject,               // our driver object
                    sizeof (FDO_DEVICE_DATA),   // device object extension size
                    NULL,                       // FDOs do not have names
                    FILE_DEVICE_BUS_EXTENDER,   // We are a bus
                    FILE_DEVICE_SECURE_OPEN,    //
                    TRUE,                       // our FDO is exclusive
                    &deviceObject);             // The device object created

    if (!NT_SUCCESS (status))
    {
        goto End;
    }

    deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
    RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA));

    //
    // Set the initial state of the FDO
    //

    INITIALIZE_PNP_STATE(deviceData);

    deviceData->DebugLevel = BusEnumDebugLevel;

    deviceData->IsFDO = TRUE;

    deviceData->Self = deviceObject;

    ExInitializeFastMutex (&deviceData->Mutex);

    InitializeListHead (&deviceData->ListOfPDOs);

    // Set the PDO for use with PlugPlay functions

    deviceData->UnderlyingPDO = PhysicalDeviceObject;

    //
    // Set the initial powerstate of the FDO
    //

    deviceData->DevicePowerState = PowerDeviceUnspecified;
    deviceData->SystemPowerState = PowerSystemWorking;


    //
    // Biased to 1. Transition to zero during remove device
    // means IO is finished. Transition to 1 means the device
    // can be stopped.
    //

    deviceData->OutstandingIO = 1;

    //
    // Initialize the remove event to Not-Signaled.  This event
    // will be set when the OutstandingIO will become 0.
    //

    KeInitializeEvent(&deviceData->RemoveEvent,
                  SynchronizationEvent,
                  FALSE);
    //
    // Initialize the stop event to Signaled:
    // there are no Irps that prevent the device from being
    // stopped. This event will be set when the OutstandingIO
    // will become 0.
    //

    KeInitializeEvent(&deviceData->StopEvent,
                      SynchronizationEvent,
                      TRUE);

    deviceObject->Flags |= DO_POWER_PAGABLE|DO_BUFFERED_IO;

    //
    // Tell the Plug & Play system that this device will need a
    // device interface.
    //

    status = IoRegisterDeviceInterface (
                PhysicalDeviceObject,
                (LPGUID) &GUID_DEVINTERFACE_BUSENUM_TOASTER,
                NULL,
                &deviceData->InterfaceName);

    if (!NT_SUCCESS (status)) {
        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
                      ("AddDevice: IoRegisterDeviceInterface failed (%x)", status));
        goto End;
    }

    //
    // Attach our FDO to the device stack.
    // The return value of IoAttachDeviceToDeviceStack is the top of the
    // attachment chain.  This is where all the IRPs should be routed.
    //

    deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (
                                    deviceObject,
                                    PhysicalDeviceObject);

    if (NULL == deviceData->NextLowerDriver) {

        status = STATUS_NO_SUCH_DEVICE;
        goto End;
    }


#if DBG
    //
    // We will demonstrate here the step to retrieve the name of the PDO
    //

    status = IoGetDeviceProperty (PhysicalDeviceObject,
                                  DevicePropertyPhysicalDeviceObjectName,
                                  0,
                                  NULL,
                                  &nameLength);

    if (status != STATUS_BUFFER_TOO_SMALL)
    {
        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
                      ("AddDevice:IoGDP failed (0x%x)\n", status));
        goto End;
    }

    deviceName = ExAllocatePoolWithTag (NonPagedPool,
                            nameLength, BUSENUM_POOL_TAG);

    if (NULL == deviceName) {
        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
        ("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength));
        status =  STATUS_INSUFFICIENT_RESOURCES;
        goto End;
    }

    status = IoGetDeviceProperty (PhysicalDeviceObject,
                         DevicePropertyPhysicalDeviceObjectName,
                         nameLength,
                         deviceName,
                         &nameLength);

    if (!NT_SUCCESS (status)) {

        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
                      ("AddDevice:IoGDP(2) failed (0x%x)", status));
        goto End;
    }

    Bus_KdPrint (deviceData, BUS_DBG_SS_TRACE,
                  ("AddDevice: %p to %p->%p (%ws) \n",
                   deviceObject,
                   deviceData->NextLowerDriver,
                   PhysicalDeviceObject,
                   deviceName));

#endif

    //
    // We are done with initializing, so let's indicate that and return.
    // This should be the final step in the AddDevice process.
    //
    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

End:
    if (deviceName){
        ExFreePool(deviceName);
    }

    if (!NT_SUCCESS(status) && deviceObject){
        if (deviceData && deviceData->NextLowerDriver){
            IoDetachDevice (deviceData->NextLowerDriver);
        }
        IoDeleteDevice (deviceObject);
    }

    return status;

}
예제 #4
0
파일: pnp.c 프로젝트: Shmuma/usbip
NTSTATUS
Bus_FDO_PnP (
    __in PDEVICE_OBJECT       DeviceObject,
    __in PIRP                 Irp,
    __in PIO_STACK_LOCATION   IrpStack,
    __in PFDO_DEVICE_DATA     DeviceData
    )
/*++
Routine Description:

    Handle requests from the Plug & Play system for the BUS itself

--*/
{
    NTSTATUS            status;
    ULONG               length, prevcount, numPdosPresent;
    PLIST_ENTRY         entry, listHead, nextEntry;
    PPDO_DEVICE_DATA    pdoData;
    PDEVICE_RELATIONS   relations, oldRelations;

    PAGED_CODE ();

    Bus_IncIoCount (DeviceData);

    switch (IrpStack->MinorFunction) {

    case IRP_MN_START_DEVICE:

        //
        // Send the Irp down and wait for it to come back.
        // Do not touch the hardware until then.
        //
        status = Bus_SendIrpSynchronously (DeviceData->NextLowerDriver, Irp);

        if (NT_SUCCESS(status)) {

            //
            // Initialize your device with the resources provided
            // by the PnP manager to your device.
            //
            status = Bus_StartFdo (DeviceData, Irp);
        }

        //
        // We must now complete the IRP, since we stopped it in the
        // completion routine with MORE_PROCESSING_REQUIRED.
        //

        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        Bus_DecIoCount (DeviceData);

        return status;

    case IRP_MN_QUERY_STOP_DEVICE:

        //
        // The PnP manager is trying to stop the device
        // for resource rebalancing. Fail this now if you
        // cannot stop the device in response to STOP_DEVICE.
        //
        SET_NEW_PNP_STATE(DeviceData, StopPending);
        Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP.
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // The PnP Manager sends this IRP, at some point after an
        // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a
        // device that the device will not be stopped for
        // resource reconfiguration.
        //
        //
        // First check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if
        //  someone above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //

        if (StopPending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
            ASSERT(DeviceData->DevicePnPState == Started);
        }
        Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP.
        break;

    case IRP_MN_STOP_DEVICE:

        //
        // Stop device means that the resources given during Start device
        // are now revoked. Note: You must not fail this Irp.
        // But before you relieve resources make sure there are no I/O in
        // progress. Wait for the existing ones to be finished.
        // To do that, first we will decrement this very operation.
        // When the counter goes to 1, Stop event is set.
        //

        Bus_DecIoCount(DeviceData);

        KeWaitForSingleObject(
                   &DeviceData->StopEvent,
                   Executive, // Waiting reason of a driver
                   KernelMode, // Waiting in kernel mode
                   FALSE, // No allert
                   NULL); // No timeout

        //
        // Increment the counter back because this IRP has to
        // be sent down to the lower stack.
        //

        Bus_IncIoCount (DeviceData);

        //
        // Free resources given by start device.
        //

        SET_NEW_PNP_STATE(DeviceData, Stopped);

        //
        // We don't need a completion routine so fire and forget.
        //
        // Set the current stack location to the next stack location and
        // call the next device object.
        //

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        SET_NEW_PNP_STATE(DeviceData, RemovePending);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        //
        // First check to see whether you have received cancel-remove
        // without first receiving a query-remove. This could happen if
        // someone above us fails a query-remove and passes down the
        // subsequent cancel-remove.
        //

        if (RemovePending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-remove, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        Irp->IoStatus.Status = STATUS_SUCCESS;// You must not fail the IRP.
        break;

    case IRP_MN_SURPRISE_REMOVAL:

        //
        // The device has been unexpectedly removed from the machine
        // and is no longer available for I/O. Bus_RemoveFdo clears
        // all the resources, frees the interface and de-registers
        // with WMI, but it doesn't delete the FDO. That's done
        // later in Remove device query.
        //

        SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
        Bus_RemoveFdo(DeviceData);

        ExAcquireFastMutex (&DeviceData->Mutex);

        listHead = &DeviceData->ListOfPDOs;

        for(entry = listHead->Flink,nextEntry = entry->Flink;
            entry != listHead;
            entry = nextEntry,nextEntry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            RemoveEntryList (&pdoData->Link);
            InitializeListHead (&pdoData->Link);
            pdoData->ParentFdo  = NULL;
            pdoData->ReportedMissing = TRUE;
        }

        ExReleaseFastMutex (&DeviceData->Mutex);

        Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP.
        break;

    case IRP_MN_REMOVE_DEVICE:

        //
        // The Plug & Play system has dictated the removal of this device.
        // We have no choice but to detach and delete the device object.
        //

        //
        // Check the state flag to see whether you are surprise removed
        //

        if (DeviceData->DevicePnPState != SurpriseRemovePending)
        {
            Bus_RemoveFdo(DeviceData);
        }

        SET_NEW_PNP_STATE(DeviceData, Deleted);

        //
        // Wait for all outstanding requests to complete.
        // We need two decrements here, one for the increment in
        // the beginning of this function, the other for the 1-biased value of
        // OutstandingIO.
        //

        Bus_DecIoCount (DeviceData);

        //
        // The requestCount is at least one here (is 1-biased)
        //

        Bus_DecIoCount (DeviceData);

        KeWaitForSingleObject (
                &DeviceData->RemoveEvent,
                Executive,
                KernelMode,
                FALSE,
                NULL);

        //
        // Typically the system removes all the  children before
        // removing the parent FDO. If for any reason child Pdos are
        // still present we will destroy them explicitly, with one exception -
        // we will not delete the PDOs that are in SurpriseRemovePending state.
        //

        ExAcquireFastMutex (&DeviceData->Mutex);

        listHead = &DeviceData->ListOfPDOs;

        for(entry = listHead->Flink,nextEntry = entry->Flink;
            entry != listHead;
            entry = nextEntry,nextEntry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            RemoveEntryList (&pdoData->Link);
            if (SurpriseRemovePending == pdoData->DevicePnPState)
            {
                //
                // We will reinitialize the list head so that we
                // wouldn't barf when we try to delink this PDO from
                // the parent's PDOs list, when the system finally
                // removes the PDO. Let's also not forget to set the
                // ReportedMissing flag to cause the deletion of the PDO.
                //
                Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO,
                ("\tFound a surprise removed device: 0x%p\n", pdoData->Self));
                InitializeListHead (&pdoData->Link);
                pdoData->ParentFdo  = NULL;
                pdoData->ReportedMissing = TRUE;
                continue;
            }
            DeviceData->NumPDOs--;
            Bus_DestroyPdo (pdoData->Self, pdoData);
        }

        ExReleaseFastMutex (&DeviceData->Mutex);

        //
        // We need to send the remove down the stack before we detach,
        // but we don't need to wait for the completion of this operation
        // (and to register a completion routine).
        //

        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->NextLowerDriver, Irp);
        //
        // Detach from the underlying devices.
        //

        IoDetachDevice (DeviceData->NextLowerDriver);

        Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO,
                        ("\tDeleting FDO: 0x%p\n", DeviceObject));

        IoDeleteDevice (DeviceObject);

        return status;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                   ("\tQueryDeviceRelation Type: %s\n",
                    DbgDeviceRelationString(\
                    IrpStack->Parameters.QueryDeviceRelations.Type)));

        if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) {
            //
            // We don't support any other Device Relations
            //
            break;
        }

        //
        // Tell the plug and play system about all the PDOs.
        //
        // There might also be device relations below and above this FDO,
        // so, be sure to propagate the relations from the upper drivers.
        //
        // No Completion routine is needed so long as the status is preset
        // to success.  (PDOs complete plug and play irps with the current
        // IoStatus.Status and IoStatus.Information as the default.)
        //

        ExAcquireFastMutex (&DeviceData->Mutex);

        oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
        if (oldRelations) {
            prevcount = oldRelations->Count;
            if (!DeviceData->NumPDOs) {
                //
                // There is a device relations struct already present and we have
                // nothing to add to it, so just call IoSkip and IoCall
                //
                ExReleaseFastMutex (&DeviceData->Mutex);
                break;
            }
        }
        else  {
            prevcount = 0;
        }

        //
        // Calculate the number of PDOs actually present on the bus
        //
        numPdosPresent = 0;
        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {
            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            if (pdoData->Present)
                numPdosPresent++;
        }

        //
        // Need to allocate a new relations structure and add our
        // PDOs to it.
        //

        length = sizeof(DEVICE_RELATIONS) +
                ((numPdosPresent + prevcount) * sizeof (PDEVICE_OBJECT)) -1;

        relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag (PagedPool,
                                        length, BUSENUM_POOL_TAG);

        if (NULL == relations) {
            //
            // Fail the IRP
            //
            ExReleaseFastMutex (&DeviceData->Mutex);
            Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
            Bus_DecIoCount (DeviceData);
            return status;

        }

        //
        // Copy in the device objects so far
        //
        if (prevcount) {
            RtlCopyMemory (relations->Objects, oldRelations->Objects,
                                      prevcount * sizeof (PDEVICE_OBJECT));
        }

        relations->Count = prevcount + numPdosPresent;

        //
        // For each PDO present on this bus add a pointer to the device relations
        // buffer, being sure to take out a reference to that object.
        // The Plug & Play system will dereference the object when it is done
        // with it and free the device relations buffer.
        //

        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            if (pdoData->Present) {
                relations->Objects[prevcount] = pdoData->Self;
                ObReferenceObject (pdoData->Self);
                prevcount++;
            } else {
                pdoData->ReportedMissing = TRUE;
            }
        }

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                           ("\t#PDOS present = %d\n\t#PDOs reported = %d\n",
                             DeviceData->NumPDOs, relations->Count));

        //
        // Replace the relations structure in the IRP with the new
        // one.
        //
        if (oldRelations) {
            ExFreePool (oldRelations);
        }
        Irp->IoStatus.Information = (ULONG_PTR) relations;

        ExReleaseFastMutex (&DeviceData->Mutex);

        //
        // Set up and pass the IRP further down the stack
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    default:

        //
        // In the default case we merely call the next driver.
        // We must not modify Irp->IoStatus.Status or complete the IRP.
        //

        break;
    }

    IoSkipCurrentIrpStackLocation (Irp);
    status = IoCallDriver (DeviceData->NextLowerDriver, Irp);
    Bus_DecIoCount (DeviceData);
    return status;
}
예제 #5
0
NTSTATUS	
DPDispatchPnp(
	IN	PDEVICE_OBJECT	DeviceObject,
	IN	PIRP			Irp
	)
{
	//用来指向过滤设备的设备扩展的指针
	PDP_FILTER_DEV_EXTENSION	DevExt = DeviceObject->DeviceExtension;
	//返回值
	NTSTATUS ntStatus = STATUS_SUCCESS;
	//用来指向irp stack的指针
	PIO_STACK_LOCATION  irpsp = IoGetCurrentIrpStackLocation(Irp);

	switch(irpsp->MinorFunction) 
	{
	case IRP_MN_REMOVE_DEVICE:
		//如果是PnP manager发过来的移除设备的irp,将进入这里
		{
			//这里主要做一些清理工作
			if (DevExt->ThreadTermFlag != TRUE && NULL != DevExt->ThreadHandle)
			{
				//如果线程还在运行的话需要停止它,这里通过设置线程停止运行的标志并且发送事件信息,让线程自己终止运行
				DevExt->ThreadTermFlag = TRUE;
				KeSetEvent(
					&DevExt->ReqEvent,
					(KPRIORITY) 0,
					FALSE
					);
				//等待线程结束
				KeWaitForSingleObject(
					DevExt->ThreadHandle,
					Executive,
					KernelMode,
					FALSE,
					NULL
					);
				//解除引用线程对象
				ObDereferenceObject(DevExt->ThreadHandle);
			}
	 		if (NULL != DevExt->Bitmap)
	 		{
				//如果还有位图,就释放
	 			DPBitmapFree(DevExt->Bitmap);
	 		}
			if (NULL != DevExt->LowerDevObj)
			{
				//如果存在着下层设备,就先去掉挂接
				IoDetachDevice(DevExt->LowerDevObj);
			}
	 		if (NULL != DevExt->FltDevObj)
	 		{
				//如果存在过滤设备,就要删除它
	 			IoDeleteDevice(DevExt->FltDevObj);
	 		}
			break;
		}
	//这个是PnP 管理器用来询问设备能否支持特殊文件的irp,作为卷的过滤驱动,我们必须处理
	case IRP_MN_DEVICE_USAGE_NOTIFICATION:
		{
			BOOLEAN setPagable;
			//如果是询问是否支持休眠文件和dump文件,则直接下发给下层设备去处理
			if (irpsp->Parameters.UsageNotification.Type != DeviceUsageTypePaging) 
			{
				ntStatus = DPSendToNextDriver(
					DevExt->LowerDevObj,
					Irp);
				return ntStatus; 
			}
			//这里等一下分页计数事件
			ntStatus = KeWaitForSingleObject(
				&DevExt->PagingPathCountEvent,
				Executive, 
				KernelMode,
				FALSE, 
				NULL);

			//setPagable初始化为假,是没有设置过DO_POWER_PAGABLE的意思
			setPagable = FALSE;
			if (!irpsp->Parameters.UsageNotification.InPath &&
				DevExt->PagingPathCount == 1 ) 
			{
				//如果是PnP manager通知我们将要删去分页文件,且我们目前只剩下最后一个分页文件的时候会进入这里
				if (DeviceObject->Flags & DO_POWER_INRUSH)
				{} 
				else 
				{
					//到这里说明没有分页文件在这个设备上了,需要设置DO_POWER_PAGABLE这一位了
					DeviceObject->Flags |= DO_POWER_PAGABLE;
					setPagable = TRUE;
				}
			}
			//到这里肯定是关于分页文件的是否可建立查询,或者是删除的通知,我们交给下层设备去做。这里需要用同步的方式给下层设备,也就是说要等待下层设备的返回
			ntStatus = DPForwardIrpSync(DevExt->LowerDevObj,Irp);

			if (NT_SUCCESS(ntStatus)) 
			{
				//如果发给下层设备的请求成功了,说明下层设备支持这个操作,会执行到这里
				//在成功的条件下我们来改变我们自己的计数值,这样就能记录我们现在这个设备上到底有多少个分页文件
				IoAdjustPagingPathCount(
					&DevExt->PagingPathCount,
					irpsp->Parameters.UsageNotification.InPath);
				if (irpsp->Parameters.UsageNotification.InPath) 
				{
					if (DevExt->PagingPathCount == 1) 
					{
						//如果这个请求是一个建立分页文件的查询请求,并且下层设备支持这个请求,而且这是第一个在这个设备上的分页文件,那么我们需要清除DO_POWER_PAGABLE位
						DeviceObject->Flags &= ~DO_POWER_PAGABLE;
					}
				}
			}
			else 
			{
				//到这里说明给下层设备发请求失败了,下层设备不支持这个请求,这时候我们需要把之前做过的操作还原
				if (setPagable == TRUE) 
				{
					//根据setPagable变量的值来判断我们之前是否做过对DO_POWER_PAGABLE的设置,如果有的话就清楚这个设置
					DeviceObject->Flags &= ~DO_POWER_PAGABLE;
					setPagable = FALSE;
				}
			}
			//设置分页计数事件
			KeSetEvent(
				&DevExt->PagingPathCountEvent,
				IO_NO_INCREMENT, 
				FALSE
				);
			//到这里我们就可以完成这个irp请求了
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			return ntStatus;
		}		
	default:
		break;
	}
	return DPSendToNextDriver(
		DevExt->LowerDevObj,
		Irp);

}
예제 #6
0
// add device
NTSTATUS AddDevice(PDRIVER_OBJECT pDriver,PDEVICE_OBJECT pPhysicalDeviceObject)
{
	NTSTATUS status;
	PDEVICE_OBJECT pDevice = NULL;
	PFdoExt pFdoExt = NULL;
	__try
	{
		UNICODE_STRING busFdoName;
		RtlInitUnicodeString(&busFdoName,BUS_FDO_NAME);
		status = IoCreateDevice(pDriver,sizeof(FdoExt),&busFdoName,FILE_DEVICE_BUS_EXTENDER,FILE_DEVICE_SECURE_OPEN,
								FALSE,&pDevice);

		if(!NT_SUCCESS(status))
			ExRaiseStatus(status);

		pFdoExt = static_cast<PFdoExt>(pDevice->DeviceExtension);
		RtlZeroMemory(pFdoExt,sizeof(FdoExt));

		status = IoRegisterDeviceInterface(pPhysicalDeviceObject,&GUID_TIAMO_BUS,NULL,&pFdoExt->m_symbolicName);
		if(!NT_SUCCESS(status))
			ExRaiseStatus(status);

		KeInitializeEvent(&pFdoExt->m_evRemove,SynchronizationEvent,FALSE);

		KeInitializeEvent(&pFdoExt->m_evStop,SynchronizationEvent,TRUE);

		ExInitializeFastMutex (&pFdoExt->m_mutexEnumPdo);

		pFdoExt->m_sysPowerState = PowerSystemWorking;
		pFdoExt->m_devPowerState = PowerDeviceD3;

		pFdoExt->m_bFdo = TRUE;
		pFdoExt->m_pPhysicalDevice = pPhysicalDeviceObject;

		pFdoExt->m_pLowerDevice = IoAttachDeviceToDeviceStack(pDevice,pPhysicalDeviceObject);

		pFdoExt->m_ulCurrentPnpState = -1;
		pFdoExt->m_ulPrevPnpState = -1;

		pFdoExt->m_ulOutstandingIO = 1;

		//pDevice->Flags |= DO_POWER_PAGABLE;

		POWER_STATE state;
		state.DeviceState = PowerDeviceD0;
		PoSetPowerState(pDevice,DevicePowerState,state);

		pDevice->Flags &= ~DO_DEVICE_INITIALIZING;

		devDebugPrint(DRIVER_NAME"*******AddDevice called,fdo createed.\n");
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		if(pFdoExt && pFdoExt->m_pLowerDevice)
		{
			IoDetachDevice(pFdoExt->m_pLowerDevice);
			RtlFreeUnicodeString(&pFdoExt->m_symbolicName);
		}

		if(pDevice)
		{
			IoDeleteDevice(pDevice);
		}
	}

	return status;
}
예제 #7
0
파일: fdo.c 프로젝트: GYGit/reactos
NTSTATUS NTAPI
PciIdeXAddDevice(
	IN PDRIVER_OBJECT DriverObject,
	IN PDEVICE_OBJECT Pdo)
{
	PPCIIDEX_DRIVER_EXTENSION DriverExtension;
	PFDO_DEVICE_EXTENSION DeviceExtension;
	PDEVICE_OBJECT Fdo;
	ULONG BytesRead;
	PCI_COMMON_CONFIG PciConfig;
	NTSTATUS Status;

	DPRINT("PciIdeXAddDevice(%p %p)\n", DriverObject, Pdo);

	DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
	ASSERT(DriverExtension);

	Status = IoCreateDevice(
		DriverObject,
		sizeof(FDO_DEVICE_EXTENSION) + DriverExtension->MiniControllerExtensionSize,
		NULL,
		FILE_DEVICE_BUS_EXTENDER,
		FILE_DEVICE_SECURE_OPEN,
		TRUE,
		&Fdo);
	if (!NT_SUCCESS(Status))
	{
		DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
		return Status;
	}

	DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
	RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));

	DeviceExtension->Common.IsFDO = TRUE;

	Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
	if (!NT_SUCCESS(Status))
	{
		DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
		return Status;
	}

	Status = GetBusInterface(DeviceExtension);
	if (!NT_SUCCESS(Status))
	{
		DPRINT("GetBusInterface() failed with status 0x%08lx\n", Status);
		IoDetachDevice(DeviceExtension->LowerDevice);
		return Status;
	}

	BytesRead = (*DeviceExtension->BusInterface->GetBusData)(
		DeviceExtension->BusInterface->Context,
		PCI_WHICHSPACE_CONFIG,
		&PciConfig,
		0,
		PCI_COMMON_HDR_LENGTH);
	if (BytesRead != PCI_COMMON_HDR_LENGTH)
	{
		DPRINT("BusInterface->GetBusData() failed()\n");
		ReleaseBusInterface(DeviceExtension);
		IoDetachDevice(DeviceExtension->LowerDevice);
		return STATUS_IO_DEVICE_ERROR;
	}

	DeviceExtension->VendorId = PciConfig.VendorID;
	DeviceExtension->DeviceId = PciConfig.DeviceID;

	Fdo->Flags &= ~DO_DEVICE_INITIALIZING;

	return STATUS_SUCCESS;
}
예제 #8
0
/**
 * PnP Request handler.
 *
 * @param  pDevObj    Device object.
 * @param  pIrp       Request packet.
 */
NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    PVBOXGUESTDEVEXT   pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
    PIO_STACK_LOCATION pStack  = IoGetCurrentIrpStackLocation(pIrp);

#ifdef LOG_ENABLED
    static char* aszFnctName[] =
    {
        "IRP_MN_START_DEVICE",
        "IRP_MN_QUERY_REMOVE_DEVICE",
        "IRP_MN_REMOVE_DEVICE",
        "IRP_MN_CANCEL_REMOVE_DEVICE",
        "IRP_MN_STOP_DEVICE",
        "IRP_MN_QUERY_STOP_DEVICE",
        "IRP_MN_CANCEL_STOP_DEVICE",
        "IRP_MN_QUERY_DEVICE_RELATIONS",
        "IRP_MN_QUERY_INTERFACE",
        "IRP_MN_QUERY_CAPABILITIES",
        "IRP_MN_QUERY_RESOURCES",
        "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
        "IRP_MN_QUERY_DEVICE_TEXT",
        "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
        "",
        "IRP_MN_READ_CONFIG",
        "IRP_MN_WRITE_CONFIG",
        "IRP_MN_EJECT",
        "IRP_MN_SET_LOCK",
        "IRP_MN_QUERY_ID",
        "IRP_MN_QUERY_PNP_DEVICE_STATE",
        "IRP_MN_QUERY_BUS_INFORMATION",
        "IRP_MN_DEVICE_USAGE_NOTIFICATION",
        "IRP_MN_SURPRISE_REMOVAL",
    };
    Log(("VBoxGuest::vboxguestwinGuestPnp: MinorFunction: %s\n",
           pStack->MinorFunction < (sizeof(aszFnctName) / sizeof(aszFnctName[0]))
         ? aszFnctName[pStack->MinorFunction]
         : "Unknown"));
#endif

    NTSTATUS rc = STATUS_SUCCESS;
    switch (pStack->MinorFunction)
    {
        case IRP_MN_START_DEVICE:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE\n"));

            /* This must be handled first by the lower driver. */
            rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE);

            if (   NT_SUCCESS(rc)
                && NT_SUCCESS(pIrp->IoStatus.Status))
            {
                Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n",
                     pStack->Parameters.StartDevice.AllocatedResources));

                if (!pStack->Parameters.StartDevice.AllocatedResources)
                {
                    Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE: No resources, pDevExt = %p, nextLowerDriver = %p!\n",
                         pDevExt, pDevExt ? pDevExt->win.s.pNextLowerDriver : NULL));
                    rc = STATUS_UNSUCCESSFUL;
                }
                else
                {
                    rc = vboxguestwinInit(pDevObj, pIrp);
                }
            }

            if (NT_ERROR(rc))
            {
                Log(("VBoxGuest::vboxguestwinGuestPnp: START_DEVICE: Error: rc = 0x%x\n", rc));

                /* Need to unmap memory in case of errors ... */
                vboxguestwinUnmapVMMDevMemory(pDevExt);
            }
            break;
        }

        case IRP_MN_CANCEL_REMOVE_DEVICE:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_REMOVE_DEVICE\n"));

            /* This must be handled first by the lower driver. */
            rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE);

            if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGREMOVE)
            {
                /* Return to the state prior to receiving the IRP_MN_QUERY_REMOVE_DEVICE request. */
                pDevExt->win.s.devState = pDevExt->win.s.prevDevState;
            }

            /* Complete the IRP. */
            break;
        }

        case IRP_MN_SURPRISE_REMOVAL:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: IRP_MN_SURPRISE_REMOVAL\n"));

            VBOXGUEST_UPDATE_DEVSTATE(pDevExt, SURPRISEREMOVED);

            /* Do nothing here actually. Cleanup is done in IRP_MN_REMOVE_DEVICE.
             * This request is not expected for VBoxGuest.
             */
            LogRel(("VBoxGuest: unexpected device removal\n"));

            /* Pass to the lower driver. */
            pIrp->IoStatus.Status = STATUS_SUCCESS;

            IoSkipCurrentIrpStackLocation(pIrp);

            rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);

            /* Do not complete the IRP. */
            return rc;
        }

        case IRP_MN_QUERY_REMOVE_DEVICE:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_REMOVE_DEVICE\n"));

#ifdef VBOX_REBOOT_ON_UNINSTALL
            Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n"));
            rc = STATUS_UNSUCCESSFUL;
#endif /* VBOX_REBOOT_ON_UNINSTALL */

            if (NT_SUCCESS(rc))
            {
                VBOXGUEST_UPDATE_DEVSTATE(pDevExt, PENDINGREMOVE);

                /* This IRP passed down to lower driver. */
                pIrp->IoStatus.Status = STATUS_SUCCESS;

                IoSkipCurrentIrpStackLocation(pIrp);

                rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
                Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));

                /* we must not do anything the IRP after doing IoSkip & CallDriver
                 * since the driver below us will complete (or already have completed) the IRP.
                 * I.e. just return the status we got from IoCallDriver */
                return rc;
            }

            /* Complete the IRP on failure. */
            break;
        }

        case IRP_MN_REMOVE_DEVICE:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: REMOVE_DEVICE\n"));

            VBOXGUEST_UPDATE_DEVSTATE(pDevExt, REMOVED);

            /* Free hardware resources. */
            /* @todo this should actually free I/O ports, interrupts, etc. */
            rc = vboxguestwinCleanup(pDevObj);
            Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: vboxguestwinCleanup rc = 0x%08X\n", rc));

            /*
             * We need to send the remove down the stack before we detach,
             * but we don't need to wait for the completion of this operation
             * (and to register a completion routine).
             */
            pIrp->IoStatus.Status = STATUS_SUCCESS;

            IoSkipCurrentIrpStackLocation(pIrp);

            rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
            Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc));

            IoDetachDevice(pDevExt->win.s.pNextLowerDriver);

            Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Removing device ...\n"));

            /* Destroy device extension and clean up everything else. */
            VBoxGuestDeleteDevExt(pDevExt);

            /* Remove DOS device + symbolic link. */
            UNICODE_STRING win32Name;
            RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
            IoDeleteSymbolicLink(&win32Name);

            Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Deleting device ...\n"));

            /* Last action: Delete our device! pDevObj is *not* failed
             * anymore after this call! */
            IoDeleteDevice(pDevObj);

            Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Device removed!\n"));

            /* Propagating rc from IoCallDriver. */
            return rc; /* Make sure that we don't do anything below here anymore! */
        }

        case IRP_MN_CANCEL_STOP_DEVICE:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_STOP_DEVICE\n"));

            /* This must be handled first by the lower driver. */
            rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE);

            if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGSTOP)
            {
                /* Return to the state prior to receiving the IRP_MN_QUERY_STOP_DEVICE request. */
                pDevExt->win.s.devState = pDevExt->win.s.prevDevState;
            }

            /* Complete the IRP. */
            break;
        }

        case IRP_MN_QUERY_STOP_DEVICE:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_STOP_DEVICE\n"));

#ifdef VBOX_REBOOT_ON_UNINSTALL
            Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n"));
            pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
#endif /* VBOX_REBOOT_ON_UNINSTALL */

            if (NT_SUCCESS(rc))
            {
                VBOXGUEST_UPDATE_DEVSTATE(pDevExt, PENDINGSTOP);

                /* This IRP passed down to lower driver. */
                pIrp->IoStatus.Status = STATUS_SUCCESS;

                IoSkipCurrentIrpStackLocation(pIrp);

                rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
                Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));

                /* we must not do anything with the IRP after doing IoSkip & CallDriver
                 * since the driver below us will complete (or already have completed) the IRP.
                 * I.e. just return the status we got from IoCallDriver */
                return rc;
            }

            /* Complete the IRP on failure. */
            break;
        }

        case IRP_MN_STOP_DEVICE:
        {
            Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: STOP_DEVICE\n"));

            VBOXGUEST_UPDATE_DEVSTATE(pDevExt, STOPPED);

            /* Free hardware resources. */
            /* @todo this should actually free I/O ports, interrupts, etc. */
            rc = vboxguestwinCleanup(pDevObj);
            Log(("VBoxGuest::vboxguestwinGuestPnp: STOP_DEVICE: cleaning up, rc = 0x%x\n", rc));

            /* Pass to the lower driver. */
            pIrp->IoStatus.Status = STATUS_SUCCESS;

            IoSkipCurrentIrpStackLocation(pIrp);

            rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
            Log(("VBoxGuest::vboxguestwinGuestPnp: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc));

            return rc;
        }

        default:
        {
            IoSkipCurrentIrpStackLocation(pIrp);
            rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
            return rc;
        }
    }

    pIrp->IoStatus.Status = rc;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    Log(("VBoxGuest::vboxguestwinGuestPnp: Returning with rc = 0x%x\n", rc));
    return rc;
}
예제 #9
0
//-------------------------------------------------------------------------------------------------
NTSTATUS
CHCDController::Initialize(
    IN PROOTHDCCONTROLLER RootHCDController,
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PhysicalDeviceObject)
{
    NTSTATUS Status;
    PCOMMON_DEVICE_EXTENSION DeviceExtension;

    //
    // create usb hardware
    //
    Status = CreateUSBHardware(&m_Hardware);
    if (!NT_SUCCESS(Status))
    {
        //
        // failed to create hardware object
        //
        DPRINT1("Failed to create hardware object\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // initialize members
    //
    m_DriverObject = DriverObject;
    m_PhysicalDeviceObject = PhysicalDeviceObject;
    m_RootController = RootHCDController;

    //
    // create FDO
    //
    Status = CreateFDO(m_DriverObject, &m_FunctionalDeviceObject);
    if (!NT_SUCCESS(Status))
    {
        //
        // failed to create PDO
        //
        return Status;
    }

    //
    // now attach to device stack
    //
    m_NextDeviceObject = IoAttachDeviceToDeviceStack(m_FunctionalDeviceObject, m_PhysicalDeviceObject);
    if (!m_NextDeviceObject)
    {
        //
        // failed to attach to device stack
        //
        IoDeleteDevice(m_FunctionalDeviceObject);
        m_FunctionalDeviceObject = 0;

        return STATUS_NO_SUCH_DEVICE;
    }

    //
    // initialize hardware object
    //
    Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("[%s] Failed to initialize hardware object %x\n", m_Hardware->GetUSBType(), Status);

        //
        // failed to initialize hardware object, detach from device stack
        //
        IoDetachDevice(m_NextDeviceObject);

        //
        // now delete the device
        //
        IoDeleteDevice(m_FunctionalDeviceObject);

        //
        // nullify pointers :)
        //
        m_FunctionalDeviceObject = 0;
        m_NextDeviceObject = 0;

        return Status;
    }

    //
    // get usb controller type
    //
    m_USBType = m_Hardware->GetUSBType();


    //
    // set device flags
    //
    m_FunctionalDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;


    //
    // get device extension
    //
    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_FunctionalDeviceObject->DeviceExtension;
    PC_ASSERT(DeviceExtension);

    //
    // initialize device extension
    //
    DeviceExtension->IsFDO = TRUE;
    DeviceExtension->IsHub = FALSE;
    DeviceExtension->Dispatcher = PDISPATCHIRP(this);

    //
    // device is initialized
    //
    m_FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;


    //
    // is there a root controller
    //
    if (m_RootController)
    {
        //
        // add reference
        //
        m_RootController->AddRef();

        //
        // register with controller
        //
        m_RootController->RegisterHCD(this);
    }


    //
    // done
    //
    return STATUS_SUCCESS;
}
예제 #10
0
NTSTATUS
FdoPnpControl(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp)
/*
 * FUNCTION: Handle Plug and Play IRPs for the PCI device object
 * ARGUMENTS:
 *     DeviceObject = Pointer to functional device object of the PCI driver
 *     Irp          = Pointer to IRP that should be handled
 * RETURNS:
 *     Status
 */
{
    PFDO_DEVICE_EXTENSION DeviceExtension;
    PIO_STACK_LOCATION IrpSp;
    NTSTATUS Status = Irp->IoStatus.Status;

    DPRINT("Called\n");

    DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    IrpSp = IoGetCurrentIrpStackLocation(Irp);
    switch (IrpSp->MinorFunction)
    {
#if 0
        case IRP_MN_CANCEL_REMOVE_DEVICE:
            Status = STATUS_NOT_IMPLEMENTED;
            break;

        case IRP_MN_CANCEL_STOP_DEVICE:
            Status = STATUS_NOT_IMPLEMENTED;
            break;

        case IRP_MN_DEVICE_USAGE_NOTIFICATION:
            Status = STATUS_NOT_IMPLEMENTED;
            break;

        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
            Status = STATUS_NOT_IMPLEMENTED;
            break;
#endif
        case IRP_MN_QUERY_DEVICE_RELATIONS:
            if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
                break;

            Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
            Irp->IoStatus.Status = Status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return Status;
#if 0
        case IRP_MN_QUERY_PNP_DEVICE_STATE:
            Status = STATUS_NOT_IMPLEMENTED;
            break;

        case IRP_MN_QUERY_REMOVE_DEVICE:
            Status = STATUS_NOT_IMPLEMENTED;
            break;
#endif
        case IRP_MN_START_DEVICE:
            DPRINT("IRP_MN_START_DEVICE received\n");
            Status = ForwardIrpAndWait(DeviceObject, Irp);
            if (NT_SUCCESS(Status))
                Status = FdoStartDevice(DeviceObject, Irp);

            Irp->IoStatus.Status = Status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return Status;

        case IRP_MN_QUERY_STOP_DEVICE:
            /* We don't support stopping yet */
            Status = STATUS_UNSUCCESSFUL;
            Irp->IoStatus.Status = Status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return Status;

        case IRP_MN_STOP_DEVICE:
            /* We can't fail this one so we fail the QUERY_STOP request that precedes it */
            break;
#if 0
        case IRP_MN_SURPRISE_REMOVAL:
            Status = STATUS_NOT_IMPLEMENTED;
            break;
#endif

        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
            break;

        case IRP_MN_REMOVE_DEVICE:
            /* Detach the device object from the device stack */
            IoDetachDevice(DeviceExtension->Ldo);

            /* Delete the device object */
            IoDeleteDevice(DeviceObject);

            /* Return success */
            Status = STATUS_SUCCESS;
            break;

        default:
            DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
            break;
    }

    Irp->IoStatus.Status = Status;
    IoSkipCurrentIrpStackLocation(Irp);
    Status = IoCallDriver(DeviceExtension->Ldo, Irp);

    DPRINT("Leaving. Status 0x%X\n", Status);

    return Status;
}
예제 #11
0
NTSTATUS
CHCDController::HandlePnp(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
{
    PIO_STACK_LOCATION IoStack;
    PCOMMON_DEVICE_EXTENSION DeviceExtension;
    PCM_RESOURCE_LIST RawResourceList;
    PCM_RESOURCE_LIST TranslatedResourceList;
    PDEVICE_RELATIONS DeviceRelations;
    NTSTATUS Status;

    //
    // get device extension
    //
    DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    //
    // sanity check
    //
    PC_ASSERT(DeviceExtension->IsFDO);

    //
    // get current stack location
    //
    IoStack = IoGetCurrentIrpStackLocation(Irp);

    switch(IoStack->MinorFunction)
    {
        case IRP_MN_START_DEVICE:
        {
            DPRINT("[%s] HandlePnp IRP_MN_START FDO\n", m_USBType);

            //
            // first start lower device object
            //
            Status = SyncForwardIrp(m_NextDeviceObject, Irp);

            if (NT_SUCCESS(Status))
            {
                //
                // operation succeeded, lets start the device
                //
                RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
                TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;

                if (m_Hardware)
                {
                    //
                    // start the hardware
                    //
                    Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList);
                }

                //
                // enable symbolic link
                //
                Status = SetSymbolicLink(TRUE);
            }

            DPRINT("[%s] HandlePnp IRP_MN_START FDO: Status %x\n", m_USBType ,Status);
            break;
        }
        case IRP_MN_QUERY_DEVICE_RELATIONS:
        {
            DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type);

            if (m_HubController == NULL)
            {
                //
                // create hub controller
                //
                Status = CreateHubController(&m_HubController);
                if (!NT_SUCCESS(Status))
                {
                    //
                    // failed to create hub controller
                    //
                    break;
                }

                //
                // initialize hub controller
                //
                Status = m_HubController->Initialize(m_DriverObject, PHCDCONTROLLER(this), m_Hardware, TRUE, 0 /* FIXME*/);
                if (!NT_SUCCESS(Status))
                {
                    //
                    // failed to initialize hub controller
                    //
                    break;
                }

                //
                // add reference to prevent it from getting deleting while hub driver adds / removes references
                //
                m_HubController->AddRef();
            }

            if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations)
            {
                //
                // allocate device relations
                //
                DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
 
                if (!DeviceRelations)
                {
                    //
                    // no memory
                    //
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                    break;
                }

                //
                // init device relations
                //
                DeviceRelations->Count = 1;
                Status = m_HubController->GetHubControllerDeviceObject(&DeviceRelations->Objects [0]);

                //
                // sanity check
                //
                PC_ASSERT(Status == STATUS_SUCCESS);

                ObReferenceObject(DeviceRelations->Objects [0]);

                //
                // store result
                //
                Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
                Status = STATUS_SUCCESS;
            }
            else
            {
                //
                // not supported
                //
                Status = STATUS_NOT_SUPPORTED;
            }
            break;
        }
        case IRP_MN_STOP_DEVICE:
        {
            DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType);

            if (m_Hardware)
            {
                //
                // stop the hardware
                //
                Status = m_Hardware->PnpStop();
            }
            else
            {
                //
                // fake success 
                //
                Status = STATUS_SUCCESS;
            }

            if (NT_SUCCESS(Status))
            {
                //
                // stop lower device
                //
                Status = SyncForwardIrp(m_NextDeviceObject, Irp);
            }
            break;
        }
        case IRP_MN_QUERY_REMOVE_DEVICE:
        case IRP_MN_QUERY_STOP_DEVICE:
        {
#if 0
            //
            // sure
            //
            Irp->IoStatus.Status = STATUS_SUCCESS;

            //
            // forward irp to next device object
            //
            IoSkipCurrentIrpStackLocation(Irp);
            return IoCallDriver(m_NextDeviceObject, Irp);
#else
            DPRINT1("[%s] Denying controller removal due to reinitialization bugs\n", m_USBType);
            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return STATUS_UNSUCCESSFUL;
#endif
        }
        case IRP_MN_REMOVE_DEVICE:
        {
            DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE FDO\n", m_USBType);

            //
            // delete the symbolic link
            //
            SetSymbolicLink(FALSE);

            //
            // forward irp to next device object
            //
            IoSkipCurrentIrpStackLocation(Irp);
            IoCallDriver(m_NextDeviceObject, Irp);

            //
            // detach device from device stack
            //
            IoDetachDevice(m_NextDeviceObject);

            //
            // delete device
            //
            IoDeleteDevice(m_FunctionalDeviceObject);

            return STATUS_SUCCESS;
        }
        default:
        {
            //
            // forward irp to next device object
            //
            IoSkipCurrentIrpStackLocation(Irp);
            return IoCallDriver(m_NextDeviceObject, Irp);
        }
    }

    //
    // store result and complete request
    //
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return Status;
}
예제 #12
0
파일: pnp.c 프로젝트: kcrazy/winekit
NTSTATUS
Serenum_FDO_PnP (
    IN PDEVICE_OBJECT       DeviceObject,
    IN PIRP                 Irp,
    IN PIO_STACK_LOCATION   IrpStack,
    IN PFDO_DEVICE_DATA     DeviceData
)
/*++
Routine Description:
    Handle requests from the PlugPlay system for the BUS itself

    NB: the various Minor functions of the PlugPlay system will not be
    overlapped and do not have to be reentrant

--*/
{
    NTSTATUS    status;
    KEVENT      event;
    ULONG       length;
    ULONG       i;
    PDEVICE_RELATIONS   relations;
    PIO_STACK_LOCATION  stack;
    PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
    ULONG DebugLevelDefault = SER_DEFAULT_DEBUG_OUTPUT_LEVEL;

    PAGED_CODE();

    status = Serenum_IncIoCount (DeviceData);
    if (!NT_SUCCESS (status)) {
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }

    stack = IoGetCurrentIrpStackLocation (Irp);

    switch (IrpStack->MinorFunction) {
    case IRP_MN_START_DEVICE:
        //
        // BEFORE you are allowed to ``touch'' the device object to which
        // the FDO is attached (that send an irp from the bus to the Device
        // object to which the bus is attached).   You must first pass down
        // the start IRP.  It might not be powered on, or able to access or
        // something.
        //

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Start Device\n"));

        if (DeviceData->Started) {
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                             ("Device already started\n"));
            status = STATUS_SUCCESS;
            break;
        }

        KeInitializeEvent (&event, NotificationEvent, FALSE);
        IoCopyCurrentIrpStackLocationToNext (Irp);

        IoSetCompletionRoutine (Irp,
                                SerenumSyncCompletion,
                                &event,
                                TRUE,
                                TRUE,
                                TRUE);

        status = IoCallDriver (DeviceData->TopOfStack, Irp);

        if (STATUS_PENDING == status) {
            // wait for it...

            status = KeWaitForSingleObject (&event,
                                            Executive,
                                            KernelMode,
                                            FALSE, // Not allertable
                                            NULL); // No timeout structure

            ASSERT (STATUS_SUCCESS == status);

            status = Irp->IoStatus.Status;
        }

        if (NT_SUCCESS(status)) {
            //
            // Now we can touch the lower device object as it is now started.
            //



            //
            // Get the debug level from the registry
            //

            if (NULL == (QueryTable = ExAllocatePool(
                                          PagedPool,
                                          sizeof(RTL_QUERY_REGISTRY_TABLE)*2
                                      ))) {
                Serenum_KdPrint (DeviceData, SER_DBG_PNP_ERROR,
                                 ("Failed to allocate memory to query registy\n"));
                DeviceData->DebugLevel = DebugLevelDefault;
            } else {
                RtlZeroMemory(
                    QueryTable,
                    sizeof(RTL_QUERY_REGISTRY_TABLE)*2
                );

                QueryTable[0].QueryRoutine = NULL;
                QueryTable[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
                QueryTable[0].EntryContext = &DeviceData->DebugLevel;
                QueryTable[0].Name      = L"DebugLevel";
                QueryTable[0].DefaultType   = REG_DWORD;
                QueryTable[0].DefaultData   = &DebugLevelDefault;
                QueryTable[0].DefaultLength= sizeof(ULONG);

                // CIMEXCIMEX: The rest of the table isn't filled in!

                if (!NT_SUCCESS(RtlQueryRegistryValues(
                                    RTL_REGISTRY_SERVICES,
                                    L"Serenum",
                                    QueryTable,
                                    NULL,
                                    NULL))) {
                    Serenum_KdPrint (DeviceData,SER_DBG_PNP_ERROR,
                                     ("Failed to get debug level from registry.  "
                                      "Using default\n"));
                    DeviceData->DebugLevel = DebugLevelDefault;
                }

                ExFreePool( QueryTable );
            }


            Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                             ("Start Device: Device started successfully\n"));
            DeviceData->Started = TRUE;
        }

        //
        // We must now complete the IRP, since we stopped it in the
        // completetion routine with MORE_PROCESSING_REQUIRED.
        //
        break;

    case IRP_MN_QUERY_STOP_DEVICE:
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                         ("Query Stop Device\n"));

        //
        // Test to see if there are any PDO created as children of this FDO
        // If there are then conclude the device is busy and fail the
        // query stop.
        //
        // CIMEXCIMEX
        // We could do better, by seing if the children PDOs are actually
        // currently open.  If they are not then we could stop, get new
        // resouces, fill in the new resouce values, and then when a new client
        // opens the PDO use the new resources.  But this works for now.
        //

        if (DeviceData->AttachedPDO
                || (DeviceData->EnumFlags & SERENUM_ENUMFLAG_PENDING)) {
            status = STATUS_UNSUCCESSFUL;

        } else {
            status = STATUS_SUCCESS;
        }

        Irp->IoStatus.Status = status;

        if (NT_SUCCESS(status)) {
            IoSkipCurrentIrpStackLocation (Irp);
            status = IoCallDriver (DeviceData->TopOfStack, Irp);
        } else {
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
        }

        Serenum_DecIoCount (DeviceData);
        return status;

    case IRP_MN_CANCEL_STOP_DEVICE:
        //
        // We always succeed a cancel stop
        //

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                         ("Cancel Stop Device\n"));

        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(DeviceData->TopOfStack, Irp);

        Serenum_DecIoCount (DeviceData);
        return status;

    case IRP_MN_STOP_DEVICE:
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Stop Device\n"));

        //
        // Wait for the enum thread to complete if it's running
        //

        SerenumWaitForEnumThreadTerminate(DeviceData);

        //
        // After the start IRP has been sent to the lower driver object, the
        // bus may NOT send any more IRPS down ``touch'' until another START
        // has occured.
        // What ever access is required must be done before the Irp is passed
        // on.
        //
        // Stop device means that the resources given durring Start device
        // are no revoked.  So we need to stop using them
        //

        DeviceData->Started = FALSE;

        //
        // We don't need a completion routine so fire and forget.
        //
        // Set the current stack location to the next stack location and
        // call the next device object.
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->TopOfStack, Irp);

        Serenum_DecIoCount (DeviceData);
        return status;

    case IRP_MN_REMOVE_DEVICE:
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Remove Device\n"));

        //
        // The PlugPlay system has detected the removal of this device.  We
        // have no choice but to detach and delete the device object.
        // (If we wanted to express and interest in preventing this removal,
        // we should have filtered the query remove and query stop routines.)
        //
        // Note! we might receive a remove WITHOUT first receiving a stop.
        // ASSERT (!DeviceData->Removed);


        //
        // Synchronize with the enum thread if it is running and wait
        // for it to finish
        //


        SerenumWaitForEnumThreadTerminate(DeviceData);

        // We will accept no new requests
        //
        DeviceData->Removed = TRUE;

        //
        // Complete any outstanding IRPs queued by the driver here.
        //

        //
        // Make the DCA go away.  Some drivers may choose to remove the DCA
        // when they receive a stop or even a query stop.  We just don't care.
        //
        (void)IoSetDeviceInterfaceState (&DeviceData->DevClassAssocName, FALSE);

        //
        // Here if we had any outstanding requests in a personal queue we should
        // complete them all now.
        //
        // Note, the device is guarenteed stopped, so we cannot send it any non-
        // PNP IRPS.
        //

        //
        // Fire and forget
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->TopOfStack, Irp);

        //
        // Wait for any outstanding threads to complete
        //

        //
        // Wait for all outstanding requests to complete
        //
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                         ("Waiting for outstanding requests\n"));
        i = InterlockedDecrement ((volatile LONG*)&DeviceData->OutstandingIO);

        ASSERT (0 < i);

        if (0 != InterlockedDecrement ((volatile LONG*)&DeviceData->OutstandingIO)) {
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_INFO,
                             ("Remove Device waiting for request to complete\n"));

            KeWaitForSingleObject (&DeviceData->RemoveEvent,
                                   Executive,
                                   KernelMode,
                                   FALSE, // Not Alertable
                                   NULL); // No timeout
        }
        //
        // Free the associated resources
        //

        //
        // Detach from the underlying devices.
        //
        Serenum_KdPrint(DeviceData, SER_DBG_PNP_INFO,
                        ("IoDetachDevice: 0x%x\n", DeviceData->TopOfStack));
        IoDetachDevice (DeviceData->TopOfStack);

        //
        // Clean up any resources here
        //


        ExFreePool (DeviceData->DevClassAssocName.Buffer);
        Serenum_KdPrint(DeviceData, SER_DBG_PNP_INFO,
                        ("IoDeleteDevice: 0x%x\n", DeviceObject));

        //
        // Remove any PDO's we ejected
        //

        if (DeviceData->AttachedPDO != NULL) {
            ASSERT(DeviceData->NumPDOs == 1);

            Serenum_PnPRemove(DeviceData->AttachedPDO, DeviceData->PdoData);
            DeviceData->PdoData = NULL;
            DeviceData->AttachedPDO = NULL;
            DeviceData->NumPDOs = 0;
        }

        IoDeleteDevice(DeviceObject);

        return status;

    case IRP_MN_QUERY_DEVICE_RELATIONS:
        if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) {
            //
            // We don't support this
            //
            Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                             ("Query Device Relations - Non bus\n"));
            goto SER_FDO_PNP_DEFAULT;
        }

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                         ("Query Bus Relations\n"));

        status = SerenumCheckEnumerations(DeviceData);


        //
        // Tell the plug and play system about all the PDOs.
        //
        // There might also be device relations below and above this FDO,
        // so, be sure to propagate the relations from the upper drivers.
        //
        // No Completion routine is needed so long as the status is preset
        // to success.  (PDOs complete plug and play irps with the current
        // IoStatus.Status and IoStatus.Information as the default.)
        //

        //KeAcquireSpinLock (&DeviceData->Spin, &oldIrq);

        i = (0 == Irp->IoStatus.Information) ? 0 :
            ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Count;
        // The current number of PDOs in the device relations structure

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                         ("#PDOS = %d + %d\n", i, DeviceData->NumPDOs));

        length = sizeof(DEVICE_RELATIONS) +
                 ((DeviceData->NumPDOs + i) * sizeof (PDEVICE_OBJECT));

        relations = (PDEVICE_RELATIONS) ExAllocatePool (NonPagedPool, length);

        if (NULL == relations) {
            Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            Serenum_DecIoCount(DeviceData);
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        //
        // Copy in the device objects so far
        //
        if (i) {
            RtlCopyMemory (
                relations->Objects,
                ((PDEVICE_RELATIONS) Irp->IoStatus.Information)->Objects,
                i * sizeof (PDEVICE_OBJECT));
        }
        relations->Count = DeviceData->NumPDOs + i;

        //
        // For each PDO on this bus add a pointer to the device relations
        // buffer, being sure to take out a reference to that object.
        // The PlugPlay system will dereference the object when it is done with
        // it and free the device relations buffer.
        //

        if (DeviceData->NumPDOs) {
            relations->Objects[relations->Count-1] = DeviceData->AttachedPDO;
            ObReferenceObject (DeviceData->AttachedPDO);
        }

        //
        // Set up and pass the IRP further down the stack
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;

        if (0 != Irp->IoStatus.Information) {
            ExFreePool ((PVOID) Irp->IoStatus.Information);
        }
        Irp->IoStatus.Information = (ULONG_PTR)relations;

        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->TopOfStack, Irp);

        Serenum_DecIoCount (DeviceData);

        return status;

    case IRP_MN_QUERY_REMOVE_DEVICE:
        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE,
                         ("Query Remove Device\n"));

        //
        // Wait for the enum thread to complete if it's running
        //
        SerenumWaitForEnumThreadTerminate(DeviceData);


        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->TopOfStack, Irp);
        Serenum_DecIoCount (DeviceData);
        return status;


    case IRP_MN_QUERY_CAPABILITIES: {

        PIO_STACK_LOCATION  irpSp;

        //
        // Send this down to the PDO first
        //

        KeInitializeEvent (&event, NotificationEvent, FALSE);
        IoCopyCurrentIrpStackLocationToNext (Irp);

        IoSetCompletionRoutine (Irp,
                                SerenumSyncCompletion,
                                &event,
                                TRUE,
                                TRUE,
                                TRUE);

        status = IoCallDriver (DeviceData->TopOfStack, Irp);

        if (STATUS_PENDING == status) {
            // wait for it...

            status = KeWaitForSingleObject (&event,
                                            Executive,
                                            KernelMode,
                                            FALSE, // Not allertable
                                            NULL); // No timeout structure

            ASSERT (STATUS_SUCCESS == status);

            status = Irp->IoStatus.Status;
        }

        if (NT_SUCCESS(status)) {

            irpSp = IoGetCurrentIrpStackLocation(Irp);

            DeviceData->SystemWake
                = irpSp->Parameters.DeviceCapabilities.Capabilities->SystemWake;
            DeviceData->DeviceWake
                = irpSp->Parameters.DeviceCapabilities.Capabilities->DeviceWake;
        }

        break;
    }



SER_FDO_PNP_DEFAULT:
    default:
        //
        // In the default case we merely call the next driver since
        // we don't know what to do.
        //
        Serenum_KdPrint (DeviceData, SER_DBG_PNP_TRACE, ("Default Case\n"));

        //
        // Fire and Forget
        //
        IoSkipCurrentIrpStackLocation (Irp);

        //
        // Done, do NOT complete the IRP, it will be processed by the lower
        // device object, which will complete the IRP
        //

        status = IoCallDriver (DeviceData->TopOfStack, Irp);
        Serenum_DecIoCount (DeviceData);
        return status;
    }

    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    Serenum_DecIoCount (DeviceData);
    return status;
}
예제 #13
0
파일: pnp.c 프로젝트: kcrazy/winekit
NTSTATUS
Serenum_AddDevice(IN PDRIVER_OBJECT DriverObject,
                  IN PDEVICE_OBJECT BusPhysicalDeviceObject)
/*++
Routine Description.
    A bus has been found.  Attach our FDO to it.
    Allocate any required resources.  Set things up.  And be prepared for the
    first ``start device.''

Arguments:
    BusPhysicalDeviceObject - Device object representing the bus.  That to which
        we attach a new FDO.

    DriverObject - This very self referenced driver.

--*/
{
    NTSTATUS status;
    PDEVICE_OBJECT deviceObject;
    PFDO_DEVICE_DATA pDeviceData;
    HANDLE keyHandle;
    ULONG actualLength;

    PAGED_CODE();

    Serenum_KdPrint_Def(SER_DBG_PNP_TRACE, ("Add Device: 0x%x\n",
                                            BusPhysicalDeviceObject));
    //
    // Create our FDO
    //

    status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_DATA), NULL,
                            FILE_DEVICE_BUS_EXTENDER, 0, TRUE, &deviceObject);

    if (NT_SUCCESS(status)) {
        pDeviceData = (PFDO_DEVICE_DATA)deviceObject->DeviceExtension;
        RtlFillMemory (pDeviceData, sizeof (FDO_DEVICE_DATA), 0);

        pDeviceData->IsFDO = TRUE;
        pDeviceData->DebugLevel = SER_DEFAULT_DEBUG_OUTPUT_LEVEL;
        pDeviceData->Self = deviceObject;
        pDeviceData->AttachedPDO = NULL;
        pDeviceData->NumPDOs = 0;
        pDeviceData->DeviceState = PowerDeviceD0;
        pDeviceData->SystemState = PowerSystemWorking;
        pDeviceData->PDOForcedRemove = FALSE;

        pDeviceData->SystemWake=PowerSystemUnspecified;
        pDeviceData->DeviceWake=PowerDeviceUnspecified;

        pDeviceData->Removed = FALSE;

        //
        // Set the PDO for use with PlugPlay functions
        //

        pDeviceData->UnderlyingPDO = BusPhysicalDeviceObject;


        //
        // Attach our filter driver to the device stack.
        // the return value of IoAttachDeviceToDeviceStack is the top of the
        // attachment chain.  This is where all the IRPs should be routed.
        //
        // Our filter will send IRPs to the top of the stack and use the PDO
        // for all PlugPlay functions.
        //

        pDeviceData->TopOfStack
            = IoAttachDeviceToDeviceStack(deviceObject, BusPhysicalDeviceObject);

        if (!pDeviceData->TopOfStack) {
            Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR,
                            ("AddDevice: IoAttach failed (%x)", status));
            IoDeleteDevice(deviceObject);
            return STATUS_UNSUCCESSFUL;
        }

        //
        // Set the type of IO we do
        //

        if (pDeviceData->TopOfStack->Flags & DO_BUFFERED_IO) {
            deviceObject->Flags |= DO_BUFFERED_IO;
        } else if (pDeviceData->TopOfStack->Flags & DO_DIRECT_IO) {
            deviceObject->Flags |= DO_DIRECT_IO;
        }

        //
        // Bias outstanding request to 1 so that we can look for a
        // transition to zero when processing the remove device PlugPlay IRP.
        //

        pDeviceData->OutstandingIO = 1;

        KeInitializeEvent(&pDeviceData->RemoveEvent, SynchronizationEvent,
                          FALSE);
        KeInitializeSemaphore(&pDeviceData->CreateSemaphore, 1, 1);
        KeInitializeSpinLock(&pDeviceData->EnumerationLock);



        //
        // Tell the PlugPlay system that this device will need an interface
        // device class shingle.
        //
        // It may be that the driver cannot hang the shingle until it starts
        // the device itself, so that it can query some of its properties.
        // (Aka the shingles guid (or ref string) is based on the properties
        // of the device.)
        //

        status = IoRegisterDeviceInterface(BusPhysicalDeviceObject,
                                           (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR,
                                           NULL,
                                           &pDeviceData->DevClassAssocName);

        if (!NT_SUCCESS(status)) {
            Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR,
                            ("AddDevice: IoRegisterDCA failed (%x)", status));
            IoDetachDevice(pDeviceData->TopOfStack);
            IoDeleteDevice(deviceObject);
            return status;
        }

        //
        // If for any reason you need to save values in a safe location that
        // clients of this DeviceClassAssociate might be interested in reading
        // here is the time to do so, with the function
        // IoOpenDeviceClassRegistryKey
        // the symbolic link name used is was returned in
        // pDeviceData->DevClassAssocName (the same name which is returned by
        // IoGetDeviceClassAssociations and the SetupAPI equivs.
        //

#if DBG
        {
            PWCHAR deviceName = NULL;
            ULONG nameLength = 0;

            status = IoGetDeviceProperty(BusPhysicalDeviceObject,
                                         DevicePropertyPhysicalDeviceObjectName, 0,
                                         NULL, &nameLength);

            if ((nameLength != 0) && (status == STATUS_BUFFER_TOO_SMALL)) {
                deviceName = ExAllocatePool(NonPagedPool, nameLength);

                if (NULL == deviceName) {
                    goto someDebugStuffExit;
                }

                IoGetDeviceProperty(BusPhysicalDeviceObject,
                                    DevicePropertyPhysicalDeviceObjectName,
                                    nameLength, deviceName, &nameLength);

                Serenum_KdPrint(pDeviceData, SER_DBG_PNP_TRACE,
                                ("AddDevice: %x to %x->%x (%ws) \n", deviceObject,
                                 pDeviceData->TopOfStack, BusPhysicalDeviceObject,
                                 deviceName));
            }

someDebugStuffExit:
            ;
            if (deviceName != NULL) {
                ExFreePool(deviceName);
            }
        }
#endif // DBG

        //
        // Turn on the shingle and point it to the given device object.
        //
        status = IoSetDeviceInterfaceState(&pDeviceData->DevClassAssocName,
                                           TRUE);

        if (!NT_SUCCESS(status)) {
            Serenum_KdPrint(pDeviceData, SER_DBG_PNP_ERROR,
                            ("AddDevice: IoSetDeviceClass failed (%x)", status));
            return status;
        }

        //
        // Open the registry and read in our settings
        //

        status = IoOpenDeviceRegistryKey(pDeviceData->UnderlyingPDO,
                                         PLUGPLAY_REGKEY_DEVICE,
                                         STANDARD_RIGHTS_READ, &keyHandle);

        if (status == STATUS_SUCCESS) {
            status
                = Serenum_GetRegistryKeyValue(keyHandle, L"SkipEnumerations",
                                              sizeof(L"SkipEnumerations"),
                                              &pDeviceData->SkipEnumerations,
                                              sizeof(pDeviceData->SkipEnumerations),
                                              &actualLength);

            if ((status != STATUS_SUCCESS)
                    || (actualLength != sizeof(pDeviceData->SkipEnumerations))) {
                pDeviceData->SkipEnumerations = 0;
                status = STATUS_SUCCESS;

            }

            ZwClose(keyHandle);
        }
    }

    if (NT_SUCCESS(status)) {
        deviceObject->Flags |= DO_POWER_PAGABLE;
        deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    }

    return status;
}
예제 #14
0
파일: pnp.c 프로젝트: imahmoodz/ScpToolkit
NTSTATUS Bus_AddDevice(__in PDRIVER_OBJECT DriverObject, __in PDEVICE_OBJECT PhysicalDeviceObject)
{
    NTSTATUS            status;
    PDEVICE_OBJECT      deviceObject = NULL;
    PFDO_DEVICE_DATA    deviceData = NULL;
    PWCHAR              deviceName = NULL;
    ULONG               nameLength;

    UNREFERENCED_PARAMETER(nameLength);
    PAGED_CODE();

    Bus_KdPrint(("Add Device: 0x%p\n", PhysicalDeviceObject));

    status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_DATA), NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject);

    if (!NT_SUCCESS (status))
    {
        goto End;
    }

    deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
    RtlZeroMemory(deviceData, sizeof (FDO_DEVICE_DATA));

    INITIALIZE_PNP_STATE(deviceData);

    deviceData->IsFDO = TRUE;
    deviceData->Self  = deviceObject;

    ExInitializeFastMutex(&deviceData->Mutex);
    InitializeListHead(&deviceData->ListOfPDOs);

    deviceData->UnderlyingPDO = PhysicalDeviceObject;

    deviceData->DevicePowerState = PowerDeviceUnspecified;
    deviceData->SystemPowerState = PowerSystemWorking;
    deviceData->OutstandingIO = 1;

    KeInitializeEvent(&deviceData->RemoveEvent, SynchronizationEvent, FALSE);
    KeInitializeEvent(&deviceData->StopEvent,   SynchronizationEvent, TRUE);

    deviceObject->Flags |= DO_POWER_PAGABLE;

    status = IoRegisterDeviceInterface(PhysicalDeviceObject, (LPGUID) &GUID_DEVINTERFACE_SCPVBUS, NULL, &deviceData->InterfaceName);

    if (!NT_SUCCESS(status))
	{
        Bus_KdPrint(("AddDevice: IoRegisterDeviceInterface failed (%x)", status));
        goto End;
    }

    deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);

    if (deviceData->NextLowerDriver == NULL)
	{
        status = STATUS_NO_SUCH_DEVICE;
        goto End;
    }

    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

End:

    if (deviceName)
	{
        ExFreePool(deviceName);
    }

    if (!NT_SUCCESS(status) && deviceObject)
	{
        if (deviceData && deviceData->NextLowerDriver)
		{
            IoDetachDevice(deviceData->NextLowerDriver);
        }

        IoDeleteDevice(deviceObject);
    }

    return status;
}
예제 #15
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;
}
예제 #16
0
void  
MalwFind_FastIoDetachDevice( IN PDEVICE_OBJECT pSourceDevice, IN PDEVICE_OBJECT pTargetDevice ) 
{
	PFLT_EXTENSION     pDevExt = NULL;
	PFAST_IO_DISPATCH  pFastIoDispatch = NULL;
	NAME_BUFFER        FullPath = {0};

	ASSERT( pSourceDevice && pTargetDevice );
	if(!pSourceDevice || !pTargetDevice) return;
	if(!MmIsAddressValid( pSourceDevice ) || !MmIsAddressValid( pTargetDevice )) return;

	__try
	{

		if(IS_MALFIND_DEVICE_OBJECT( pSourceDevice ))
		{
			pDevExt = (PFLT_EXTENSION)pSourceDevice->DeviceExtension;
			if(pDevExt) KdPrint(("MalwFind_DeviceObject--MalwFind_FastIoDetachDevice: [ %c:\\ ] \n", pDevExt->wcVol ));
			else        KdPrint(("MalwFind_DeviceObject--MalwFind_FastIoDetachDevice: \n"));
	
			ALLOCATE_N_POOL( FullPath );
			if(FullPath.pBuffer)
			{
				SET_POOL_ZERO( FullPath );
				FullPath.pBuffer[0] = pDevExt->wcVol;
				FullPath.pBuffer[1] = L':';
				FullPath.pBuffer[2] = L'\\';
				FullPath.pBuffer[3] = L'\0';
				FREE_N_POOL( FullPath );
			}

			FsdCleanupMountDevice( pSourceDevice );
			IoDetachDevice( pTargetDevice );
			IoDeleteDevice( pSourceDevice );
			pSourceDevice = NULL;
			return;
		}
		
		/*
		pDevExt = (PFLT_EXTENSION)pSourceDevice->DeviceExtension;
		ASSERT( pDevExt );
		if(!pDevExt) return;

		pFastIoDispatch = pDevExt->pLowerDeviceObject->DriverObject->FastIoDispatch;
		ASSERT( pFastIoDispatch );
		if(!pFastIoDispatch) return;

		if(VALID_FAST_IO( pFastIoDispatch, FastIoDetachDevice ))
		{
			(pFastIoDispatch->FastIoDetachDevice)( pSourceDevice, pTargetDevice );
		}
		*/

	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{

		KdPrint(("MalwFind_FastIoDetachDevice Exception Occured. \n"));

	}


}
예제 #17
0
static NTSTATUS
V4vAddDevice(PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
{
    NTSTATUS          status = STATUS_SUCCESS;
    UNICODE_STRING    deviceName;
    PDEVICE_OBJECT    fdo = NULL;
    PXENV4V_EXTENSION pde = NULL;
    LONG              val;
    BOOLEAN           symlink = FALSE;
    LARGE_INTEGER     seed;
    WCHAR            *szSddl = NULL;
    UNICODE_STRING    sddlString;
    CHAR             *szFpath = NULL;

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

    // We only allow one instance of this device type. If more than on pdo is created we need
    val = InterlockedCompareExchange(&g_deviceCreated, 1, 0);
    if (val != 0) {
        TraceWarning(("cannot instantiate more that one v4v device node.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    do {
        // Create our device
        RtlInitUnicodeString(&deviceName, V4V_DEVICE_NAME);
        szSddl = g_win5Sddl;
        RtlInitUnicodeString(&sddlString, szSddl);

        status = 
            IoCreateDeviceSecure(driverObject,
                                 sizeof(XENV4V_EXTENSION),
                                 &deviceName,
                                 FILE_DEVICE_UNKNOWN,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &sddlString,
                                 (LPCGUID)&GUID_SD_XENV4V_CONTROL_OBJECT,
                                 &fdo);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create device object - error: 0x%x\n", status));
            fdo = NULL;
            break;
        }

        pde = (PXENV4V_EXTENSION)fdo->DeviceExtension;
        RtlZeroMemory(pde, sizeof(XENV4V_EXTENSION));
        RtlStringCchCopyW(pde->symbolicLinkText, XENV4V_SYM_NAME_LEN, V4V_SYMBOLIC_NAME);
        RtlInitUnicodeString(&pde->symbolicLink, pde->symbolicLinkText);

        // Create our symbolic link
        status = IoCreateSymbolicLink(&pde->symbolicLink, &deviceName);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create symbolic - error: 0x%x\n", status));
            break;
        }
        symlink = TRUE;       

        // Get our xenstore path
        szFpath = xenbus_find_frontend(pdo);
        if (szFpath == NULL) {
            status = STATUS_NO_SUCH_DEVICE;
            TraceError(("failed to locate XenStore front end path\n"));
            break;
        }

        // Setup the extension
        pde->magic = XENV4V_MAGIC;
        pde->pdo = pdo;
        pde->fdo = fdo;
        IoInitializeRemoveLock(&pde->removeLock, 'v4vx', 0, 0);
        pde->frontendPath = szFpath;
        szFpath = NULL;
        pde->state = XENV4V_DEV_STOPPED; // wait for start
        pde->lastPoState = PowerSystemWorking;
        pde->virqPort = null_EVTCHN_PORT();
        KeInitializeDpc(&pde->virqDpc, V4vVirqNotifyDpc, fdo);
        KeInitializeSpinLock(&pde->virqLock);
        KeInitializeSpinLock(&pde->dpcLock);
        KeInitializeTimerEx(&pde->timer, NotificationTimer);
        KeInitializeDpc(&pde->timerDpc,
                        V4vConnectTimerDpc,
                        fdo);
        KeInitializeSpinLock(&pde->timerLock);
        pde->timerCounter = 0;
        InitializeListHead(&pde->contextList);
        KeInitializeSpinLock(&pde->contextLock);
        pde->contextCount = 0;
        InitializeListHead(&pde->ringList);
        KeInitializeSpinLock(&pde->ringLock);
        InitializeListHead(&pde->pendingIrpQueue);
        pde->pendingIrpCount = 0;
        KeInitializeSpinLock(&pde->queueLock);
        IoCsqInitializeEx(&pde->csqObject,
                          V4vCsqInsertIrpEx,
                          V4vCsqRemoveIrp,
                          V4vCsqPeekNextIrp,
                          V4vCsqAcquireLock,
                          V4vCsqReleaseLock,
                          V4vCsqCompleteCanceledIrp);
        InitializeListHead(&pde->destList);
        pde->destCount = 0;
        ExInitializeNPagedLookasideList(&pde->destLookasideList,
                                        NULL,
                                        NULL,
                                        0,
                                        sizeof(XENV4V_DESTINATION),
                                        XENV4V_TAG,
                                        0);
        KeQueryTickCount(&seed);
        pde->seed = seed.u.LowPart;

        // Now attach us to the stack
        pde->ldo = IoAttachDeviceToDeviceStack(fdo, pdo);
        if (pde->ldo == NULL) {
            TraceError(("failed to attach device to stack - error: 0x%x\n", status));
            status = STATUS_NO_SUCH_DEVICE;
            break;
        }

        // Use direct IO and let the IO manager directly map user buffers; clear the init flag
        fdo->Flags |= DO_DIRECT_IO;
        fdo->Flags &= ~DO_DEVICE_INITIALIZING;        

        // Made it here, go to connected state to be consistent
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CONNECTED);
    } while (FALSE);

    if (!NT_SUCCESS(status)) {
        if (fdo != NULL) {         
            if ((pde != NULL)&&(pde->ldo != NULL)) {
                IoDetachDevice(pde->ldo);
            }
            if (szFpath != NULL) {
                XmFreeMemory(szFpath);
            }
            if (symlink) {
                IoDeleteSymbolicLink(&pde->symbolicLink);
            }
            IoDeleteDevice(fdo);
        }
    }

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

    return status;
}
예제 #18
0
파일: fdo.c 프로젝트: RareHare/reactos
NTSTATUS
FDO_HandlePnp(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp)
{
    PIO_STACK_LOCATION IoStack;
    NTSTATUS Status;
    PFDO_DEVICE_EXTENSION FDODeviceExtension;

    /* Get device extension */
    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    ASSERT(FDODeviceExtension->Common.IsFDO);


    /* Get stack location */
    IoStack = IoGetCurrentIrpStackLocation(Irp);
    DPRINT("[USBCCGP] PnP Minor %x\n", IoStack->MinorFunction);
    switch(IoStack->MinorFunction)
    {
        case IRP_MN_REMOVE_DEVICE:
        {
            // Unconfigure device */
            DPRINT1("[USBCCGP] FDO IRP_MN_REMOVE\n");
            FDO_CloseConfiguration(DeviceObject);

            /* Send the IRP down the stack */
            Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject,
                                            Irp);
            if (NT_SUCCESS(Status))
            {
                /* Detach from the device stack */
                IoDetachDevice(FDODeviceExtension->NextDeviceObject);

                /* Delete the device object */
                IoDeleteDevice(DeviceObject);
            }

            /* Request completed */
            break;
        }
        case IRP_MN_START_DEVICE:
        {
            /* Start the device */
            Status = FDO_StartDevice(DeviceObject, Irp);
            break;
        }
        case IRP_MN_QUERY_DEVICE_RELATIONS:
        {
            /* Handle device relations */
            Status = FDO_DeviceRelations(DeviceObject, Irp);
            break;
        }
        case IRP_MN_QUERY_CAPABILITIES:
        {
            /* Copy capabilities */
            RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities,
                          &FDODeviceExtension->Capabilities,
                          sizeof(DEVICE_CAPABILITIES));
            Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
            if (NT_SUCCESS(Status))
            {
                /* Surprise removal ok */
                IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
            }
            break;
       }
        case IRP_MN_QUERY_REMOVE_DEVICE:
        case IRP_MN_QUERY_STOP_DEVICE:
        {
            /* Sure */
            Irp->IoStatus.Status = STATUS_SUCCESS;

            /* Forward irp to next device object */
            IoSkipCurrentIrpStackLocation(Irp);
            return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
        }
       default:
       {
            /* Forward irp to next device object */
            IoSkipCurrentIrpStackLocation(Irp);
            return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
       }

    }

    /* Complete request */
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return Status;
}
예제 #19
0
NTSTATUS
DPAddDevice(
    IN	PDRIVER_OBJECT	DriverObject,
    IN	PDEVICE_OBJECT	PhysicalDeviceObject
    )
{
	//NTSTATUS类型的函数返回值
	NTSTATUS					ntStatus = STATUS_SUCCESS;
    //用来指向过滤设备的设备扩展的指针
	PDP_FILTER_DEV_EXTENSION	DevExt = NULL;
	//过滤设备的下层设备的指针对象
	PDEVICE_OBJECT				LowerDevObj = NULL;
	//过滤设备的设备指针的指针对象
	PDEVICE_OBJECT				FltDevObj = NULL;
	//过滤设备的处理线程的线程句柄
	HANDLE						ThreadHandle = NULL;

	//建立一个过滤设备,这个设备是FILE_DEVICE_DISK类型的设备并且具有DP_FILTER_DEV_EXTENSION类型的设备扩展
	ntStatus = IoCreateDevice(
		DriverObject,
		sizeof(DP_FILTER_DEV_EXTENSION),
		NULL,
		FILE_DEVICE_DISK,
		FILE_DEVICE_SECURE_OPEN,
		FALSE,
		&FltDevObj);
	if (!NT_SUCCESS(ntStatus)) 
		goto ERROUT;
	//将DevExt指向过滤设备的设备扩展指针
	DevExt = FltDevObj->DeviceExtension;
	//清空过滤设备的设备扩展
	RtlZeroMemory(DevExt,sizeof(DP_FILTER_DEV_EXTENSION));

	//将刚刚建立的过滤设备附加到这个卷设备的物理设备上
	LowerDevObj = IoAttachDeviceToDeviceStack(
		FltDevObj, 
		PhysicalDeviceObject);
	if (NULL == LowerDevObj)
	{
		ntStatus = STATUS_NO_SUCH_DEVICE;
		goto ERROUT;
	}

	//初始化这个卷设备的分页路径计数的计数事件
	KeInitializeEvent(
		&DevExt->PagingPathCountEvent,
		NotificationEvent, 
		TRUE);

	//对过滤设备的设备属性进行初始化,过滤设备的设备属性应该和它的下层设备相同
	FltDevObj->Flags = LowerDevObj->Flags;
	//给过滤设备的设备属性加上电源可分页的属性
	FltDevObj->Flags |= DO_POWER_PAGABLE;
	//对过滤设备进行设备初始化
	FltDevObj->Flags &= ~DO_DEVICE_INITIALIZING;

	//将过滤设备对应的设备扩展中的相应变量进行初始化
	//卷设备的过滤设备对象
	DevExt->FltDevObj = FltDevObj;
	//卷设备的物理设备对象
	DevExt->PhyDevObj = PhysicalDeviceObject;
	//卷设备的下层设备对象
	DevExt->LowerDevObj = LowerDevObj;

	//初始化这个卷的请求处理队列
	InitializeListHead(&DevExt->ReqList);
	//初始化请求处理队列的锁
	KeInitializeSpinLock(&DevExt->ReqLock);
	//初始化请求处理队列的同步事件
	KeInitializeEvent(
		&DevExt->ReqEvent,
		SynchronizationEvent,
		FALSE
		);

	//初始化终止处理线程标志
	DevExt->ThreadTermFlag = FALSE;
	//建立用来处理这个卷的请求的处理线程,线程函数的参数则是设备扩展
	ntStatus = PsCreateSystemThread(
		&ThreadHandle,
		(ACCESS_MASK)0L,
		NULL,
		NULL,
		NULL,
		DPReadWriteThread,
		DevExt
		);
	if (!NT_SUCCESS(ntStatus))
		goto ERROUT;

	//获取处理线程的对象
	ntStatus = ObReferenceObjectByHandle(
		ThreadHandle,
		THREAD_ALL_ACCESS,
		NULL,
		KernelMode,
		&DevExt->ThreadHandle,
		NULL
		);
	if (!NT_SUCCESS(ntStatus))
	{
		DevExt->ThreadTermFlag = TRUE;
		KeSetEvent(
			&DevExt->ReqEvent,
			(KPRIORITY)0,
			FALSE
			);
		goto ERROUT;
	}

ERROUT:
	if (!NT_SUCCESS(ntStatus))
	{	
		//如果上面有不成功的地方,首先需要解除可能存在的附加
		if (NULL != LowerDevObj)
		{
			IoDetachDevice(LowerDevObj);
			DevExt->LowerDevObj = NULL;
		}
		//然后删除可能建立的过滤设备
		if (NULL != FltDevObj)
		{
			IoDeleteDevice(FltDevObj);
			DevExt->FltDevObj = NULL;
		}
	}
	//关闭线程句柄,我们今后不会用到它,所有对线程的引用都通过线程对象来进行了
	if (NULL != ThreadHandle)
		ZwClose(ThreadHandle);
	//返回状态值
    return ntStatus;
}