NTSTATUS Registry_ReadAllDeviceKeys(__in PDEVICE_CONTEXT deviceContext) { WDFKEY hKey = NULL; NTSTATUS status = STATUS_INVALID_DEVICE_STATE; UNICODE_STRING valueName; WDF_OBJECT_ATTRIBUTES collectionAttributes; WDF_OBJECT_ATTRIBUTES stringAttributes; GUID guidTest = {0}; PAGED_CODE(); if (!deviceContext->WdfDevice) { USBERR("deviceContext->WdfDevice is NULL.\n"); return status; } // The driver sets the PLUGPLAY_REGKEY_DEVICE flag to open the Device // Parameters subkey under the device's hardware key, or it sets the // PLUGPLAY_REGKEY_DRIVER flag to open the driver's software key. If the // PLUGPLAY_REGKEY_CURRENT_HWPROFILE flag is also set, // WdfDeviceOpenRegistryKey opens the copy of the hardware or software key // that is in the current hardware profile. status = WdfDeviceOpenRegistryKey(deviceContext->WdfDevice, PLUGPLAY_REGKEY_DEVICE, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &hKey); if (!NT_SUCCESS (status)) { USBERR("WdfDeviceOpenRegistryKey failed.\n"); hKey = NULL; return status; } ////////////////////////////////////////////////////////////////////////// // Read the device interface guids from the registry. // These are set in the inf files [Device_AddReg] group. // WDF_OBJECT_ATTRIBUTES_INIT(&collectionAttributes); collectionAttributes.ParentObject = deviceContext->WdfDevice; status = WdfCollectionCreate(&collectionAttributes, &deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs); if (!NT_SUCCESS(status)) { USBERR("collection object could not be allocated. status=%Xh", status); goto Done; } WDF_OBJECT_ATTRIBUTES_INIT(&stringAttributes); stringAttributes.ParentObject = deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs; RtlInitUnicodeString(&valueName, L"DeviceInterfaceGUIDs"); status = WdfRegistryQueryMultiString(hKey, &valueName, &stringAttributes, deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs); if (NT_SUCCESS(status)) { ULONG guidCount = WdfCollectionGetCount(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs); ULONG guidIndex; WDFSTRING wdfGuidString; BOOLEAN removeGuidFromCollection; USBMSG("Found %u DeviceInterfaceGUIDs strings.", guidCount); for (guidIndex = 0; guidIndex < guidCount; guidIndex++) { removeGuidFromCollection = TRUE; wdfGuidString = (WDFSTRING)WdfCollectionGetItem(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs, guidIndex); status = GUIDFromWdfString(wdfGuidString, &guidTest); if (!NT_SUCCESS(status)) { USBERR("removing invalid DeviceInterfaceGUID string at index %u\n", guidIndex); } else { if (IsEqualGUID(&guidTest, &Libusb0DeviceGuid)) { USBWRN("libusb0 device DeviceInterfaceGUID found. skippng..\n"); } else if (IsEqualGUID(&guidTest, &Libusb0FilterGuid)) { USBWRN("libusb0 filter DeviceInterfaceGUID found. skippng..\n"); } else if (IsEqualGUID(&guidTest, &LibusbKDeviceGuid)) { USBWRN("libusbK default device DeviceInterfaceGUID found. skippng..\n"); } else { removeGuidFromCollection = FALSE; } } if (removeGuidFromCollection) { WdfCollectionRemoveItem(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs, guidIndex); guidIndex--; guidCount--; } } } else { USBWRN("DeviceInterfaceGUIDs registry key does not exist.\n" " Ensure the DeviceInterfaceGUIDs key has been properly set in the .inf and re-install the device.\n\n"); } if (WdfCollectionGetCount(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs) == 0) { status = AddDefaultDeviceInterfaceGUID(deviceContext); if (!NT_SUCCESS(status)) { goto Done; } } ////////////////////////////////////////////////////////////////////////// // Read the device power policy settings (if any). // These are set in the inf files [Device_AddReg] group. // GetDeviceRegSettingKey(DeviceIdleEnabled, FALSE); GetDeviceRegSettingKey(DeviceIdleIgnoreWakeEnable, FALSE); GetDeviceRegSettingKey(UserSetDeviceIdleEnabled, FALSE); GetDeviceRegSettingKey(DefaultIdleState, FALSE); GetDeviceRegSettingKey(DefaultIdleTimeout, 5000); GetDeviceRegSettingKey(SystemWakeEnabled, FALSE); status = STATUS_SUCCESS; Done: if (hKey) { WdfRegistryClose(hKey); hKey = NULL; } return status; }
NTSTATUS ToastMon_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: ToastMon_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 toaster device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status = STATUS_SUCCESS; WDFDEVICE device; PDEVICE_EXTENSION deviceExtension; KdPrint( ("ToastMon_EvtDeviceAdd routine\n")); UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); // // Specify the size of device extension where we track per device // context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); attributes.EvtCleanupCallback = ToastMon_EvtDeviceContextCleanup; // // Create a framework device object.This call will inturn create // a WDM deviceobject, attach to the lower stack and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with Status 0x%x\n", status)); return status; } // // Get the DeviceExtension and initialize it. // deviceExtension = GetDeviceExtension(device); deviceExtension->WdfDevice = device; // // Create a collection to store information about target devices. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfCollectionCreate(&attributes, &deviceExtension->TargetDeviceCollection); if (!NT_SUCCESS(status)) { KdPrint( ("WdfCollectionCreate failed with status 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfWaitLockCreate(&attributes, &deviceExtension->TargetDeviceCollectionLock); if (!NT_SUCCESS(status)) { KdPrint( ("WdfWaitLockCreate failed with status 0x%x\n", status)); return status; } // // Register for TOASTER device interface change notification. // We will get GUID_DEVICE_INTERFACE_ARRIVAL and // GUID_DEVICE_INTERFACE_REMOVAL notification when the toaster // device is started and removed. // Framework doesn't provide a WDF interface to register for interface change // notification. However if the target device is opened by symboliclink using // IoTarget, framework registers itself EventCategoryTargetDeviceChange // notification on the handle and responds to the pnp notifications. // // Note that as soon as you register, arrival notification will be sent // about all existing toaster devices even before this device is started. So if // you cannot handle these notification before start then you should register this in // PrepareHardware or SelfManagedIoInit callback. // You must unregister this notification when the device is removed in the // DeviceContextCleanup callback. This call takes a reference on the driverobject. // So if you don't unregister it will prevent the driver from unloading. // status = IoRegisterPlugPlayNotification ( EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&GUID_DEVINTERFACE_TOASTER, WdfDriverWdmGetDriverObject(WdfDeviceGetDriver(device)), (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) ToastMon_PnpNotifyInterfaceChange, (PVOID)deviceExtension, &deviceExtension->NotificationHandle); if (!NT_SUCCESS(status)) { KdPrint(("RegisterPnPNotifiction failed: 0x%x\n", status)); return status; } RegisterForWMINotification(deviceExtension); return status; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: DriverObject - pointer to the driver object RegistryPath - pointer to a unicode string representing the path, to driver-specific key in the registry. Return Value: STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise. --*/ { WDF_DRIVER_CONFIG config; NTSTATUS status; WDFDRIVER hDriver; KdPrint(("Toaster SideBand Filter Driver Sample - Driver Framework Edition.\n")); KdPrint(("Built %s %s\n", __DATE__, __TIME__)); // // Initiialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, // you can override that by manually setting the EvtDriverUnload in the // config structure. In general xxx_CONFIG_INIT macros are provided to // initialize most commonly used members. // WDF_DRIVER_CONFIG_INIT( &config, FilterEvtDeviceAdd ); // // Create a framework driver object to represent our driver. // status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &hDriver); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDriverCreate failed with status 0x%x\n", status)); } // // Since there is only one control-device for all the instances // of the physical device, we need an ability to get to particular instance // of the device in our FilterEvtIoDeviceControlForControl. For that we // will create a collection object and store filter device objects. // The collection object has the driver object as a default parent. // status = WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &FilterDeviceCollection); if (!NT_SUCCESS(status)) { KdPrint( ("WdfCollectionCreate failed with status 0x%x\n", status)); return status; } // // The wait-lock object has the driver object as a default parent. // status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &FilterDeviceCollectionLock); if (!NT_SUCCESS(status)) { KdPrint( ("WdfWaitLockCreate failed with status 0x%x\n", status)); return status; } return status; }
/** * @brief Called by the framework when a new PDO has arrived that this driver manages. * The device in question is not operational at this point in time. * * @param[in] Driver handle to WDFDRIVER object created by DriverEntry() * @param[in,out] DeviceInit device init object provided by framework. * * @returns NTSTATUS value indicating success or failure. * */ NTSTATUS FdoEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) { UNREFERENCED_PARAMETER(Driver); WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status; TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, __FUNCTION__"\n"); WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); WdfDeviceInitSetExclusive(DeviceInit, FALSE); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, USB_FDO_CONTEXT); attributes.EvtCleanupCallback = FdoEvtDeviceContextCleanup; // // Device state callbacks. // WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = FdoEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = FdoEvtDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = FdoEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = FdoEvtDeviceD0EntryPostInterruptsEnabled; pnpPowerCallbacks.EvtDeviceD0Exit = FdoEvtDeviceD0Exit; pnpPowerCallbacks.EvtDeviceSurpriseRemoval = FdoEvtDeviceSurpriseRemoval; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // establish a request context // WDF_OBJECT_ATTRIBUTES requestAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestAttributes, FDO_REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes); // // static verifier seems to have a rule that the FDO must call // WdfFdoInitSetDefaultChildListConfig if any component in the driver has // dynamic child devices, and the roothub has one if it is not operating in // connect usb hub mode. // WDF_CHILD_LIST_CONFIG config; WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_INDENTIFICATION_DESCRIPTION), FdoEvtChildListCreateDevice); WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES); // // add a preprocess callback for QueryInterface to support multi-version USBDI intefaces // UCHAR MinorFunctionTable[1] = {IRP_MN_QUERY_INTERFACE}; status = WdfDeviceInitAssignWdmIrpPreprocessCallback( DeviceInit, FdoPreProcessQueryInterface, IRP_MJ_PNP, MinorFunctionTable, 1); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfDeviceInitAssignWdmIrpPreprocessCallback failed error %x\n", status); return status; } // // Add create/close handlers // WDF_OBJECT_ATTRIBUTES fileAttributes; WDF_OBJECT_ATTRIBUTES_INIT(&fileAttributes); fileAttributes.SynchronizationScope = WdfSynchronizationScopeNone; WDF_FILEOBJECT_CONFIG FileObjectConfig; WDF_FILEOBJECT_CONFIG_INIT( &FileObjectConfig, FdoEvtDeviceFileCreate, FdoEvtFileClose, WDF_NO_EVENT_CALLBACK); WdfDeviceInitSetFileObjectConfig( DeviceInit, &FileObjectConfig, &fileAttributes); WDFDEVICE device; status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfDeviceCreate failed error %x\n", status); return status; } PUSB_FDO_CONTEXT fdoContext = DeviceGetFdoContext(device); RtlZeroMemory(fdoContext, sizeof(USB_FDO_CONTEXT)); fdoContext->WdfDevice = device; KeInitializeEvent(&fdoContext->resetCompleteEvent, SynchronizationEvent, FALSE); // // allocate the dpc request collection. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfCollectionCreate(&attributes, &fdoContext->RequestCollection); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfCollectionCreate failed\n"); return status; }; // // The FDO is the USB Controller, create a device interface for that. // status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfDeviceCreateDeviceInterface for device %p error %x\n", device, status); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfStringCreate(NULL, &attributes, &fdoContext->hcdsymlink); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfStringCreate for device %p error %x\n", device, status); return status; } status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, fdoContext->hcdsymlink); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfStringCreate for device %p error %x\n", device, status); return status; } // // Some of our resources are independent of the device state and // can be allocated/initialized here. // status = InitScratchpad(fdoContext); if (!NT_SUCCESS(status)) { return status; } // // Initialize the I/O Package and any Queues // status = FdoQueueInitialize(device); if (!NT_SUCCESS(status)) { return status; } // // --XT-- All of the WDF ISR and DPC setup code was removed // here. The DPC is now setup through the Xen interface in the // previous call. Note the event channel is setup but not active // until the backend is connected. // // // Allocate a watchdog timer for our Xen interface. // WDF_TIMER_CONFIG timerConfig; WDF_OBJECT_ATTRIBUTES timerAttributes; WDF_TIMER_CONFIG_INIT( &timerConfig, FdoEvtTimerFunc); WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); timerAttributes.ParentObject = device; timerAttributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfTimerCreate( &timerConfig, &timerAttributes, &fdoContext->WatchdogTimer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfTimerCreate error %x\n", status); return status; } // // Create a collection of work items. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfCollectionCreate(&attributes, &fdoContext->FreeWorkItems); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfCollectionCreate error %x\n", status); return status; } for (ULONG index = 0; index < INIT_WORK_ITEM_COUNT; index++) { WDFWORKITEM workitem = NewWorkItem(fdoContext, NULL, 0,0,0,0); if (workitem) { status = WdfCollectionAdd(fdoContext->FreeWorkItems, workitem); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfCollectionAdd for workitem index %d error %x\n", index, status); WdfObjectDelete(workitem); return status; } } } PNP_BUS_INFORMATION busInformation; busInformation.BusNumber = 0; busInformation.BusTypeGuid = GUID_BUS_TYPE_USB; busInformation.LegacyBusType = PNPBus; WdfDeviceSetBusInformationForChildren( device, &busInformation); if (NT_SUCCESS(status)) { status = LateSetup(device); } return status; }
NTSTATUS UfxDevice_DeviceCreate ( _In_ WDFDEVICE WdfDevice ) /*++ Routine Description: Routine that registers with UFX and creates the UFX device object. Arguments: WdfDevice - Wdf object representing the device. Return Value: NTSTATUS. --*/ { NTSTATUS Status; PCONTROLLER_CONTEXT ControllerContext; UFX_DEVICE_CALLBACKS UfxDeviceCallbacks; UFX_DEVICE_CAPABILITIES UfxDeviceCapabilities; PUFXDEVICE_CONTEXT UfxDeviceContext; UFXDEVICE UfxDevice; WDF_OBJECT_ATTRIBUTES Attributes; PAGED_CODE(); TraceEntry(); ControllerContext = DeviceGetControllerContext(WdfDevice); UFX_DEVICE_CAPABILITIES_INIT(&UfxDeviceCapabilities); UfxDeviceCapabilities.MaxSpeed = UsbSuperSpeed; UfxDeviceCapabilities.RemoteWakeSignalDelay = REMOTE_WAKEUP_TIMEOUT_INTERVAL_MS; // // Set bitmasks that define the IN and OUT endpoint numbers that are available on the controller // // // #### TODO: Set the IN endpoint mask here if not all endpoint addresses are supported #### // // For illustration purposes sample will set default control endpoint 0, 1-4, 8 UfxDeviceCapabilities.InEndpointBitmap = 0x011F; // // #### TODO: Set the OUT endpoint mask here if not all endpoint addresses are supported #### // // For illustration purposes sample will set default control endpoint 0, 2-7 // UfxDeviceCapabilities.OutEndpointBitmap = 0x00FD; // // Set the event callbacks for the ufxdevice // UFX_DEVICE_CALLBACKS_INIT(&UfxDeviceCallbacks); UfxDeviceCallbacks.EvtDeviceHostConnect = UfxDevice_EvtDeviceHostConnect; UfxDeviceCallbacks.EvtDeviceHostDisconnect = UfxDevice_EvtDeviceHostDisconnect; UfxDeviceCallbacks.EvtDeviceAddressed = UfxDevice_EvtDeviceAddressed; UfxDeviceCallbacks.EvtDeviceEndpointAdd = UfxDevice_EvtDeviceEndpointAdd; UfxDeviceCallbacks.EvtDeviceDefaultEndpointAdd = UfxDevice_EvtDeviceDefaultEndpointAdd; UfxDeviceCallbacks.EvtDeviceUsbStateChange = UfxDevice_EvtDeviceUsbStateChange; UfxDeviceCallbacks.EvtDevicePortChange = UfxDevice_EvtDevicePortChange; UfxDeviceCallbacks.EvtDevicePortDetect = UfxDevice_EvtDevicePortDetect; UfxDeviceCallbacks.EvtDeviceRemoteWakeupSignal = UfxDevice_EvtDeviceRemoteWakeupSignal; UfxDeviceCallbacks.EvtDeviceTestModeSet = UfxDevice_EvtDeviceTestModeSet; UfxDeviceCallbacks.EvtDeviceSuperSpeedPowerFeature = UfxDevice_EvtDeviceSuperSpeedPowerFeature; // Context associated with UFXDEVICE object WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attributes, UFXDEVICE_CONTEXT); Attributes.EvtCleanupCallback = UfxDevice_EvtCleanupCallback; // Create the UFXDEVICE object Status = UfxDeviceCreate(WdfDevice, &UfxDeviceCallbacks, &UfxDeviceCapabilities, &Attributes, &UfxDevice); CHK_NT_MSG(Status, "Failed to create UFXDEVICE object"); // Initialize the client context space in UFXDEVICE object UfxDeviceContext = UfxDeviceGetContext(UfxDevice); UfxDeviceContext->FdoWdfDevice = WdfDevice; UfxDeviceContext->UsbState = UsbfnDeviceStateDetached; UfxDeviceContext->UsbPort = UsbfnUnknownPort; UfxDeviceContext->IsIdle = TRUE; ControllerContext->UfxDevice = UfxDevice; // // Create endpoints collection // WDF_OBJECT_ATTRIBUTES_INIT(&Attributes); Attributes.ParentObject = UfxDevice; Status = WdfCollectionCreate(&Attributes, &UfxDeviceContext->Endpoints); CHK_NT_MSG(Status, "Failed to create endpoint collection object"); End: TraceExit(); return Status; }