NTSTATUS bareflankCreateDevice( _Inout_ PWDFDEVICE_INIT DeviceInit ) { NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) return status; status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_bareflank, NULL); if (!NT_SUCCESS(status)) return status; status = bareflankQueueInitialize(device); if (!NT_SUCCESS(status)) return status; DEBUG("bareflankCreateDevice: success\n"); return status; }
NTSTATUS EvtDriverDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { WDFDEVICE Device = NULL; WDF_OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(Driver); __try { SetDeviceInit(DeviceInit); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ObjectAttributes, DEVICE_DATA); Status = WdfDeviceCreate(&DeviceInit, &ObjectAttributes, &Device); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfDeviceCreate", Status); __leave; } Status = PciDtfDeviceInit(Device); if (!NT_SUCCESS(Status)) { TRACE_ERR("DeviceInit", Status); __leave; } } __finally { if (!NT_SUCCESS(Status) && Device != NULL) WdfObjectDelete(Device); } return Status; }
NTSTATUS EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) { WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status; WDFDEVICE device; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; UNREFERENCED_PARAMETER(Driver); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { KdPrint(("WdfDeviceCreate failed 0x%x\n", status)); return status; } status = WdfDeviceCreateDeviceInterface(device, (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2, NULL);// Reference String if (!NT_SUCCESS(status)) { KdPrint(("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); return status; } return status; }
// Add device NTSTATUS GFilterAddDevice( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDF_OBJECT_ATTRIBUTES deviceAttributes; WDFDEVICE device; PFILTER_EXTENSION filtExt; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDFQUEUE ioDefaultQueue; DEBUG("Adding Device"); // Indicate we are a filter driver, This forwards all IRPs on to the lower filters WdfFdoInitSetFilter(DeviceInit); // Setup the actual filter for the IRPs #ifdef USE_SETIOINCALLERCONTEXTCALLBACK // Use built in KMDF filter WdfDeviceInitSetIoInCallerContextCallback( DeviceInit, GFilterIOCallback); #endif // Create a new device WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &deviceAttributes, FILTER_EXTENSION); // no cleanup callback needed -- deviceAttributes.EvtCleanupCallback = GFilterDeviceCleanUp; // Set device unload callback status = WdfDeviceCreate( &DeviceInit, // Create the device &deviceAttributes, &device); CHECKSTATUS(status, return(status)); // Create the filter extension -- We don't really care about this really filtExt = FilterGetData(device); filtExt->Instance = 0x00; #ifndef USE_SETIOINCALLERCONTEXTCALLBACK // Create IO queue and set callbacks to be filtered. //!todo, we created a parrallel que here but some drivers may need multiple parallel queues which is not done WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &ioQueueConfig, // Create parallel IO queue in case the device we filter does not like sequential WdfIoQueueDispatchParallel ); ioQueueConfig.EvtIoRead = GFilterRead; // Read ioQueueConfig.EvtIoWrite = GFilterWrite; // Write status = WdfIoQueueCreate( device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ioDefaultQueue); CHECKSTATUS(status, ERROR("Failed to create queues. status=0x%0.4x",status); goto GFilterAddDeviceCleanup); #endif // Create sideband communications to userspace #ifdef USE_CONTROL_DEVICE GFilterCreateControlDevice( device, ++DeviceInstances); //!todo, should we lock instance ?? #else GFilterCreateRawPDO( device, ++DeviceInstances); //!todo, should we lock instance ?? #endif GFilterAddDeviceCleanup: return(status); }
NTSTATUS CUsbDkFilterDevice::Create(PWDFDEVICE_INIT DevInit) { CUsbDkFilterDeviceInit DeviceInit(DevInit); TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Entry"); auto status = DeviceInit.Configure(GetInstanceNumber()); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Failed to create device init"); return status; } WDF_OBJECT_ATTRIBUTES attr; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, USBDK_FILTER_DEVICE_EXTENSION); attr.EvtCleanupCallback = CUsbDkFilterDevice::ContextCleanup; status = CWdfDevice::Create(DeviceInit, attr); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FILTERDEVICE, "%!FUNC! Failed to create device"); return status; } auto deviceContext = UsbDkFilterGetContext(m_Device); deviceContext->UsbDkFilter = this; return STATUS_SUCCESS; }
// This routine is called by the framework when the PnP manager sends an // IRP_MN_START_DEVICE request to the driver stack. This routine is // responsible for performing operations that are necessary to make the // driver's device operational (for e.g. mapping the hardware resources // into memory). NTSTATUS ActivityDevice::OnPrepareHardware( _In_ WDFDEVICE device, // Supplies a handle to the framework device object _In_ WDFCMRESLIST /*ResourcesRaw*/, // Supplies a handle to a collection of framework resource // objects. This collection identifies the raw (bus-relative) hardware // resources that have been assigned to the device. _In_ WDFCMRESLIST /*ResourcesTranslated*/) // Supplies a handle to a collection of framework // resource objects. This collection identifies the translated // (system-physical) hardware resources that have been assigned to the // device. The resources appear from the CPU's point of view. { NTSTATUS status = STATUS_SUCCESS; SENSOR_FunctionEnter(); // Create WDFOBJECT for the sensor WDF_OBJECT_ATTRIBUTES sensorAttributes = {}; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&sensorAttributes, ActivityDevice); // Register sensor instance with clx SENSOROBJECT sensorInstance = NULL; status = SensorsCxSensorCreate(device, &sensorAttributes, &sensorInstance); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! SensorsCxSensorCreate failed %!STATUS!", status); } else { PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance); if (nullptr == pDevice) { status = STATUS_INSUFFICIENT_RESOURCES; TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status); } else { // Fill out properties status = pDevice->Initialize(device, sensorInstance); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! Initialize device object failed %!STATUS!", status); } else { SENSOR_CONFIG sensorConfig = {}; SENSOR_CONFIG_INIT(&sensorConfig); sensorConfig.pEnumerationList = pDevice->m_pEnumerationProperties; status = SensorsCxSensorInitialize(sensorInstance, &sensorConfig); if (!NT_SUCCESS(status)) { TraceError("ACT %!FUNC! SensorsCxSensorInitialize failed %!STATUS!", status); } } } } SENSOR_FunctionExit(status); return status; }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; WDF_DRIVER_CONFIG config; WDF_OBJECT_ATTRIBUTES attributes; WDFDRIVER Driver; PDRIVER_CONTEXT Context; #if (NTDDI_VERSION > NTDDI_WIN7) ExInitializeDriverRuntime(DrvRtPoolNxOptIn); #endif WPP_INIT_TRACING(DriverObject, RegistryPath); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Virtio-Serial driver started...built on %s %s\n", __DATE__, __TIME__); WDF_DRIVER_CONFIG_INIT(&config,VIOSerialEvtDeviceAdd); config.DriverPoolTag = VIOSERIAL_DRIVER_MEMORY_TAG; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DRIVER_CONTEXT); attributes.EvtCleanupCallback = VIOSerialEvtDriverContextCleanup; status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, &Driver); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDriverCreate failed - 0x%x\n", status); WPP_CLEANUP(DriverObject); return status; } Context = GetDriverContext(Driver); // create a lookaside list used for allocating WRITE_BUFFER_ENTRY // structures by all devices status = WdfLookasideListCreate(WDF_NO_OBJECT_ATTRIBUTES, sizeof(WRITE_BUFFER_ENTRY), NonPagedPool, WDF_NO_OBJECT_ATTRIBUTES, VIOSERIAL_DRIVER_MEMORY_TAG, &Context->WriteBufferLookaside); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfLookasideListCreate failed - 0x%x\n", status); return status; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__); return status; }
/***************************************************************************** Harness. *****************************************************************************/ int main (int argc, char* argv[]) { NTSTATUS status = STATUS_SUCCESS; //PDEVICE_EXTENSION deviceExtension; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, DEVICE_EXTENSION); return STATUS_SUCCESS; }
NTSTATUS DeviceCreate( _In_ WDFDRIVER Driver, _In_ PWDFDEVICE_INIT DeviceInit, _Out_ PDEVICE_CONTEXT *DeviceContext ) /*++ Routine Description: This method creates and initializs an instance of the VirtualSerial driver's device callback object. Arguments: FxDeviceInit - the settings for the device. Device - a location to store the referenced pointer to the device object. Return Value: Status --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES deviceAttributes; WDFDEVICE device; PDEVICE_CONTEXT deviceContext; UNREFERENCED_PARAMETER (Driver); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &deviceAttributes, DEVICE_CONTEXT); deviceAttributes.SynchronizationScope = WdfSynchronizationScopeDevice; deviceAttributes.EvtCleanupCallback = EvtDeviceCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: WdfDeviceCreate failed 0x%x", status); return status; } deviceContext = GetDeviceContext(device); deviceContext->Device = device; *DeviceContext = deviceContext; return status; }
static NTSTATUS VIOSerialInitInterruptHandling( IN WDFDEVICE hDevice) { WDF_OBJECT_ATTRIBUTES attributes; WDF_INTERRUPT_CONFIG interruptConfig; PPORTS_DEVICE pContext = GetPortsDevice(hDevice); NTSTATUS status = STATUS_SUCCESS; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, PORTS_DEVICE); WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, VIOSerialInterruptIsr, VIOSerialInterruptDpc ); interruptConfig.EvtInterruptEnable = VIOSerialInterruptEnable; interruptConfig.EvtInterruptDisable = VIOSerialInterruptDisable; status = WdfInterruptCreate( hDevice, &interruptConfig, &attributes, &pContext->WdfInterrupt ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "Failed to create control queue interrupt: %x\n", status); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, VIOSerialInterruptIsr, VIOSerialQueuesInterruptDpc); status = WdfInterruptCreate(hDevice, &interruptConfig, &attributes, &pContext->QueuesInterrupt); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "Failed to create general queue interrupt: %x\n", status); return status; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__); return status; }
_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; }
NTSTATUS SLAyer_harness_init() { PWDFDEVICE_INIT DInit; WDF_OBJECT_ATTRIBUTES DAttrib; WDFDEVICE Device; NTSTATUS status; // malloc SL_Device WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DAttrib,DEVICE_EXTENSION); status = WdfDeviceCreate(&DInit,&DAttrib,&Device); 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 HwSimInitialize( _In_ WDFDEVICE Device ) /*++ Routine Description: This routine initializes the hardware simulator Arguments: Device - Handle to the framework device object Return Value: An NTSTATUS value representing success or failure of the function. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES objectAttributes; PHWSIM_CONTEXT devCtx; Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry\n"); // // Allocate our context for this device // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, HWSIM_CONTEXT); status = WdfObjectAllocateContext((WDFOBJECT) Device, &objectAttributes, (PVOID*) &devCtx); if (FALSE == NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfObjectAllocateContext failed with %!status!", status); goto exit; } devCtx->FirstD0Entry = TRUE; status = STATUS_SUCCESS; Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit\n"); exit: return status; }
NTSTATUS CUsbDkFilterDeviceInit::Configure(ULONG InstanceNumber) { PAGED_CODE(); WDF_OBJECT_ATTRIBUTES requestAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestAttributes, WDF_REQUEST_CONTEXT); requestAttributes.ContextSizeOverride = CUsbDkFilterDevice::CStrategist::GetRequestContextSize(); SetRequestAttributes(requestAttributes); SetFilter(); CString DeviceName; auto status = DeviceName.Create(TEXT("\\Device\\UsbDkFilter"), InstanceNumber); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_FILTERDEVICE, "%!FUNC! Failed to allocate filter device name (%!STATUS!)", status); return status; } status = SetName(*DeviceName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_FILTERDEVICE, "%!FUNC! SetName failed %!STATUS!", status); return status; } SetPowerCallbacks([](_In_ WDFDEVICE Device) { return Strategy(Device)->MakeAvailable(); }); SetIoInCallerContextCallback([](_In_ WDFDEVICE Device, WDFREQUEST Request) { return Strategy(Device)->IoInCallerContext(Device, Request); }); SetFileEventCallbacks(WDF_NO_EVENT_CALLBACK, [](_In_ WDFFILEOBJECT FileObject) { WDFDEVICE Device = WdfFileObjectGetDevice(FileObject); Strategy(Device)->OnClose(); }, WDF_NO_EVENT_CALLBACK); status = SetPreprocessCallback([](_In_ WDFDEVICE Device, _Inout_ PIRP Irp) { return Strategy(Device)->PNPPreProcess(Irp); }, IRP_MJ_PNP); return status; }
void FileObjectContext::DeviceInit( _Inout_ PWDFDEVICE_INIT DeviceInit ) { TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); WDF_FILEOBJECT_CONFIG config; WDF_FILEOBJECT_CONFIG_INIT(&config, CreateCallback, CloseCallback, nullptr); WDF_OBJECT_ATTRIBUTES objectAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, FileObjectContext); objectAttributes.EvtDestroyCallback = DestroyCallback; WdfDeviceInitSetFileObjectConfig(DeviceInit, &config, &objectAttributes); TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE); }
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; 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; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %!FUNC!"); return status; }
NTSTATUS TpmEntropyInit(PTPM_CONTEXT TpmContext) { NTSTATUS status = STATUS_SUCCESS; #if _NT_TARGET_VERSION >= 0x601 // win7 WDF_TIMER_CONFIG timerConfig; WDF_OBJECT_ATTRIBUTES timerAttributes; WDFTIMER timerHandle; PTPM_ENTROPY_TIMER_CONTEXT TimerContext; PAGED_CODE(); status = EntropyRegisterSource(&TpmContext->hEntropySource, ENTROPY_SOURCE_TYPE_TPM, CNG_ENTROPY_NAME); TpmContext->EntropyDensity = TpmGetEntropyDensity(); TpmContext->TimeOutSecond = 60000; timerConfig.TolerableDelay = 60000; TpmContext->bUseTimeOut = FALSE; TpmContext->PendingEntropy = FALSE; WDF_TIMER_CONFIG_INIT(&timerConfig, TpmEvtEntropyTimer); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&timerAttributes,TPM_ENTROPY_TIMER_CONTEXT); timerAttributes.ParentObject = TpmContext->Device; status = WdfTimerCreate( &timerConfig, &timerAttributes, &TpmContext->timerHandle ); if(NT_SUCCESS(status)) { TimerContext = GetTimerContext(TpmContext->timerHandle); TimerContext->TpmContext = TpmContext; } #endif return status; }
NTSTATUS MouseTrapEvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT deviceInit) { UNREFERENCED_PARAMETER(driver); PAGED_CODE(); // Ensure paging is allowed in current IRQL // Create filter WdfFdoInitSetFilter(deviceInit); // Set driver type to mouse WdfDeviceInitSetDeviceType(deviceInit, FILE_DEVICE_MOUSE); // Create attributes for a device extension WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); // Create framework device object WDFDEVICE hDevice; NTSTATUS status = WdfDeviceCreate(&deviceInit, &deviceAttributes, &hDevice); if(!NT_SUCCESS(status)) { DebugPrint(("[MouseTrap] WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } // Set request queue type WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // Set handler for device control requests ioQueueConfig.EvtIoInternalDeviceControl = MouseTrapEvtIoInternalDeviceControl; // Create queue for filter device status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE); if(!NT_SUCCESS(status)) { DebugPrint(("[MouseTrap] WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
// This static routine performs simulator initialization. The routine creates a // timer object that periodically updates the m_Index location NTSTATUS HardwareSimulator::Initialize( _In_ WDFDEVICE Device, // WDF device representing the sensor _Out_ WDFOBJECT *SimulatorInstance) // Instance of the WDF object for the simulator { PHardwareSimulator pSimulator = nullptr; NTSTATUS Status = STATUS_SUCCESS; WDF_OBJECT_ATTRIBUTES HardwareSimulatorAttributes = {}; SENSOR_FunctionEnter(); // Create WDFOBJECT for the hardware simulator WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&HardwareSimulatorAttributes, HardwareSimulator); HardwareSimulatorAttributes.ParentObject = Device; Status = WdfObjectCreate(&HardwareSimulatorAttributes, SimulatorInstance); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!FUNC! WdfObjectCreate failed %!STATUS!", Status); goto Exit; } pSimulator = GetHardwareSimulatorContextFromInstance(*SimulatorInstance); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); goto Exit; } pSimulator->InitializeInternal(*SimulatorInstance); Exit: SENSOR_FunctionExit(Status); return Status; }
NTSTATUS EchoQueueInitialize( WDFDEVICE Device ) /*++ Routine Description: The I/O dispatch callbacks for the frameworks device object are configured in this function. A single default I/O Queue is configured for serial request processing, and a driver context memory allocation is created to hold our structure QUEUE_CONTEXT. This memory may be used by the driver automatically synchronized by the Queue's presentation lock. The lifetime of this memory is tied to the lifetime of the I/O Queue object, and we register an optional destructor callback to release any private allocations, and/or resources. Arguments: Device - Handle to a framework device object. Return Value: NTSTATUS --*/ { WDFQUEUE queue; NTSTATUS status; PQUEUE_CONTEXT queueContext; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES queueAttributes; // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchSequential ); queueConfig.EvtIoRead = EchoEvtIoRead; queueConfig.EvtIoWrite = EchoEvtIoWrite; // // Fill in a callback for destroy, and our QUEUE_CONTEXT size // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_CONTEXT); // // Set synchronization scope on queue and have the timer to use queue as // the parent object so that queue and timer callbacks are synchronized // with the same lock. // queueAttributes.SynchronizationScope = WdfSynchronizationScopeQueue; queueAttributes.EvtDestroyCallback = EchoEvtIoQueueContextDestroy; status = WdfIoQueueCreate( Device, &queueConfig, &queueAttributes, &queue ); if( !NT_SUCCESS(status) ) { KdPrint(("WdfIoQueueCreate failed 0x%x\n",status)); return status; } // Get our Driver Context memory from the returned Queue handle queueContext = QueueGetContext(queue); queueContext->WriteMemory = NULL; queueContext->Timer = NULL; queueContext->CurrentRequest = NULL; queueContext->CurrentStatus = STATUS_INVALID_DEVICE_REQUEST; // // Create the Queue timer // status = EchoTimerCreate(&queueContext->Timer, queue); if (!NT_SUCCESS(status)) { KdPrint(("Error creating timer 0x%x\n",status)); return status; } return status; }
NTSTATUS FilterEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Here you can query the device properties using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based on that, decide to create a filter device object and attach to the function stack. If you are not interested in filtering this particular instance of the device, you can just return STATUS_SUCCESS without creating a framework device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES deviceAttributes; PFILTER_EXTENSION filterExt; NTSTATUS status; WDFDEVICE device; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDFQUEUE hQueue; PAGED_CODE (); UNREFERENCED_PARAMETER(Driver); KdPrint(("--> FilterEvtDeviceAdd\n")); // // Tell the framework that you are filter driver. Framework // takes care of inherting all the device flags & characterstics // from the lower device you are attaching to. // WdfFdoInitSetFilter(DeviceInit); // // Initialize the pnpPowerCallbacks structure. Callback events for PNP // and Power are specified here. If you don't supply any callbacks, // the Framework will take appropriate default actions based on whether // DeviceInit is initialized to be an FDO, a PDO or a filter device // object. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // For usb devices, PrepareHardware callback is the to place select the // interface and configure the device. // pnpPowerCallbacks.EvtDevicePrepareHardware = FilterEvtDevicePrepareHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // Specify the size of device extension where we track per device // context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, FILTER_EXTENSION); // // Create a framework device object.This call will inturn create // a WDM deviceobject, attach to the lower stack and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } filterExt = FilterGetData(device); // // Configure the default queue to be Parallel. // to handle IOCTLs that will be forwarded to us from // the rawPDO. WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoDeviceControl = FilterEvtIoDeviceControlFromRawPdo; status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue // pointer to default queue ); if (!NT_SUCCESS(status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } filterExt->rawPdoQueue = hQueue; // // Create a RAW pdo so we can provide a sideband communication with // the application. Please note that not filter drivers desire to // produce such a communication and not all of them are contrained // by other filter above which prevent communication thru the device // interface exposed by the main stack. So use this only if absolutely // needed. Also look at the toaster filter driver sample for an alternate // approach to providing sideband communication. // status = FiltrCreateRawPdo(device, ++InstanceNo); KdPrint(("<-- FilterEvtDeviceAdd\n")); return status; }
NTSTATUS SingleCompEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by UMDF in response to AddDevice call from the PnP manager. Arguments: Driver - Handle to the UMDF driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: An NTSTATUS value representing success or failure of the function. --*/ { NTSTATUS status; WDFDEVICE device; WDFQUEUE queue; WDF_IO_QUEUE_CONFIG queueConfig; FDO_DATA *fdoContext = NULL; WDF_OBJECT_ATTRIBUTES objectAttributes; WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; UNREFERENCED_PARAMETER(Driver); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, FDO_DATA); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); pnpCallbacks.EvtDeviceD0Entry = SingleCompEvtDeviceD0Entry; pnpCallbacks.EvtDeviceD0Exit = SingleCompEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceCreate failed with %!status!.", status); goto exit; } fdoContext = FdoGetContext(device); // // Our initial state is active // fdoContext->IsActive = TRUE; // // Create a power-managed queue for IOCTL requests. // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = SingleCompEvtIoDeviceControl; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); __analysis_assume(queueConfig.EvtIoStop == 0); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfIoQueueCreate for IoDeviceControl failed with %!status!.", status); goto exit; } status = WdfDeviceConfigureRequestDispatching(device, queue, WdfRequestTypeDeviceControl); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeDeviceControl failed with %!status!.", status); goto exit; } status = AssignS0IdleSettings(device); if (!NT_SUCCESS(status)) { goto exit; } // // Create a device interface so that applications can open a handle to this // device. // status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_POWERFX, NULL /* ReferenceString */); if (FALSE == NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceCreateDeviceInterface failed with %!status!.", status); goto exit; } // // Initialize the hardware simulator // status = HwSimInitialize(device); if (FALSE == NT_SUCCESS(status)) { goto exit; } exit: return status; }
// This routine is called by the framework when the PnP manager sends an // IRP_MN_START_DEVICE request to the driver stack. This routine is // responsible for performing operations that are necessary to make the // driver's device operational (for e.g. mapping the hardware resources // into memory). NTSTATUS CustomSensorDevice::OnPrepareHardware( _In_ WDFDEVICE Device, // Supplies a handle to the framework device object _In_ WDFCMRESLIST /*ResourcesRaw*/, // Supplies a handle to a collection of framework resource // objects. This collection identifies the raw (bus-relative) hardware // resources that have been assigned to the device. _In_ WDFCMRESLIST /*ResourcesTranslated*/) // Supplies a handle to a collection of framework // resource objects. This collection identifies the translated // (system-physical) hardware resources that have been assigned to the // device. The resources appear from the CPU's point of view. { PCustomSensorDevice pDevice = nullptr; WDF_OBJECT_ATTRIBUTES SensorAttr = {}; SENSOR_CONFIG SensorConfig = {}; SENSOROBJECT SensorInstance = nullptr; NTSTATUS Status = STATUS_SUCCESS; SENSOR_FunctionEnter(); // Construct sensor instance // Create WDFOBJECT for the sensor WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&SensorAttr, CustomSensorDevice); // Register sensor instance with clx Status = SensorsCxSensorCreate(Device, &SensorAttr, &SensorInstance); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!FUNC! SensorsCxSensorCreate failed %!STATUS!", Status); goto Exit; } pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance); if (nullptr == pDevice) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("CSTM %!FUNC! GetCustomSensorContextFromSensorInstance failed %!STATUS!", Status); goto Exit; } // Fill out properties Status = pDevice->Initialize(Device, SensorInstance); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!FUNC! Initialize device object failed %!STATUS!", Status); goto Exit; } SENSOR_CONFIG_INIT(&SensorConfig); SensorConfig.pEnumerationList = pDevice->m_pEnumerationProperties; Status = SensorsCxSensorInitialize(SensorInstance, &SensorConfig); if (!NT_SUCCESS(Status)) { TraceError("CSTM %!FUNC! SensorsCxSensorInitialize failed %!STATUS!", Status); goto Exit; } Exit: SENSOR_FunctionExit(Status); return Status; }
NTSTATUS Bus_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Bus_EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of toaster bus. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_CHILD_LIST_CONFIG config; WDF_OBJECT_ATTRIBUTES fdoAttributes; NTSTATUS status; WDFDEVICE device; WDF_IO_QUEUE_CONFIG queueConfig; PNP_BUS_INFORMATION busInfo; //PFDO_DEVICE_DATA deviceData; WDFQUEUE queue; UNREFERENCED_PARAMETER(Driver); PAGED_CODE (); KdPrint(("Bus_EvtDeviceAdd: 0x%p\n", Driver)); // // Initialize all the properties specific to the device. // Framework has default values for the one that are not // set explicitly here. So please read the doc and make sure // you are okay with the defaults. // WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); WdfDeviceInitSetExclusive(DeviceInit, TRUE); // // Since this is pure software bus enumerator, we don't have to register for // any PNP/Power callbacks. Framework will take the default action for // all the PNP and Power IRPs. // // // WDF_ DEVICE_LIST_CONFIG describes how the framework should handle // dynamic child enumeration on behalf of the driver writer. // Since we are a bus driver, we need to specify identification description // for our child devices. This description will serve as the identity of our // child device. Since the description is opaque to the framework, we // have to provide bunch of callbacks to compare, copy, or free // any other resources associated with the description. // WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(PDO_IDENTIFICATION_DESCRIPTION), Bus_EvtDeviceListCreatePdo // callback to create a child device. ); // // This function pointer will be called when the framework needs to copy a // identification description from one location to another. An implementation // of this function is only necessary if the description contains description // relative pointer values (like LIST_ENTRY for instance) . // If set to NULL, the framework will use RtlCopyMemory to copy an identification . // description. In this sample, it's not required to provide these callbacks. // they are added just for illustration. // config.EvtChildListIdentificationDescriptionDuplicate = Bus_EvtChildListIdentificationDescriptionDuplicate; // // This function pointer will be called when the framework needs to compare // two identificaiton descriptions. If left NULL a call to RtlCompareMemory // will be used to compare two identificaiton descriptions. // config.EvtChildListIdentificationDescriptionCompare = Bus_EvtChildListIdentificationDescriptionCompare; // // This function pointer will be called when the framework needs to free a // identification description. An implementation of this function is only // necessary if the description contains dynamically allocated memory // (by the driver writer) that needs to be freed. The actual identification // description pointer itself will be freed by the framework. // config.EvtChildListIdentificationDescriptionCleanup = Bus_EvtChildListIdentificationDescriptionCleanup; // // Tell the framework to use the built-in childlist to track the state // of the device based on the configuration we just created. // WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES); // // Initialize attributes structure to specify size and accessor function // for storing device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DEVICE_DATA); // // Create a framework device object. In response to this call, framework // creates a WDM deviceobject and attach to the PDO. // status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS(status)) { KdPrint(("Error creating device 0x%x\n", status)); return status; } // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel ); queueConfig.EvtIoDeviceControl = Bus_EvtIoDeviceControl; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate( device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); __analysis_assume(queueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { KdPrint(("WdfIoQueueCreate failed status 0x%x\n", status)); return status; } // // Get the device context. // //deviceData = FdoGetData(device); // // Create device interface for this device. The interface will be // enabled by the framework when we return from StartDevice successfully. // Clients of this driver will open this interface and send ioctls. // status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_BUSENUM_TOASTER, NULL // No Reference String. If you provide one it will appended to the ); // symbolic link. Some drivers register multiple interfaces for the same device // and use the reference string to distinguish between them if (!NT_SUCCESS(status)) { return status; } // // This value is used in responding to the IRP_MN_QUERY_BUS_INFORMATION // for the child devices. This is an optional information provided to // uniquely idenitfy the bus the device is connected. // busInfo.BusTypeGuid = GUID_DEVCLASS_TOASTER; busInfo.LegacyBusType = PNPBus; busInfo.BusNumber = 0; WdfDeviceSetBusInformationForChildren(device, &busInfo); status = Bus_WmiRegistration(device); if (!NT_SUCCESS(status)) { return status; } // // Check the registry to see if we need to enumerate child devices during // start. // status = Bus_DoStaticEnumeration(device); return status; }
NTSTATUS 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; }
_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; }
NTSTATUS EchoDeviceCreate( PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Worker routine called to create a device and its software resources. Arguments: DeviceInit - Pointer to an opaque init structure. Memory for this structure will be freed by the framework when the WdfDeviceCreate succeeds. So don't access the structure after that point. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES attributes; PDEVICE_CONTEXT deviceContext; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDFDEVICE device; NTSTATUS status; PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Register pnp/power callbacks so that we can start and stop the timer as the device // gets started and stopped. // pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = EchoEvtDeviceSelfManagedIoStart; pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend = EchoEvtDeviceSelfManagedIoSuspend; // // Function used for both Init and Restart Callbacks // #pragma warning(suppress: 28024) pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = EchoEvtDeviceSelfManagedIoStart; // // Register the PnP and power callbacks. Power policy related callbacks will be registered // later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(DeviceInit, &attributes); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (NT_SUCCESS(status)) { // // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the // device.h header file. This function will do the type checking and return // the device context. If you pass a wrong object handle // it will return NULL and assert if run under framework verifier mode. // deviceContext = WdfObjectGet_DEVICE_CONTEXT(device); deviceContext->PrivateDeviceData = 0; // // Create a device interface so that application can find and talk // to us. // status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_ECHO, NULL // ReferenceString ); if (NT_SUCCESS(status)) { // // Initialize the I/O Package and any Queues // status = EchoQueueInitialize(device); } } return status; }
VOID NdisProtEvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: Dispatch routine to handle Request_MJ_WRITE. Arguments: Queue - Default queue handle Request - Handle to the read/write request Lenght - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero lenght read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: VOID --*/ { ULONG DataLength; NTSTATUS NtStatus; PNDISPROT_OPEN_CONTEXT pOpenContext; PNET_BUFFER_LIST pNetBufferList; NDISPROT_ETH_HEADER UNALIGNED *pEthHeader; PVOID CancelId; ULONG SendFlags = 0; PMDL pMdl = NULL; WDFFILEOBJECT fileObject; PREQUEST_CONTEXT reqContext; WDF_OBJECT_ATTRIBUTES attributes; UNREFERENCED_PARAMETER(Queue); fileObject = WdfRequestGetFileObject(Request); pOpenContext = GetFileObjectContext(fileObject)->OpenContext; do { // // Create a context to track the length of transfer and NDIS packet // associated with this request. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); NtStatus = WdfObjectAllocateContext(Request, &attributes, &reqContext); if(!NT_SUCCESS(NtStatus)){ DEBUGP(DL_WARN, ("Write: WdfObjectAllocateContext failed: %x\n", NtStatus)); NtStatus = STATUS_INVALID_HANDLE; break; } reqContext->Length = (ULONG) Length; if (pOpenContext == NULL) { DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n", fileObject)); NtStatus = STATUS_INVALID_HANDLE; break; } NPROT_STRUCT_ASSERT(pOpenContext, oc); NtStatus = WdfRequestRetrieveInputWdmMdl(Request, &pMdl); if (!NT_SUCCESS(NtStatus)) { DEBUGP(DL_FATAL, ("Write: WdfRequestRetrieveInputWdmMdl failed %x\n", NtStatus)); break; } // // Try to get a virtual address for the MDL. // pEthHeader = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority | MdlMappingNoExecute); if (pEthHeader == NULL) { DEBUGP(DL_FATAL, ("Write: MmGetSystemAddr failed for" " Request %p, MDL %p\n", Request, pMdl)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } // // Sanity-check the length. // DataLength = MmGetMdlByteCount(pMdl); if (DataLength < sizeof(NDISPROT_ETH_HEADER)) { DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)\n", DataLength)); NtStatus = STATUS_BUFFER_TOO_SMALL; break; } if (DataLength > (pOpenContext->MaxFrameSize + sizeof(NDISPROT_ETH_HEADER))) { DEBUGP(DL_WARN, ("Write: Open %p: data length (%d)" " larger than max frame size (%d)\n", pOpenContext, DataLength, pOpenContext->MaxFrameSize)); NtStatus = STATUS_INVALID_BUFFER_SIZE; break; } // // To prevent applications from sending packets with spoofed // mac address, we will do the following check to make sure the source // address in the packet is same as the current MAC address of the NIC. // if ((WdfRequestGetRequestorMode(Request) == UserMode) && !NPROT_MEM_CMP(pEthHeader->SrcAddr, pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN)) { DEBUGP(DL_WARN, ("Write: Failing with invalid Source address")); NtStatus = STATUS_INVALID_PARAMETER; break; } NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_ACTIVE)) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); DEBUGP(DL_FATAL, ("Write: Open %p is not bound" " or in low power state\n", pOpenContext)); NtStatus = STATUS_INVALID_HANDLE; break; } if ((pOpenContext->State == NdisprotPaused) || (pOpenContext->State == NdisprotPausing)) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); DEBUGP(DL_INFO, ("Device is paused.\n")); NtStatus = STATUS_UNSUCCESSFUL; break; } NPROT_ASSERT(pOpenContext->SendNetBufferListPool != NULL); pNetBufferList = NdisAllocateNetBufferAndNetBufferList( pOpenContext->SendNetBufferListPool, sizeof(NPROT_SEND_NETBUFLIST_RSVD), //Request control offset delta 0, // back fill size pMdl, 0, // Data offset DataLength); if (pNetBufferList == NULL) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send net buffer list\n", pOpenContext)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } pOpenContext->PendedSendCount++; NPROT_REF_OPEN(pOpenContext); // pended send // // Initialize the NetBufferList ref count. This NetBufferList will be freed // when this count goes to zero. // NPROT_SEND_NBL_RSVD(pNetBufferList)->RefCount = 1; // // We set up a cancel ID on each send NetBufferList (which maps to a Write IRP), // and save the NetBufferList pointer in the IRP. If the IRP gets cancelled, we use // NdisCancelSendNetBufferLists() to cancel the NetBufferList. // // Note that this sample code does not implement the cancellation logic. An actual // driver may find value in implementing this. // CancelId = NPROT_GET_NEXT_CANCEL_ID(); NDIS_SET_NET_BUFFER_LIST_CANCEL_ID(pNetBufferList, CancelId); reqContext->NetBufferList = (PVOID)pNetBufferList; NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); // // Set a back pointer from the packet to the IRP. // NPROT_REQUEST_FROM_SEND_NBL(pNetBufferList) = Request; NtStatus = STATUS_PENDING; pNetBufferList->SourceHandle = pOpenContext->BindingHandle; NPROT_ASSERT (pMdl->Next == NULL); SendFlags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK; NdisSendNetBufferLists( pOpenContext->BindingHandle, pNetBufferList, NDIS_DEFAULT_PORT_NUMBER, SendFlags); } while (FALSE); if (NtStatus != STATUS_PENDING) { WdfRequestComplete(Request, NtStatus); } return; }
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; }