VOID GetEnhancedVerifierOptions( __in PCLIENT_INFO ClientInfo, __out PULONG Options ) { NTSTATUS status; ULONG value; FxAutoRegKey hKey, hWdf; DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf"); DECLARE_CONST_UNICODE_STRING(valueName, WDF_ENHANCED_VERIFIER_OPTIONS_VALUE_NAME); *Options = 0; if (ClientInfo == NULL || ClientInfo->Size != sizeof(CLIENT_INFO) || ClientInfo->RegistryPath == NULL || ClientInfo->RegistryPath->Length == 0 || ClientInfo->RegistryPath->Buffer == NULL || Options == NULL) { __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": Invalid ClientInfo received from wdfldr \n")); return; } status = FxRegKey::_OpenKey(NULL, ClientInfo->RegistryPath, &hWdf.m_Key, KEY_READ); if (!NT_SUCCESS(status)) { return; } status = FxRegKey::_OpenKey(hWdf.m_Key, ¶metersPath, &hKey.m_Key, KEY_READ); if (!NT_SUCCESS(status)) { return; } status = FxRegKey::_QueryULong( hKey.m_Key, &valueName, &value); // // Examine key values and set Options only on success. // if (NT_SUCCESS(status)) { if (value) { *Options = value; } } }
_Must_inspect_result_ BOOLEAN FX_DRIVER_GLOBALS::IsCorrectVersionRegistered( _In_ PCUNICODE_STRING ServiceKeyName ) { FxAutoRegKey hDriver, hWdf; DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf"); DECLARE_CONST_UNICODE_STRING(wdfMajorValue, WDF_MAJOR_VERSION_VALUE); DECLARE_CONST_UNICODE_STRING(wdfMinorValue, WDF_MINOR_VERSION_VALUE); ULONG registeredMajor = 0, registeredMinor = 0; NTSTATUS status; status = FxRegKey::_OpenKey(NULL, ServiceKeyName, &hDriver.m_Key, KEY_READ ); if (!NT_SUCCESS(status)) { return FALSE; } status = FxRegKey::_OpenKey(hDriver.m_Key, ¶metersPath, &hWdf.m_Key, KEY_READ ); if (!NT_SUCCESS(status)) { return FALSE; } status = FxRegKey::_QueryULong(hWdf.m_Key, &wdfMajorValue, ®isteredMajor); if (!NT_SUCCESS(status) || registeredMajor != WdfBindInfo->Version.Major) { return FALSE; } status = FxRegKey::_QueryULong(hWdf.m_Key, &wdfMinorValue, ®isteredMinor); if (!NT_SUCCESS(status) || registeredMinor != WdfBindInfo->Version.Minor){ return FALSE; } else { return TRUE; } }
_Use_decl_annotations_ NTSTATUS SaveSimBattStateToRegistry ( WDFDEVICE Device, PSIMBATT_STATE State ) /* Routine Description: Called to save simbatt state data to the registry. Arguments: Device - Supplies WDF device handle. State - Supplies the pointer to the simbatt state. Return Value: NTSTATUS --*/ { WDFKEY KeyHandle; DECLARE_CONST_UNICODE_STRING(SimbattStateRegNameStr, SIMBATT_STATE_REG_NAME); NTSTATUS Status; PAGED_CODE(); Status = WdfDeviceOpenRegistryKey( Device, PLUGPLAY_REGKEY_DEVICE, KEY_WRITE, NULL, &KeyHandle ); if (!NT_SUCCESS (Status)) { goto SaveSimBattStateToRegistryEnd; } Status = WdfRegistryAssignValue( KeyHandle, &SimbattStateRegNameStr, REG_BINARY, sizeof(SIMBATT_STATE), State ); WdfRegistryClose(KeyHandle); if (!NT_SUCCESS (Status)) { goto SaveSimBattStateToRegistryEnd; } SaveSimBattStateToRegistryEnd: return Status; }
NTSTATUS WriteBackupRegistersToRegistry(HANDLE_DEV Device) { WDFKEY key = NULL; WDFKEY subkey = NULL; NTSTATUS status; // Retrieve registry settings. DECLARE_CONST_UNICODE_STRING(subConfigName, L"Config"); DECLARE_CONST_UNICODE_STRING(backupName, L"backup"); status = WdfDeviceOpenRegistryKey(Device, PLUGPLAY_REGKEY_DEVICE, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(status)) { TraceLog(TRACE_LEVEL_WARNING, TRACE_ALGO, "Error opening device registry key - %!STATUS!", status); } else { status = WdfRegistryOpenKey(key, &subConfigName, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &subkey); if (!NT_SUCCESS(status)) { TraceLog(TRACE_LEVEL_WARNING, TRACE_ALGO, "Error opening registry subkey for 'Config' - %!STATUS!", status); } else { ULONG length = sizeof(gs_backupRegisters); status = WdfRegistryAssignValue(subkey, &backupName, REG_BINARY, length, gs_backupRegisters); if (!NT_SUCCESS(status)) { TraceLog(TRACE_LEVEL_WARNING, TRACE_ALGO, "Error querying registry value for 'backup reg' - %!STATUS!", status); } } if (subkey != NULL) { WdfRegistryClose(subkey); subkey = NULL; } } if (key != NULL) { WdfRegistryClose(key); key = NULL; } return status; }
VOID EvtDeviceCleanup( _In_ WDFOBJECT Object ) { WDFDEVICE device = (WDFDEVICE) Object; PDEVICE_CONTEXT deviceContext = GetDeviceContext(device); NTSTATUS status; WDFKEY key = NULL; UNICODE_STRING pdoString = {0}; DECLARE_CONST_UNICODE_STRING(deviceSubkey, SERIAL_DEVICE_MAP); if (deviceContext->CreatedLegacyHardwareKey == TRUE) { RtlInitUnicodeString(&pdoString, deviceContext->PdoName); status = WdfDeviceOpenDevicemapKey(device, &deviceSubkey, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to open DEVICEMAP\\SERIALCOMM key 0x%x", status); goto exit; } status = WdfRegistryRemoveValue(key, &pdoString); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to delete %S key, 0x%x", pdoString.Buffer, status); goto exit; } status = WdfRegistryRemoveKey(key); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to delete %S, 0x%x", SERIAL_DEVICE_MAP, status); goto exit; } } exit: if (key != NULL) { WdfRegistryClose(key); key = NULL; } return; }
VOID MamakuRegistryInit(IN WDFDRIVER Driver) { NTSTATUS status; WDFKEY key; DECLARE_CONST_UNICODE_STRING(UseMultitouchName, L"UseMultitouchDebug"); DECLARE_CONST_UNICODE_STRING(DragThresholdName, L"DragThreshold"); status = WdfDriverOpenParametersRegistryKey(Driver, STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(status)) { MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "WdfDriverOpenParametersRegistryKey failed with status 0x%x\n", status); return; } status = WdfRegistryQueryULong(key, &UseMultitouchName, &UseMultitouch); if (!NT_SUCCESS(status)) { MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "WdfRegistryQueryULong(UseMultitouch) failed with status 0x%x\n", status); } MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "UseMultitouchDebug = %d\n", UseMultitouch); status = WdfRegistryQueryULong(key, &DragThresholdName, &DragThreshold); if (!NT_SUCCESS(status)) { MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "WdfRegistryQueryULong(DragThreshold) failed with status 0x%x\n", status); } MamakuPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "DragThreshold = %d\n", DragThreshold); WdfRegistryClose(key); }
_Use_decl_annotations_ NTSTATUS TreeSampleCreateSecureDeviceContext( WDFDEVICE MasterDevice ) /*++ Routine Description: This routine is called when the secure environment is first started. Arguments: MasterDevice - Supplies a handle to the master device object. DeviceContext - Supplies a pointer to store any context information required for future calls. Return Value: NTSTATUS code. --*/ { WDF_OBJECT_ATTRIBUTES ContextAttributes; PTREE_SAMPLE_DEVICE_CONTEXT MasterContext; NTSTATUS Status; DECLARE_CONST_UNICODE_STRING(SymbolicLink, L"\\DosDevices\\SampleTrEEDriver"); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes, TREE_SAMPLE_DEVICE_CONTEXT); Status = WdfObjectAllocateContext(MasterDevice, &ContextAttributes, &MasterContext); if (!NT_SUCCESS(Status)) { goto TreeSampleCreateSecureDeviceContextEnd; } MasterContext->MasterDevice = MasterDevice; // // Create a symbolic link so that usermode program can access master device. // Status = WdfDeviceCreateSymbolicLink(MasterDevice, &SymbolicLink); if (!NT_SUCCESS(Status)) { goto TreeSampleCreateSecureDeviceContextEnd; } TreeSampleCreateSecureDeviceContextEnd: return Status; }
// // Register our GUID and Datablock generated from the Firefly.mof file. // NTSTATUS WmiInitialize( WDFDEVICE Device, PDEVICE_CONTEXT DeviceContext ) { WDF_WMI_PROVIDER_CONFIG providerConfig; WDF_WMI_INSTANCE_CONFIG instanceConfig; WDF_OBJECT_ATTRIBUTES woa; WDFWMIINSTANCE instance; NTSTATUS status; DECLARE_CONST_UNICODE_STRING(mofRsrcName, MOFRESOURCENAME); UNREFERENCED_PARAMETER(DeviceContext); PAGED_CODE(); status = WdfDeviceAssignMofResourceName(Device, &mofRsrcName); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: Error in WdfDeviceAssignMofResourceName %x\n", status)); return status; } WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &FireflyDeviceInformation_GUID); providerConfig.MinInstanceBufferSize = sizeof(FireflyDeviceInformation); WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig); instanceConfig.Register = TRUE; instanceConfig.EvtWmiInstanceQueryInstance = EvtWmiInstanceQueryInstance; instanceConfig.EvtWmiInstanceSetInstance = EvtWmiInstanceSetInstance; instanceConfig.EvtWmiInstanceSetItem = EvtWmiInstanceSetItem; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, FireflyDeviceInformation); // // No need to store the WDFWMIINSTANCE in the device context because it is // passed back in the WMI instance callbacks and is not referenced outside // of those callbacks. // status = WdfWmiInstanceCreate(Device, &instanceConfig, &woa, &instance); if (NT_SUCCESS(status)) { FireflyDeviceInformation* info; info = InstanceGetInfo(instance); info->TailLit = TRUE; } return status; }
NTSTATUS TLInspectLoadConfig( _In_ const WDFKEY key ) { NTSTATUS status; DECLARE_CONST_UNICODE_STRING(valueName, L"RemoteAddressToInspect"); DECLARE_UNICODE_STRING_SIZE(value, INET6_ADDRSTRLEN); status = WdfRegistryQueryUnicodeString(key, &valueName, NULL, &value); if (NT_SUCCESS(status)) { PWSTR terminator; // Defensively null-terminate the string value.Length = min(value.Length, value.MaximumLength - sizeof(WCHAR)); value.Buffer[value.Length/sizeof(WCHAR)] = UNICODE_NULL; status = RtlIpv4StringToAddressW( value.Buffer, TRUE, &terminator, &remoteAddrStorageV4 ); if (NT_SUCCESS(status)) { remoteAddrStorageV4.S_un.S_addr = RtlUlongByteSwap(remoteAddrStorageV4.S_un.S_addr); configInspectRemoteAddrV4 = &remoteAddrStorageV4.S_un.S_un_b.s_b1; } else { status = RtlIpv6StringToAddressW( value.Buffer, &terminator, &remoteAddrStorageV6 ); if (NT_SUCCESS(status)) { configInspectRemoteAddrV6 = (UINT8*)(&remoteAddrStorageV6.u.Byte[0]); } } } return status; }
NTSTATUS DeviceWriteLegacyHardwareKey( _In_ PWSTR PdoName, _In_ PWSTR ComPort, _In_ WDFDEVICE Device ) { WDFKEY key = NULL; NTSTATUS status; UNICODE_STRING pdoString = {0}; UNICODE_STRING comPort = {0}; DECLARE_CONST_UNICODE_STRING(deviceSubkey, SERIAL_DEVICE_MAP); RtlInitUnicodeString(&pdoString, PdoName); RtlInitUnicodeString(&comPort, ComPort); status = WdfDeviceOpenDevicemapKey(Device, &deviceSubkey, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to open DEVICEMAP\\SERIALCOMM key 0x%x", status); goto exit; } status = WdfRegistryAssignUnicodeString(key, &pdoString, &comPort); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to write to DEVICEMAP\\SERIALCOMM key 0x%x", status); goto exit; } exit: if (key != NULL) { WdfRegistryClose(key); key = NULL; } return status; }
void otPlatSettingsInit(otInstance *otCtx) { NT_ASSERT(otCtx); PMS_FILTER pFilter = otCtxToFilter(otCtx); DECLARE_CONST_UNICODE_STRING(SubKeyName, L"OpenThread"); OBJECT_ATTRIBUTES attributes; ULONG disposition; LogFuncEntry(DRIVER_DEFAULT); InitializeObjectAttributes( &attributes, (PUNICODE_STRING)&SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, pFilter->InterfaceRegKey, NULL); // Create/Open the 'OpenThread' sub key NTSTATUS status = ZwCreateKey( &pFilter->otSettingsRegKey, KEY_ALL_ACCESS, &attributes, 0, NULL, REG_OPTION_NON_VOLATILE, &disposition); NT_ASSERT(NT_SUCCESS(status)); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwCreateKey for 'OpenThread' key failed, %!STATUS!", status); } LogFuncExit(DRIVER_DEFAULT); }
NTSTATUS RamDiskEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of the device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); // // Storage drivers have to name their FDOs. Since we are not unique'fying // the device name, we wouldn't be able to install more than one instance // of this ramdisk driver. // status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Since this is a pure software only driver, there is no need to register // any PNP/Power event callbacks. Framework will respond to these // events appropriately. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Now that the WDF device object has been created, set up any context // that it requires. // pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchSequential ); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate( device, &ioQueueConfig, &queueAttributes, &queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { return status; } // Context is the Queue handle pQueueContext = QueueGetExtension(queue); // // Set the context for our default queue as our device extension. // pQueueContext->DeviceExtension = pDeviceExtension; #if KMDF_VERSION_MINOR >= 9 // // Enable forward progress on the queue we just created. // NOTE: If you are planning to use this code without forward progress, // comment out the call to SetForwardProgressOnQueue below. // status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } #endif // // Now do any RAM-Disk specific initialization // pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); // // Get the disk parameters from the registry // RamDiskQueryDiskRegParameters( WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)), &pDeviceExtension->DiskRegInfo ); // // Allocate memory for the disk image. // pDeviceExtension->DiskImage = ExAllocatePoolWithTag( NonPagedPool, pDeviceExtension->DiskRegInfo.DiskSize, RAMDISK_TAG ); if (pDeviceExtension->DiskImage) { UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); status = STATUS_SUCCESS; // // Now try to create a symbolic link for the drive letter. // RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); pDeviceExtension->SymbolicLink.Buffer = (PWSTR) &pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink, &pDeviceExtension->DiskRegInfo.DriveLetter); status = WdfDeviceCreateSymbolicLink(device, &pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS 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 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 DeviceConfigure( _In_ PDEVICE_CONTEXT DeviceContext ) /*++ Routine Description: This method is called after the device callback object has been initialized and returned to the driver. It would setup the device's queues and their corresponding callback objects. Arguments: FxDevice - the framework device object for which we're handling events. Return Value: status --*/ { NTSTATUS status; WDFDEVICE device = DeviceContext->Device; WDFKEY key; LPGUID guid; errno_t errorNo; DECLARE_CONST_UNICODE_STRING(portName, REG_VALUENAME_PORTNAME); DECLARE_UNICODE_STRING_SIZE (comPort, 10); DECLARE_UNICODE_STRING_SIZE (symbolicLinkName, SYMBOLIC_LINK_NAME_LENGTH); #ifdef _FAKE_MODEM // // Compiled as fake modem // guid = (LPGUID) &GUID_DEVINTERFACE_MODEM; #else // // Compiled as virtual serial port // guid = (LPGUID) &GUID_DEVINTERFACE_COMPORT; #endif // // Create device interface // status = WdfDeviceCreateDeviceInterface( device, guid, NULL); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Cannot create device interface"); goto Exit; } // // Read the COM port number from the registry, which has been automatically // created by "MsPorts!PortsClassInstaller" if INF file says "Class=Ports" // status = WdfDeviceOpenRegistryKey( device, PLUGPLAY_REGKEY_DEVICE, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to retrieve device hardware key root"); goto Exit; } status = WdfRegistryQueryUnicodeString( key, &portName, NULL, &comPort); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to read PortName"); goto Exit; } // // Manually create the symbolic link name. Length is the length in // bytes not including the NULL terminator. // // 6054 and 26035 are code analysis warnings that comPort.Buffer might // not be NULL terminated, while we know that they are. // #pragma warning(suppress: 6054 26035) symbolicLinkName.Length = (USHORT)((wcslen(comPort.Buffer) * sizeof(wchar_t)) + sizeof(SYMBOLIC_LINK_NAME_PREFIX) - sizeof(UNICODE_NULL)); if (symbolicLinkName.Length >= symbolicLinkName.MaximumLength) { Trace(TRACE_LEVEL_ERROR, "Error: Buffer overflow when creating COM port name. Size" " is %d, buffer length is %d", symbolicLinkName.Length, symbolicLinkName.MaximumLength); status = STATUS_BUFFER_OVERFLOW; goto Exit; } errorNo = wcscpy_s(symbolicLinkName.Buffer, SYMBOLIC_LINK_NAME_LENGTH, SYMBOLIC_LINK_NAME_PREFIX); if (errorNo != 0) { Trace(TRACE_LEVEL_ERROR, "Failed to copy %ws to buffer with error %d", SYMBOLIC_LINK_NAME_PREFIX, errorNo); status = STATUS_INVALID_PARAMETER; goto Exit; } errorNo = wcscat_s(symbolicLinkName.Buffer, SYMBOLIC_LINK_NAME_LENGTH, comPort.Buffer); if (errorNo != 0) { Trace(TRACE_LEVEL_ERROR, "Failed to copy %ws to buffer with error %d", comPort.Buffer, errorNo); status = STATUS_INVALID_PARAMETER; goto Exit; } // // Create symbolic link // status = WdfDeviceCreateSymbolicLink( device, &symbolicLinkName); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Cannot create symbolic link %ws", symbolicLinkName.Buffer); goto Exit; } status = DeviceGetPdoName(DeviceContext); if (!NT_SUCCESS(status)) { goto Exit; } status = DeviceWriteLegacyHardwareKey( DeviceContext->PdoName, comPort.Buffer, DeviceContext->Device); if (NT_SUCCESS(status)) { DeviceContext->CreatedLegacyHardwareKey = TRUE; } status = QueueCreate(DeviceContext); if (!NT_SUCCESS(status)) { goto Exit; } Exit: return status; }
VOID FX_DRIVER_GLOBALS::RegisterClientVersion( _In_ PCUNICODE_STRING ServiceKeyName ) { FxAutoRegKey hDriver, hParameters, hWdf; DECLARE_CONST_UNICODE_STRING(parametersPart, L"Parameters"); DECLARE_CONST_UNICODE_STRING(wdfPart, L"Wdf"); // // Not defined with the macro because ZwSetValue doesn't use PCUNICODE_STRING // UNICODE_STRING wdfMajorValue; UNICODE_STRING wdfMinorValue; NTSTATUS status; RtlInitUnicodeString(&wdfMajorValue, WDF_MAJOR_VERSION_VALUE); RtlInitUnicodeString(&wdfMinorValue, WDF_MINOR_VERSION_VALUE); status = FxRegKey::_OpenKey(NULL, ServiceKeyName, &hDriver.m_Key, KEY_WRITE | KEY_READ ); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, "Unable to open driver's service key, status %!STATUS!", status); return; } // // Key creation, unlike user mode, must happen one level at a time, since // create will also open take both steps instead of trying open first // status = FxRegKey::_Create(hDriver.m_Key, ¶metersPart, &hParameters.m_Key, KEY_WRITE | KEY_READ ); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, "Unable to write Parameters key, status %!STATUS!", status); return; } status = FxRegKey::_Create(hParameters.m_Key, &wdfPart, &hWdf.m_Key, KEY_WRITE | KEY_READ ); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, "Unable to write Parameters key, status %!STATUS!", status); return; } // // Using ZwSetValueKey here to avoid having to change the implementation // in FxRegKey of SetValue to a static / thiscall pair // status = ZwSetValueKey(hWdf.m_Key, &wdfMajorValue, 0, REG_DWORD, &WdfBindInfo->Version.Major, sizeof(WdfBindInfo->Version.Major) ); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, "Failed to record driver major version value, status %!STATUS!", status); } status = ZwSetValueKey(hWdf.m_Key, &wdfMinorValue, 0, REG_DWORD, &WdfBindInfo->Version.Minor, sizeof(WdfBindInfo->Version.Minor) ); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER, "Failed to record driver version value, status %!STATUS!", 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 NonPnpDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Called by the DriverEntry to create a control-device. This call is responsible for freeing the memory for DeviceInit. Arguments: DriverObject - a pointer to the object that represents this device driver. DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure. Return Value: STATUS_SUCCESS if initialized; an error otherwise. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_FILEOBJECT_CONFIG fileConfig; WDFQUEUE queue; WDFDEVICE controlDevice; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; UNREFERENCED_PARAMETER( Driver ); PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpDeviceAdd DeviceInit %p\n", DeviceInit); // // Set exclusive to TRUE so that no more than one app can talk to the // control device at any time. // WdfDeviceInitSetExclusive(DeviceInit, TRUE); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceInitAssignName failed %!STATUS!", status); goto End; } WdfControlDeviceInitSetShutdownNotification(DeviceInit, NonPnpShutdown, WdfDeviceShutdown); // // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the // framework whether you are interested in handling Create, Close and // Cleanup requests that gets generated when an application or another // kernel component opens an handle to the device. If you don't register // the framework default behaviour would be to complete these requests // with STATUS_SUCCESS. A driver might be interested in registering these // events if it wants to do security validation and also wants to maintain // per handle (fileobject) context. // WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, NonPnpEvtDeviceFileCreate, NonPnpEvtFileClose, WDF_NO_EVENT_CALLBACK // not interested in Cleanup ); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); // // In order to support METHOD_NEITHER Device controls, or // NEITHER device I/O type, we need to register for the // EvtDeviceIoInProcessContext callback so that we can handle the request // in the calling threads context. // WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, NonPnpEvtDeviceIoInCallerContext); // // Specify the size of device context // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CONTROL_DEVICE_EXTENSION); status = WdfDeviceCreate(&DeviceInit, &attributes, &controlDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed %!STATUS!", status); goto End; } // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { // // Control device will be deleted automatically by the framework. // TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed %!STATUS!", status); goto End; } // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoRead = FileEvtIoRead; ioQueueConfig.EvtIoWrite = FileEvtIoWrite; ioQueueConfig.EvtIoDeviceControl = FileEvtIoDeviceControl; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); // // Since we are using Zw function set execution level to passive so that // framework ensures that our Io callbacks called at only passive-level // even if the request came in at DISPATCH_LEVEL from another driver. // //attributes.ExecutionLevel = WdfExecutionLevelPassive; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, &attributes, &queue // pointer to default queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed %!STATUS!", status); goto End; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); End: // // If the device is created successfully, framework would clear the // DeviceInit value. Otherwise device create must have failed so we // should free the memory ourself. // if (DeviceInit != NULL) { WdfDeviceInitFree(DeviceInit); } 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 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 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; }
VCHIQ_PAGED_SEGMENT_BEGIN /*++ Routine Description: Worker routine called to create a device and its software resources. Arguments: DeviceInitPtr - Pointer to an opaque init structure. Memory for this structure will be freed by the framework when the WdfDeviceCreate succeeds. So don't access the structure after that point. Return Value: NTSTATUS --*/ _Use_decl_annotations_ NTSTATUS VchiqCreateDevice ( WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInitPtr ) { WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES deviceAttributes; DEVICE_CONTEXT* deviceContextPtr; WDFDEVICE device; NTSTATUS status; WDF_IO_TYPE_CONFIG ioConfig; DECLARE_CONST_UNICODE_STRING(vchiqSymbolicLink, VCHIQ_SYMBOLIC_NAME); UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); { WDF_FILEOBJECT_CONFIG fileobjectConfig; WDF_FILEOBJECT_CONFIG_INIT( &fileobjectConfig, WDF_NO_EVENT_CALLBACK, VchiqFileClose, WDF_NO_EVENT_CALLBACK); fileobjectConfig.FileObjectClass = WdfFileObjectWdfCanUseFsContext; WdfDeviceInitSetFileObjectConfig( DeviceInitPtr, &fileobjectConfig, WDF_NO_OBJECT_ATTRIBUTES); } WDF_IO_TYPE_CONFIG_INIT(&ioConfig); ioConfig.ReadWriteIoType = WdfDeviceIoDirect; ioConfig.DeviceControlIoType = WdfDeviceIoDirect; ioConfig.DirectTransferThreshold = 0; WdfDeviceInitSetIoTypeEx(DeviceInitPtr, &ioConfig); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = VchiqPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = VchiqReleaseHardware; pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = VchiqInitOperation; WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInitPtr, &pnpPowerCallbacks); WdfDeviceInitSetIoInCallerContextCallback( DeviceInitPtr, VchiqInCallerContext); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate( &DeviceInitPtr, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "WdfDeviceCreate fail %!STATUS!", status); goto End; } { WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG queueConfig; WDFQUEUE queue; deviceContextPtr = VchiqGetDeviceContext(device); deviceContextPtr->Device = device; deviceContextPtr->VersionMajor = VCHIQ_VERSION_MAJOR; deviceContextPtr->VersionMinor = VCHIQ_VERSION_MINOR; deviceContextPtr->PhyDeviceObjectPtr = WdfDeviceWdmGetPhysicalDevice(device); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = VchiqIoDeviceControl; queueConfig.EvtIoStop = VchiqIoStop; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfIoQueueCreate( device, &queueConfig, &attributes, &queue); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "WdfIoQueueCreate fail %!STATUS!", status); goto End; } } // Create symbolic and device interface status = WdfDeviceCreateSymbolicLink( device, &vchiqSymbolicLink); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "Fail to register symbolic link %!STATUS!", status); goto End; } End: VCHIQ_LOG_INFORMATION("Exit Status %!STATUS!", status); return status; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbEvtDeviceAdd // // This routine is called by the framework when a device of // the type we support is found in the system. // // INPUTS: // // DriverObject - Our WDFDRIVER object // // DeviceInit - The device iniitalization structure we'll // be using to create our WDFDEVICE // // OUTPUTS: // // None. // // RETURNS: // // STATUS_SUCCESS, otherwise an error indicating why the driver could not // load. // // IRQL: // // This routine is called at IRQL == PASSIVE_LEVEL. // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// NTSTATUS BasicUsbEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDF_OBJECT_ATTRIBUTES objAttributes; WDFDEVICE device; WDF_IO_QUEUE_CONFIG queueConfig; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; PBASICUSB_DEVICE_CONTEXT devContext; #if DBG DbgPrint("BasicUsbEvtDeviceAdd\n"); #endif // // Our "internal" (native) and user-accessible device names // DECLARE_CONST_UNICODE_STRING(nativeDeviceName, L"\\Device\\BasicUsb"); DECLARE_CONST_UNICODE_STRING(userDeviceName, L"\\Global??\\BasicUsb"); UNREFERENCED_PARAMETER(Driver); // // Life is a bit more complicated in this driver... // // We need an EvtPrepareHardware to configure our device. In addition, we // must handle EvtD0Entry and EvtD0Exit in order to manage our continuous // reader. // // // Prepare for WDFDEVICE creation // // Initialize standard WDF Object Attributes structure // WDF_OBJECT_ATTRIBUTES_INIT(&objAttributes); // // Specify our device context // WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objAttributes, BASICUSB_DEVICE_CONTEXT); // // We want our device object NAMED, thank you very much // status = WdfDeviceInitAssignName(DeviceInit, &nativeDeviceName); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceInitAssignName failed 0x%0x\n", status); #endif return(status); } // // Set our I/O type to DIRECT, meaning that we want to receive // MDLs for both read and write requests. // // While we are not obligated to choose direct, USB drivers // typically do so because the USB bus driver needs MDLs to // actually perform the transfer. If we select DIRECT I/O, the // bus driver can just use the MDL that we're given as opposed // to creating his own. // WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); // // In this driver we need to be notified of some Pnp/Power // events, so initialize a pnp power callbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // USB drivers configure their device within prepare hardware, // so register an EvtDevicePrepareHardware callback. // pnpPowerCallbacks.EvtDevicePrepareHardware = BasicUsbEvtDevicePrepareHardware; // // Our driver uses a continuous reader on the interrupt pipe to // be notified asynchronously of changes to the OSRFX2's // switchpack. We need to start the reader in D0Entry and stop // it in D0Exit, so register for EvtDeviceD0Entry and // EvtDeviceD0Exit callbacks // pnpPowerCallbacks.EvtDeviceD0Entry = BasicUsbEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = BasicUsbEvtDeviceD0Exit; // // Update the DeviceInit structure to contain the new callbacks. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // We want to send control transfers synchronously from within // EvtIoDeviceControl, so we'll apply a PASSIVE_LEVEL constraint // to our device // objAttributes.ExecutionLevel = WdfExecutionLevelPassive; // // Now let's create our device object // status = WdfDeviceCreate(&DeviceInit, &objAttributes, &device); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceCreate failed 0x%0x\n", status); #endif return status; } // // Create a symbolic link for the control object so that usermode can open // the device by name. // status = WdfDeviceCreateSymbolicLink(device, &userDeviceName); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceCreateSymbolicLink failed 0x%0x\n", status); #endif return(status); } // // ALSO create a device interface for the device // This allows usage of the lovely SetupApiXxxx functions to locate // the device // status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BASICUSB, NULL); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceCreateDeviceInterface failed 0x%0x\n", status); #endif return(status); } // // Configure our queue of incoming requests // // We only use the default queue, and we set it for parallel processing. // We chose this because we may have, say, a bulk read hanging on the bus // driver that won't get completed until we send down a bulk write. // // If we chose a sequential queue we wouldn't be presented the write from // the user until the read completed, but the read wouldn't complete // until we were presented the write from the user - resulting in an "I/O // deadlock". // // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); // // Declare our I/O Event Processing callbacks // // We handle, read, write, and device control requests. // // WDF will automagically handle Create and Close requests for us and will // will complete any OTHER request types with STATUS_INVALID_DEVICE_REQUEST. // queueConfig.EvtIoRead = BasicUsbEvtRead; queueConfig.EvtIoWrite = BasicUsbEvtWrite; queueConfig.EvtIoDeviceControl = BasicUsbEvtDeviceControl; // // Because this is a queue for a real hardware // device, indicate that the queue needs to be // power managed // queueConfig.PowerManaged = WdfTrue; status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL); // optional pointer to receive queue handle if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfIoQueueCreate for default queue failed 0x%0x\n", status); #endif return(status); } devContext = BasicUsbGetContextFromDevice(device); WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &devContext->SwitchPackStateChangeQueue); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfIoQueueCreate for manual queue failed 0x%0x\n", status); #endif return(status); } return(STATUS_SUCCESS); }
_Must_inspect_result_ NTSTATUS FxLibraryCommonCommission( VOID ) { DECLARE_CONST_UNICODE_STRING(usName, L"RtlGetVersion"); PFN_RTL_GET_VERSION pRtlGetVersion = NULL; NTSTATUS status; __Print((LITERAL(WDF_LIBRARY_COMMISSION) "\n")); // // Commission this version's DLL globals. // status = FxLibraryGlobalsCommission(); if (!NT_SUCCESS(status)) { __Print(("FxLibraryGlobalsCommission failed %X\n", status)); return status; } // // register telemetry provider. // RegisterTelemetryProvider(); // // Initialize internal WPP tracing. // status = FxTraceInitialize(); if (NT_SUCCESS(status)) { FxLibraryGlobals.InternalTracingInitialized = TRUE; } else { __Print(("Failed to initialize tracing for WDF\n")); // // Failure to initialize is not critical enough to fail driver load. // status = STATUS_SUCCESS; } // // Attempt to load RtlGetVersion (works for > w2k). // pRtlGetVersion = (PFN_RTL_GET_VERSION) MmGetSystemRoutineAddress( (PUNICODE_STRING) &usName ); // // Now attempt to get this OS's version. // if (pRtlGetVersion != NULL) { pRtlGetVersion(&gOsVersion); } __Print(("OsVersion(%d.%d)\n", gOsVersion.dwMajorVersion, gOsVersion.dwMinorVersion )); // // Init triage info for 9f bugcheck analysis. // GetTriageInfo(); return STATUS_SUCCESS; }
NTSTATUS Bus_WmiRegistration( WDFDEVICE Device ) /*++ Routine Description Registers with WMI as a data provider for this instance of the device --*/ { WDF_WMI_PROVIDER_CONFIG providerConfig; WDF_WMI_INSTANCE_CONFIG instanceConfig; PFDO_DEVICE_DATA deviceData; NTSTATUS status; DECLARE_CONST_UNICODE_STRING(busRsrcName, BUSRESOURCENAME); PAGED_CODE(); deviceData = FdoGetData(Device); // // Register WMI classes. // First specify the resource name which contain the binary mof resource. // status = WdfDeviceAssignMofResourceName(Device, &busRsrcName); if (!NT_SUCCESS(status)) { return status; } WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, &ToasterBusInformation_GUID); providerConfig.MinInstanceBufferSize = sizeof(TOASTER_BUS_WMI_STD_DATA); // // You would want to create a WDFWMIPROVIDER handle separately if you are // going to dynamically create instances on the provider. Since we are // statically creating one instance, there is no need to create the provider // handle. // WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig); // // By setting Regsiter to TRUE, we tell the framework to create a provider // as part of the Instance creation call. This eliminates the need to // call WdfWmiProviderRegister. // instanceConfig.Register = TRUE; instanceConfig.EvtWmiInstanceQueryInstance = Bus_EvtStdDataQueryInstance; instanceConfig.EvtWmiInstanceSetInstance = Bus_EvtStdDataSetInstance; instanceConfig.EvtWmiInstanceSetItem = Bus_EvtStdDataSetItem; status = WdfWmiInstanceCreate( Device, &instanceConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE ); if (NT_SUCCESS(status)) { deviceData->StdToasterBusData.ErrorCount = 0; } return status; }
NTSTATUS XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init) { NTSTATUS status; WDF_CHILD_LIST_CONFIG child_list_config; WDFDEVICE device; PXENUSB_DEVICE_DATA xudd; //UNICODE_STRING reference; WDF_OBJECT_ATTRIBUTES device_attributes; PNP_BUS_INFORMATION pbi; WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks; WDF_DEVICE_POWER_CAPABILITIES power_capabilities; WDF_IO_QUEUE_CONFIG queue_config; UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE }; DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName"); WDFSTRING symbolicname_value_wdfstring; WDFKEY device_key; UNICODE_STRING symbolicname_value; UNREFERENCED_PARAMETER(driver); FUNCTION_ENTER(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks); pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry; pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks); status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE, IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions)); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER); WdfDeviceInitSetExclusive(device_init, FALSE); WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice); child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren; WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES); WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered); WdfDeviceInitSetPowerNotPageable(device_init); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA); status = WdfDeviceCreate(&device_init, &device_attributes, &device); if (!NT_SUCCESS(status)) { FUNCTION_MSG("Error creating device %08x\n", status); return status; } xudd = GetXudd(device); xudd->pdo = WdfDeviceWdmGetPhysicalDevice(device); xudd->child_list = WdfFdoGetDefaultChildList(device); KeInitializeEvent(&xudd->backend_event, SynchronizationEvent, FALSE); InitializeListHead(&xudd->partial_pvurb_queue); InitializeListHead(&xudd->partial_pvurb_ring); KeInitializeDpc(&xudd->event_dpc, XenUsb_HandleEventDpc, xudd); KeInitializeSpinLock(&xudd->urb_ring_lock); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel); queue_config.PowerManaged = FALSE; /* ? */ queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl; queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl; queue_config.EvtIoDefault = XenUsb_EvtIoDefault; status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue); if (!NT_SUCCESS(status)) { FUNCTION_MSG("Error creating io_queue 0x%x\n", status); return status; } WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel); queue_config.PowerManaged = FALSE; /* ? */ //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl; queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB; //queue_config.EvtIoDefault = XenUsb_EvtIoDefault; queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */ status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue); if (!NT_SUCCESS(status)) { FUNCTION_MSG("Error creating urb_queue 0x%x\n", status); return status; } WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities); power_capabilities.DeviceD1 = WdfTrue; power_capabilities.WakeFromD1 = WdfTrue; power_capabilities.DeviceWake = PowerDeviceD1; power_capabilities.DeviceState[PowerSystemWorking] = PowerDeviceD0; power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1; power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2; power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2; power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3; power_capabilities.DeviceState[PowerSystemShutdown] = PowerDeviceD3; WdfDeviceSetPowerCapabilities(device, &power_capabilities); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE); pbi.BusTypeGuid = GUID_BUS_TYPE_XEN; pbi.LegacyBusType = PNPBus; pbi.BusNumber = 0; WdfDeviceSetBusInformationForChildren(device, &pbi); status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n"); return status; } /* USB likes to have a registry key with the symbolic link name in it */ status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfStringCreate returned %08x\n"); return status; } status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n"); return status; } WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value); status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n"); return status; } WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value); FUNCTION_EXIT(); return status; }
_Use_decl_annotations_ NTSTATUS OnDeviceAdd (WDFDRIVER /*WdfDriver*/, WDFDEVICE_INIT* DeviceInitPtr) { PAGED_CODE(); BCM_I2C_ASSERT_MAX_IRQL(PASSIVE_LEVEL); NTSTATUS status; // // Configure DeviceInit structure // status = SpbDeviceInitConfig(DeviceInitPtr); if (!NT_SUCCESS(status)) { BSC_LOG_ERROR( "SpbDeviceInitConfig() failed. (DeviceInitPtr = %p, status = %!STATUS!)", DeviceInitPtr, status); return status; } // // 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(DeviceInitPtr, &pnpCallbacks); } // // Create the device. // WDFDEVICE wdfDevice; BCM_I2C_DEVICE_CONTEXT* devicePtr; { WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &deviceAttributes, BCM_I2C_DEVICE_CONTEXT); status = WdfDeviceCreate( &DeviceInitPtr, &deviceAttributes, &wdfDevice); if (!NT_SUCCESS(status)) { BSC_LOG_ERROR( "Failed to create WDFDEVICE. (DeviceInitPtr = %p, status = %!STATUS!)", DeviceInitPtr, status); return status; } devicePtr = GetDeviceContext(wdfDevice); NT_ASSERT(devicePtr); devicePtr->WdfDevice = wdfDevice; } // // Query registry for ClockStretchTimeout // { WDFKEY wdfKey; status = WdfDeviceOpenRegistryKey( wdfDevice, PLUGPLAY_REGKEY_DEVICE, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &wdfKey); if (!NT_SUCCESS(status)) { BSC_LOG_ERROR( "Failed to open device parameters registry key. (status=%!STATUS!)", status); return status; } auto closeRegKey = Finally([&] { PAGED_CODE(); WdfRegistryClose(wdfKey); }); DECLARE_CONST_UNICODE_STRING( regValString, REGSTR_VAL_CLOCK_STRETCH_TIMEOUT); ULONG clockStretchTimeout; status = WdfRegistryQueryULong( wdfKey, ®ValString, &clockStretchTimeout); if (NT_SUCCESS(status)) { if ((clockStretchTimeout & BCM_I2C_REG_CLKT_TOUT_MASK) != clockStretchTimeout) { BSC_LOG_ERROR( "Clock stretch timeout value from registry is out of range. (clockStretchTimeout=0x%x, BCM_I2C_REG_CLKT_TOUT_MASK=0x%x)", clockStretchTimeout, BCM_I2C_REG_CLKT_TOUT_MASK); return STATUS_INVALID_PARAMETER; } BSC_LOG_INFORMATION( "Using ClockStretchTimeout value from registry. (clockStretchTimeout=0x%x)", clockStretchTimeout); } else { switch (status) { case STATUS_OBJECT_NAME_NOT_FOUND: clockStretchTimeout = BCM_I2C_REG_CLKT_TOUT_DEFAULT; status = STATUS_SUCCESS; break; default: BSC_LOG_ERROR( "Failed to query clock stretch timeout from registry. (status=%!STATUS!, REGSTR_VAL_CLOCK_STRETCH_TIMEOUT=%S)", status, REGSTR_VAL_CLOCK_STRETCH_TIMEOUT); return status; } } devicePtr->ClockStretchTimeout = clockStretchTimeout; } // // Ensure device is disable-able // { WDF_DEVICE_STATE deviceState; WDF_DEVICE_STATE_INIT(&deviceState); deviceState.NotDisableable = WdfFalse; WdfDeviceSetDeviceState(wdfDevice, &deviceState); } // // Bind a SPB controller object to the device. // { SPB_CONTROLLER_CONFIG spbConfig; SPB_CONTROLLER_CONFIG_INIT(&spbConfig); // // Register for target connect callback. The driver // does not need to respond to target disconnect. // spbConfig.EvtSpbTargetConnect = OnTargetConnect; // // Register for IO callbacks. // spbConfig.ControllerDispatchType = WdfIoQueueDispatchSequential; spbConfig.EvtSpbIoRead = OnRead; spbConfig.EvtSpbIoWrite = OnWrite; spbConfig.EvtSpbIoSequence = OnSequence; status = SpbDeviceInitialize(wdfDevice, &spbConfig); if (!NT_SUCCESS(status)) { BSC_LOG_ERROR( "SpbDeviceInitialize failed. (wdfDevice = %p, status = %!STATUS!)", wdfDevice, status); return status; } } // // Set target object attributes. // { WDF_OBJECT_ATTRIBUTES targetAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &targetAttributes, BCM_I2C_TARGET_CONTEXT); SpbControllerSetTargetAttributes(wdfDevice, &targetAttributes); } // // Create an interrupt object // BCM_I2C_INTERRUPT_CONTEXT* interruptContextPtr; { WDF_OBJECT_ATTRIBUTES interruptObjectAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &interruptObjectAttributes, BCM_I2C_INTERRUPT_CONTEXT); WDF_INTERRUPT_CONFIG interruptConfig; WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, OnInterruptIsr, OnInterruptDpc); status = WdfInterruptCreate( wdfDevice, &interruptConfig, &interruptObjectAttributes, &devicePtr->WdfInterrupt); if (!NT_SUCCESS(status)) { BSC_LOG_ERROR( "Failed to create interrupt object. (wdfDevice = %p, status = %!STATUS!)", wdfDevice, status); return status; } interruptContextPtr = GetInterruptContext(devicePtr->WdfInterrupt); interruptContextPtr->WdfInterrupt = devicePtr->WdfInterrupt; } devicePtr->InterruptContextPtr = interruptContextPtr; NT_ASSERT(NT_SUCCESS(status)); return STATUS_SUCCESS; }
// Sets up a new device. NTSTATUS DeviceContext::DeviceAdd( _Inout_ PWDFDEVICE_INIT DeviceInit ) { TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); NTSTATUS status; NFC_CX_CLIENT_CONFIG nfcCxConfig; NFC_CX_CLIENT_CONFIG_INIT(&nfcCxConfig, NFC_CX_TRANSPORT_CUSTOM); nfcCxConfig.EvtNfcCxWriteNciPacket = WriteNciPacketCallback; nfcCxConfig.EvtNfcCxDeviceIoControl = DeviceIoCallback; nfcCxConfig.DriverFlags = NFC_CX_DRIVER_ENABLE_EEPROM_WRITE_PROTECTION | NFC_CX_DRIVER_POWER_AND_LINK_CONTROL_SUPPORTED; status = NfcCxDeviceInitConfig(DeviceInit, &nfcCxConfig); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "NfcCxDeviceInitConfig failed. %!STATUS!", status); return status; } WDF_OBJECT_ATTRIBUTES deviceObjectAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceObjectAttributes, DeviceContext); deviceObjectAttributes.EvtCleanupCallback = ShutdownCallback; deviceObjectAttributes.EvtDestroyCallback = DestroyCallback; WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); pnpCallbacks.EvtDeviceD0Entry = D0EntryCallback; pnpCallbacks.EvtDeviceD0Exit = D0ExitCallback; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); FileObjectContext::DeviceInit(DeviceInit); WDFDEVICE device; status = WdfDeviceCreate(&DeviceInit, &deviceObjectAttributes, &device); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "WdfDeviceCreate failed. %!STATUS!", status); return status; } // Initialize device context. DeviceContext* deviceContext = DeviceGetContext(device); new (deviceContext) DeviceContext(); deviceContext->_Device = device; status = NfcCxDeviceInitialize(device); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "NfcCxDeviceInitialize failed. %!STATUS!", status); return status; } // Create lock for clients (and sequence handling). WDF_OBJECT_ATTRIBUTES lockAttributes; WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; status = WdfWaitLockCreate(&lockAttributes, &deviceContext->_ClientLock); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "WdfWaitLockCreate failed. %!STATUS!", status); return status; } // Initialize RF discovery config (enable everything). NFC_CX_RF_DISCOVERY_CONFIG discoveryConfig; NFC_CX_RF_DISCOVERY_CONFIG_INIT(&discoveryConfig); discoveryConfig.PollConfig = NFC_CX_POLL_NFC_A | NFC_CX_POLL_NFC_B | NFC_CX_POLL_NFC_F_212 | NFC_CX_POLL_NFC_F_424 | NFC_CX_POLL_NFC_15693 | NFC_CX_POLL_NFC_ACTIVE | NFC_CX_POLL_NFC_A_KOVIO; discoveryConfig.NfcIPMode = NFC_CX_NFCIP_NFC_A | NFC_CX_NFCIP_NFC_F_212 | NFC_CX_NFCIP_NFC_F_424 | NFC_CX_NFCIP_NFC_ACTIVE | NFC_CX_NFCIP_NFC_ACTIVE_A | NFC_CX_NFCIP_NFC_ACTIVE_F_212 | NFC_CX_NFCIP_NFC_ACTIVE_F_424; discoveryConfig.NfcIPTgtMode = NFC_CX_NFCIP_TGT_NFC_A | NFC_CX_NFCIP_TGT_NFC_F | NFC_CX_NFCIP_TGT_NFC_ACTIVE_A | NFC_CX_NFCIP_TGT_NFC_ACTIVE_F; discoveryConfig.NfcCEMode = NFC_CX_CE_NFC_A | NFC_CX_CE_NFC_B | NFC_CX_CE_NFC_F; status = NfcCxSetRfDiscoveryConfig(device, &discoveryConfig); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "NfcCxSetRfDiscoveryConfig failed. %!STATUS!", status); return status; } // Set the sequence handlers. for (int sequenceType = 0; sequenceType != SequenceMaximum; ++sequenceType) { status = NfcCxRegisterSequenceHandler(device, NFC_CX_SEQUENCE(sequenceType), SequenceHandlerCallback); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "NfcCxRegisterSequenceHandler failed. %!STATUS!", status); return status; } } // Initialize callbacks manager. status = deviceContext->_ApiCallbacksManager.Initialize(device); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "CallbacksManager::Initialize failed. %!STATUS!", status); return status; } // Create device interface for NciSim DECLARE_CONST_UNICODE_STRING(interfaceName, FILE_NAMESPACE_NCI_SIMULATOR); status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_NCI_SIMULATOR, &interfaceName); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "WdfDeviceCreateDeviceInterface failed. %!STATUS!", status); return status; } TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE); return STATUS_SUCCESS; }
NTSTATUS Bus_DoStaticEnumeration( IN WDFDEVICE Device ) /*++ Routine Description: The routine enables you to statically enumerate child devices during start instead of running the enum.exe/notify.exe to enumerate toaster devices. In order to statically enumerate, user must specify the number of toasters in the Toaster Bus driver's device registry. The default value is zero. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\SYSTEM\0002\ Device Parameters NumberOfToasters:REG_DWORD:2 You can also configure this value in the Toaster Bus Inf file. --*/ { WDFKEY hKey = NULL; NTSTATUS status; ULONG value, i; DECLARE_CONST_UNICODE_STRING(valueName, L"NumberOfToasters"); // // If the registry value doesn't exist, we will use the // hardcoded default number. // value = DEF_STATICALLY_ENUMERATED_TOASTERS; // // Open the device registry and read the "NumberOfToasters" value. // status = WdfDeviceOpenRegistryKey(Device, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, NULL, // PWDF_OBJECT_ATTRIBUTES &hKey); if (NT_SUCCESS (status)) { status = WdfRegistryQueryULong(hKey, &valueName, &value); WdfRegistryClose(hKey); hKey = NULL; // Set hKey to NULL to catch any accidental subsequent use. if (NT_SUCCESS (status)) { // // Make sure it doesn't exceed the max. This is required to prevent // denial of service by enumerating large number of child devices. // value = min(value, MAX_STATICALLY_ENUMERATED_TOASTERS); }else { return STATUS_SUCCESS; // This is an optional property. } } KdPrint(("Enumerating %d toaster devices\n", value)); for(i=1; i<= value; i++) { // // Value of i is used as serial number. // status = Bus_PlugInDevice(Device, BUS_HARDWARE_IDS, BUS_HARDWARE_IDS_LENGTH / sizeof(WCHAR), i ); } return status; }
NTSTATUS PVPanicEvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDFDEVICE device; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_FILEOBJECT_CONFIG fileConfig; WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG queueConfig; PDEVICE_CONTEXT context; DECLARE_CONST_UNICODE_STRING(dosDeviceName, PVPANIC_DOS_DEVICE_NAME); UNREFERENCED_PARAMETER(Driver); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "--> %!FUNC!"); PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = PVPanicEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = PVPanicEvtDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = PVPanicEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = PVPanicEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PVPanicEvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed: %!STATUS!", status); return status; } status = WdfDeviceCreateSymbolicLink(device, &dosDeviceName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed: %!STATUS!", status); return status; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoDeviceControl = PVPanicEvtQueueDeviceControl; context = GetDeviceContext(device); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &context->IoctlQueue); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed: %!STATUS!", status); return status; } status = WdfDeviceConfigureRequestDispatching(device, context->IoctlQueue, WdfRequestTypeDeviceControl); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceConfigureRequestDispatching failed: %!STATUS!", status); return status; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %!FUNC!"); return status; }