UNREFERENCED_PARAMETER(Device); KdPrint(("Entered Bus_CreatePdo\n")); // // Set DeviceType // WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); // // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId // RtlInitUnicodeString(&deviceId, HardwareIds); status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId); if (!NT_SUCCESS(status)) { return status; } // // NOTE: same string is used to initialize hardware id too // status = WdfPdoInitAddHardwareID(DeviceInit, &deviceId); if (!NT_SUCCESS(status)) { return status; } status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId ); if (!NT_SUCCESS(status)) { 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 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 KbFiltr_CreateRawPdo( WDFDEVICE Device, ULONG InstanceNo ) /*++ Routine Description: This routine creates and initialize a PDO. Arguments: Return Value: NT Status code. --*/ { NTSTATUS status; PWDFDEVICE_INIT pDeviceInit = NULL; PRPDO_DEVICE_DATA pdoData = NULL; WDFDEVICE hChild = NULL; WDF_OBJECT_ATTRIBUTES pdoAttributes; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDFQUEUE queue; WDF_DEVICE_STATE deviceState; PDEVICE_EXTENSION devExt; DECLARE_CONST_UNICODE_STRING(deviceId,KBFILTR_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(hardwareId,KBFILTR_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(deviceLocation,L"Keyboard Filter\0" ); DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN); DebugPrint(("Entered KbFiltr_CreateRawPdo\n")); // // Allocate a WDFDEVICE_INIT structure and set the properties // so that we can create a device object for the child. // pDeviceInit = WdfPdoInitAllocate(Device); if (pDeviceInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } // // Mark the device RAW so that the child device can be started // and accessed without requiring a function driver. Since we are // creating a RAW PDO, we must provide a class guid. // status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVCLASS_KEYBOARD); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Since keyboard is secure device, we must protect ourselves from random // users sending ioctls and creating trouble. // status = WdfDeviceInitAssignSDDLString(pDeviceInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID // status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId); if (!NT_SUCCESS(status)) { goto Cleanup; } // // For RAW PDO, there is no need to provide BusQueryHardwareIDs // and BusQueryCompatibleIDs IDs unless we are running on // Windows 2000. // if (!RtlIsNtDdiVersionAvailable(NTDDI_WINXP)) { // // On Win2K, we must provide a HWID for the device to get enumerated. // Since we are providing a HWID, we will have to provide a NULL inf // to avoid the "found new device" popup and get the device installed // silently. // status = WdfPdoInitAddHardwareID(pDeviceInit, &hardwareId); if (!NT_SUCCESS(status)) { goto Cleanup; } } // // We could be enumerating more than one children if the filter attaches // to multiple instances of keyboard, so we must provide a // BusQueryInstanceID. If we don't, system will throw CA bugcheck. // status = RtlUnicodeStringPrintf(&buffer, L"%02d", InstanceNo); if (!NT_SUCCESS(status)) { goto Cleanup; } status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Provide a description about the device. This text is usually read from // the device. In the case of USB device, this text comes from the string // descriptor. This text is displayed momentarily by the PnP manager while // it's looking for a matching INF. If it finds one, it uses the Device // Description from the INF file to display in the device manager. // Since our device is raw device and we don't provide any hardware ID // to match with an INF, this text will be displayed in the device manager. // status = RtlUnicodeStringPrintf(&buffer,L"Keyboard_Filter_%02d", InstanceNo ); if (!NT_SUCCESS(status)) { goto Cleanup; } // // You can call WdfPdoInitAddDeviceText multiple times, adding device // text for multiple locales. When the system displays the text, it // chooses the text that matches the current locale, if available. // Otherwise it will use the string for the default locale. // The driver can specify the driver's default locale by calling // WdfPdoInitSetDefaultLocale. // status = WdfPdoInitAddDeviceText(pDeviceInit, &buffer, &deviceLocation, 0x409 ); if (!NT_SUCCESS(status)) { goto Cleanup; } WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); // // Initialize the attributes to specify the size of PDO device extension. // All the state information private to the PDO will be tracked here. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA); // // Set up our queue to allow forwarding of requests to the parent // This is done so that the cached Keyboard Attributes can be retrieved // WdfPdoInitAllowForwardingRequestToParent(pDeviceInit); status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Get the device context. // pdoData = PdoGetData(hChild); pdoData->InstanceNo = InstanceNo; // // Get the parent queue we will be forwarding to // devExt = FilterGetData(Device); pdoData->ParentQueue = devExt->rawPdoQueue; // // Configure the default queue associated with the control device object // to be Serial so that request passed to EvtIoDeviceControl are serialized. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlForRawPdo; status = WdfIoQueueCreate(hChild, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); goto Cleanup; } // // Set some properties for the child device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.Removable = WdfTrue; pnpCaps.SurpriseRemovalOK = WdfTrue; pnpCaps.NoDisplayInUI = WdfTrue; pnpCaps.Address = InstanceNo; pnpCaps.UINumber = InstanceNo; WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); // // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we // have to do the following to hide the device. Following call // tells the framework to report the device state in // IRP_MN_QUERY_DEVICE_STATE request. // WDF_DEVICE_STATE_INIT(&deviceState); deviceState.DontDisplayInUI = WdfTrue; WdfDeviceSetDeviceState(hChild, &deviceState); // // Tell the Framework that this device will need an interface so that // application can find our device and talk to it. // status = WdfDeviceCreateDeviceInterface( hChild, &GUID_DEVINTERFACE_KBFILTER, NULL ); if (!NT_SUCCESS (status)) { DebugPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); goto Cleanup; } // // Add this device to the FDO's collection of children. // After the child device is added to the static collection successfully, // driver must call WdfPdoMarkMissing to get the device deleted. It // shouldn't delete the child device directly by calling WdfObjectDelete. // status = WdfFdoAddStaticChild(Device, hChild); if (!NT_SUCCESS(status)) { goto Cleanup; } // // pDeviceInit will be freed by WDF. // return STATUS_SUCCESS; Cleanup: DebugPrint(("KbFiltr_CreatePdo failed %x\n", status)); // // Call WdfDeviceInitFree if you encounter an error while initializing // a new framework device object. If you call WdfDeviceInitFree, // do not call WdfDeviceCreate. // if (pDeviceInit != NULL) { WdfDeviceInitFree(pDeviceInit); } if(hChild) { WdfObjectDelete(hChild); } return status; }
NTSTATUS vJoy_CreateRawPdo( WDFDEVICE Device, ULONG InstanceNo ) /*++ Routine Description: This routine creates and initialize a PDO. Arguments: Return Value: NT Status code. --*/ { NTSTATUS status; PWDFDEVICE_INIT pDeviceInit = NULL; PRPDO_DEVICE_DATA pdoData = NULL; WDFDEVICE hChild = NULL; WDF_OBJECT_ATTRIBUTES pdoAttributes; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDFQUEUE queue; WDF_DEVICE_STATE deviceState; PDEVICE_EXTENSION devExt; DECLARE_CONST_UNICODE_STRING(deviceId,VJOY_RAW_DEVICE_ID ); //DECLARE_CONST_UNICODE_STRING(hardwareId,VJOY_HARDWARE_ID ); DECLARE_CONST_UNICODE_STRING(deviceLocation,L"vJoy Raw Device\0" ); DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN); PDEVICE_OBJECT ChildDeviceObject; PDEVICE_OBJECT ParentDeviceObject; DECLARE_CONST_UNICODE_STRING( SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_R_RES_R, L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GR;;;WD)(A;;GR;;;RC)" ); DECLARE_CONST_UNICODE_STRING( SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R, L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GR;;;RC)" ); int iInterface; WCHAR RefStr[20]; UNICODE_STRING RefStr2; WDF_FILEOBJECT_CONFIG FileObjInit; WDF_OBJECT_ATTRIBUTES FileObjAttributes; WDF_OBJECT_ATTRIBUTES LockAttributes; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_CreateRawPdo\n"); // // Allocate a WDFDEVICE_INIT structure and set the properties // so that we can create a device object for the child. // pDeviceInit = WdfPdoInitAllocate(Device); if (pDeviceInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAllocate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Mark the device RAW so that the child device can be started // and accessed without requiring a function driver. Since we are // creating a RAW PDO, we must provide a class guid. // status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVINTERFACE_VJOY); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignRawDevice", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // TODO: Assign correct SDDL //// status = WdfDeviceInitAssignSDDLString(pDeviceInit, &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceInitAssignSDDLString", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID // status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignDeviceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // We could be enumerating more than one children if the filter attaches // to multiple instances of keyboard, so we must provide a // BusQueryInstanceID. If we don't, system will throw CA bugcheck. // status = RtlUnicodeStringPrintf(&buffer, VJOY_DEVICE_INSTANCE, InstanceNo); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignInstanceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Provide a description about the device. This text is usually read from // the device. This text is displayed momentarily by the PnP manager while // it's looking for a matching INF. If it finds one, it uses the Device // Description from the INF file to display in the device manager. // Since our device is raw device and we don't provide any hardware ID // to match with an INF, this text will be displayed in the device manager. // status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_409 ); // English - United States if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // You can call WdfPdoInitAddDeviceText multiple times, adding device // text for multiple locales. When the system displays the text, it // chooses the text that matches the current locale, if available. // Otherwise it will use the string for the default locale. // The driver can specify the driver's default locale by calling // WdfPdoInitSetDefaultLocale. // status = WdfPdoInitAddDeviceText(pDeviceInit, &buffer, &deviceLocation, 0x409 // English - United States ); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } #if 0 // Hebrew (No real ned - just for fun) status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_40D, InstanceNo ); // Hebrew if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (3)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } status = WdfPdoInitAddDeviceText(pDeviceInit, &buffer, &deviceLocation, 0x40D // Hebrew ); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } #endif // 0 WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); // English - United States WdfDeviceInitSetExclusive(pDeviceInit, FALSE); // Create a WDFFILEOBJECT WDF_OBJECT_ATTRIBUTES_INIT(&FileObjAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&FileObjAttributes, FILEOBJECT_EXTENSION); WDF_FILEOBJECT_CONFIG_INIT(&FileObjInit, vJoy_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, vJoy_EvtFileCleanup); WdfDeviceInitSetFileObjectConfig(pDeviceInit, &FileObjInit, &FileObjAttributes); // // Initialize the attributes to specify the size of PDO device extension. // All the state information private to the PDO will be tracked here. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA); pdoAttributes.EvtCleanupCallback = rawEvtCleanupCallback; // // Set up our queue to allow forwarding of requests to the parent // This is done so that the cached data can be retrieved // //WdfPdoInitAllowForwardingRequestToParent(pDeviceInit); // TODO: Replace the above because it is needed for WdfRequestForwardToParentDeviceIoQueue() status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Get the device context. // pdoData = PdoGetData(hChild); pdoData->InstanceNo = InstanceNo; pdoData->hParentDevice = Device; // // Save the I/O target handle and adjust the I/O stack size: // devExt = GetDeviceContext(Device); pdoData->IoTargetToParent = devExt->IoTargetToSelf; ChildDeviceObject = WdfDeviceWdmGetDeviceObject(hChild); ParentDeviceObject = WdfDeviceWdmGetDeviceObject(Device); ChildDeviceObject->StackSize = ParentDeviceObject->StackSize+1; // Create a wait-lock object that will be used to synch access to positions[i] // The lock is created when the raw device is created so the raw device is set to be its parent WDF_OBJECT_ATTRIBUTES_INIT(&LockAttributes); LockAttributes.ParentObject = hChild; status = WdfWaitLockCreate(&LockAttributes, &(devExt->positionLock)); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfWaitLockCreate failed 0x%x\n", status); LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfWaitLockCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Configure the default queue associated with the control device object // to be Serial so that request passed to EvtIoDeviceControl are serialized. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = vJoy_EvtIoDeviceControlForRawPdo; status = WdfIoQueueCreate(hChild, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed 0x%x\n", status); LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfIoQueueCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Set some properties for the child device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.Removable = WdfTrue; // Remove Icon from " Devices and Printers" pnpCaps.SurpriseRemovalOK = WdfTrue; pnpCaps.NoDisplayInUI = WdfTrue; // pnpCaps.Address = InstanceNo; pnpCaps.UINumber = 0; WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); // // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we // have to do the following to hide the device. Following call // tells the framework to report the device state in // IRP_MN_QUERY_DEVICE_STATE request. // WDF_DEVICE_STATE_INIT(&deviceState); deviceState.DontDisplayInUI = WdfTrue; // Remove Icon from Device manager WdfDeviceSetDeviceState(hChild, &deviceState); // // Create 16 interfaces // for (iInterface=1 ; iInterface <= MAX_N_DEVICES; iInterface++) { RtlStringCchPrintfW((NTSTRSAFE_PWSTR)RefStr, 20, VJOY_INTERFACE L"%03d", iInterface); RtlInitUnicodeString(&RefStr2, (PCWSTR)RefStr); status = WdfDeviceCreateDeviceInterface(hChild,&GUID_DEVINTERFACE_VJOY,&RefStr2); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateDeviceInterface number %d failed 0x%x\n", iInterface, status); LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreateDeviceInterface", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } }; // Mark all interfaces as unused pdoData->UsedInterfacesMask=0; // // Add this device to the FDO's collection of children. // After the child device is added to the static collection successfully, // driver must call WdfPdoMarkMissing to get the device deleted. It // shouldn't delete the child device directly by calling WdfObjectDelete. // status = WdfFdoAddStaticChild(Device, hChild); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfFdoAddStaticChild", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } return STATUS_SUCCESS; Cleanup: TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "KbFiltr_CreatePdo failed %x\n", status); // // Call WdfDeviceInitFree if you encounter an error while initializing // a new framework device object. If you call WdfDeviceInitFree, // do not call WdfDeviceCreate. // if (pDeviceInit != NULL) { WdfDeviceInitFree(pDeviceInit); } if(hChild) { WdfObjectDelete(hChild); } return status; }
NTSTATUS OsrEvtDeviceListCreatePdo( WDFCHILDLIST DeviceList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit ) /*++ Routine Description: Called by the framework in response to Query-Device relation when a new PDO for a child device needs to be created. Arguments: DeviceList - Handle to the default WDFCHILDLIST created by the framework as part of FDO. IdentificationDescription - Decription of the new child device. ChildInit - It's a opaque structure used in collecting device settings and passed in as a parameter to CreateDevice. Return Value: NT Status code. --*/ { NTSTATUS status; WDFDEVICE hChild = NULL; PPDO_IDENTIFICATION_DESCRIPTION pDesc; WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; DECLARE_CONST_UNICODE_STRING(deviceId, OSRUSBFX2_SWITCH_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(hardwareId, OSRUSBFX2_SWITCH_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(deviceLocation, L"OSR USB-FX2 Learning Kit" ); DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH); UNREFERENCED_PARAMETER(DeviceList); pDesc = CONTAINING_RECORD(IdentificationDescription, PDO_IDENTIFICATION_DESCRIPTION, Header); // // Mark the device RAW so that the child device can be started // and accessed without requiring a function driver. Since we are // creating a RAW PDO, we must provide a class guid. // status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_OSRUSBFX2); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Since our devices for switches can trigger nuclear explosion, // we must protect them from random users sending I/Os. // status = WdfDeviceInitAssignSDDLString(ChildInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL); if (!NT_SUCCESS(status)) { goto Cleanup; } status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId); if (!NT_SUCCESS(status)) { goto Cleanup; } // // On XP and later, there is no need to provide following IDs for raw pdos. // BusQueryHardwareIDs but on On Win2K, we must provide a HWID and a NULL // section in the INF to get the device installed without any problem. // status = WdfPdoInitAddHardwareID(ChildInit, &hardwareId); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Since we are enumerating more than one children, we must // provide a BusQueryInstanceID. If we don't, system will throw // CA bugcheck. // status = RtlUnicodeStringPrintf(&buffer, L"%02d", pDesc->SwitchNumber); if (!NT_SUCCESS(status)) { return status; } status = WdfPdoInitAssignInstanceID(ChildInit, &buffer); if (!NT_SUCCESS(status)) { return status; } // // Provide a description about the device. This text is usually read from // the device. In the case of USB device, this text comes from the string // descriptor. This text is displayed momentarily by the PnP manager while // it's looking for a matching INF. If it finds one, it uses the Device // Description from the INF file to display in the device manager. // Since our device is raw device and we don't provide any hardware ID // to match with an INF, this text will be displayed in the device manager. // status = RtlUnicodeStringPrintf(&buffer, L"OsrUsbFX2 RawPdo For Switch %02d", pDesc->SwitchNumber); if (!NT_SUCCESS(status)) { goto Cleanup; } // // You can call WdfPdoInitAddDeviceText multiple times, adding device // text for multiple locales. When the system displays the text, it // chooses the text that matches the current locale, if available. // Otherwise it will use the string for the default locale. // The driver can specify the driver's default locale by calling // WdfPdoInitSetDefaultLocale. // status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &deviceLocation, 0x409); if (!NT_SUCCESS(status)) { goto Cleanup; } WdfPdoInitSetDefaultLocale(ChildInit, 0x409); status = WdfDeviceCreate(&ChildInit, WDF_NO_OBJECT_ATTRIBUTES, &hChild); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Set idle-time out on the child device. This is required to allow // the parent device to idle-out when there are no active I/O. // WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); idleSettings.IdleTimeout = 1000; // 1-sec status = WdfDeviceAssignS0IdleSettings(hChild, &idleSettings); if ( !NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status); return status; } return status; Cleanup: TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"CreatePdo failed %x\n", status); // // On error, framework will cleanup all the resources when it deletes // the device. So there is nothing to do. // return status; }