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; }
NTSTATUS GUIDFromWdfString(__in WDFSTRING guidString, __out PGUID guid) { UNICODE_STRING guidStringW; WdfStringGetUnicodeString(guidString, &guidStringW); return RtlGUIDFromString (&guidStringW, guid); }
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; }
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(); }
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; }
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; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- 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; }
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; }