_Must_inspect_result_ NTSTATUS FxLibraryCreateDevice( __in PUNICODE_STRING DeviceName ) { NTSTATUS status; ULONG i; i = 0; // // Repeatedly try to create a named device object until we run out of buffer // space or we succeed. // do { status = RtlUnicodeStringPrintf(DeviceName, L"%s%d", KMDF_DEVICE_NAME, i++); if (!NT_SUCCESS(status)) { return status; } // // Create a device with no device extension // status = IoCreateDevice( FxLibraryGlobals.DriverObject, 0, DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &FxLibraryGlobals.LibraryDeviceObject ); } while (STATUS_OBJECT_NAME_COLLISION == status); if (NT_SUCCESS(status)) { // // Clear the initializing bit now because the loader will attempt to // open the device before we return from DriverEntry // ASSERT(FxLibraryGlobals.LibraryDeviceObject != NULL); FxLibraryGlobals.LibraryDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; } return status; }
VOID USBPcapDeleteRootHubControlDevice(IN PDEVICE_OBJECT controlDevice) { UNICODE_STRING symbolicLinkName; PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN]; USHORT id; PDEVICE_EXTENSION pDevExt; NTSTATUS status; pDevExt = ((PDEVICE_EXTENSION)controlDevice->DeviceExtension); ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL); id = pDevExt->context.control.id; symbolicLinkName.Length = 0; symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN; symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer; status = RtlUnicodeStringPrintf(&symbolicLinkName, SYMBOLIC_PREFIX L"%hu", id); IoAcquireRemoveLock(&pDevExt->removeLock, NULL); IoReleaseRemoveLockAndWait(&pDevExt->removeLock, NULL); IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL); ASSERT(NT_SUCCESS(status)); if (NT_SUCCESS(status)) { IoDeleteSymbolicLink(&symbolicLinkName); IoDeleteDevice(controlDevice); } else { /* Very bad */ KdPrint(("Failed to init symbolic link name\n")); pDevExt->context.control.pRootHubObject = NULL; } }
NTSTATUS OnDeviceAdd( _In_ WDFDRIVER FxDriver, _Inout_ PWDFDEVICE_INIT FxDeviceInit ) /*++ Routine Description: This routine creates the device object for an SPB controller and the device's child objects. Arguments: FxDriver - the WDF driver object handle FxDeviceInit - information about the PDO that we are loading on Return Value: Status --*/ { //FuncEntry(TRACE_FLAG_WDFLOADING); PDEVICE_CONTEXT pDevice; NTSTATUS status; UNREFERENCED_PARAMETER(FxDriver); // // Setup PNP/Power callbacks. // { WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(FxDeviceInit, &pnpCallbacks); } // // Prepare for file object handling. // { WDF_FILEOBJECT_CONFIG fileObjectConfig; WDF_FILEOBJECT_CONFIG_INIT( &fileObjectConfig, nullptr, nullptr, OnFileCleanup); WDF_OBJECT_ATTRIBUTES fileObjectAttributes; WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes); WdfDeviceInitSetFileObjectConfig( FxDeviceInit, &fileObjectConfig, &fileObjectAttributes); } // // Set request attributes. // { WDF_OBJECT_ATTRIBUTES attributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &attributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes); } // // Create the device. // { WDFDEVICE fxDevice; WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate( &FxDeviceInit, &deviceAttributes, &fxDevice); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating WDFDEVICE - %!STATUS!", status); goto exit; } pDevice = GetDeviceContext(fxDevice); NT_ASSERT(pDevice != nullptr); pDevice->FxDevice = fxDevice; } // // Ensure device is disable-able // { WDF_DEVICE_STATE deviceState; WDF_DEVICE_STATE_INIT(&deviceState); deviceState.NotDisableable = WdfFalse; WdfDeviceSetDeviceState(pDevice->FxDevice, &deviceState); } // // Create queues to handle IO // { WDF_IO_QUEUE_CONFIG queueConfig; WDFQUEUE queue; // // Top-level queue // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDefault = OnTopLevelIoDefault; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( pDevice->FxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating top-level IO queue - %!STATUS!", status); goto exit; } // // Sequential SPB queue // WDF_IO_QUEUE_CONFIG_INIT( &queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoRead = OnIoRead; queueConfig.EvtIoWrite = OnIoWrite; queueConfig.EvtIoDeviceControl = OnIoDeviceControl; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( pDevice->FxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->SpbQueue ); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating SPB IO queue - %!STATUS!", status); goto exit; } } // // Create a symbolic link. // { DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128); status = RtlUnicodeStringPrintf( &symbolicLinkName, L"%ws", sensy_SYMBOLIC_NAME); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating symbolic link string for device " "- %!STATUS!", status); goto exit; } status = WdfDeviceCreateSymbolicLink( pDevice->FxDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating symbolic link for device " "- %!STATUS!", status); goto exit; } } // // Retrieve registry settings. // { WDFKEY key = NULL; WDFKEY subkey = NULL; ULONG connectInterrupt = 0; NTSTATUS settingStatus; DECLARE_CONST_UNICODE_STRING(subkeyName, L"Settings"); DECLARE_CONST_UNICODE_STRING(connectInterruptName, L"ConnectInterrupt"); settingStatus = WdfDeviceOpenRegistryKey( pDevice->FxDevice, PLUGPLAY_REGKEY_DEVICE, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(settingStatus)) { Trace( TRACE_LEVEL_WARNING, TRACE_FLAG_WDFLOADING, "Error opening device registry key - %!STATUS!", settingStatus); } if (NT_SUCCESS(settingStatus)) { settingStatus = WdfRegistryOpenKey( key, &subkeyName, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &subkey); if (!NT_SUCCESS(settingStatus)) { Trace( TRACE_LEVEL_WARNING, TRACE_FLAG_WDFLOADING, "Error opening registry subkey for 'Settings' - %!STATUS!", settingStatus); } } if (NT_SUCCESS(settingStatus)) { settingStatus = WdfRegistryQueryULong( subkey, &connectInterruptName, &connectInterrupt); if (!NT_SUCCESS(settingStatus)) { Trace( TRACE_LEVEL_WARNING, TRACE_FLAG_WDFLOADING, "Error querying registry value for 'ConnectInterrupt' - %!STATUS!", settingStatus); } } if (key != NULL) { WdfRegistryClose(key); } if (subkey != NULL) { WdfRegistryClose(subkey); } pDevice->ConnectInterrupt = (connectInterrupt == 1); } exit: //FuncExit(TRACE_FLAG_WDFLOADING); return status; }
NTSTATUS SerialGetConfigDefaults( IN PSERIAL_FIRMWARE_DATA DriverDefaultsPtr, IN WDFDRIVER Driver ) /*++ Routine Description: This routine reads the default configuration data from the registry for the serial driver. It also builds fields in the registry for several configuration options if they don't exist. Arguments: DriverDefaultsPtr - Pointer to a structure that will contain the default configuration values. RegistryPath - points to the entry for this driver in the current control set of the registry. Return Value: STATUS_SUCCESS if we got the defaults, otherwise we failed. The only way to fail this call is if the STATUS_INSUFFICIENT_RESOURCES. --*/ { NTSTATUS status = STATUS_SUCCESS; // return value WDFKEY hKey; DECLARE_UNICODE_STRING_SIZE(valueName,PARAMATER_NAME_LEN); status = WdfDriverOpenParametersRegistryKey(Driver, STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &hKey); if (!NT_SUCCESS (status)) { return status; } status = RtlUnicodeStringPrintf(&valueName,L"BreakOnEntry"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->ShouldBreakOnEntry); if (!NT_SUCCESS (status)) { DriverDefaultsPtr->ShouldBreakOnEntry = 0; } status = RtlUnicodeStringPrintf(&valueName,L"DebugLevel"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->DebugLevel); if (!NT_SUCCESS (status)) { DriverDefaultsPtr->DebugLevel = 0; } status = RtlUnicodeStringPrintf(&valueName,L"ForceFifoEnable"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->ForceFifoEnableDefault); if (!NT_SUCCESS (status)) { // // If it isn't then write out values so that it could // be adjusted later. // DriverDefaultsPtr->ForceFifoEnableDefault = SERIAL_FORCE_FIFO_DEFAULT; status = WdfRegistryAssignULong(hKey, &valueName, DriverDefaultsPtr->ForceFifoEnableDefault ); if (!NT_SUCCESS (status)) { goto End; } } status = RtlUnicodeStringPrintf(&valueName,L"RxFIFO"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->RxFIFODefault); if (!NT_SUCCESS (status)) { DriverDefaultsPtr->RxFIFODefault = SERIAL_RX_FIFO_DEFAULT; status = WdfRegistryAssignULong(hKey, &valueName, DriverDefaultsPtr->RxFIFODefault ); if (!NT_SUCCESS (status)) { goto End; } } status = RtlUnicodeStringPrintf(&valueName,L"TxFIFO"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->TxFIFODefault); if (!NT_SUCCESS (status)) { DriverDefaultsPtr->TxFIFODefault = SERIAL_TX_FIFO_DEFAULT; status = WdfRegistryAssignULong(hKey, &valueName, DriverDefaultsPtr->TxFIFODefault ); if (!NT_SUCCESS (status)) { goto End; } } status = RtlUnicodeStringPrintf(&valueName,L"PermitShare"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->PermitShareDefault); if (!NT_SUCCESS (status)) { DriverDefaultsPtr->PermitShareDefault = SERIAL_PERMIT_SHARE_DEFAULT; status = WdfRegistryAssignULong(hKey, &valueName, DriverDefaultsPtr->PermitShareDefault ); if (!NT_SUCCESS (status)) { goto End; } } status = RtlUnicodeStringPrintf(&valueName,L"LogFifo"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->LogFifoDefault); if (!NT_SUCCESS (status)) { DriverDefaultsPtr->LogFifoDefault = SERIAL_LOG_FIFO_DEFAULT; status = WdfRegistryAssignULong(hKey, &valueName, DriverDefaultsPtr->LogFifoDefault ); if (!NT_SUCCESS (status)) { goto End; } DriverDefaultsPtr->LogFifoDefault = 1; } status = RtlUnicodeStringPrintf(&valueName,L"UartRemovalDetect"); if (!NT_SUCCESS (status)) { goto End; } status = WdfRegistryQueryULong (hKey, &valueName, &DriverDefaultsPtr->UartRemovalDetect); if (!NT_SUCCESS (status)) { DriverDefaultsPtr->UartRemovalDetect = 0; } End: WdfRegistryClose(hKey); return (status); }
NTSTATUS Ds4_AssignPdoContext(WDFDEVICE Device, PPDO_IDENTIFICATION_DESCRIPTION Description) { NTSTATUS status; PDS4_DEVICE_DATA ds4 = Ds4GetData(Device); KdPrint(("Initializing DS4 context...\n")); // I/O Queue for pending IRPs WDF_IO_QUEUE_CONFIG pendingUsbQueueConfig, notificationsQueueConfig; // Create and assign queue for incoming interrupt transfer WDF_IO_QUEUE_CONFIG_INIT(&pendingUsbQueueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(Device, &pendingUsbQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ds4->PendingUsbInRequests); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // Initialize periodic timer WDF_TIMER_CONFIG timerConfig; WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, Ds4_PendingUsbRequestsTimerFunc, DS4_QUEUE_FLUSH_PERIOD); // Timer object attributes WDF_OBJECT_ATTRIBUTES timerAttribs; WDF_OBJECT_ATTRIBUTES_INIT(&timerAttribs); // PDO is parent timerAttribs.ParentObject = Device; // Create timer status = WdfTimerCreate(&timerConfig, &timerAttribs, &ds4->PendingUsbInRequestsTimer); if (!NT_SUCCESS(status)) { KdPrint(("WdfTimerCreate failed 0x%x\n", status)); return status; } // Create and assign queue for user-land notification requests WDF_IO_QUEUE_CONFIG_INIT(¬ificationsQueueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(Device, ¬ificationsQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ds4->PendingNotificationRequests); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // Load/generate MAC address // TODO: tidy up this region WDFKEY keyParams, keyTargets, keyDS, keySerial; UNICODE_STRING keyName, valueName; status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &keyParams); if (!NT_SUCCESS(status)) { KdPrint(("WdfDriverOpenParametersRegistryKey failed 0x%x\n", status)); return status; } RtlUnicodeStringInit(&keyName, L"Targets"); status = WdfRegistryCreateKey(keyParams, &keyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL, WDF_NO_OBJECT_ATTRIBUTES, &keyTargets); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryCreateKey failed 0x%x\n", status)); return status; } RtlUnicodeStringInit(&keyName, L"DualShock"); status = WdfRegistryCreateKey(keyTargets, &keyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL, WDF_NO_OBJECT_ATTRIBUTES, &keyDS); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryCreateKey failed 0x%x\n", status)); return status; } DECLARE_UNICODE_STRING_SIZE(serialPath, 4); RtlUnicodeStringPrintf(&serialPath, L"%04d", Description->SerialNo); status = WdfRegistryCreateKey(keyDS, &serialPath, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL, WDF_NO_OBJECT_ATTRIBUTES, &keySerial); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryCreateKey failed 0x%x\n", status)); return status; } RtlUnicodeStringInit(&valueName, L"TargetMacAddress"); status = WdfRegistryQueryValue(keySerial, &valueName, sizeof(MAC_ADDRESS), &ds4->TargetMacAddress, NULL, NULL); KdPrint(("MAC-Address: %02X:%02X:%02X:%02X:%02X:%02X\n", ds4->TargetMacAddress.Vendor0, ds4->TargetMacAddress.Vendor1, ds4->TargetMacAddress.Vendor2, ds4->TargetMacAddress.Nic0, ds4->TargetMacAddress.Nic1, ds4->TargetMacAddress.Nic2)); if (status == STATUS_OBJECT_NAME_NOT_FOUND) { GenerateRandomMacAddress(&ds4->TargetMacAddress); status = WdfRegistryAssignValue(keySerial, &valueName, REG_BINARY, sizeof(MAC_ADDRESS), (PVOID)&ds4->TargetMacAddress); if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryAssignValue failed 0x%x\n", status)); return status; } } else if (!NT_SUCCESS(status)) { KdPrint(("WdfRegistryQueryValue failed 0x%x\n", status)); return status; } WdfRegistryClose(keySerial); WdfRegistryClose(keyDS); WdfRegistryClose(keyTargets); WdfRegistryClose(keyParams); return STATUS_SUCCESS; }
NTSTATUS NdasPortWmipQueryRegInfo( __in PDEVICE_OBJECT DeviceObject, __out PULONG RegFlags, __out PUNICODE_STRING InstanceName, __out PUNICODE_STRING *RegistryPath, __out PUNICODE_STRING MofResourceName, __out PDEVICE_OBJECT *Pdo) { NTSTATUS status; PNDASPORT_PDO_EXTENSION PdoExtension; PNDASPORT_DRIVER_EXTENSION DriverExtension; PAGED_CODE(); NdasPortTrace(NDASPORT_PDO_GENERAL, TRACE_LEVEL_WARNING, __FUNCTION__ "\n"); PdoExtension = NdasPortPdoGetExtension(DeviceObject); DriverExtension = NdasPortDriverGetExtension(DeviceObject->DriverObject); *RegFlags = WMIREG_FLAG_INSTANCE_BASENAME; // -- InstanceName is ignored as WMIREG_FLAG_INSTANCE_BASENAME is not cleared InstanceName->Length = 0; InstanceName->MaximumLength = 60; InstanceName->Buffer = (PWCH) ExAllocatePoolWithTag( NonPagedPool, 60, NDASPORT_TAG_WMI); if (NULL == InstanceName->Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } status = RtlUnicodeStringPrintf( InstanceName, L"NdasLogicalUnit_%08X", PdoExtension->LogicalUnitAddress.Address); ASSERT(NT_SUCCESS(status)); *RegistryPath = &DriverExtension->RegistryPath; // Pdo is ignored as WMIREG_FLAG_INSTANCE_PDO is cleared ASSERT(NULL != PdoExtension->LogicalUnitWmiInfo); status = (*PdoExtension->LogicalUnitWmiInfo->QueryWmiRegInfo)( NdasPortPdoGetLogicalUnitExtension(PdoExtension), RegistryPath, MofResourceName); ASSERT(STATUS_PENDING != status); if (!NT_SUCCESS(status)) { ExFreePoolWithTag(InstanceName->Buffer, NDASPORT_TAG_WMI); InstanceName->Buffer = NULL; return status; } if (NULL == *RegistryPath) { *RegistryPath = &DriverExtension->RegistryPath; } 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; }
VOID VIOSerialPortSymbolicNameWork( IN WDFWORKITEM WorkItem ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WorkItem); PVIOSERIAL_PORT pport = pdoData->port; UNICODE_STRING deviceUnicodeString = {0}; NTSTATUS status = STATUS_SUCCESS; DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 256); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); do { if (pport->NameString.Buffer) { status = RtlAnsiStringToUnicodeString( &deviceUnicodeString, &pport->NameString, TRUE ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlAnsiStringToUnicodeString failed 0x%x\n", status); break; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"deviceUnicodeString = %ws\n", deviceUnicodeString.Buffer); status = RtlUnicodeStringPrintf( &symbolicLinkName, L"%ws%ws", L"\\DosDevices\\", deviceUnicodeString.Buffer ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed 0x%x\n", status); break; } status = WdfDeviceCreateSymbolicLink( pport->Device, &symbolicLinkName ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreateSymbolicLink %ws failed 0x%x\n", &symbolicLinkName, status); break; } } } while (0); if (deviceUnicodeString.Buffer != NULL) { RtlFreeUnicodeString( &deviceUnicodeString ); } WdfObjectDelete(WorkItem); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__); }
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 NdasPortFdoRegDeleteLogicalUnit( __in PNDASPORT_FDO_EXTENSION FdoExtension, __in NDAS_LOGICALUNIT_ADDRESS LogicalUnitAddress) { NTSTATUS status, status2; HANDLE keyHandle; WCHAR valueNameBuffer[32]; UNICODE_STRING valueName; PAGED_CODE(); keyHandle = NULL; status = NdasPortFdoOpenRegistryKey( FdoExtension, NDASPORT_FDO_REGKEY_LOGICALUNIT_LIST, KEY_WRITE, &keyHandle); if (!NT_SUCCESS(status)) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR, "IoOpenDeviceRegistryKey failed, status=%X, fdo=%p\n", status, FdoExtension->DeviceObject); return status; } RtlInitEmptyUnicodeString( &valueName, valueNameBuffer, sizeof(valueNameBuffer)); status2 = RtlUnicodeStringPrintf( &valueName, L"LU%08X", LogicalUnitAddress); ASSERT(NT_SUCCESS(status2)); status = ZwDeleteValueKey( keyHandle, &valueName); if (!NT_SUCCESS(status)) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR, "ZwDeleteValueKey failed, keyHandle=%p, value=%wZ, status=%X\n", keyHandle, &valueName, status); goto ret; } status = STATUS_SUCCESS; goto ret; ret: status2 = ZwClose(keyHandle); ASSERT(NT_SUCCESS(status2)); if (!NT_SUCCESS(status2)) { NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_WARNING, "ZwClose failed, keyHandle=%p, status=%X\n", keyHandle, status2); } 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; }
NTSTATUS DriverEntry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath) { NTSTATUS status; PDEVICE_OBJECT deviceObject; PCONTROL_DEVICE_EXTENSION deviceExtension; ULONG i; WCHAR controlDeviceUnicodeStringBuffer[64]; UNICODE_STRING controlDeviceUnicodeString = { 0, sizeof(controlDeviceUnicodeStringBuffer), controlDeviceUnicodeStringBuffer}; KdPrint(("NdasPortExt DriverEntry build on %s %s at %s MSVC %d\n", __DATE__, __TIME__, __BUILDMACHINE_STRING__, _MSC_VER)); i = 0; do { status = RtlUnicodeStringPrintf( &controlDeviceUnicodeString, L"\\Device\\NdasPortExt%d", i++); if (!NT_SUCCESS(status)) { return status; } status = IoCreateDeviceSecure( DriverObject, sizeof(CONTROL_DEVICE_EXTENSION), &controlDeviceUnicodeString, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &SDDL_DEVOBJ_KERNEL_ONLY, &GUID_DEVCLASS_UNKNOWN, &deviceObject); } while (STATUS_OBJECT_NAME_COLLISION == status); if (!NT_SUCCESS(status)) { KdPrint(("IoCreateDevice failed, status=%x\n", status)); return status; } KdPrint(("Control device=%p, name=%wZ\n", deviceObject, &controlDeviceUnicodeString)); deviceExtension = (PCONTROL_DEVICE_EXTENSION) deviceObject->DeviceExtension; RtlZeroMemory( deviceExtension, sizeof(CONTROL_DEVICE_EXTENSION)); for (i = 0; i < HOST_DEVICE_TYPE_COUNT; ++i) { deviceExtension->SymbolicLinkNames[i].Buffer = deviceExtension->SymbolicLinkNameBuffers[i]; deviceExtension->SymbolicLinkNames[i].MaximumLength = sizeof(deviceExtension->SymbolicLinkNameBuffers[i]); status = NdasPortExtRegisterExternalTypes( &controlDeviceUnicodeString, HostingDeviceTypes[i], &deviceExtension->SymbolicLinkNames[i]); if (!NT_SUCCESS(status)) { ULONG j = i; for (j = 0; j + 1 < i; ++j) { IoDeleteSymbolicLink(&deviceExtension->SymbolicLinkNames[i]); } return status; } } DriverObject->DriverUnload = NdasPortExtDriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = NdasPortExtCreateClose; DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = NdasPortExtInternalDeviceControl; deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; KdPrint(("NdasPortExt loaded successfully.\n")); return STATUS_SUCCESS; }
NTSTATUS USBPcapCreateRootHubControlDevice(IN PDEVICE_EXTENSION hubExt, OUT PDEVICE_OBJECT *control, OUT USHORT *busId) { UNICODE_STRING ntDeviceName; UNICODE_STRING symbolicLinkName; PDEVICE_OBJECT controlDevice = NULL; PDEVICE_EXTENSION controlExt = NULL; NTSTATUS status; USHORT id; PWCHAR ntNameBuffer[MAX_NTNAME_LEN]; PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN]; ASSERT(hubExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB); /* Acquire the control device ID */ id = (USHORT) InterlockedIncrement(&g_controlId); ntDeviceName.Length = 0; ntDeviceName.MaximumLength = MAX_NTNAME_LEN; ntDeviceName.Buffer = (PWSTR)ntNameBuffer; symbolicLinkName.Length = 0; symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN; symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer; status = RtlUnicodeStringPrintf(&ntDeviceName, NTNAME_PREFIX L"%hu", id); if (!NT_SUCCESS(status)) { return status; } status = RtlUnicodeStringPrintf(&symbolicLinkName, SYMBOLIC_PREFIX L"%hu", id); if (!NT_SUCCESS(status)) { return status; } KdPrint(("Creating device %wZ (%wZ)\n", &ntDeviceName, &symbolicLinkName)); status = IoCreateDeviceSecure(hubExt->pDrvObj, sizeof(DEVICE_EXTENSION), &ntDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, TRUE, /* Exclusive device */ &SDDL_DEVOBJ_SYS_ALL_ADM_ALL_EVERYONE_ANY, NULL, &controlDevice); if (NT_SUCCESS(status)) { controlDevice->Flags |= DO_DIRECT_IO; status = IoCreateSymbolicLink(&symbolicLinkName, &ntDeviceName); if (!NT_SUCCESS(status)) { IoDeleteDevice(controlDevice); KdPrint(("IoCreateSymbolicLink failed %x\n", status)); return status; } controlExt = (PDEVICE_EXTENSION)controlDevice->DeviceExtension; controlExt->deviceMagic = USBPCAP_MAGIC_CONTROL; controlExt->pThisDevObj = controlDevice; controlExt->pNextDevObj = NULL; controlExt->pDrvObj = hubExt->pDrvObj; IoInitializeRemoveLock(&controlExt->removeLock, 0, 0, 0); controlExt->parentRemoveLock = &hubExt->removeLock; /* Initialize USBPcap control context */ controlExt->context.control.id = id; controlExt->context.control.pRootHubObject = hubExt->pThisDevObj; KeInitializeSpinLock(&controlExt->context.control.csqSpinLock); InitializeListHead(&controlExt->context.control.lePendIrp); status = IoCsqInitialize(&controlExt->context.control.ioCsq, DkCsqInsertIrp, DkCsqRemoveIrp, DkCsqPeekNextIrp, DkCsqAcquireLock, DkCsqReleaseLock, DkCsqCompleteCanceledIrp); if (!NT_SUCCESS(status)) { DkDbgVal("Error initialize Cancel-safe queue!", status); goto End; } controlDevice->Flags &= ~DO_DEVICE_INITIALIZING; } else { KdPrint(("IoCreateDevice failed %x\n", status)); } End: if ((!NT_SUCCESS(status)) || (controlExt == NULL)) { if (controlDevice != NULL) { IoDeleteSymbolicLink(&symbolicLinkName); IoDeleteDevice(controlDevice); } } else { IoAcquireRemoveLock(controlExt->parentRemoveLock, NULL); *control = controlDevice; *busId = id; } return status; }