NTSTATUS StreamEditInitDriverObjects( _Inout_ DRIVER_OBJECT* driverObject, const UNICODE_STRING* registryPath, _Out_ WDFDRIVER* pDriver, _Out_ WDFDEVICE* pDevice ) { NTSTATUS status; WDF_DRIVER_CONFIG config; PWDFDEVICE_INIT pInit = NULL; WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK); config.DriverInitFlags |= WdfDriverInitNonPnpDriver; config.EvtDriverUnload = StreamEditEvtDriverUnload; status = WdfDriverCreate( driverObject, registryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, pDriver ); if (!NT_SUCCESS(status)) { goto Exit; } pInit = WdfControlDeviceInitAllocate(*pDriver, &SDDL_DEVOBJ_KERNEL_ONLY); if (!pInit) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } WdfDeviceInitSetCharacteristics(pInit, FILE_AUTOGENERATED_DEVICE_NAME, TRUE); WdfDeviceInitSetDeviceType(pInit, FILE_DEVICE_NETWORK); WdfDeviceInitSetCharacteristics(pInit, FILE_DEVICE_SECURE_OPEN, TRUE); status = WdfDeviceCreate(&pInit, WDF_NO_OBJECT_ATTRIBUTES, pDevice); if (!NT_SUCCESS(status)) { WdfDeviceInitFree(pInit); goto Exit; } WdfControlFinishInitializing(*pDevice); Exit: return status; }
NTSTATUS MouseTrapEvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT deviceInit) { UNREFERENCED_PARAMETER(driver); PAGED_CODE(); // Ensure paging is allowed in current IRQL // Create filter WdfFdoInitSetFilter(deviceInit); // Set driver type to mouse WdfDeviceInitSetDeviceType(deviceInit, FILE_DEVICE_MOUSE); // Create attributes for a device extension WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); // Create framework device object WDFDEVICE hDevice; NTSTATUS status = WdfDeviceCreate(&deviceInit, &deviceAttributes, &hDevice); if(!NT_SUCCESS(status)) { DebugPrint(("[MouseTrap] WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } // Set request queue type WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // Set handler for device control requests ioQueueConfig.EvtIoInternalDeviceControl = MouseTrapEvtIoInternalDeviceControl; // Create queue for filter device status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE); if(!NT_SUCCESS(status)) { DebugPrint(("[MouseTrap] WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
NTSTATUS Bus_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Bus_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 bus. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_CHILD_LIST_CONFIG config; WDF_OBJECT_ATTRIBUTES fdoAttributes; NTSTATUS status; WDFDEVICE device; WDF_IO_QUEUE_CONFIG queueConfig; PNP_BUS_INFORMATION busInfo; //PFDO_DEVICE_DATA deviceData; WDFQUEUE queue; UNREFERENCED_PARAMETER(Driver); PAGED_CODE (); KdPrint(("Bus_EvtDeviceAdd: 0x%p\n", Driver)); // // Initialize all the properties specific to the device. // Framework has default values for the one that are not // set explicitly here. So please read the doc and make sure // you are okay with the defaults. // WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); WdfDeviceInitSetExclusive(DeviceInit, TRUE); // // Since this is pure software bus enumerator, we don't have to register for // any PNP/Power callbacks. Framework will take the default action for // all the PNP and Power IRPs. // // // WDF_ DEVICE_LIST_CONFIG describes how the framework should handle // dynamic child enumeration on behalf of the driver writer. // Since we are a bus driver, we need to specify identification description // for our child devices. This description will serve as the identity of our // child device. Since the description is opaque to the framework, we // have to provide bunch of callbacks to compare, copy, or free // any other resources associated with the description. // WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_IDENTIFICATION_DESCRIPTION), Bus_EvtDeviceListCreatePdo // callback to create a child device. ); // // This function pointer will be called when the framework needs to copy a // identification description from one location to another. An implementation // of this function is only necessary if the description contains description // relative pointer values (like LIST_ENTRY for instance) . // If set to NULL, the framework will use RtlCopyMemory to copy an identification . // description. In this sample, it's not required to provide these callbacks. // they are added just for illustration. // config.EvtChildListIdentificationDescriptionDuplicate = Bus_EvtChildListIdentificationDescriptionDuplicate; // // This function pointer will be called when the framework needs to compare // two identificaiton descriptions. If left NULL a call to RtlCompareMemory // will be used to compare two identificaiton descriptions. // config.EvtChildListIdentificationDescriptionCompare = Bus_EvtChildListIdentificationDescriptionCompare; // // This function pointer will be called when the framework needs to free a // identification description. An implementation of this function is only // necessary if the description contains dynamically allocated memory // (by the driver writer) that needs to be freed. The actual identification // description pointer itself will be freed by the framework. // config.EvtChildListIdentificationDescriptionCleanup = Bus_EvtChildListIdentificationDescriptionCleanup; // // Tell the framework to use the built-in childlist to track the state // of the device based on the configuration we just created. // WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES); // // Initialize attributes structure to specify size and accessor function // for storing device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA); // // Create a framework device object. In response to this call, framework // creates a WDM deviceobject and attach to the PDO. // status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS(status)) { KdPrint(("Error creating device 0x%x\n", status)); return status; } // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel ); queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl; // // 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 or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. 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(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate( device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); __analysis_assume(queueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoQueueCreate failed status 0x%x\n", status)); return status; } // // Get the device context. // //deviceData = FdoGetData(device); // // Create device interface for this device. The interface will be // enabled by the framework when we return from StartDevice successfully. // Clients of this driver will open this interface and send ioctls. // status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_BUSENUM_TOASTER, NULL // No Reference String. If you provide one it will appended to the ); // symbolic link. Some drivers register multiple interfaces for the same device // and use the reference string to distinguish between them if (!NT_SUCCESS(status)) { return status; } // // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION // for the child devices. This is an optional information provided to // uniquely idenitfy the bus the device is connected. // busInfo.BusTypeGuid = GUID_DEVCLASS_TOASTER; busInfo.LegacyBusType = PNPBus; busInfo.BusNumber = 0; WdfDeviceSetBusInformationForChildren(device, &busInfo); status = Bus_WmiRegistration(device); if (!NT_SUCCESS(status)) { return status; } // // Check the registry to see if we need to enumerate child devices during // start. // status = Bus_DoStaticEnumeration(device); return status; }
NTSTATUS PortIODeviceCreate( PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Worker routine called to create a device and its software resources. Arguments: DeviceInit - Pointer to an opaque init structure. Memory for this structure will be freed by the framework when the WdfDeviceCreate succeeds. So don't access the structure after that point. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; PDEVICE_CONTEXT deviceContext; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDFDEVICE device; NTSTATUS status; UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; WDF_FILEOBJECT_CONFIG fileConfig; PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Register pnp/power callbacks so that we can start and stop the timer as // the device gets started and stopped. // pnpPowerCallbacks.EvtDevicePrepareHardware = PortIOEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = PortIOEvtDeviceReleaseHardware; // // Register the PnP and power callbacks. Power policy related callbacks will // be registered later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK // not interested in Cleanup ); // Let the framework complete create and close fileConfig.AutoForwardCleanupClose = WdfFalse; WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); // // Create a named deviceobject so that legacy applications can talk to us. // Since we are naming the object, we wouldn't able to install multiple // instance of this driver. Please note that as per PNP guidelines, we // should not name the FDO or create symbolic links. We are doing it because // we have a legacy APP that doesn't know how to open an interface. // RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME); status = WdfDeviceInitAssignName(DeviceInit,&ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, GPD_TYPE); // // Call this if the device is not holding a pagefile // crashdump file or hibernate file. // WdfDeviceInitSetPowerPageable(DeviceInit); status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the // device.h header file. This function will do the type checking and return // the device context. If you pass a wrong object handle // it will return NULL and assert if run under framework verifier mode. // deviceContext = PortIOGetDeviceContext(device); // // This values is based on the hardware design. // I'm assuming the address is in I/O space for our hardware. // Refer http://support.microsoft.com/default.aspx?scid=kb;en-us;Q323595 // for more info. // deviceContext-> PortMemoryType = 1; // // Create a device interface so that application can find and talk // to us. // RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); status = WdfDeviceCreateSymbolicLink( device, &win32DeviceName); if (!NT_SUCCESS(status)) { return status; } // // Initialize the I/O Package and any Queues // status = PortIOQueueInitialize(device); return status; }
NTSTATUS VIOSerialDeviceListCreatePdo( IN WDFCHILDLIST DeviceList, IN PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, IN PWDFDEVICE_INIT ChildInit ) { PVIOSERIAL_PORT pport = NULL; NTSTATUS status = STATUS_SUCCESS; WDFDEVICE hChild = NULL; WDF_OBJECT_ATTRIBUTES attributes; WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_DEVICE_STATE deviceState; WDF_IO_QUEUE_CONFIG queueConfig; PRAWPDO_VIOSERIAL_PORT rawPdo = NULL; WDF_FILEOBJECT_CONFIG fileConfig; DECLARE_CONST_UNICODE_STRING(deviceId, PORT_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(deviceLocation, L"RedHat VIOSerial Port" ); DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH); UNREFERENCED_PARAMETER(DeviceList); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); pport = CONTAINING_RECORD(IdentificationDescription, VIOSERIAL_PORT, Header ); WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_SERIAL_PORT); WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect); do { WdfDeviceInitSetExclusive(ChildInit, TRUE); status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_PORT_DEVICE); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignRawDevice failed - 0x%x\n", status); break; } status = WdfDeviceInitAssignSDDLString(ChildInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceInitAssignSDDLString failed - 0x%x\n", status); break; } status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignDeviceID failed - 0x%x\n", status); break; } status = WdfPdoInitAddHardwareID(ChildInit, &deviceId); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAddHardwareID failed - 0x%x\n", status); break; } status = RtlUnicodeStringPrintf( &buffer, L"%02u", pport->PortId ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed - 0x%x\n", status); break; } status = WdfPdoInitAssignInstanceID(ChildInit, &buffer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignInstanceID failed - 0x%x\n", status); break; } status = RtlUnicodeStringPrintf( &buffer, L"vport%up%u", pport->DeviceId, pport->PortId ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed 0x%x\n", status); break; } status = WdfPdoInitAddDeviceText( ChildInit, &buffer, &deviceLocation, 0x409 ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAddDeviceText failed 0x%x\n", status); break; } WdfPdoInitSetDefaultLocale(ChildInit, 0x409); WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, VIOSerialPortCreate, VIOSerialPortClose, WDF_NO_EVENT_CALLBACK ); WdfDeviceInitSetFileObjectConfig( ChildInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES ); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks); PnpPowerCallbacks.EvtDeviceD0Entry = VIOSerialPortEvtDeviceD0Entry; PnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = VIOSerialPortEvtDeviceD0ExitPreInterruptsDisabled; PnpPowerCallbacks.EvtDeviceD0Exit = VIOSerialPortEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT); attributes.SynchronizationScope = WdfSynchronizationScopeDevice; attributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfDeviceCreate( &ChildInit, &attributes, &hChild ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreate failed 0x%x\n", status); break; } rawPdo = RawPdoSerialPortGetData(hChild); rawPdo->port = pport; pport->Device = hChild; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential ); queueConfig.EvtIoDeviceControl = VIOSerialPortDeviceControl; status = WdfIoQueueCreate(hChild, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pport->IoctlQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed (IoCtrl Queue): 0x%x\n", status); break; } status = WdfDeviceConfigureRequestDispatching( hChild, pport->IoctlQueue, WdfRequestTypeDeviceControl ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "DeviceConfigureRequestDispatching failed (IoCtrl Queue): 0x%x\n", status); break; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoRead = VIOSerialPortRead; queueConfig.EvtIoStop = VIOSerialPortIoStop; status = WdfIoQueueCreate(hChild, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pport->ReadQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate (Read Queue) failed 0x%x\n", status); break; } status = WdfDeviceConfigureRequestDispatching( hChild, pport->ReadQueue, WdfRequestTypeRead ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "DeviceConfigureRequestDispatching failed (Read Queue): 0x%x\n", status); break; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.AllowZeroLengthRequests = WdfFalse; queueConfig.EvtIoWrite = VIOSerialPortWrite; status = WdfIoQueueCreate(hChild, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pport->WriteQueue); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed (Write Queue): 0x%x\n", status); break; } status = WdfDeviceConfigureRequestDispatching( hChild, pport->WriteQueue, WdfRequestTypeWrite ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "DeviceConfigureRequestDispatching failed (Write Queue): 0x%x\n", status); break; } WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.NoDisplayInUI = WdfTrue; pnpCaps.Removable = WdfTrue; pnpCaps.EjectSupported = WdfTrue; pnpCaps.SurpriseRemovalOK= WdfTrue; pnpCaps.Address = pport->DeviceId; pnpCaps.UINumber = pport->PortId; WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); WDF_DEVICE_STATE_INIT(&deviceState); deviceState.DontDisplayInUI = WdfTrue; WdfDeviceSetDeviceState(hChild, &deviceState); status = WdfDeviceCreateDeviceInterface( hChild, &GUID_VIOSERIAL_PORT, NULL ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreateDeviceInterface failed 0x%x\n", status); break; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hChild; status = WdfSpinLockCreate( &attributes, &pport->InBufLock ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfSpinLockCreate failed 0x%x\n", status); break; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hChild; status = WdfSpinLockCreate( &attributes, &pport->OutVqLock ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfSpinLockCreate failed 0x%x\n", status); break; } } while (0); if (!NT_SUCCESS(status)) { // We can send this before PDO is PRESENT since the device won't send any response. VIOSerialSendCtrlMsg(pport->BusDevice, pport->PortId, VIRTIO_CONSOLE_PORT_READY, 0); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s status 0x%x\n", __FUNCTION__, status); return status; }
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; }
/** * @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 XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header, PWDFDEVICE_INIT child_init) { NTSTATUS status = STATUS_SUCCESS; WDF_OBJECT_ATTRIBUTES child_attributes; WDFDEVICE child_device; PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header; WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities; DECLARE_UNICODE_STRING_SIZE(buffer, 512); DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus"); PXENPCI_PDO_DEVICE_DATA xppdd; PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list)); //WDF_PDO_EVENT_CALLBACKS pdo_callbacks; WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks; //UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE }; WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities; FUNCTION_ENTER(); WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks); child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry; child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit; child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification; WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks); FUNCTION_MSG("device = '%s', index = '%d', path = '%s'\n", identification->device, identification->index, identification->path); //status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE, // IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions)); //if (!NT_SUCCESS(status)) { // return status; //} //WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks); //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery; //pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery; //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject; //pdo_callbacks.EvtDeviceSetLock = XenPciPdo_EvtDeviceSetLock; //WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks); RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device); status = WdfPdoInitAssignDeviceID(child_init, &buffer); if (!NT_SUCCESS(status)) { return status; } status = WdfPdoInitAddHardwareID(child_init, &buffer); if (!NT_SUCCESS(status)) { return status; } status = WdfPdoInitAddCompatibleID(child_init, &buffer); if (!NT_SUCCESS(status)) { return status; } RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index); status = WdfPdoInitAssignInstanceID(child_init, &buffer); if (!NT_SUCCESS(status)) { return status; } RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index); status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409); if (!NT_SUCCESS(status)) { return status; } WdfPdoInitSetDefaultLocale(child_init, 0x0409); WdfDeviceInitSetPowerNotPageable(child_init); WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA); status = WdfDeviceCreate(&child_init, &child_attributes, &child_device); if (!NT_SUCCESS(status)) { return status; } xppdd = GetXppdd(child_device); xppdd->wdf_device = child_device; xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list); xppdd->xpdd = xpdd; WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE); WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE); WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE); WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities); child_pnp_capabilities.LockSupported = WdfFalse; child_pnp_capabilities.EjectSupported = WdfTrue; child_pnp_capabilities.Removable = WdfTrue; child_pnp_capabilities.DockDevice = WdfFalse; child_pnp_capabilities.UniqueID = WdfFalse; child_pnp_capabilities.SilentInstall = WdfTrue; child_pnp_capabilities.SurpriseRemovalOK = WdfTrue; child_pnp_capabilities.HardwareDisabled = WdfFalse; WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities); WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities); child_power_capabilities.DeviceD1 = WdfTrue; child_power_capabilities.WakeFromD1 = WdfTrue; child_power_capabilities.DeviceWake = PowerDeviceD1; child_power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0; child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1; child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2; child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2; child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3; child_power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3; WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities); RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path); RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device); xppdd->index = identification->index; KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE); ExInitializeFastMutex(&xppdd->backend_state_mutex); xppdd->backend_state = XenbusStateUnknown; xppdd->frontend_state = XenbusStateUnknown; xppdd->backend_path[0] = '\0'; xppdd->backend_id = 0; FUNCTION_EXIT(); return status; }
NTSTATUS RamDiskEvtDeviceAdd( IN WDFDRIVER Driver, IN 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. 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 deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); // // Storage drivers have to name their FDOs. Since we are not unique'fying // the device name, we wouldn't be able to install more than one instance // of this ramdisk driver. // status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Since this is a pure software only driver, there is no need to register // any PNP/Power event callbacks. Framework will respond to these // events appropriately. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Now that the WDF device object has been created, set up any context // that it requires. // pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchSequential ); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); // // 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 or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. 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, &queueAttributes, &queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { return status; } // Context is the Queue handle pQueueContext = QueueGetExtension(queue); // // Set the context for our default queue as our device extension. // pQueueContext->DeviceExtension = pDeviceExtension; #if KMDF_VERSION_MINOR >= 9 // // Enable forward progress on the queue we just created. // NOTE: If you are planning to use this code without forward progress, // comment out the call to SetForwardProgressOnQueue below. // status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } #endif // // Now do any RAM-Disk specific initialization // pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); // // Get the disk parameters from the registry // RamDiskQueryDiskRegParameters( WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)), &pDeviceExtension->DiskRegInfo ); // // Allocate memory for the disk image. // pDeviceExtension->DiskImage = ExAllocatePoolWithTag( NonPagedPool, pDeviceExtension->DiskRegInfo.DiskSize, RAMDISK_TAG ); if (pDeviceExtension->DiskImage) { UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); status = STATUS_SUCCESS; // // Now try to create a symbolic link for the drive letter. // RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); pDeviceExtension->SymbolicLink.Buffer = (PWSTR) &pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink, &pDeviceExtension->DiskRegInfo.DriveLetter); status = WdfDeviceCreateSymbolicLink(device, &pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS FmEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: FmEvtDeviceAdd 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 Fm device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PFM_DEVICE_DATA fmDeviceData; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDFDEVICE hDevice; WDFQUEUE defQueue; UNREFERENCED_PARAMETER(Driver); KdPrint( ("FmEvtDeviceAdd routine \n")); PAGED_CODE(); // // Modem type is serial port. // WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SERIAL_PORT); // // Use Buffered IO. // WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // // Specify the size of device extension where we track per device // context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FM_DEVICE_DATA); // // Register a cleanup callback on the device to free up some resources at the // time the device is deleted. // fdoAttributes.EvtCleanupCallback = FmDeviceCleanup; // // By opting for SynchronizationScopeDevice, we tell the framework to // synchronize callbacks events of all the objects directly associated // with the device. In this driver, we will associate queues. // By doing that we don't have to worrry about synchronizing // access to device-context by various io Events. // Framework will serialize them by using an internal device-lock. // fdoAttributes.SynchronizationScope = WdfSynchronizationScopeDevice; // // 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, &fdoAttributes, &hDevice); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with Status code 0x%x\n", status)); return status; } // // Get the DeviceExtension and initialize it. // fmDeviceData = FmDeviceDataGet(hDevice); // // Tell the Framework that this device will need an interface // status = WdfDeviceCreateDeviceInterface( hDevice, (LPGUID) &GUID_DEVINTERFACE_MODEM, NULL ); if (!NT_SUCCESS (status)) { KdPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); return status; } fmDeviceData->Flags = 0; status = FmCreateDosDevicesSymbolicLink(hDevice, fmDeviceData); if (!NT_SUCCESS(status)) { KdPrint( ("FmCreateDosDevicesSymbolicLink failed with Status code 0x%x\n", status)); return status; } // // Initialize the context // fmDeviceData->BaudRate=1200; fmDeviceData->LineControl = SERIAL_7_DATA | SERIAL_EVEN_PARITY | SERIAL_NONE_PARITY; // // Register I/O callbacks to tell the framework that you are interested // in handling IRP_MJ_READ, IRP_MJ_WRITE, and IRP_MJ_DEVICE_CONTROL requests. // In case a specific handler is not specified for one of these, // the request will be dispatched to the EvtIoDefault handler, if any. // If there is no EvtIoDefault handler, the request will be failed with // STATUS_INVALID_DEVICE_REQUEST. // WdfIoQueueDispatchParallel means that we are capable of handling // all the I/O request simultaneously and we are responsible for protecting // data that could be accessed by these callbacks simultaneously. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoRead = FmEvtIoRead; queueConfig.EvtIoWrite = FmEvtIoWrite; queueConfig.EvtIoDeviceControl = FmEvtIoDeviceControl; status = WdfIoQueueCreate( hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &defQueue // pointer to default queue ); if (!NT_SUCCESS (status)) { // // We don't need to cleanup symbolic link here. The destroy callback for // the device object will do it. // return status; } // // Create a manual queue to hold pending read requests. By keeping // them in the queue, framework takes care of cancelling them if the app exits // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &fmDeviceData->FmReadQueue ); if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // // Create a manual queue to hold pending ioctl wait mask requests. By keeping // them in the queue, framework takes care of cancelling them if the app exits // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &fmDeviceData->FmMaskWaitQueue ); if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
static NTSTATUS XenVbd_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init) { PXENVBD_FILTER_DATA xvfd; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES device_attributes; WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks; WDF_DPC_CONFIG dpc_config; WDF_OBJECT_ATTRIBUTES oa; UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE }; UCHAR power_minor_functions[] = { IRP_MN_SET_POWER }; UNREFERENCED_PARAMETER(driver); FUNCTION_ENTER(); WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN); WdfFdoInitSetFilter(device_init); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks); pnp_power_callbacks.EvtDeviceD0Entry = XenVbd_EvtDeviceD0Entry; pnp_power_callbacks.EvtDeviceD0Exit = XenVbd_EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks); status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE, IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions)); if (!NT_SUCCESS(status)) { return status; } status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER, IRP_MJ_POWER, power_minor_functions, ARRAY_SIZE(power_minor_functions)); if (!NT_SUCCESS(status)) { return status; } WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENVBD_FILTER_DATA); status = WdfDeviceCreate(&device_init, &device_attributes, &device); if (!NT_SUCCESS(status)) { FUNCTION_MSG("Error creating device 0x%x\n", status); return status; } xvfd = GetXvfd(device); xvfd->wdf_device = device; xvfd->wdf_target = WdfDeviceGetIoTarget(device); xvfd->xvdd.xvfd = xvfd; xvfd->xvdd.pdo = WdfDeviceWdmGetPhysicalDevice(device); xvfd->xvdd.grant_tag = XENVBD_POOL_TAG; KeInitializeEvent(&xvfd->xvdd.backend_event, SynchronizationEvent, FALSE); WDF_DPC_CONFIG_INIT(&dpc_config, XenVbd_EvtDpcEvent); WDF_OBJECT_ATTRIBUTES_INIT(&oa); oa.ParentObject = device; status = WdfDpcCreate(&dpc_config, &oa, &xvfd->dpc); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE); FUNCTION_EXIT(); return status; }
// 添加设备 NTSTATUS RamDiskEvtDeviceAdd(IN WDFDRIVER Driver,IN PWDFDEVICE_INIT DeviceInit) { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; //设备名 DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); //检查指定名称状态 status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } //指定设备类型 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); //IO类型 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); //是否独占 WdfDeviceInitSetExclusive(DeviceInit, FALSE); //初始化 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); //设定cleanup 函数指针 deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; //获取创建设备状态 status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (&ioQueueConfig,WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); status = WdfIoQueueCreate( device,&ioQueueConfig,&queueAttributes,&queue ); if (!NT_SUCCESS(status)) { return status; } //获得设备扩展 pQueueContext = QueueGetExtension(queue); //设置队列的设备扩展为该设备 pQueueContext->DeviceExtension = pDeviceExtension; status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } //设备初始化 pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); //从注册表获取信息 RamDiskQueryDiskRegParameters(WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)),&pDeviceExtension->DiskRegInfo); //内存分配 要使用分页内存 pDeviceExtension->DiskImage = ExAllocatePoolWithTag(PagedPool,pDeviceExtension->DiskRegInfo.DiskSize,RAMDISK_TAG); if (pDeviceExtension->DiskImage) { //成功分配 UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); //格式化 status = STATUS_SUCCESS; //创建符号链接 RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); //符号链接初始化 pDeviceExtension->SymbolicLink.Buffer = (PWSTR)&pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink,&pDeviceExtension->DiskRegInfo.DriveLetter); //创建符号链接 status = WdfDeviceCreateSymbolicLink(device,&pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS Bus_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Bus_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 bus. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status; WDFDEVICE device; PFDO_DEVICE_DATA deviceData; PNP_BUS_INFORMATION busInfo; WDFQUEUE queue; UNREFERENCED_PARAMETER(Driver); PAGED_CODE (); KdPrint(("Bus_EvtDeviceAdd: 0x%p\n", Driver)); // // Initialize all the properties specific to the device. // Framework has default values for the one that are not // set explicitly here. So please read the doc and make sure // you are okay with the defaults. // WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); WdfDeviceInitSetExclusive(DeviceInit, TRUE); // // Initialize attributes structure to specify size and accessor function // for storing device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA); // // Create a framework device object. In response to this call, framework // creates a WDM deviceobject. // status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Get the device context. // deviceData = FdoGetData(device); WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; // // Purpose of this lock is documented in Bus_PlugInDevice routine below. // status = WdfWaitLockCreate(&attributes, &deviceData->ChildLock); if (!NT_SUCCESS(status)) { return status; } // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel ); queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl; // // 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 or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. 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(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); __analysis_assume(queueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoQueueCreate failed with status 0x%x\n", status)); return status; } // // Create device interface for this device. The interface will be // enabled by the framework when we return from StartDevice successfully. // status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_BUSENUM_TOASTER, NULL // No Reference String ); if (!NT_SUCCESS(status)) { return status; } // // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION // for the child devices. This is an optional information provided to // uniquely idenitfy the bus the device is connected. // busInfo.BusTypeGuid = GUID_DEVCLASS_TOASTER; busInfo.LegacyBusType = PNPBus; busInfo.BusNumber = 0; WdfDeviceSetBusInformationForChildren(device, &busInfo); status = Bus_WmiRegistration(device); if (!NT_SUCCESS(status)) { return status; } status = Bus_DoStaticEnumeration(device); return status; }
NTSTATUS KbFilter_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Here you can query the device properties using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based on that, decide to create a filter device object and attach to the function stack. If you are not interested in filtering this particular instance of the device, you can just return STATUS_SUCCESS without creating a framework 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 deviceAttributes; NTSTATUS status; WDFDEVICE hDevice; WDFQUEUE hQueue; PDEVICE_EXTENSION filterExt; WDF_IO_QUEUE_CONFIG ioQueueConfig; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); DebugPrint(("Enter FilterEvtDeviceAdd \n")); // // Tell the framework that you are filter driver. Framework // takes care of inherting all the device flags & characterstics // from the lower device you are attaching to. // WdfFdoInitSetFilter(DeviceInit); WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_KEYBOARD); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); // // Create a framework device object. This call will in turn create // a WDM deviceobject, attach to the lower stack and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice); if (!NT_SUCCESS(status)) { DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } filterExt = FilterGetData(hDevice); // // Configure the default queue to be Parallel. Do not use sequential queue // if this driver is going to be filtering PS2 ports because it can lead to // deadlock. The PS2 port driver sends a request to the top of the stack when it // receives an ioctl request and waits for it to be completed. If you use a // a sequential queue, this request will be stuck in the queue because of the // outstanding ioctl request sent earlier to the port driver. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoInternalDeviceControl = KbFilter_EvtIoInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE // pointer to default queue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // // Create a new queue to handle IOCTLs that will be forwarded to us from // the rawPDO. // WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlFromRawPdo; status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } filterExt->rawPdoQueue = hQueue; // // Create a RAW pdo so we can provide a sideband communication with // the application. Please note that not filter drivers desire to // produce such a communication and not all of them are contrained // by other filter above which prevent communication thru the device // interface exposed by the main stack. So use this only if absolutely // needed. Also look at the toaster filter driver sample for an alternate // approach to providing sideband communication. // status = KbFiltr_CreateRawPdo(hDevice, ++InstanceNo); return status; }
NTSTATUS MouFilter_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Here you can query the device properties using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based on that, decide to create a filter device object and attach to the function stack. If you are not interested in filtering this particular instance of the device, you can just return STATUS_SUCCESS without creating a framework 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 deviceAttributes; NTSTATUS status; WDFDEVICE hDevice; WDF_IO_QUEUE_CONFIG ioQueueConfig; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); DebugPrint(("Enter FilterEvtDeviceAdd \n")); // // Tell the framework that you are filter driver. Framework // takes care of inherting all the device flags & characterstics // from the lower device you are attaching to. // WdfFdoInitSetFilter(DeviceInit); WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_MOUSE); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); // // Create a framework device object. This call will in turn create // a WDM deviceobject, attach to the lower stack and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice); if (!NT_SUCCESS(status)) { DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } // // Configure the default queue to be Parallel. Do not use sequential queue // if this driver is going to be filtering PS2 ports because it can lead to // deadlock. The PS2 port driver sends a request to the top of the stack when it // receives an ioctl request and waits for it to be completed. If you use a // a sequential queue, this request will be stuck in the queue because of the // outstanding ioctl request sent earlier to the port driver. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoInternalDeviceControl = MouFilter_EvtIoInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE // pointer to default queue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
NTSTATUS RamDiskEvtDeviceAdd( IN WDFDRIVER Driver, IN 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. 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 deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); // // Storage drivers have to name their FDOs. Since we are not unique'fying // the device name, we wouldn't be able to install more than one instance // of this ramdisk driver. // status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Since this is a pure software only driver, there is no need to register // any PNP/Power event callbacks. Framework will respond to these // events appropriately. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Now that the WDF device object has been created, set up any context // that it requires. // pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchSequential ); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); status = WdfIoQueueCreate( device, &ioQueueConfig, &queueAttributes, &queue ); if (!NT_SUCCESS(status)) { return status; } // Context is the Queue handle pQueueContext = QueueGetExtension(queue); // // Set the context for our default queue as our device extension. // pQueueContext->DeviceExtension = pDeviceExtension; // // Enable forward progress on the queue we just created. // NOTE: If you are planning to use this code without forward progress, // comment out the call to SetForwardProgressOnQueue below. // status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } // // Now do any RAM-Disk specific initialization // pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); // // Get the disk parameters from the registry // RamDiskQueryDiskRegParameters( WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)), &pDeviceExtension->DiskRegInfo ); // // Allocate memory for the disk image. // pDeviceExtension->DiskImage = ExAllocatePoolWithTag( NonPagedPool, pDeviceExtension->DiskRegInfo.DiskSize, RAMDISK_TAG ); if (pDeviceExtension->DiskImage) { UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); status = STATUS_SUCCESS; // // Now try to create a symbolic link for the drive letter. // RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); pDeviceExtension->SymbolicLink.Buffer = (PWSTR) &pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink, &pDeviceExtension->DiskRegInfo.DriveLetter); status = WdfDeviceCreateSymbolicLink(device, &pDeviceExtension->SymbolicLink); } return status; }