Esempio n. 1
0
NTSTATUS CWdfDevice::CacheDeviceName()
{
    WDFSTRING deviceName;
    auto status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &deviceName);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! WdfStringCreate failed. %!STATUS!", status);
        return status;
    }

    status = WdfDeviceRetrieveDeviceName(m_Device, deviceName);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! WdfDeviceRetrieveDeviceName failed. %!STATUS!", status);
        WdfObjectDelete(deviceName);
        return status;
    }

    UNICODE_STRING UnicodeDeviceName;
    WdfStringGetUnicodeString(deviceName, &UnicodeDeviceName);

    status = m_CachedName.Create(&UnicodeDeviceName);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! CString creation failed. %!STATUS!", status);
        WdfObjectDelete(deviceName);
        return status;
    }

    TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! Newly created device name is %wZ", &UnicodeDeviceName);
    WdfObjectDelete(deviceName);
    return STATUS_SUCCESS;
}
Esempio n. 2
0
NTSTATUS GUIDFromWdfString(__in WDFSTRING guidString, __out PGUID guid)
{
    UNICODE_STRING guidStringW;

    WdfStringGetUnicodeString(guidString, &guidStringW);

    return RtlGUIDFromString (&guidStringW, guid);
}
Esempio n. 3
0
NTSTATUS
OsrFxEvtDeviceAdd(
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device. All the software resources
    should be allocated in this callback.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES               attributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_DEVICE_PNP_CAPABILITIES         pnpCaps;
    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;
    PDEVICE_CONTEXT                     pDevContext;
    WDFQUEUE                            queue;
    GUID                                activity;
    UNICODE_STRING                      symbolicLinkName;
    WDFSTRING                           symbolicLinkString;
    DEVPROP_BOOLEAN                     isRestricted;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n");

    //
    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,
    // the Framework will take appropriate default actions based on whether
    // DeviceInit is initialized to be an FDO, a PDO or a filter device
    // object.
    //

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    //
    // For usb devices, PrepareHardware callback is the to place select the
    // interface and configure the device.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = OsrFxEvtDevicePrepareHardware;

    //
    // These two callbacks start and stop the wdfusb pipe continuous reader
    // as we go in and out of the D0-working state.
    //

    pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = OsrFxEvtDeviceD0Exit;
    pnpPowerCallbacks.EvtDeviceSelfManagedIoFlush = OsrFxEvtDeviceSelfManagedIoFlush;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

    //
    // Now specify the size of device extension where we track per device
    // context.DeviceInit is completely initialized. So call the framework
    // to create the device and attach it to the lower stack.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceCreate failed with Status code %!STATUS!\n", status);
        return status;
    }

    //
    // Setup the activity ID so that we can log events using it.
    //

    activity = DeviceToActivityId(device);

    //
    // Get the DeviceObject context by using accessor function specified in
    // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT.
    //
    pDevContext = GetDeviceContext(device);

    //
    // Get the device's friendly name and location so that we can use it in
    // error logging.  If this fails then it will setup dummy strings.
    //

    GetDeviceEventLoggingNames(device);

    //
    // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    // that you don't get the popup in usermode when you surprise remove the device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
    pnpCaps.SurpriseRemovalOK = WdfTrue;

    WdfDeviceSetPnpCapabilities(device, &pnpCaps);

    //
    // Create a parallel default queue and register an event callback to
    // receive ioctl requests. We will create separate queues for
    // handling read and write requests. All other requests will be
    // completed with error status automatically by the framework.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                             WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl    = OsrFxEvtIoDeviceControl;
    
    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests for 
    // long time or forward them to other drivers. 
    // If the EvtIoStop callback is not implemented, the framework waits for
    // all driver-owned requests to be done before moving in the Dx/sleep 
    // states or before removing the device, which is the correct behavior 
    // for this type of driver. If the requests were taking an indeterminate
    // amount of time to complete, or if the driver forwarded the requests
    // to a lower driver/another stack, the queue should have an 
    // EvtIoStop/EvtIoResume.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate(device,
                             &ioQueueConfig,
                             WDF_NO_OBJECT_ATTRIBUTES,
                             &queue);// pointer to default queue
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                            "WdfIoQueueCreate failed  %!STATUS!\n", status);
        goto Error;
    }

    //
    // We will create a separate sequential queue and configure it
    // to receive read requests.  We also need to register a EvtIoStop
    // handler so that we can acknowledge requests that are pending
    // at the target driver.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoRead = OsrFxEvtIoRead;
    ioQueueConfig.EvtIoStop = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

    status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeRead);

    if(!NT_SUCCESS (status)){
        NT_ASSERT(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        goto Error;
    }


    //
    // We will create another sequential queue and configure it
    // to receive write requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoWrite = OsrFxEvtIoWrite;
    ioQueueConfig.EvtIoStop  = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

     status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeWrite);

    if(!NT_SUCCESS (status)){
        NT_ASSERT(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        goto Error;
    }

    //
    // Register a manual I/O queue for handling Interrupt Message Read Requests.
    // This queue will be used for storing Requests that need to wait for an
    // interrupt to occur before they can be completed.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual);

    //
    // This queue is used for requests that dont directly access the device. The
    // requests in this queue are serviced only when the device is in a fully
    // powered state and sends an interrupt. So we can use a non-power managed
    // queue to park the requests since we dont care whether the device is idle
    // or fully powered up.
    //
    ioQueueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(device,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &pDevContext->InterruptMsgQueue
                              );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

    //
    // Register a device interface so that app can find our device and talk to it.
    //
    status = WdfDeviceCreateDeviceInterface(device,
                                            (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                                            NULL); // Reference String

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfDeviceCreateDeviceInterface failed  %!STATUS!\n", status);
        goto Error;
    }

    // 
    // Create the lock that we use to serialize calls to ResetDevice(). As an 
    // alternative to using a WDFWAITLOCK to serialize the calls, a sequential 
    // WDFQUEUE can be created and reset IOCTLs would be forwarded to it.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = device;

    status = WdfWaitLockCreate(&attributes, &pDevContext->ResetDeviceWaitLock);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfWaitLockCreate failed  %!STATUS!\n", status);
        goto Error;
    }

    //
    // Get the string for the device interface and set the restricted
    // property on it to allow applications bound with device metadata
    // to access the interface.
    //
    if (g_pIoSetDeviceInterfacePropertyData != NULL) {

        status = WdfStringCreate(NULL,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &symbolicLinkString);

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                     "WdfStringCreate failed  %!STATUS!\n", status);
            goto Error;
        }

        status = WdfDeviceRetrieveDeviceInterfaceString(device,
                                                        (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                                                        NULL,
                                                        symbolicLinkString);

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                     "WdfDeviceRetrieveDeviceInterfaceString failed  %!STATUS!\n", status);
            goto Error;
        }

        WdfStringGetUnicodeString(symbolicLinkString, &symbolicLinkName);

        isRestricted = DEVPROP_TRUE;

        status = g_pIoSetDeviceInterfacePropertyData(&symbolicLinkName,
                                                     &DEVPKEY_DeviceInterface_Restricted,
                                                     0,
                                                     0,
                                                     DEVPROP_TYPE_BOOLEAN,
                                                     sizeof(isRestricted),
                                                     &isRestricted );

        WdfObjectDelete(symbolicLinkString);

        if (!NT_SUCCESS(status)) {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                     "IoSetDeviceInterfacePropertyData failed  %!STATUS!\n", status);
            goto Error;
        }
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- OsrFxEvtDeviceAdd\n");

    return status;

Error:

    //
    // Log fail to add device to the event log
    //
    EventWriteFailAddDevice(&activity,
                            pDevContext->DeviceName,
                            pDevContext->Location,
                            status);

    return status;
}
Esempio n. 4
0
static VOID
XenUsb_EvtIoDeviceControl(
  WDFQUEUE queue,
  WDFREQUEST request,
  size_t output_buffer_length,
  size_t input_buffer_length,
  ULONG io_control_code)
{
  NTSTATUS status;
  WDFDEVICE device = WdfIoQueueGetDevice(queue);
  PXENUSB_DEVICE_DATA xudd = GetXudd(device);

  UNREFERENCED_PARAMETER(queue);
  UNREFERENCED_PARAMETER(input_buffer_length);
  UNREFERENCED_PARAMETER(output_buffer_length);

  FUNCTION_ENTER();

  status = STATUS_BAD_INITIAL_PC;

  // these are in api\usbioctl.h
  switch(io_control_code)
  {
  case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
    break;
  case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
    FUNCTION_MSG("IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_NAME:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
    break;
  case IOCTL_USB_DIAG_IGNORE_HUBS_ON:
    FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_ON\n");
    break;
  case IOCTL_USB_DIAG_IGNORE_HUBS_OFF:
    FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
    break;
  case IOCTL_USB_GET_HUB_CAPABILITIES:
    FUNCTION_MSG("IOCTL_USB_GET_HUB_CAPABILITIES\n");
    break;
  case IOCTL_USB_HUB_CYCLE_PORT:
    FUNCTION_MSG("IOCTL_USB_HUB_CYCLE_PORT\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n");
    break;
  case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX:
    FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n");
    break;
  case IOCTL_USB_GET_ROOT_HUB_NAME:
  {
    PUSB_HCD_DRIVERKEY_NAME uhdn;
    size_t length;
    ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
    
    FUNCTION_MSG("IOCTL_USB_GET_ROOT_HUB_NAME\n");
    FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length);
      
    if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
      status = STATUS_BUFFER_TOO_SMALL;
    } else {
      status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
      if (NT_SUCCESS(status)) {
        WDFSTRING symbolic_link_wdfstring;
        UNICODE_STRING symbolic_link;
        
        uhdn->DriverKeyName[0] = 0;
        status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolic_link_wdfstring);
        if (NT_SUCCESS(status)) {
          status = WdfDeviceRetrieveDeviceInterfaceString(xudd->root_hub_device, &GUID_DEVINTERFACE_USB_HUB, NULL, symbolic_link_wdfstring);
          if (NT_SUCCESS(status)) {
            WdfStringGetUnicodeString(symbolic_link_wdfstring, &symbolic_link);
            /* remove leading \??\ from name */
            symbolic_link.Buffer += 4;
            symbolic_link.Length -= 4 * sizeof(WCHAR);
            required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + symbolic_link.Length + sizeof(WCHAR);
            FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
            FUNCTION_MSG("required_length = %d\n", required_length);
            if (output_buffer_length >= required_length) {
              uhdn->ActualLength = required_length;
              memcpy(uhdn->DriverKeyName, symbolic_link.Buffer, symbolic_link.Length);
              uhdn->DriverKeyName[symbolic_link.Length / 2] = 0;
              WdfRequestSetInformation(request, required_length);
            } else {
              uhdn->ActualLength = required_length;
              uhdn->DriverKeyName[0] = 0;
              status = STATUS_SUCCESS;
              WdfRequestSetInformation(request, output_buffer_length);
            }
          } else {
            FUNCTION_MSG("WdfStringCreate = %08x\n", status);
          }
        } else {
          FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString = %08x\n", status);
          status = STATUS_INVALID_PARAMETER;
        }
      } else {
        FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status);
      }
      FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
      FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
    }
    break;
  }
  case IOCTL_GET_HCD_DRIVERKEY_NAME:
  {
    PUSB_HCD_DRIVERKEY_NAME uhdn;
    size_t length;
    ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME);
    ULONG key_length;
    
    FUNCTION_MSG("IOCTL_GET_HCD_DRIVERKEY_NAME\n");
    FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length);
      
    if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) {
      FUNCTION_MSG("Buffer too small (%d < %d)\n", output_buffer_length, sizeof(USB_HCD_DRIVERKEY_NAME));
      status = STATUS_BUFFER_TOO_SMALL;
      break;
    }
    status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length);
    if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status);
      break;
    }
    status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 0, NULL, &key_length);
    if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("WdfDeviceQueryProperty = %08x\n", status);
      break;
    }    
    FUNCTION_MSG(" key_length = %d\n", key_length);
    required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + key_length + 2;
    uhdn->ActualLength = required_length;
    FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length);
    FUNCTION_MSG("required_length = %d\n", required_length);
    if (output_buffer_length >= required_length)
    {
      status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 
        required_length - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName), uhdn->DriverKeyName,
        &key_length);
      WdfRequestSetInformation(request, required_length);
    }
    else
    {
      uhdn->DriverKeyName[0] = 0;
      status = STATUS_SUCCESS;
      WdfRequestSetInformation(request, output_buffer_length);
    }
    FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength);
    FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName);
    break;
  }
#if 0
  case IOCTL_USB_RESET_HUB:
    FUNCTION_MSG("IOCTL_USB_RESET_HUB\n");
    break;
#endif
  default:
    FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code);
    break;
  }
  FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n", status);
  WdfRequestComplete(request, status);

  FUNCTION_EXIT();
}
Esempio n. 5
0
NTSTATUS
XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
{
  NTSTATUS status;
  WDF_CHILD_LIST_CONFIG child_list_config;
  WDFDEVICE device;
  PXENUSB_DEVICE_DATA xudd;
  //UNICODE_STRING reference;
  WDF_OBJECT_ATTRIBUTES device_attributes;
  PNP_BUS_INFORMATION pbi;
  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
  WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
  WDF_IO_QUEUE_CONFIG queue_config;
  UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
  DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
  WDFSTRING symbolicname_value_wdfstring;
  WDFKEY device_key;
  UNICODE_STRING symbolicname_value;

  UNREFERENCED_PARAMETER(driver);

  FUNCTION_ENTER();

  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
  pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry;
  pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit;

  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);

  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
    IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
  WdfDeviceInitSetExclusive(device_init, FALSE);

  WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice);
  child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren;
  WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);

  WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);

  WdfDeviceInitSetPowerNotPageable(device_init);
  
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA);
  status = WdfDeviceCreate(&device_init, &device_attributes, &device);
  if (!NT_SUCCESS(status))
  {
    FUNCTION_MSG("Error creating device %08x\n", status);
    return status;
  }

  xudd = GetXudd(device);
  xudd->pdo = WdfDeviceWdmGetPhysicalDevice(device);
  xudd->child_list = WdfFdoGetDefaultChildList(device);
  KeInitializeEvent(&xudd->backend_event, SynchronizationEvent, FALSE);
  InitializeListHead(&xudd->partial_pvurb_queue);
  InitializeListHead(&xudd->partial_pvurb_ring);
  KeInitializeDpc(&xudd->event_dpc, XenUsb_HandleEventDpc, xudd);

  KeInitializeSpinLock(&xudd->urb_ring_lock);
  
  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl;
  queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating io_queue 0x%x\n", status);
      return status;
  }

  WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB;
  //queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating urb_queue 0x%x\n", status);
      return status;
  }

  WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
  power_capabilities.DeviceD1 = WdfTrue;
  power_capabilities.WakeFromD1 = WdfTrue;
  power_capabilities.DeviceWake = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
  power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  power_capabilities.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
  WdfDeviceSetPowerCapabilities(device, &power_capabilities);  

  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
  
  pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
  pbi.LegacyBusType = PNPBus;
  pbi.BusNumber = 0;
  WdfDeviceSetBusInformationForChildren(device, &pbi);

  status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n");
    return status;
  }

  /* USB likes to have a registry key with the symbolic link name in it */
  status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfStringCreate returned %08x\n");
    return status;
  }
  status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n");
    return status;
  }
  WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
  status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n");
    return status;
  }
  WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);

  FUNCTION_EXIT();
  return status;
}
Esempio n. 6
0
NTSTATUS
FmCreateDosDevicesSymbolicLink(
                              WDFDEVICE       Device,
                              PFM_DEVICE_DATA FmDeviceData
                              )
{
    NTSTATUS        status;
    UNICODE_STRING  comPort;
    UNICODE_STRING  pdoName;
    UNICODE_STRING  symbolicLink;
    WDFKEY          hKey = NULL;
    DECLARE_CONST_UNICODE_STRING(valueName, L"PortName");
    WDFSTRING       string = NULL;
    WDFMEMORY       memory;
    WDF_OBJECT_ATTRIBUTES  memoryAttributes;
    size_t          bufferLength;


    PAGED_CODE();

    symbolicLink.Buffer = NULL;

    //
    // Open the device registry and read the "PortName" value written by the
    // class installer.
    //
    status = WdfDeviceOpenRegistryKey(Device,
                                      PLUGPLAY_REGKEY_DEVICE,
                                      STANDARD_RIGHTS_ALL,
                                      NULL, // PWDF_OBJECT_ATTRIBUTES
                                      &hKey);

    if (!NT_SUCCESS (status)) {
        goto Error;
    }
    status = WdfStringCreate(
                            NULL,
                            WDF_NO_OBJECT_ATTRIBUTES ,
                            &string
                            );

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

    //
    // Retrieve the value of ValueName from registry
    //
    status = WdfRegistryQueryString(
                                   hKey,
                                   &valueName,
                                   string
                                   );


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

    //
    // Retrieve the UNICODE_STRING from string object
    //
    WdfStringGetUnicodeString(
                             string,
                             &comPort
                             );

    WdfRegistryClose(hKey);
    hKey = NULL;

    symbolicLink.Length=0;
    symbolicLink.MaximumLength = sizeof(OBJECT_DIRECTORY) + comPort.MaximumLength;

    symbolicLink.Buffer = ExAllocatePoolWithTag(PagedPool,
                                                symbolicLink.MaximumLength + sizeof(WCHAR),
                                                'wkaF');

    if (symbolicLink.Buffer == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Error;
    }
    RtlZeroMemory(symbolicLink.Buffer, symbolicLink.MaximumLength);
    RtlAppendUnicodeToString(&symbolicLink, OBJECT_DIRECTORY);
    RtlAppendUnicodeStringToString(&symbolicLink, &comPort);
    //
    // This DDI will get the underlying PDO name and create a symbolic to that
    // because our FDO doesn't have a name.
    //
    status = WdfDeviceCreateSymbolicLink(Device,
                                         &symbolicLink);

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

    WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes);
    memoryAttributes.ParentObject = Device;

    status = WdfDeviceAllocAndQueryProperty(Device,
                                            DevicePropertyPhysicalDeviceObjectName,
                                            PagedPool,
                                            &memoryAttributes,
                                            &memory);
    if (!NT_SUCCESS(status)) {
        //
        // We expect a zero length buffer. Anything else is fatal.
        //
        goto Error;
    }

    pdoName.Buffer = WdfMemoryGetBuffer(memory, &bufferLength);

    if (pdoName.Buffer == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Error;

    }
    pdoName.MaximumLength = (USHORT) bufferLength;
    pdoName.Length = (USHORT) bufferLength - sizeof(UNICODE_NULL);

    status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
                                   L"SERIALCOMM",
                                   pdoName.Buffer,
                                   REG_SZ,
                                   comPort.Buffer,
                                   comPort.Length);

    if (!NT_SUCCESS(status)) {
        goto Error;
    }
    FmDeviceData->Flags |= REG_VALUE_CREATED_FLAG;
    //
    // Store it so it can be deleted later.
    //

    FmDeviceData->PdoName = pdoName;

    Error:

    if (symbolicLink.Buffer != NULL) {
        ExFreePool(symbolicLink.Buffer);
    }

    if (hKey != NULL) {
        WdfRegistryClose(hKey);
    }
    if (string != NULL) {
        WdfObjectDelete(string);
    }

    return status;
}
Esempio n. 7
0
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DriverParametersKeyRead -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
NTSTATUS  DriverParametersKeyRead(
    WDFDRIVER  Driver,
    DtString*  pKeyName,
    DtString*  pValueName,
    Int64*  pBinValue,
    DtString*  pStrValue)
{
    NTSTATUS  NtStatus;
    WDFKEY  ParametersKey;
    WDFKEY  Key = NULL;
    WDFSTRING WdfString = NULL;   
    DtString  RegStrValue;

    DT_ASSERT(KeGetCurrentIrql()<=PASSIVE_LEVEL);


    // Only one value can be requested
    DT_ASSERT((pBinValue!=NULL && pStrValue==NULL)||(pBinValue==NULL && pStrValue!=NULL));

    // Open the drivers parameters key (under services)
    NtStatus = WdfDriverOpenParametersRegistryKey(Driver, KEY_READ,
                                                WDF_NO_OBJECT_ATTRIBUTES, &ParametersKey);
    if (!NT_SUCCESS(NtStatus))
    {
        DtDbgOut(ERR, SAL, "WdfDriverOpenParametersRegistryKey failed. Error: 0x%x", 
                                                                                NtStatus);
        return NtStatus;
    }

    // Open subkey
    NtStatus = WdfRegistryOpenKey(ParametersKey, pKeyName, KEY_READ, 
                                                          WDF_NO_OBJECT_ATTRIBUTES, &Key);
    if (!NT_SUCCESS(NtStatus))
    {
        if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
            DtDbgOut(MAX, SAL, "WdfRegistryOpenKey error:'STATUS_OBJECT_NAME_NOT_FOUND'");
        else
            DtDbgOut(ERR, SAL, "WdfRegistryOpenKey failed. Error: 0x%x", NtStatus);
    }

    if (NT_SUCCESS(NtStatus))
    {
        // Read string or binary value
        if (pStrValue != NULL)
        {
            // Set string attributes with the key as parent object, so that the string 
            // object is freed when the key object is destroyed. If we donot do this the
            // string object is freed when the driver unloads, meaning that the each call 
            // to DriverParametersKeyRead result in an increase of memory usage, only 
            // to be freed on the unload.
            WDF_OBJECT_ATTRIBUTES  WdfStringAttr;
            WDF_OBJECT_ATTRIBUTES_INIT(&WdfStringAttr);
            WdfStringAttr.ParentObject = Key;
            NtStatus = WdfStringCreate(pStrValue, &WdfStringAttr, &WdfString);

            // Read string from registry
            if (NT_SUCCESS(NtStatus))
                NtStatus = WdfRegistryQueryString(Key, pValueName, WdfString);

            // Convert WdfString to DtString
            if (NT_SUCCESS(NtStatus))
                WdfStringGetUnicodeString(WdfString, &RegStrValue);

            // Make a copy of the string
            if (NT_SUCCESS(NtStatus))
                NtStatus = DtStringClear(pStrValue);
            if (NT_SUCCESS(NtStatus))
                NtStatus = DtStringAppendDtString(pStrValue, &RegStrValue);
        }
        else
            NtStatus = WdfRegistryQueryValue(Key, pValueName, sizeof(Int64), pBinValue,
                                                                              NULL, NULL);

        if (!NT_SUCCESS(NtStatus))
        {
            if (NtStatus == STATUS_OBJECT_NAME_NOT_FOUND)
                DtDbgOut(MAX, SAL, "WdfRegistryQueryValue error:"
                                                        "'STATUS_OBJECT_NAME_NOT_FOUND'");
            else
                DtDbgOut(ERR, SAL, "WdfRegistryQueryValue failed. Error: 0x%x", NtStatus);
        }
    }
    if (Key != NULL)
        WdfRegistryClose(Key);
    WdfRegistryClose(ParametersKey);
    return NtStatus;
}
Esempio n. 8
0
NTSTATUS
EchoPrintDriverVersion(
    )
/*++
Routine Description:

   This routine shows how to retrieve framework version string and
   also how to find out to which version of framework library the
   client driver is bound to.

Arguments:

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS status;
    WDFSTRING string;
    UNICODE_STRING us;
    WDF_DRIVER_VERSION_AVAILABLE_PARAMS ver;

    //
    // 1) Retreive version string and print that in the debugger.
    //
    status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &string);
    if (!NT_SUCCESS(status)) {
        KdPrint(("Error: WdfStringCreate failed 0x%x\n", status));
        return status;
    }

    status = WdfDriverRetrieveVersionString(WdfGetDriver(), string);
    if (!NT_SUCCESS(status)) {
        //
        // No need to worry about delete the string object because
        // by default it's parented to the driver and it will be
        // deleted when the driverobject is deleted when the DriverEntry
        // returns a failure status.
        //
        KdPrint(("Error: WdfDriverRetrieveVersionString failed 0x%x\n", status));
        return status;
    }

    WdfStringGetUnicodeString(string, &us);
    KdPrint(("Echo Sample %wZ\n", &us));

    WdfObjectDelete(string);
    string = NULL; // To avoid referencing a deleted object.

    //
    // 2) Find out to which version of framework this driver is bound to.
    //
    WDF_DRIVER_VERSION_AVAILABLE_PARAMS_INIT(&ver, 1, 0);
    if (WdfDriverIsVersionAvailable(WdfGetDriver(), &ver) == TRUE) {
        KdPrint(("Yes, framework version is 1.0\n"));
    }else {
        KdPrint(("No, framework verison is not 1.0\n"));
    }

    return STATUS_SUCCESS;
}