// 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 MouseTrapEvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT deviceInit) { UNREFERENCED_PARAMETER(driver); PAGED_CODE(); // Ensure paging is allowed in current IRQL // Create filter WdfFdoInitSetFilter(deviceInit); // Set driver type to mouse WdfDeviceInitSetDeviceType(deviceInit, FILE_DEVICE_MOUSE); // Create attributes for a device extension WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); // Create framework device object WDFDEVICE hDevice; NTSTATUS status = WdfDeviceCreate(&deviceInit, &deviceAttributes, &hDevice); if(!NT_SUCCESS(status)) { DebugPrint(("[MouseTrap] WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } // Set request queue type WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // Set handler for device control requests ioQueueConfig.EvtIoInternalDeviceControl = MouseTrapEvtIoInternalDeviceControl; // Create queue for filter device status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE); if(!NT_SUCCESS(status)) { DebugPrint(("[MouseTrap] WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
NTSTATUS 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 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; WDFDEVICE fxDevice; WDF_INTERRUPT_CONFIG interruptConfig; NTSTATUS status; UNREFERENCED_PARAMETER(FxDriver); // // Tell framework this is a filter driver. Filter drivers by default are // not power policy owners. This works well for this driver because // HIDclass driver is the power policy owner for HID minidrivers. // WdfFdoInitSetFilter(FxDeviceInit); // // 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); } // // Set request attributes. // { WDF_OBJECT_ATTRIBUTES attributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &attributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes); } // // Create the device. // { WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate( &FxDeviceInit, &deviceAttributes, &fxDevice); if (!NT_SUCCESS(status)) { CyapaPrint( 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)) { CyapaPrint( 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.EvtIoInternalDeviceControl = OnIoDeviceControl; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( fxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->SpbQueue ); if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto exit; } } WDF_IO_QUEUE_CONFIG queueConfig; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(pDevice->FxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->ReportQueue ); if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Queue 2!\n"); CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); return status; } // // Create an interrupt object for hardware notifications // WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, OnInterruptIsr, NULL); interruptConfig.PassiveHandling = TRUE; status = WdfInterruptCreate( fxDevice, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->Interrupt); if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Error creating WDF interrupt object - %!STATUS!", status); goto exit; } WDF_TIMER_CONFIG timerConfig; WDFTIMER hTimer; WDF_OBJECT_ATTRIBUTES attributes; WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, CyapaTimerFunc, 10); WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = fxDevice; status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); pDevice->Timer = hTimer; if (!NT_SUCCESS(status)) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); return status; } CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Success! 0x%x\n", status); pDevice->DeviceMode = DEVICE_MODE_MOUSE; exit: FuncExit(TRACE_FLAG_WDFLOADING); return status; }
NTSTATUS FireFlyEvtDeviceAdd( WDFDRIVER Driver, 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 to be part of the device stack as a filter. 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 attributes; NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; WDFDEVICE device; WDFMEMORY memory; size_t bufferLength; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); // // Configure the device as a filter driver // WdfFdoInitSetFilter(DeviceInit); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: WdfDeviceCreate, Error %x\n", status)); return status; } // // Driver Framework always zero initializes an objects context memory // pDeviceContext = WdfObjectGet_DEVICE_CONTEXT(device); // // Initialize our WMI support // status = WmiInitialize(device, pDeviceContext); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: Error initializing WMI 0x%x\n", status)); return status; } // // In order to send ioctls to our PDO, we have open to open it // by name so that we have a valid filehandle (fileobject). // When we send ioctls using the IoTarget, framework automatically // sets the filobject in the stack location. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); // // By parenting it to device, we don't have to worry about // deleting explicitly. It will be deleted along witht the device. // attributes.ParentObject = device; status = WdfDeviceAllocAndQueryProperty(device, DevicePropertyPhysicalDeviceObjectName, NonPagedPoolNx, &attributes, &memory); if (!NT_SUCCESS(status)) { KdPrint(("FireFly: WdfDeviceAllocAndQueryProperty failed 0x%x\n", status)); return STATUS_UNSUCCESSFUL; } pDeviceContext->PdoName.Buffer = WdfMemoryGetBuffer(memory, &bufferLength); if (pDeviceContext->PdoName.Buffer == NULL) { return STATUS_UNSUCCESSFUL; } pDeviceContext->PdoName.MaximumLength = (USHORT) bufferLength; pDeviceContext->PdoName.Length = (USHORT) bufferLength-sizeof(UNICODE_NULL); return status; }
NTSTATUS HidFx2EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: HidFx2EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a WDF device object to represent a new instance of toaster device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; WDFDEVICE hDevice; PDEVICE_EXTENSION devContext = NULL; WDFQUEUE queue; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_TIMER_CONFIG timerConfig; WDFTIMER timerHandle; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "HidFx2EvtDeviceAdd called\n"); // // Tell framework this is a filter driver. Filter drivers by default are // not power policy owners. This works well for this driver because // HIDclass driver is the power policy owner for HID minidrivers. // WdfFdoInitSetFilter(DeviceInit); // // Initialize pnp-power callbacks, attributes and a context area for the 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 = HidFx2EvtDevicePrepareHardware; // // These two callbacks start and stop the wdfusb pipe continuous reader // as we go in and out of the D0-working state. // pnpPowerCallbacks.EvtDeviceD0Entry = HidFx2EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = HidFx2EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); // // Create a framework device object.This call will in turn create // a WDM device object, attach to the lower stack, and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &attributes, &hDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreate failed with status code 0x%x\n", status); return status; } devContext = GetDeviceContext(hDevice); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoInternalDeviceControl = HidFx2EvtInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); return status; } // // Register a manual I/O queue for handling Interrupt Message Read Requests. // This queue will be used for storing Requests that need to wait for an // interrupt to occur before they can be completed. // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); // // This queue is used for requests that dont directly access the device. The // requests in this queue are serviced only when the device is in a fully // powered state and sends an interrupt. So we can use a non-power managed // queue to park the requests since we dont care whether the device is idle // or fully powered up. // queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &devContext->InterruptMsgQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); return status; } // // Create a timer to handle debouncing of switchpack // WDF_TIMER_CONFIG_INIT( &timerConfig, HidFx2EvtTimerFunction ); timerConfig.AutomaticSerialization = FALSE; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hDevice; status = WdfTimerCreate( &timerConfig, &attributes, &timerHandle ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate failed status:0x%x\n", status); return status; } devContext->DebounceTimer = timerHandle; return status; }
NTSTATUS EvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ 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 --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES deviceAttributes; WDFDEVICE device; PDEVICE_CONTEXT deviceContext; PHID_DEVICE_ATTRIBUTES hidAttributes; UNREFERENCED_PARAMETER (Driver); KdPrint(("Enter EvtDeviceAdd\n")); // // Mark ourselves as a filter, which also relinquishes power policy ownership // WdfFdoInitSetFilter(DeviceInit); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { KdPrint(("Error: WdfDeviceCreate failed 0x%x\n", status)); return status; } deviceContext = GetDeviceContext(device); deviceContext->Device = device; deviceContext->DeviceData = 0; hidAttributes = &deviceContext->HidDeviceAttributes; RtlZeroMemory(hidAttributes, sizeof(HID_DEVICE_ATTRIBUTES)); hidAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES); hidAttributes->VendorID = HIDMINI_VID; hidAttributes->ProductID = HIDMINI_PID; hidAttributes->VersionNumber = HIDMINI_VERSION; status = QueueCreate(device, &deviceContext->DefaultQueue); if( !NT_SUCCESS(status) ) { return status; } status = ManualQueueCreate(device, &deviceContext->ManualQueue); if( !NT_SUCCESS(status) ) { return status; } // // Use default "HID Descriptor" (hardcoded). We will set the // wReportLength memeber of HID descriptor when we read the // the report descriptor either from registry or the hard-coded // one. // deviceContext->HidDescriptor = G_DefaultHidDescriptor; // // Check to see if we need to read the Report Descriptor from // registry. If the "ReadFromRegistry" flag in the registry is set // then we will read the descriptor from registry using routine // ReadDescriptorFromRegistry(). Otherwise, we will use the // hard-coded default report descriptor. // status = CheckRegistryForDescriptor(device); if (NT_SUCCESS(status)){ // // We need to read read descriptor from registry // status = ReadDescriptorFromRegistry(device); if (!NT_SUCCESS(status)){ KdPrint(("Failed to read descriptor from registry\n")); } } // // We will use hard-coded report descriptor if registry one is not used. // if (!NT_SUCCESS(status)){ deviceContext->ReportDescriptor = G_DefaultReportDescriptor; KdPrint(("Using Hard-coded Report descriptor\n")); status = STATUS_SUCCESS; } 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_OBJECT_ATTRIBUTES deviceAttributes; PFILTER_EXTENSION filterExt; NTSTATUS status; WDFDEVICE device; WDF_IO_QUEUE_CONFIG ioQueueConfig; PAGED_CODE (); UNREFERENCED_PARAMETER(Driver); // // 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); // // 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. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoDeviceControl = FilterEvtIoDeviceControl; status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE // pointer to default queue ); if (!NT_SUCCESS(status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
/////////////////////////////////////////////////////////////////////////////// // // CDFilterEvtDeviceAdd // // This routine is called by the framework when a device of // the type we filter 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 CDFilterEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDF_OBJECT_ATTRIBUTES wdfObjectAttr; WDFDEVICE wdfDevice; PFILTER_DEVICE_CONTEXT devContext; WDF_IO_QUEUE_CONFIG ioQueueConfig; #if DBG DbgPrint("CDFilterEvtDeviceAdd: Adding device...\n"); #endif UNREFERENCED_PARAMETER(Driver); // // Indicate that we're creating a FILTER device. This will cause // KMDF to attach us correctly to the device stack and auto-forward // any requests we don't explicitly handle. // WdfFdoInitSetFilter(DeviceInit); // // Setup our device attributes to have our context type // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&wdfObjectAttr, FILTER_DEVICE_CONTEXT); // // And create our WDF device. This does a multitude of things, // including: // // 1) Creating a WDM device object // 2) Attaching the device object to the filtered device object // 3) Propogates all of the flags and characteristics of the // target device to our filter device. So, for example, if // the target device is setup for direct I/O our filter // device will also be setup for direct I/O // status = WdfDeviceCreate(&DeviceInit, &wdfObjectAttr, &wdfDevice); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceCreate failed - 0x%x\n", status); #endif return status; } // // Get our filter context // devContext = CDFilterGetDeviceContext(wdfDevice); // // Get our local (aka "in-stack") I/O Target. This is the device // to which we'll be forwarding requests that we intercept (and // hence aren't automagically forwarded). // devContext->TargetToSendRequestsTo = WdfDeviceGetIoTarget(wdfDevice); // // Now that that's over with, we can create our default queue. // This queue will allow us to pick off any I/O requests // that we may be interested in before they are forwarded // to the target device. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // // For this exercise we'll intercept READ requests // ioQueueConfig.EvtIoRead = CDFilterEvtRead; // // Create the queue... // status = WdfIoQueueCreate(wdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfIoQueueCreate failed - 0x%x\n", status); #endif return status; } // // Success! // return STATUS_SUCCESS; }
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_OBJECT_ATTRIBUTES deviceAttributes; PFILTER_EXTENSION filterExt; NTSTATUS status; WDFDEVICE device; ULONG serialNo; ULONG returnSize; PAGED_CODE (); UNREFERENCED_PARAMETER(Driver); // // Get some property of the device you are about to attach and check // to see if that's the one you are interested. For demonstration // we will get the UINumber of the device. The bus driver reports the // serial number as the UINumber. // status = WdfFdoInitQueryProperty(DeviceInit, DevicePropertyUINumber, sizeof(serialNo), &serialNo, &returnSize); if(!NT_SUCCESS(status)){ KdPrint(("Failed to get the property of PDO: 0x%p\n", DeviceInit)); } // // 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); // // Specify the size of device extension where we track per device // context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, FILTER_EXTENSION); // // We will just register for cleanup notification because we have to // delete the control-device when the last instance of the device goes // away. If we don't delete, the driver wouldn't get unloaded automatcially // by the PNP subsystem. // deviceAttributes.EvtCleanupCallback = FilterEvtDeviceContextCleanup; // // 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); filterExt->SerialNo = serialNo; // // Add this device to the FilterDevice collection. // WdfWaitLockAcquire(FilterDeviceCollectionLock, NULL); // // WdfCollectionAdd takes a reference on the item object and removes // it when you call WdfCollectionRemove. // status = WdfCollectionAdd(FilterDeviceCollection, device); if (!NT_SUCCESS(status)) { KdPrint( ("WdfCollectionAdd failed with status code 0x%x\n", status)); } WdfWaitLockRelease(FilterDeviceCollectionLock); // // Create a control device // status = FilterCreateControlDevice(device); if (!NT_SUCCESS(status)) { KdPrint( ("FilterCreateControlDevice failed with status 0x%x\n", status)); // // Let us not fail AddDevice just because we weren't able to create the // control device. // status = STATUS_SUCCESS; } return status; }
static NTSTATUS XenVbd_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init) { PXENVBD_FILTER_DATA xvfd; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES device_attributes; WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks; WDF_DPC_CONFIG dpc_config; WDF_OBJECT_ATTRIBUTES oa; UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE }; UCHAR power_minor_functions[] = { IRP_MN_SET_POWER }; UNREFERENCED_PARAMETER(driver); FUNCTION_ENTER(); WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN); WdfFdoInitSetFilter(device_init); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks); pnp_power_callbacks.EvtDeviceD0Entry = XenVbd_EvtDeviceD0Entry; pnp_power_callbacks.EvtDeviceD0Exit = XenVbd_EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks); status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE, IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions)); if (!NT_SUCCESS(status)) { return status; } status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER, IRP_MJ_POWER, power_minor_functions, ARRAY_SIZE(power_minor_functions)); if (!NT_SUCCESS(status)) { return status; } WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENVBD_FILTER_DATA); status = WdfDeviceCreate(&device_init, &device_attributes, &device); if (!NT_SUCCESS(status)) { FUNCTION_MSG("Error creating device 0x%x\n", status); return status; } xvfd = GetXvfd(device); xvfd->wdf_device = device; xvfd->wdf_target = WdfDeviceGetIoTarget(device); xvfd->xvdd.xvfd = xvfd; xvfd->xvdd.pdo = WdfDeviceWdmGetPhysicalDevice(device); xvfd->xvdd.grant_tag = XENVBD_POOL_TAG; KeInitializeEvent(&xvfd->xvdd.backend_event, SynchronizationEvent, FALSE); WDF_DPC_CONFIG_INIT(&dpc_config, XenVbd_EvtDpcEvent); WDF_OBJECT_ATTRIBUTES_INIT(&oa); oa.ParentObject = device; status = WdfDpcCreate(&dpc_config, &oa, &xvfd->dpc); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE); WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE); FUNCTION_EXIT(); return status; }
//HidFx2EvtDeviceAdd is called by the framework in response to AddDevicecall from the PnP manager. //We create and initialize a WDF device object to represent a new instance of device. // NTSTATUS HidFx2EvtDeviceAdd(_In_ WDFDRIVER hDriver, _Inout_ PWDFDEVICE_INIT pDeviceInit) { NTSTATUS status = STATUS_SUCCESS; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; WDFDEVICE hDevice; PDEVICE_EXTENSION pDevContext = NULL; WDFQUEUE hQueue; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_TIMER_CONFIG timerConfig; WDFTIMER hTimer; UNREFERENCED_PARAMETER(hDriver); PAGED_CODE(); TraceVerbose(DBG_PNP, "(%!FUNC!) Enter\n"); // Tell framework this is a filter driver. WdfFdoInitSetFilter(pDeviceInit); // Initialize pnp-power callbacks, attributes and a context area for the 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 = HidFx2EvtDevicePrepareHardware; // These two callbacks start and stop the wdfusb pipe continuous reader as we go in and out of the D0-working state. pnpPowerCallbacks.EvtDeviceD0Entry = HidFx2EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = HidFx2EvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(pDeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); // Create a framework device object.This call will in turn create a WDM device object, attach to the lower stack. status = WdfDeviceCreate(&pDeviceInit, &attributes, &hDevice); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfDeviceCreate failed with status code %!STATUS!\n", status); return status; } pDevContext = GetDeviceContext(hDevice); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoInternalDeviceControl = HidFx2EvtInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue); if (!NT_SUCCESS (status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed 0x%x\n", status); return status; } // Register a manual I/O queue for handling Interrupt Message Read Requests. WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); // This queue is used for requests that dont directly access the device. // The requests in this queue are serviced only when the device is in a fully powered state and sends an interrupt. queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hInterruptMsgQueue); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfIoQueueCreate failed %!STATUS!\n", status); return status; } // Create a timer to handle debouncing of switchpack WDF_TIMER_CONFIG_INIT(&timerConfig, HidFx2EvtTimerFunction); timerConfig.AutomaticSerialization = FALSE; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hDevice; status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); if (!NT_SUCCESS(status)) { TraceErr(DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); return status; } pDevContext->hDebounceTimer = hTimer; TraceVerbose(DBG_PNP, "(%!FUNC!) Exit\n"); return status; }
NTSTATUS KbFilter_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Here you can query the device properties using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based on that, decide to create a filter device object and attach to the function stack. If you are not interested in filtering this particular instance of the device, you can just return STATUS_SUCCESS without creating a framework device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE hDevice; WDFQUEUE hQueue; PDEVICE_EXTENSION filterExt; WDF_IO_QUEUE_CONFIG ioQueueConfig; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); DebugPrint(("Enter FilterEvtDeviceAdd \n")); // // Tell the framework that you are filter driver. Framework // takes care of inherting all the device flags & characterstics // from the lower device you are attaching to. // WdfFdoInitSetFilter(DeviceInit); WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_KEYBOARD); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); // // Create a framework device object. This call will in turn create // a WDM deviceobject, attach to the lower stack and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice); if (!NT_SUCCESS(status)) { DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } filterExt = FilterGetData(hDevice); // // Configure the default queue to be Parallel. Do not use sequential queue // if this driver is going to be filtering PS2 ports because it can lead to // deadlock. The PS2 port driver sends a request to the top of the stack when it // receives an ioctl request and waits for it to be completed. If you use a // a sequential queue, this request will be stuck in the queue because of the // outstanding ioctl request sent earlier to the port driver. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoInternalDeviceControl = KbFilter_EvtIoInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE // pointer to default queue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // // Create a new queue to handle IOCTLs that will be forwarded to us from // the rawPDO. // WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlFromRawPdo; status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } filterExt->rawPdoQueue = hQueue; // // Create a RAW pdo so we can provide a sideband communication with // the application. Please note that not filter drivers desire to // produce such a communication and not all of them are contrained // by other filter above which prevent communication thru the device // interface exposed by the main stack. So use this only if absolutely // needed. Also look at the toaster filter driver sample for an alternate // approach to providing sideband communication. // status = KbFiltr_CreateRawPdo(hDevice, ++InstanceNo); return status; }
NTSTATUS MouFilter_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. Here you can query the device properties using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based on that, decide to create a filter device object and attach to the function stack. If you are not interested in filtering this particular instance of the device, you can just return STATUS_SUCCESS without creating a framework device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE hDevice; WDF_IO_QUEUE_CONFIG ioQueueConfig; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); DebugPrint(("Enter FilterEvtDeviceAdd \n")); // // Tell the framework that you are filter driver. Framework // takes care of inherting all the device flags & characterstics // from the lower device you are attaching to. // WdfFdoInitSetFilter(DeviceInit); WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_MOUSE); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); // // Create a framework device object. This call will in turn create // a WDM deviceobject, attach to the lower stack and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice); if (!NT_SUCCESS(status)) { DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } // // Configure the default queue to be Parallel. Do not use sequential queue // if this driver is going to be filtering PS2 ports because it can lead to // deadlock. The PS2 port driver sends a request to the top of the stack when it // receives an ioctl request and waits for it to be completed. If you use a // a sequential queue, this request will be stuck in the queue because of the // outstanding ioctl request sent earlier to the port driver. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); // // Framework by default creates non-power managed queues for // filter drivers. // ioQueueConfig.EvtIoInternalDeviceControl = MouFilter_EvtIoInternalDeviceControl; status = WdfIoQueueCreate(hDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE // pointer to default queue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }