NTSTATUS SimSensorDriverDeviceAdd ( WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDriverDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. A WDF device object is created and initialized to represent a new instance of the battery device. Arguments: Driver - Supplies a handle to the WDF Driver object. DeviceInit - Supplies a pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES DeviceAttributes; WDFDEVICE DeviceHandle; PFDO_DATA DevExt; BOOLEAN LockHeld; WDF_IO_QUEUE_CONFIG PendingRequestQueueConfig; WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks; WDFQUEUE Queue; WDF_IO_QUEUE_CONFIG QueueConfig; NTSTATUS Status; WDF_OBJECT_ATTRIBUTES WorkitemAttributes; WDF_WORKITEM_CONFIG WorkitemConfig; UNREFERENCED_PARAMETER(Driver); DebugEnter(); PAGED_CODE(); LockHeld = FALSE; // // Initialize attributes and a context area for the device object. // WDF_OBJECT_ATTRIBUTES_INIT(&DeviceAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&DeviceAttributes, FDO_DATA); // // Initailize power callbacks // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks); PnpPowerCallbacks.EvtDeviceD0Entry = SimSensorDeviceD0Entry; PnpPowerCallbacks.EvtDeviceD0Exit = SimSensorDeviceD0Exit; PnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend = SimSensorSelfManagedIoSuspend; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &PnpPowerCallbacks); // // 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, &DeviceAttributes, &DeviceHandle); if (!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfDeviceCreate() Failed. 0x%x\n", Status); goto DriverDeviceAddEnd; } DevExt = GetDeviceExtension(DeviceHandle); // // Configure a default queue for IO requests. This queue processes requests // to read the sensor state. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig, WdfIoQueueDispatchParallel); QueueConfig.EvtIoDeviceControl = SimSensorIoDeviceControl; // // The system uses IoInternalDeviceControl requests to communicate with the // ACPI driver on the device stack. For proper operation of thermal zones, // these requests must be forwarded unless the driver knows how to handle // them. // QueueConfig.EvtIoInternalDeviceControl = SimSensorIoInternalDeviceControl; Status = WdfIoQueueCreate(DeviceHandle, &QueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &Queue); if (!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfIoQueueCreate() (Default) Failed. 0x%x\n", Status); goto DriverDeviceAddEnd; } // // Configure a manual dispatch queue for pending requests. This queue // stores requests to read the sensor state which can't be retired // immediately. // WDF_IO_QUEUE_CONFIG_INIT(&PendingRequestQueueConfig, WdfIoQueueDispatchManual); Status = WdfIoQueueCreate(DeviceHandle, &PendingRequestQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &DevExt->PendingRequestQueue); PendingRequestQueueConfig.EvtIoStop = SimSensorQueueIoStop; if (!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfIoQueueCreate() (Pending) Failed. 0x%x\n", Status); goto DriverDeviceAddEnd; } // // Configure a workitem to process the simulated interrupt. // WDF_OBJECT_ATTRIBUTES_INIT(&WorkitemAttributes); WorkitemAttributes.ParentObject = DeviceHandle; WDF_WORKITEM_CONFIG_INIT(&WorkitemConfig, SimSensorTemperatureInterruptWorker); Status = WdfWorkItemCreate(&WorkitemConfig, &WorkitemAttributes, &DevExt->InterruptWorker); if (!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfWorkItemCreate() Failed. 0x%x\n", Status); goto DriverDeviceAddEnd; } // // Create the request queue waitlock. // Status = WdfWaitLockCreate(NULL, &DevExt->QueueLock); if (!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfWaitLockCreate() Failed. Status 0x%x\n", Status); goto DriverDeviceAddEnd; } // // Initilize the simulated sensor hardware. // DevExt->Sensor.LowerBound = 0; DevExt->Sensor.UpperBound = (ULONG)-1; DevExt->Sensor.Temperature = VIRTUAL_SENSOR_RESET_TEMPERATURE; Status = WdfWaitLockCreate(NULL, &DevExt->Sensor.Lock); if (!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfWaitLockCreate() Failed. 0x%x\n", Status); goto DriverDeviceAddEnd; } DriverDeviceAddEnd: DebugExitStatus(Status); return Status; }
NTSTATUS ToasterEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: ToasterEvtDeviceAdd 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; PFDO_DATA fdoData; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDFDEVICE hDevice; WDFQUEUE queue; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); KdPrint(("ToasterEvtDeviceAdd called\n")); // // Initialize attributes and a context area for the device object. // // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DATA); // // 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, &fdoAttributes, &hDevice); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } // // Get the device context by using the accessor function specified in // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for FDO_DATA. // fdoData = ToasterFdoGetData(hDevice); // // Tell the Framework that this device will need an interface // status = WdfDeviceCreateDeviceInterface( hDevice, (LPGUID) &GUID_DEVINTERFACE_TOASTER, NULL // ReferenceString ); if (!NT_SUCCESS (status)) { KdPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); return status; } // // Register I/O callbacks to tell the framework that you are interested // in handling IRP_MJ_READ, IRP_MJ_WRITE, and IRP_MJ_DEVICE_CONTROL requests. // If a specific callback function is not specified for one ofthese, // the request will be dispatched to the EvtIoDefault handler, if any. // If there is no EvtIoDefault handler, the request will be failed with // STATUS_INVALID_DEVICE_REQUEST. // WdfIoQueueDispatchParallel means that we are capable of handling // all the I/O requests simultaneously and we are responsible for protecting // data that could be accessed by these callbacks simultaneously. // A default queue gets all the requests that are not // configured for forwarding using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoRead = ToasterEvtIoRead; queueConfig.EvtIoWrite = ToasterEvtIoWrite; queueConfig.EvtIoDeviceControl = ToasterEvtIoDeviceControl; // // 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( hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); __analysis_assume(queueConfig.EvtIoStop == 0); if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
NTSTATUS FilterCreateControlDevice( WDFDEVICE Device ) /*++ Routine Description: This routine is called to create a control deviceobject so that application can talk to the filter driver directly instead of going through the entire device stack. This kind of control device object is useful if the filter driver is underneath another driver which prevents ioctls not known to it or if the driver's dispatch routine is owned by some other (port/class) driver and it doesn't allow any custom ioctls. NOTE: Since the control device is global to the driver and accessible to all instances of the device this filter is attached to, we create only once when the first instance of the device is started and delete it when the last instance gets removed. Arguments: Device - Handle to a filter device object. Return Value: WDF status code --*/ { PWDFDEVICE_INIT pInit = NULL; WDFDEVICE controlDevice = NULL; WDF_OBJECT_ATTRIBUTES controlAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; BOOLEAN bCreate = FALSE; NTSTATUS status; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; PAGED_CODE(); // // First find out whether any ControlDevice has been created. If the // collection has more than one device then we know somebody has already // created or in the process of creating the device. // WdfWaitLockAcquire(FilterDeviceCollectionLock, NULL); if(WdfCollectionGetCount(FilterDeviceCollection) == 1) { bCreate = TRUE; } WdfWaitLockRelease(FilterDeviceCollectionLock); if(!bCreate) { // // Control device is already created. So return success. // return STATUS_SUCCESS; } KdPrint(("Creating Control Device\n")); // // // In order to create a control device, we first need to allocate a // WDFDEVICE_INIT structure and set all properties. // pInit = WdfControlDeviceInitAllocate( WdfDeviceGetDriver(Device), &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R ); if (pInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Error; } // // Set exclusive to false so that more than one app can talk to the // control device simultaneously. // WdfDeviceInitSetExclusive(pInit, FALSE); status = WdfDeviceInitAssignName(pInit, &ntDeviceName); if (!NT_SUCCESS(status)) { goto Error; } // // Specify the size of device context // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&controlAttributes, CONTROL_DEVICE_EXTENSION); status = WdfDeviceCreate(&pInit, &controlAttributes, &controlDevice); if (!NT_SUCCESS(status)) { goto Error; } // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { goto Error; } // // Configure the default queue associated with the control device object // to be Serial so that request passed to EvtIoDeviceControl are serialized. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = FilterEvtIoDeviceControl; // // Framework by default creates non-power managed queues for // filter drivers. // status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { goto Error; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); ControlDevice = controlDevice; return STATUS_SUCCESS; Error: if (pInit != NULL) { WdfDeviceInitFree(pInit); } if (controlDevice != NULL) { // // Release the reference on the newly created object, since // we couldn't initialize it. // WdfObjectDelete(controlDevice); controlDevice = NULL; } return status; }
NTSTATUS KbFiltr_CreateRawPdo( WDFDEVICE Device, ULONG InstanceNo ) /*++ Routine Description: This routine creates and initialize a PDO. Arguments: Return Value: NT Status code. --*/ { NTSTATUS status; PWDFDEVICE_INIT pDeviceInit = NULL; PRPDO_DEVICE_DATA pdoData = NULL; WDFDEVICE hChild = NULL; WDF_OBJECT_ATTRIBUTES pdoAttributes; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDFQUEUE queue; WDF_DEVICE_STATE deviceState; PDEVICE_EXTENSION devExt; DECLARE_CONST_UNICODE_STRING(deviceId,KBFILTR_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(hardwareId,KBFILTR_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(deviceLocation,L"Keyboard Filter\0" ); DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN); DebugPrint(("Entered KbFiltr_CreateRawPdo\n")); // // Allocate a WDFDEVICE_INIT structure and set the properties // so that we can create a device object for the child. // pDeviceInit = WdfPdoInitAllocate(Device); if (pDeviceInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } // // Mark the device RAW so that the child device can be started // and accessed without requiring a function driver. Since we are // creating a RAW PDO, we must provide a class guid. // status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVCLASS_KEYBOARD); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Since keyboard is secure device, we must protect ourselves from random // users sending ioctls and creating trouble. // status = WdfDeviceInitAssignSDDLString(pDeviceInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID // status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId); if (!NT_SUCCESS(status)) { goto Cleanup; } // // For RAW PDO, there is no need to provide BusQueryHardwareIDs // and BusQueryCompatibleIDs IDs unless we are running on // Windows 2000. // if (!RtlIsNtDdiVersionAvailable(NTDDI_WINXP)) { // // On Win2K, we must provide a HWID for the device to get enumerated. // Since we are providing a HWID, we will have to provide a NULL inf // to avoid the "found new device" popup and get the device installed // silently. // status = WdfPdoInitAddHardwareID(pDeviceInit, &hardwareId); if (!NT_SUCCESS(status)) { goto Cleanup; } } // // We could be enumerating more than one children if the filter attaches // to multiple instances of keyboard, so we must provide a // BusQueryInstanceID. If we don't, system will throw CA bugcheck. // status = RtlUnicodeStringPrintf(&buffer, L"%02d", InstanceNo); if (!NT_SUCCESS(status)) { goto Cleanup; } status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Provide a description about the device. This text is usually read from // the device. In the case of USB device, this text comes from the string // descriptor. This text is displayed momentarily by the PnP manager while // it's looking for a matching INF. If it finds one, it uses the Device // Description from the INF file to display in the device manager. // Since our device is raw device and we don't provide any hardware ID // to match with an INF, this text will be displayed in the device manager. // status = RtlUnicodeStringPrintf(&buffer,L"Keyboard_Filter_%02d", InstanceNo ); if (!NT_SUCCESS(status)) { goto Cleanup; } // // You can call WdfPdoInitAddDeviceText multiple times, adding device // text for multiple locales. When the system displays the text, it // chooses the text that matches the current locale, if available. // Otherwise it will use the string for the default locale. // The driver can specify the driver's default locale by calling // WdfPdoInitSetDefaultLocale. // status = WdfPdoInitAddDeviceText(pDeviceInit, &buffer, &deviceLocation, 0x409 ); if (!NT_SUCCESS(status)) { goto Cleanup; } WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); // // Initialize the attributes to specify the size of PDO device extension. // All the state information private to the PDO will be tracked here. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA); // // Set up our queue to allow forwarding of requests to the parent // This is done so that the cached Keyboard Attributes can be retrieved // WdfPdoInitAllowForwardingRequestToParent(pDeviceInit); status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Get the device context. // pdoData = PdoGetData(hChild); pdoData->InstanceNo = InstanceNo; // // Get the parent queue we will be forwarding to // devExt = FilterGetData(Device); pdoData->ParentQueue = devExt->rawPdoQueue; // // Configure the default queue associated with the control device object // to be Serial so that request passed to EvtIoDeviceControl are serialized. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlForRawPdo; status = WdfIoQueueCreate(hChild, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); goto Cleanup; } // // Set some properties for the child device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.Removable = WdfTrue; pnpCaps.SurpriseRemovalOK = WdfTrue; pnpCaps.NoDisplayInUI = WdfTrue; pnpCaps.Address = InstanceNo; pnpCaps.UINumber = InstanceNo; WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); // // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we // have to do the following to hide the device. Following call // tells the framework to report the device state in // IRP_MN_QUERY_DEVICE_STATE request. // WDF_DEVICE_STATE_INIT(&deviceState); deviceState.DontDisplayInUI = WdfTrue; WdfDeviceSetDeviceState(hChild, &deviceState); // // Tell the Framework that this device will need an interface so that // application can find our device and talk to it. // status = WdfDeviceCreateDeviceInterface( hChild, &GUID_DEVINTERFACE_KBFILTER, NULL ); if (!NT_SUCCESS (status)) { DebugPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); goto Cleanup; } // // Add this device to the FDO's collection of children. // After the child device is added to the static collection successfully, // driver must call WdfPdoMarkMissing to get the device deleted. It // shouldn't delete the child device directly by calling WdfObjectDelete. // status = WdfFdoAddStaticChild(Device, hChild); if (!NT_SUCCESS(status)) { goto Cleanup; } // // pDeviceInit will be freed by WDF. // return STATUS_SUCCESS; Cleanup: DebugPrint(("KbFiltr_CreatePdo failed %x\n", status)); // // Call WdfDeviceInitFree if you encounter an error while initializing // a new framework device object. If you call WdfDeviceInitFree, // do not call WdfDeviceCreate. // if (pDeviceInit != NULL) { WdfDeviceInitFree(pDeviceInit); } if(hChild) { WdfObjectDelete(hChild); } return status; }
NTSTATUS TpmEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) { NTSTATUS status = STATUS_SUCCESS; WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks; WDF_OBJECT_ATTRIBUTES DeviceAttributes; WDFDEVICE device; PTPM_CONTEXT TpmContext; WDF_IO_QUEUE_CONFIG IoQueueConfig; WDFQUEUE hQueue; WDF_QUERY_INTERFACE_CONFIG InterfaceConfig; TPM_INTERFACE_STANDARD TpmInterface; WDF_DEVICE_POWER_CAPABILITIES PowerCaps; PAGED_CODE(); UNREFERENCED_PARAMETER( Driver ); RtlZeroMemory(&PnpPowerEventCallbacks,sizeof(PnpPowerEventCallbacks)); RtlZeroMemory(&PowerCaps,sizeof(PowerCaps)); KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmEvtDeviceAdd routine PDO: %p (%p)\n", WdfDriverWdmGetDriverObject(Driver))); // // Zero out the PnpPowerCallbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerEventCallbacks); // // These two callbacks set up and tear down hardware state that must be // done every time the device moves in and out of the D0-working state. // PnpPowerEventCallbacks.EvtDeviceD0Entry = TpmEvtDeviceD0Entry; PnpPowerEventCallbacks.EvtDeviceD0Exit = TpmEvtDeviceD0Exit; // // Set Callbacks for any of the functions we are interested in. // If no callback is set, Framework will take the default action // by itself. // PnpPowerEventCallbacks.EvtDevicePrepareHardware = TpmEvtDevicePrepareHardware; PnpPowerEventCallbacks.EvtDeviceReleaseHardware = TpmEvtDeviceReleaseHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit,&PnpPowerEventCallbacks); // // Specify the context type and size for the device we are about to create. // RtlZeroMemory(&DeviceAttributes,sizeof(DeviceAttributes)); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&DeviceAttributes, TPM_CONTEXT); DeviceAttributes.Size = sizeof(WDF_OBJECT_ATTRIBUTES); DeviceAttributes.SynchronizationScope = WdfSynchronizationScopeInheritFromParent; DeviceAttributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfDeviceCreate(&DeviceInit,&DeviceAttributes,&device); if(NT_SUCCESS(status)) { TpmContext = GetTpmContext(device); RtlZeroMemory(TpmContext,sizeof(TPM_CONTEXT)); TpmContext->Device = device; TpmContext->AccessRegister = FALSE; KeInitializeSpinLock(&TpmContext->SpinLock); TpmContext->TpmState = StSuspend; TpmInitStateTable(); KeInitializeEvent(&TpmContext->Event,NotificationEvent,TRUE); status = WdfDeviceCreateDeviceInterface(device,&GUID_DEVINTERFACE_TPM,NULL); if(NT_SUCCESS(status)) { WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &IoQueueConfig, WdfIoQueueDispatchParallel ); IoQueueConfig.EvtIoDeviceControl = TpmEvtIoDeviceControl; status = WdfIoQueueCreate( device, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue ); if(NT_SUCCESS(status)) { WDF_DEVICE_POWER_CAPABILITIES_INIT(&PowerCaps); WdfDeviceSetPowerCapabilities(device,&PowerCaps); // TpmGetRegistryFlags(device,TpmContext); // RtlZeroMemory(&TpmInterface,sizeof(TpmInterface)); TpmInterface.InterfaceHeader.Size = sizeof(TpmInterface); TpmInterface.InterfaceHeader.Version = 1; TpmInterface.InterfaceHeader.Context = (PVOID)TpmContext; TpmInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; TpmInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; TpmInterface.pfn_TpmSetMorBitState = TpmSetMorBitState; // // Initialize the InterfaceConfig structure. // WDF_QUERY_INTERFACE_CONFIG_INIT( &InterfaceConfig, (PINTERFACE)&TpmInterface, &GUID_TPM_INTERFACE_STANDARD, NULL ); // // Create the interface. // status = WdfDeviceAddQueryInterface( device, &InterfaceConfig ); if(!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfDeviceAddQueryInterface failed with NTSTATUS 0x%x\n",status)); } } else { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfIoQueueCreate failed with Status code 0x%x\n",status)); } } else { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfDeviceCreateDeviceInterface failed with Status code 0x%x\n",status)); } } else { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfDeviceCreate failed with Status code 0x%x\n",status)); } KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmEvtDeviceAdd exited with Status code 0x%x\n",status)); return status; }
// 添加设备 NTSTATUS RamDiskEvtDeviceAdd(IN WDFDRIVER Driver,IN PWDFDEVICE_INIT DeviceInit) { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; //设备名 DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); //检查指定名称状态 status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } //指定设备类型 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); //IO类型 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); //是否独占 WdfDeviceInitSetExclusive(DeviceInit, FALSE); //初始化 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); //设定cleanup 函数指针 deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; //获取创建设备状态 status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (&ioQueueConfig,WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); status = WdfIoQueueCreate( device,&ioQueueConfig,&queueAttributes,&queue ); if (!NT_SUCCESS(status)) { return status; } //获得设备扩展 pQueueContext = QueueGetExtension(queue); //设置队列的设备扩展为该设备 pQueueContext->DeviceExtension = pDeviceExtension; status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } //设备初始化 pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); //从注册表获取信息 RamDiskQueryDiskRegParameters(WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)),&pDeviceExtension->DiskRegInfo); //内存分配 要使用分页内存 pDeviceExtension->DiskImage = ExAllocatePoolWithTag(PagedPool,pDeviceExtension->DiskRegInfo.DiskSize,RAMDISK_TAG); if (pDeviceExtension->DiskImage) { //成功分配 UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); //格式化 status = STATUS_SUCCESS; //创建符号链接 RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); //符号链接初始化 pDeviceExtension->SymbolicLink.Buffer = (PWSTR)&pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink,&pDeviceExtension->DiskRegInfo.DriveLetter); //创建符号链接 status = WdfDeviceCreateSymbolicLink(device,&pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS OsrFxEvtDeviceAdd( 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 a new instance of the device. All the software resources should be allocated in this callback. 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 attributes; NTSTATUS status; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_CONTEXT pDevContext; WDFQUEUE queue; GUID activity; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n"); // // 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 = OsrFxEvtDevicePrepareHardware; // // These two callbacks start and stop the wdfusb pipe continuous reader // as we go in and out of the D0-working state. // pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = OsrFxEvtDeviceD0Exit; pnpPowerCallbacks.EvtDeviceSelfManagedIoFlush = OsrFxEvtDeviceSelfManagedIoFlush; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // // Now specify the size of device extension where we track per device // context.DeviceInit is completely initialized. So call the framework // to create the device and attach it to the lower stack. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreate failed with Status code %!STATUS!\n", status); return status; } // // Setup the activity ID so that we can log events using it. // activity = DeviceToActivityId(device); // // Get the DeviceObject context by using accessor function specified in // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT. // pDevContext = GetDeviceContext(device); // // Get the device's friendly name and location so that we can use it in // error logging. If this fails then it will setup dummy strings. // GetDeviceEventLoggingNames(device); // // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermodewhen you surprise remove the device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities(device, &pnpCaps); // // Create a parallel default queue and register an event callback to // receive ioctl requests. We will create separate queues for // handling read and write requests. All other requests will be // completed with error status automatically by the framework. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoDeviceControl = OsrFxEvtIoDeviceControl; // // 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 for // long time or forward them to other drivers. // If the EvtIoStop callback is not implemented, the framework waits for // all driver-owned requests to be done before moving in the Dx/sleep // states or before removing the device, which is the correct behavior // for this type of driver. If the requests were taking an indeterminate // amount of time to complete, or if the driver forwarded the requests // to a lower driver/another stack, the queue should have an // EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);// pointer to default queue __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed %!STATUS!\n", status); goto Error; } // // We will create a separate sequential queue and configure it // to receive read requests. We also need to register a EvtIoStop // handler so that we can acknowledge requests that are pending // at the target driver. // WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoRead = OsrFxEvtIoRead; ioQueueConfig.EvtIoStop = OsrFxEvtIoStop; status = WdfIoQueueCreate( device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // queue handle ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto Error; } status = WdfDeviceConfigureRequestDispatching( device, queue, WdfRequestTypeRead); if(!NT_SUCCESS (status)){ assert(NT_SUCCESS(status)); TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status); goto Error; } // // We will create another sequential queue and configure it // to receive write requests. // WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoWrite = OsrFxEvtIoWrite; ioQueueConfig.EvtIoStop = OsrFxEvtIoStop; status = WdfIoQueueCreate( device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // queue handle ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto Error; } status = WdfDeviceConfigureRequestDispatching( device, queue, WdfRequestTypeWrite); if(!NT_SUCCESS (status)){ assert(NT_SUCCESS(status)); TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status); goto Error; } // // 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(&ioQueueConfig, 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. // ioQueueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->InterruptMsgQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%x\n", status); goto Error; } // // Register a device interface so that app can find our device and talk to it. // status = WdfDeviceCreateDeviceInterface(device, (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2, NULL); // Reference String if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", status); goto Error; } // // Create the lock that we use to serialize calls to ResetDevice(). As an // alternative to using a WDFWAITLOCK to serialize the calls, a sequential // WDFQUEUE can be created and reset IOCTLs would be forwarded to it. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfWaitLockCreate(&attributes, &pDevContext->ResetDeviceWaitLock); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfWaitLockCreate failed %!STATUS!\n", status); goto Error; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- OsrFxEvtDeviceAdd\n"); return status; Error: // // Log fail to add device to the event log // EventWriteFailAddDevice(pDevContext->DeviceName, pDevContext->Location, 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: VOID --*/ { WDFQUEUE queue; NTSTATUS status; PQUEUE_CONTEXT queueContext; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES queueAttributes; PAGED_CODE(); // // 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->Buffer = NULL; queueContext->Timer = NULL; queueContext->CurrentRequest = NULL; queueContext->CurrentStatus = STATUS_INVALID_DEVICE_REQUEST; // // Create the Queue timer // status = EchoTimerCreate(&queueContext->Timer, TIMER_PERIOD, queue); if (!NT_SUCCESS(status)) { KdPrint(("Error creating timer 0x%x\n",status)); return status; } return status; }
NTSTATUS NdisProtCreateControlDevice( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Called by the DriverEntry to create a control-device. This call is responsible for freeing the memory for DeviceInit. Arguments: Driver - a pointer to the framework object that represents this device driver. DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure. Return Value: STATUS_SUCCESS if initialized; an error otherwise. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES objectAttribs; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_FILEOBJECT_CONFIG fileConfig; WDFDEVICE controlDevice = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME) ; DECLARE_CONST_UNICODE_STRING(dosDeviceName, DOS_DEVICE_NAME) ; UNREFERENCED_PARAMETER( Driver ); DEBUGP(DL_LOUD, ("NdisProtCreateControlDevice DeviceInit %p\n", DeviceInit)); // // I/O type is Buffered by default. We want to do direct I/O for Reads // and Writes so set it explicitly. // WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { goto Error; } // // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the // framework whether you are interested in handle Create, Close and // Cleanup requests that gets genereated when an application or another // kernel component opens an handle to the device. If you don't register, // the framework default behaviour would be complete these requests // with STATUS_SUCCESS. A driver might be interested in registering these // events if it wants to do security validation and also wants to maintain // per handle (fileobject) context. // WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, NdisProtEvtDeviceFileCreate, NdisProtEvtFileClose, NdisProtEvtFileCleanup ); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttribs, FILE_OBJECT_CONTEXT); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &objectAttribs); WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); status = WdfDeviceCreate(&DeviceInit, &objectAttribs, &controlDevice); if (!NT_SUCCESS(status)) { goto Error; } // // DeviceInit is set to NULL if the device is created successfully. // // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &dosDeviceName); if (!NT_SUCCESS(status)) { goto Error; } // // Configure a default queue associated with the control device to // to receive read, write, and ioctl requests in parallel. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoWrite = NdisProtEvtIoWrite; ioQueueConfig.EvtIoRead = NdisProtEvtIoRead; ioQueueConfig.EvtIoDeviceControl = NdisProtEvtIoDeviceControl; status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { goto Error; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); // // Create our device object using which an application can // access NDIS devices. // Globals.ControlDevice = controlDevice; return status; Error: if(DeviceInit != NULL) { // // Free the WDFDEVICE_INIT structure only if the device // creation fails. Otherwise framework frees the memory // itself. // WdfDeviceInitFree(DeviceInit); } return status; }
NTSTATUS CreateQueues(WDFDEVICE Device, PDEVICE_CONTEXT Context) { NTSTATUS status = STATUS_SUCCESS; WDF_IO_QUEUE_CONFIG ioQConfig; /*Create the default IO queue. this one will be used for ioctl request entry. this queue is parallel, so as to prevent unnecessary serialization for IO requests that can be handled in parallel.*/ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQConfig, WdfIoQueueDispatchParallel); ioQConfig.EvtIoDeviceControl = EvtDeviceIoControlEntry; status = WdfIoQueueCreate(Device, &ioQConfig, WDF_NO_OBJECT_ATTRIBUTES, &Context->IoControlEntryQueue); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status)); return status; } /*Create the IO queue for serialize IO requests. This queue will be filled by the IO control entry handler with the requests that have to be serialized for execution.*/ WDF_IO_QUEUE_CONFIG_INIT(&ioQConfig, WdfIoQueueDispatchSequential); ioQConfig.EvtIoDeviceControl = EvtDeviceIoControlSerial; status = WdfIoQueueCreate(Device, &ioQConfig, WDF_NO_OBJECT_ATTRIBUTES, &Context->IoControlSerialQueue); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status)); return status; } /*Create the IO queue for write requests*/ WDF_IO_QUEUE_CONFIG_INIT(&ioQConfig, WdfIoQueueDispatchSequential); ioQConfig.EvtIoWrite = EvtDeviceIoWrite; status = WdfIoQueueCreate(Device, &ioQConfig, WDF_NO_OBJECT_ATTRIBUTES, &Context->IoWriteQueue); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status)); return status; } status = WdfDeviceConfigureRequestDispatching(Device, Context->IoWriteQueue, WdfRequestTypeWrite); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfDeviceConfigureRequestDispatching failed with status 0x%08x\n", status)); return status; } /*Create the IO queue for read requests*/ WDF_IO_QUEUE_CONFIG_INIT(&ioQConfig, WdfIoQueueDispatchSequential); ioQConfig.EvtIoRead = EvtDeviceIoRead; status = WdfIoQueueCreate(Device, &ioQConfig, WDF_NO_OBJECT_ATTRIBUTES, &Context->IoReadQueue); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status)); return status; } status = WdfDeviceConfigureRequestDispatching(Device, Context->IoReadQueue, WdfRequestTypeRead); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfDeviceConfigureRequestDispatching failed with status 0x%08x\n", status)); return status; } /*Create a manual queue for storing the IOCTL_WDF_USB_GET_SWITCHSTATE_CHANGE IO control requests. If a file handle associated with one or more requests in the queue is closed, the requests themselves are automatically removed from the queue by the framework and cancelled.*/ WDF_IO_QUEUE_CONFIG_INIT(&ioQConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(Device, &ioQConfig, WDF_NO_OBJECT_ATTRIBUTES, &Context->SwitchChangeRequestQueue); if(!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME "WdfIoQueueCreate for manual queue failed with status 0x%08x\n", status)); return 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 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; }
static NTSTATUS UsbChief_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fileObjectAttributes, requestAttributes, fdoAttributes; WDF_FILEOBJECT_CONFIG fileConfig; NTSTATUS Status; WDFDEVICE device; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDFQUEUE queue; UNICODE_STRING linkname; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); UsbChief_DbgPrint(DEBUG_CONFIG, ("ExtDeviceAdd\n")); /* Init PnP */ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = UsbChief_EvtDevicePrepareHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); /* Request Attributes */ WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes); /* Fileobject init */ WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, UsbChief_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK); WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes, FILE_CONTEXT); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes); WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, DEVICE_CONTEXT); Status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfDeviceCreate: %08x\n", Status)); return Status; } RtlInitUnicodeString(&linkname, L"\\DosDevices\\ChiefUSB"); Status = WdfDeviceCreateSymbolicLink(device, &linkname); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfDeviceCreateSymbolicLink: %08x\n", Status)); goto out; } WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities(device, &pnpCaps); /* Register I/O callbacks */ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoRead = UsbChief_EvtIoRead; ioQueueConfig.EvtIoWrite = UsbChief_EvtIoWrite; ioQueueConfig.EvtIoDeviceControl = UsbChief_EvtIoDeviceControl; ioQueueConfig.EvtIoStop = UsbChief_EvtIoStop; ioQueueConfig.EvtIoResume = UsbChief_EvtIoResume; Status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfIoQueueCreate: %08x\n", Status)); goto out; } Status = WdfDeviceCreateDeviceInterface(device, (LPGUID)&GUID_CLASS_USBCHIEF_USB, NULL); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfDeviceCreateDeviceInterface: %08x\n", Status)); goto out; } UsbChief_DbgPrint(3, ("EvtDriverDeviceAdd successful\n")); return STATUS_SUCCESS; out: 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; }
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_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status; WDFDEVICE device; PFDO_DEVICE_DATA deviceData; PNP_BUS_INFORMATION busInfo; 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); // // Initialize attributes structure to specify size and accessor function // for storing device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA); // // Create a framework device object. In response to this call, framework // creates a WDM deviceobject. // status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Get the device context. // deviceData = FdoGetData(device); WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; // // Purpose of this lock is documented in Bus_PlugInDevice routine below. // status = WdfWaitLockCreate(&attributes, &deviceData->ChildLock); if (!NT_SUCCESS(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 with status 0x%x\n", status)); return status; } // // Create device interface for this device. The interface will be // enabled by the framework when we return from StartDevice successfully. // status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_BUSENUM_TOASTER, NULL // No Reference String ); 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; } status = Bus_DoStaticEnumeration(device); return status; }
NTSTATUS VioCryptDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDFDEVICE device; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES attributes; WDFQUEUE queue; WDF_IO_QUEUE_CONFIG queueConfig; WDF_INTERRUPT_CONFIG interruptConfig; PDEVICE_CONTEXT context; UNREFERENCED_PARAMETER(Driver); Trace(TRACE_LEVEL_VERBOSE, "[%s] -->", __FUNCTION__); PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = VioCryptDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = VioCryptDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = VioCryptDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = VioCryptDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); attributes.EvtCleanupCallback = VioCryptDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceCreate failed: status %X", __FUNCTION__, status); return status; } context = GetDeviceContext(device); RtlZeroMemory(context, sizeof(*context)); InitializeListHead(&context->PendingBuffers); WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, VioCryptInterruptIsr, VioCryptInterruptDpc); interruptConfig.EvtInterruptEnable = VioCryptInterruptEnable; interruptConfig.EvtInterruptDisable = VioCryptInterruptDisable; status = WdfInterruptCreate(device, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &context->WdfInterrupt); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfInterruptCreate failed: status %X", __FUNCTION__, status); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfSpinLockCreate(&attributes, &context->VirtQueueLock); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfSpinLockCreate failed: status %X", __FUNCTION__, status); return status; } status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_VIOCRYPT, NULL); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceCreateDeviceInterface failed: status %X", __FUNCTION__, status); return status; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoDeviceControl = VioCryptIoControl; queueConfig.EvtIoStop = VioCryptIoStop; queueConfig.AllowZeroLengthRequests = FALSE; status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfIoQueueCreate failed: status %X", __FUNCTION__, status); return status; } status = WdfDeviceConfigureRequestDispatching(device, queue, WdfRequestTypeDeviceControl); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "[%s] WdfDeviceConfigureRequestDispatching failed: status %X", __FUNCTION__, status); return status; } Trace(TRACE_LEVEL_VERBOSE, "[%s] <--", __FUNCTION__); return status; }
NTSTATUS VIOSerialDeviceListCreatePdo( IN WDFCHILDLIST DeviceList, IN PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, IN PWDFDEVICE_INIT ChildInit ) { PVIOSERIAL_PORT pport = NULL; NTSTATUS status = STATUS_SUCCESS; WDFDEVICE hChild = NULL; WDF_OBJECT_ATTRIBUTES attributes; WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_DEVICE_STATE deviceState; WDF_IO_QUEUE_CONFIG queueConfig; PRAWPDO_VIOSERIAL_PORT rawPdo = NULL; WDF_FILEOBJECT_CONFIG fileConfig; DECLARE_CONST_UNICODE_STRING(deviceId, PORT_DEVICE_ID ); DECLARE_CONST_UNICODE_STRING(deviceLocation, L"RedHat VIOSerial Port" ); DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH); UNREFERENCED_PARAMETER(DeviceList); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); pport = CONTAINING_RECORD(IdentificationDescription, VIOSERIAL_PORT, Header ); WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_SERIAL_PORT); WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect); do { WdfDeviceInitSetExclusive(ChildInit, TRUE); status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_PORT_DEVICE); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignRawDevice failed - 0x%x\n", status); break; } status = WdfDeviceInitAssignSDDLString(ChildInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceInitAssignSDDLString failed - 0x%x\n", status); break; } status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignDeviceID failed - 0x%x\n", status); break; } status = WdfPdoInitAddHardwareID(ChildInit, &deviceId); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAddHardwareID failed - 0x%x\n", status); break; } status = RtlUnicodeStringPrintf( &buffer, L"%02u", pport->PortId ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed - 0x%x\n", status); break; } status = WdfPdoInitAssignInstanceID(ChildInit, &buffer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignInstanceID failed - 0x%x\n", status); break; } status = RtlUnicodeStringPrintf( &buffer, L"vport%up%u", pport->DeviceId, pport->PortId ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed 0x%x\n", status); break; } status = WdfPdoInitAddDeviceText( ChildInit, &buffer, &deviceLocation, 0x409 ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAddDeviceText failed 0x%x\n", status); break; } WdfPdoInitSetDefaultLocale(ChildInit, 0x409); WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, VIOSerialPortCreate, VIOSerialPortClose, WDF_NO_EVENT_CALLBACK ); WdfDeviceInitSetFileObjectConfig( ChildInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES ); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks); PnpPowerCallbacks.EvtDeviceD0Entry = VIOSerialPortEvtDeviceD0Entry; PnpPowerCallbacks.EvtDeviceD0Exit = VIOSerialPortEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT); attributes.SynchronizationScope = WdfSynchronizationScopeDevice; attributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfDeviceCreate( &ChildInit, &attributes, &hChild ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreate failed 0x%x\n", status); break; } rawPdo = RawPdoSerialPortGetData(hChild); rawPdo->port = pport; pport->Device = hChild; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential ); queueConfig.EvtIoDeviceControl = VIOSerialPortDeviceControl; status = WdfIoQueueCreate(hChild, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pport->IoctlQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed (IoCtrl Queue): 0x%x\n", status); break; } status = WdfDeviceConfigureRequestDispatching( hChild, pport->IoctlQueue, WdfRequestTypeDeviceControl ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "DeviceConfigureRequestDispatching failed (IoCtrl Queue): 0x%x\n", status); break; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoRead = VIOSerialPortRead; queueConfig.EvtIoStop = VIOSerialPortIoStop; status = WdfIoQueueCreate(hChild, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pport->ReadQueue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate (Read Queue) failed 0x%x\n", status); break; } status = WdfDeviceConfigureRequestDispatching( hChild, pport->ReadQueue, WdfRequestTypeRead ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "DeviceConfigureRequestDispatching failed (Read Queue): 0x%x\n", status); break; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.AllowZeroLengthRequests = WdfFalse; queueConfig.EvtIoWrite = VIOSerialPortWrite; status = WdfIoQueueCreate(hChild, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pport->WriteQueue); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed (Write Queue): 0x%x\n", status); break; } status = WdfDeviceConfigureRequestDispatching( hChild, pport->WriteQueue, WdfRequestTypeWrite ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "DeviceConfigureRequestDispatching failed (Write Queue): 0x%x\n", status); break; } WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.NoDisplayInUI = WdfTrue; pnpCaps.Removable = WdfTrue; pnpCaps.EjectSupported = WdfTrue; pnpCaps.SurpriseRemovalOK= WdfTrue; pnpCaps.Address = pport->DeviceId; pnpCaps.UINumber = pport->PortId; WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); WDF_DEVICE_STATE_INIT(&deviceState); deviceState.DontDisplayInUI = WdfTrue; WdfDeviceSetDeviceState(hChild, &deviceState); status = WdfDeviceCreateDeviceInterface( hChild, &GUID_VIOSERIAL_PORT, NULL ); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreateDeviceInterface failed 0x%x\n", status); break; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hChild; status = WdfSpinLockCreate( &attributes, &pport->InBufLock ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfSpinLockCreate failed 0x%x\n", status); break; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = hChild; status = WdfSpinLockCreate( &attributes, &pport->OutVqLock ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfSpinLockCreate failed 0x%x\n", status); break; } } while (0); if (!NT_SUCCESS(status)) { // We can send this before PDO is PRESENT since the device won't send any response. VIOSerialSendCtrlMsg(pport->BusDevice, pport->PortId, VIRTIO_CONSOLE_PORT_READY, 0); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s status 0x%x\n", __FUNCTION__, status); return status; }
NTSTATUS t1394_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. 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; PDEVICE_EXTENSION deviceExtension; PNODE_DEVICE_EXTENSION pNodeExt; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fdoAttributes,lockAttributes; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_IO_TARGET_OPEN_PARAMS openParams; //UNREFERENCED_PARAMETER(Driver); //ENTER("t1394_PnpAddDevice"); // // Zero out the PnpPowerCallbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Set Callbacks for any of the functions we are interested in. // If no callback is set, Framework will take the default action // by itself. // // These two callbacks set up and tear down hardware state, // specifically that which only has to be done once. // pnpPowerCallbacks.EvtDevicePrepareHardware = t1394_EvtPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = t1394_EvtReleaseHardware; pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = t1394_EvtDeviceSelfManagedIoCleanup; pnpPowerCallbacks.EvtDeviceD0Entry = t1394_EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = t1394_EvtDeviceD0Exit; // // Register the PnP and power callbacks. Power policy related callbacks // will be registered// later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); if ( !NT_SUCCESS(status)) { //TRACE(TL_ERROR, ("WdfDeviceInitSetPnpPowerEventCallbacks failed %x\n", // status)); return status; } WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Specify the size and type of device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, DEVICE_EXTENSION); status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if ( !NT_SUCCESS(status)) { //TRACE(TL_ERROR, ("WdfDeviceInitialize failed %x\n", status)); return status; } deviceExtension = GetDeviceContext (device); deviceExtension->WdfDevice = device; //TRACE(TL_TRACE, ("PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n", // WdfDeviceWdmGetPhysicalDevice (device), // WdfDeviceWdmGetDeviceObject (device), // WdfDeviceWdmGetAttachedDevice(device), // deviceExtension)); // // Tell the Framework that this device will need an interface so that // application can interact with it. // status = WdfDeviceCreateDeviceInterface( device, #if defined(_1394VDEV_DRIVER_) (LPGUID) &GUID_1394VDEV, #else (LPGUID) &GUID_1394DIAG, #endif NULL ); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfDeviceCreateDeviceInterface failed %x\n", status)); return status; } // // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermode (on Win2K) when you surprise // remove the device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities(device, &pnpCaps); // save the device object we created as our physical device object deviceExtension->PhysicalDeviceObject = WdfDeviceWdmGetPhysicalDevice (device); if (deviceExtension->PhysicalDeviceObject == NULL) { //TRACE(TL_ERROR, ("WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n")); return STATUS_UNSUCCESSFUL; } // // This is our default IoTarget representing the deviceobject // we are attached to. // deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device); deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device); if (deviceExtension->StackDeviceObject == NULL) { //TRACE(TL_ERROR, ("WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n")); return STATUS_UNSUCCESSFUL; } // Patch: this code is not in DDK 7600.16385.1 { // // Get the port device object from the passed in PhysicalDeviceObject // created by the 1394 stack for us. // Note: we can't use the top of the stack and get its device extension // in case there is a filter driver between us and our PDO. // //pNodeExt = WdfDeviceWdmGetPhysicalDevice(device)->DeviceExtension; //deviceExtension->PortDeviceObject = pNodeExt->PortDeviceObject; // Patch: this code is not in DDK 7600.16385.1 } //TRACE(TL_TRACE, ("PortDeviceObject = 0x%x\n", // deviceExtension->PortDeviceObject)); // // Create a automanaged queue for dispatching ioctl requests. // All other requests are automatically failed by the framework. // By creating an automanaged queue we don't have to worry about // PNP/Power synchronization. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &ioQueueConfig, WdfIoQueueDispatchParallel ); ioQueueConfig.EvtIoDeviceControl = t1394_EvtIoDeviceControl; status = WdfIoQueueCreate( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->IoctlQueue // queue handle ); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // // Create an additional queue to hold bus reset requests. // WDF_IO_QUEUE_CONFIG_INIT( &ioQueueConfig, WdfIoQueueDispatchManual ); status = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->BusResetRequestsQueue ); if(!NT_SUCCESS (status)){ //TRACE(TL_ERROR, ("Error Creating Reset Request Queue 0x%x\n", // status)); return status; } // // Create another IoTarget representing PortDeviceObject so that // we can send async requests in rawmode directly to the port device. // WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(&openParams, pNodeExt->PortDeviceObject); status = WdfIoTargetCreate(device, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->PortDeviceIoTarget); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfIoTargetCreate failed 0x%x\n", status)); return status; } status = WdfIoTargetOpen(deviceExtension->PortDeviceIoTarget, &openParams); if (!NT_SUCCESS (status)) { //TRACE(TL_ERROR, ("WdfIoTargetCreate failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; // initialize the spinlock/list to store the bus reset irps... status = WdfSpinLockCreate(&lockAttributes,&deviceExtension->CromSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate CromSpinLock " // "failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; status = WdfSpinLockCreate(&lockAttributes, &deviceExtension->AsyncSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate AsyncSpinLock " // "failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; status = WdfSpinLockCreate(&lockAttributes, &deviceExtension->IsochSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate IsochSpinLock " // "failed 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes); lockAttributes.ParentObject = device; status = WdfSpinLockCreate(&lockAttributes, &deviceExtension->IsochResourceSpinLock ); if(!NT_SUCCESS(status)){ //TRACE(TL_ERROR, ("WdfSpinLockCreate IsochResourceSpinLock " // "failed 0x%x\n", status)); return status; } InitializeListHead(&deviceExtension->CromData); InitializeListHead(&deviceExtension->AsyncAddressData); InitializeListHead(&deviceExtension->IsochDetachData); InitializeListHead(&deviceExtension->IsochResourceData); //EXIT("t1394_PnpAddDevice", status); return(status); } // t1394_PnpAddDevice
_Use_decl_annotations_ NTSTATUS OnDeviceAdd( WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: OnDeviceAdd 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: Status --*/ { PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES objectAttributes; PDEVICE_CONTEXT deviceContext; WDFDEVICE device; NTSTATUS status; DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128); // // Set PnP callbacks. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = PrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = ReleaseHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // PWM only allows exclusive access. // WdfDeviceInitSetExclusive(DeviceInit, TRUE); // // Create device object. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, DEVICE_CONTEXT); objectAttributes.EvtCleanupCallback = OnDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create device (0x%08x)", status); goto Exit; } deviceContext = GetContext(device); // // Prepare config spin lock. // WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); status = WdfSpinLockCreate(&objectAttributes, &deviceContext->pwmLock); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create config spin lock (0x%08x)", status); goto Exit; } // // Prepare notification list spin lock. // WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); status = WdfSpinLockCreate(&objectAttributes, &deviceContext->notificationListLock); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create notification list spin lock (0x%08x)", status); goto Exit; } // // Prepare interrupt object. // WDF_INTERRUPT_CONFIG interruptConfig; WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, DmaIsr, DmaDpc ); status = WdfInterruptCreate( device, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceContext->interruptObj ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create interrupt object (0x%08x)", status); goto Exit; } // // Create queues to handle IO. // WDF_IO_QUEUE_CONFIG queueConfig; WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = OnIoDeviceControl; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceContext->queueObj ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create IO queue (0x%08x)", status); goto Exit; } // // Create a symbolic link. // status = RtlUnicodeStringInit(&symbolicLinkName, BCM_PWM_SYMBOLIC_NAME); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not process the symbolic name (0x%08x)", status); goto Exit; } status = WdfDeviceCreateSymbolicLink( device, &symbolicLinkName ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create a symbolic name (0x%08x)", status); goto Exit; } 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 EvtDriverDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) { NTSTATUS status; WDFDEVICE device; // 设备对象 WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_FILEOBJECT_CONFIG fileConfig; PAGED_CODE(); // 互斥访问,同时刻只能一个应用程序与设备通信 WdfDeviceInitSetExclusive(DeviceInit, TRUE); // 缓冲IO方式 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // 初始化文件对象 WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, EvtDeviceFileCreate, EvtFileClose, WDF_NO_EVENT_CALLBACK); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); // 创建设备 status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &device); if( !NT_SUCCESS(status) ) { KdPrint(("[EvtDriverDeviceAdd] WdfDeviceCreate failed!")); return status; } //使用缺省队列,设置I/O请求分发处理方式为串行 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); // 设置EvtIoRead回调例程 ioQueueConfig.EvtIoRead = EvtIoRead; // 设置EvtIoWrite回调例程 ioQueueConfig.EvtIoWrite = EvtIoWrite; //设置EvtIoDeviceControl回调例程 ioQueueConfig.EvtIoDeviceControl = EvtIoDeviceControl; // 创建队列 status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE); if( !NT_SUCCESS(status) ) { KdPrint(("[EvtDriverDeviceAdd] WdfIoQueueCreate failed!")); return status; } // 创建设备接口 status = WdfDeviceCreateDeviceInterface(device,(LPGUID)&IOSample_DEVINTERFACE_GUID ,NULL); if( !NT_SUCCESS(status) ) { KdPrint(("[EvtDriverDeviceAdd] WdfDeviceCreateDeviceInterface failed!")); } return status; }
NTSTATUS FmEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: FmEvtDeviceAdd 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 Fm 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; PFM_DEVICE_DATA fmDeviceData; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDFDEVICE hDevice; WDFQUEUE defQueue; UNREFERENCED_PARAMETER(Driver); KdPrint( ("FmEvtDeviceAdd routine \n")); PAGED_CODE(); // // Modem type is serial port. // WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SERIAL_PORT); // // Use Buffered IO. // WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // // Specify the size of device extension where we track per device // context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FM_DEVICE_DATA); // // Register a cleanup callback on the device to free up some resources at the // time the device is deleted. // fdoAttributes.EvtCleanupCallback = FmDeviceCleanup; // // By opting for SynchronizationScopeDevice, we tell the framework to // synchronize callbacks events of all the objects directly associated // with the device. In this driver, we will associate queues. // By doing that we don't have to worrry about synchronizing // access to device-context by various io Events. // Framework will serialize them by using an internal device-lock. // fdoAttributes.SynchronizationScope = WdfSynchronizationScopeDevice; // // 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, &fdoAttributes, &hDevice); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with Status code 0x%x\n", status)); return status; } // // Get the DeviceExtension and initialize it. // fmDeviceData = FmDeviceDataGet(hDevice); // // Tell the Framework that this device will need an interface // status = WdfDeviceCreateDeviceInterface( hDevice, (LPGUID) &GUID_DEVINTERFACE_MODEM, NULL ); if (!NT_SUCCESS (status)) { KdPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); return status; } fmDeviceData->Flags = 0; status = FmCreateDosDevicesSymbolicLink(hDevice, fmDeviceData); if (!NT_SUCCESS(status)) { KdPrint( ("FmCreateDosDevicesSymbolicLink failed with Status code 0x%x\n", status)); return status; } // // Initialize the context // fmDeviceData->BaudRate=1200; fmDeviceData->LineControl = SERIAL_7_DATA | SERIAL_EVEN_PARITY | SERIAL_NONE_PARITY; // // Register I/O callbacks to tell the framework that you are interested // in handling IRP_MJ_READ, IRP_MJ_WRITE, and IRP_MJ_DEVICE_CONTROL requests. // In case a specific handler is not specified for one of these, // the request will be dispatched to the EvtIoDefault handler, if any. // If there is no EvtIoDefault handler, the request will be failed with // STATUS_INVALID_DEVICE_REQUEST. // WdfIoQueueDispatchParallel means that we are capable of handling // all the I/O request simultaneously and we are responsible for protecting // data that could be accessed by these callbacks simultaneously. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoRead = FmEvtIoRead; queueConfig.EvtIoWrite = FmEvtIoWrite; queueConfig.EvtIoDeviceControl = FmEvtIoDeviceControl; __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate( hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &defQueue // pointer to default queue ); __analysis_assume(queueConfig.EvtIoStop == 0); if (!NT_SUCCESS (status)) { // // We don't need to cleanup symbolic link here. The destroy callback for // the device object will do it. // return status; } // // Create a manual queue to hold pending read requests. By keeping // them in the queue, framework takes care of cancelling them if the app exits // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &fmDeviceData->FmReadQueue ); __analysis_assume(queueConfig.EvtIoStop == 0); if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } // // Create a manual queue to hold pending ioctl wait mask requests. By keeping // them in the queue, framework takes care of cancelling them if the app exits // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &fmDeviceData->FmMaskWaitQueue ); __analysis_assume(queueConfig.EvtIoStop == 0); if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
NTSTATUS NonPnpDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Called by the DriverEntry to create a control-device. This call is responsible for freeing the memory for DeviceInit. Arguments: DriverObject - a pointer to the object that represents this device driver. DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure. Return Value: STATUS_SUCCESS if initialized; an error otherwise. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_FILEOBJECT_CONFIG fileConfig; WDFQUEUE queue; WDFDEVICE controlDevice; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; UNREFERENCED_PARAMETER( Driver ); PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpDeviceAdd DeviceInit %p\n", DeviceInit); // // Set exclusive to TRUE so that no more than one app can talk to the // control device at any time. // WdfDeviceInitSetExclusive(DeviceInit, TRUE); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceInitAssignName failed %!STATUS!", status); goto End; } WdfControlDeviceInitSetShutdownNotification(DeviceInit, NonPnpShutdown, WdfDeviceShutdown); // // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the // framework whether you are interested in handling Create, Close and // Cleanup requests that gets generated when an application or another // kernel component opens an handle to the device. If you don't register // the framework default behaviour would be to complete these requests // with STATUS_SUCCESS. A driver might be interested in registering these // events if it wants to do security validation and also wants to maintain // per handle (fileobject) context. // WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, NonPnpEvtDeviceFileCreate, NonPnpEvtFileClose, WDF_NO_EVENT_CALLBACK // not interested in Cleanup ); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); // // In order to support METHOD_NEITHER Device controls, or // NEITHER device I/O type, we need to register for the // EvtDeviceIoInProcessContext callback so that we can handle the request // in the calling threads context. // WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, NonPnpEvtDeviceIoInCallerContext); // // Specify the size of device context // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CONTROL_DEVICE_EXTENSION); status = WdfDeviceCreate(&DeviceInit, &attributes, &controlDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed %!STATUS!", status); goto End; } // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { // // Control device will be deleted automatically by the framework. // TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed %!STATUS!", status); goto End; } // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoRead = FileEvtIoRead; ioQueueConfig.EvtIoWrite = FileEvtIoWrite; ioQueueConfig.EvtIoDeviceControl = FileEvtIoDeviceControl; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); // // Since we are using Zw function set execution level to passive so that // framework ensures that our Io callbacks called at only passive-level // even if the request came in at DISPATCH_LEVEL from another driver. // //attributes.ExecutionLevel = WdfExecutionLevelPassive; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, &attributes, &queue // pointer to default queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed %!STATUS!", status); goto End; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); End: // // If the device is created successfully, framework would clear the // DeviceInit value. Otherwise device create must have failed so we // should free the memory ourself. // if (DeviceInit != NULL) { WdfDeviceInitFree(DeviceInit); } return status; }
NTSTATUS kmdf1394_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. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fdoAttributes,lockAttributes; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; UNREFERENCED_PARAMETER (Driver); PAGED_CODE(); Enter(); // // Zero out the PnpPowerCallbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Set Callbacks for any of the functions we are interested in. // If no callback is set, Framework will take the default action // by itself. // // These two callbacks set up and tear down hardware state, // specifically that which only has to be done once. // pnpPowerCallbacks.EvtDevicePrepareHardware = kmdf1394_EvtPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = kmdf1394_EvtReleaseHardware; pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = \ kmdf1394_EvtDeviceSelfManagedIoCleanup; pnpPowerCallbacks.EvtDeviceD0Entry = kmdf1394_EvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = kmdf1394_EvtDeviceD0Exit; // // Register the PnP and power callbacks. Power policy related callbacks // will be registered// later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks (DeviceInit, &pnpPowerCallbacks); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n", ntStatus); return ntStatus; } // // We'll allow multiple handles to be opened to this device driver // so we'll set exclusivity to FALSE. // WdfDeviceInitSetExclusive (DeviceInit, FALSE); // // Specify the size and type of device context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (&fdoAttributes, DEVICE_EXTENSION); ntStatus = WdfDeviceCreate (&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceInitialize failed %!STATUS!\n", ntStatus); return ntStatus; } deviceExtension = GetDeviceContext (device); deviceExtension->WdfDevice = device; DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n", WdfDeviceWdmGetPhysicalDevice (device), WdfDeviceWdmGetDeviceObject (device), WdfDeviceWdmGetAttachedDevice(device), deviceExtension); // // Tell the Framework that this device will need an interface so that // application can interact with it. // ntStatus = WdfDeviceCreateDeviceInterface ( device, (LPGUID) &GUID_KMDF_VDEV, NULL); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", ntStatus); return ntStatus; } // // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermode (on Win2K) when you surprise // remove the device. // WDF_DEVICE_PNP_CAPABILITIES_INIT (&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities (device, &pnpCaps); // // save the device object we created as our physical device object // deviceExtension->PhysicalDeviceObject = \ WdfDeviceWdmGetPhysicalDevice (device); if (NULL == deviceExtension->PhysicalDeviceObject) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n"); return STATUS_UNSUCCESSFUL; } // // This is our default IoTarget representing the deviceobject // we are attached to. // deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device); deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device); if (NULL == deviceExtension->StackDeviceObject) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n"); return STATUS_UNSUCCESSFUL; } // // Create a automanaged queue for dispatching ioctl requests. // All other requests are automatically failed by the framework. // By creating an automanaged queue we don't have to worry about // PNP/Power synchronization. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoDeviceControl = kmdf1394_EvtIoDeviceControl; __analysis_assume(ioQueueConfig.EvtIoStop != 0); ntStatus = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->IoctlQueue); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfIoQueueCreate failed %!STATUS!\n", ntStatus); return ntStatus; } // // Create an additional queue to hold bus reset requests. // WDF_IO_QUEUE_CONFIG_INIT (&ioQueueConfig, WdfIoQueueDispatchManual); __analysis_assume(ioQueueConfig.EvtIoStop != 0); ntStatus = WdfIoQueueCreate ( deviceExtension->WdfDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceExtension->BusResetRequestsQueue); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "Error Creating Reset Request Queue %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate (&lockAttributes,&deviceExtension->CromSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate CromSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->AsyncSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate AsyncSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->IsochSpinLock ); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate IsochSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes); lockAttributes.ParentObject = device; ntStatus = WdfSpinLockCreate ( &lockAttributes, &deviceExtension->IsochResourceSpinLock); if(!NT_SUCCESS (ntStatus)) { DoTraceLevelMessage(TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "WdfSpinLockCreate IsochResourceSpinLock failed %!STATUS!\n", ntStatus); return ntStatus; } InitializeListHead (&deviceExtension->CromData); InitializeListHead (&deviceExtension->AsyncAddressData); InitializeListHead (&deviceExtension->IsochDetachData); InitializeListHead (&deviceExtension->IsochResourceData); ExitS(ntStatus); return(ntStatus); } // kmdf1394_PnpAddDevice
NTSTATUS MarsEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. 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; PFDO_DATA fdoData; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDFDEVICE device; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; SDBUS_INTERFACE_PARAMETERS interfaceParameters = {0}; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); WdfDeviceInitSetPowerPageable(DeviceInit); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Register PNP callbacks. // pnpPowerCallbacks.EvtDevicePrepareHardware = MarsEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = MarsEvtDeviceReleaseHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, FDO_DATA); status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS(status)) { return status; } fdoData = MarsFdoGetData(device); //Gets device context // // Open an interface to the SD bus driver // status = SdBusOpenInterface(WdfDeviceWdmGetPhysicalDevice (device), &fdoData->BusInterface, sizeof(SDBUS_INTERFACE_STANDARD), SDBUS_INTERFACE_VERSION); if (!NT_SUCCESS(status)) { return status; } interfaceParameters.Size = sizeof(SDBUS_INTERFACE_PARAMETERS); interfaceParameters.TargetObject = WdfDeviceWdmGetAttachedDevice(device); interfaceParameters.DeviceGeneratesInterrupts = TRUE; //change to true eventually interfaceParameters.CallbackRoutine = MarsEventCallback; interfaceParameters.CallbackRoutineContext = fdoData; status = STATUS_UNSUCCESSFUL; if (fdoData->BusInterface.InitializeInterface) { status = (fdoData->BusInterface.InitializeInterface)(fdoData->BusInterface.Context, &interfaceParameters); } if (!NT_SUCCESS(status)) { return status; } // // Register New device // status = WdfDeviceCreateDeviceInterface(device, (LPGUID) &GUID_DEVINTERFACE_MARS, NULL ); if (!NT_SUCCESS(status)) { return status; } fdoData->WdfDevice = device; WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoRead = MarsEvtIoRead; queueConfig.EvtIoWrite = MarsEvtIoWrite; queueConfig.EvtIoDeviceControl = MarsEvtIoDeviceControl; status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &fdoData->IoctlQueue ); return status; }
NTSTATUS ToasterEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: ToasterEvtDeviceAdd 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; PFDO_DATA fdoData; WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDFDEVICE hDevice; WDFQUEUE queue; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); KdPrint(("ToasterEvtDeviceAdd called\n")); // // Initialize attributes and a context area for the device object. // // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, FDO_DATA); // // 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, &fdoAttributes, &hDevice); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with status code 0x%x\n", status)); return status; } // // Get the device context by using the accessor function specified in // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for FDO_DATA. // fdoData = ToasterFdoGetData(hDevice); // // Tell the Framework that this device will need an interface // status = WdfDeviceCreateDeviceInterface( hDevice, (LPGUID) &GUID_DEVINTERFACE_TOASTER, NULL // ReferenceString ); if (!NT_SUCCESS (status)) { KdPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); return status; } // // Register I/O callbacks to tell the framework that you are interested // in handling IRP_MJ_READ, IRP_MJ_WRITE, and IRP_MJ_DEVICE_CONTROL requests. // If a specific callback function is not specified for one ofthese, // the request will be dispatched to the EvtIoDefault handler, if any. // If there is no EvtIoDefault handler, the request will be failed with // STATUS_INVALID_DEVICE_REQUEST. // WdfIoQueueDispatchParallel means that we are capable of handling // all the I/O requests simultaneously and we are responsible for protecting // data that could be accessed by these callbacks simultaneously. // A default queue gets all the requests that are not // configured for forwarding using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoRead = ToasterEvtIoRead; queueConfig.EvtIoWrite = ToasterEvtIoWrite; queueConfig.EvtIoDeviceControl = ToasterEvtIoDeviceControl; status = WdfIoQueueCreate( hDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); if (!NT_SUCCESS (status)) { KdPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); return status; } return status; }
NTSTATUS RamDiskEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of the device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); // // Storage drivers have to name their FDOs. Since we are not unique'fying // the device name, we wouldn't be able to install more than one instance // of this ramdisk driver. // status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Since this is a pure software only driver, there is no need to register // any PNP/Power event callbacks. Framework will respond to these // events appropriately. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Now that the WDF device object has been created, set up any context // that it requires. // pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchSequential ); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate( device, &ioQueueConfig, &queueAttributes, &queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { return status; } // Context is the Queue handle pQueueContext = QueueGetExtension(queue); // // Set the context for our default queue as our device extension. // pQueueContext->DeviceExtension = pDeviceExtension; #if KMDF_VERSION_MINOR >= 9 // // Enable forward progress on the queue we just created. // NOTE: If you are planning to use this code without forward progress, // comment out the call to SetForwardProgressOnQueue below. // status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } #endif // // Now do any RAM-Disk specific initialization // pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); // // Get the disk parameters from the registry // RamDiskQueryDiskRegParameters( WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)), &pDeviceExtension->DiskRegInfo ); // // Allocate memory for the disk image. // pDeviceExtension->DiskImage = ExAllocatePoolWithTag( NonPagedPool, pDeviceExtension->DiskRegInfo.DiskSize, RAMDISK_TAG ); if (pDeviceExtension->DiskImage) { UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); status = STATUS_SUCCESS; // // Now try to create a symbolic link for the drive letter. // RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); pDeviceExtension->SymbolicLink.Buffer = (PWSTR) &pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink, &pDeviceExtension->DiskRegInfo.DriveLetter); status = WdfDeviceCreateSymbolicLink(device, &pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS SingleCompEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the KMDF in response to AddDevice call from the PnP manager. Arguments: Driver - Handle to the KMDF 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; WDF_IO_QUEUE_CONFIG queueConfig; FDO_DATA *fdoContext = NULL; ULONG queueIndex = 0; WDF_OBJECT_ATTRIBUTES objectAttributes; WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; PAGED_CODE(); 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 three power-managed queues, one each for read, write and IOCTL // requests. The handles to these power-managed queues are stored in an // array in the device object context space. When the component becomes idle // we need to stop our power-managed queues. When the component becomes // active we need to start them. In those situations, we go through this // array of power-managed queues and stop or start each queue as // appropriate. Handles to non-power-managed queues should not be stored in // this array. // 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, &(fdoContext->Queues[queueIndex])); __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, fdoContext->Queues[queueIndex], WdfRequestTypeDeviceControl); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeDeviceControl failed with %!status!.", status); goto exit; } ++queueIndex; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoRead = SingleCompEvtIoRead; // // 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, &(fdoContext->Queues[queueIndex])); __analysis_assume(queueConfig.EvtIoStop == 0); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfIoQueueCreate for IoRead failed with %!status!.", status); goto exit; } status = WdfDeviceConfigureRequestDispatching(device, fdoContext->Queues[queueIndex], WdfRequestTypeRead); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeRead failed with %!status!.", status); goto exit; } ++queueIndex; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoWrite = SingleCompEvtIoWrite; // // 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, &(fdoContext->Queues[queueIndex])); __analysis_assume(queueConfig.EvtIoStop == 0); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfIoQueueCreate for IoWrite failed with %!status!.", status); goto exit; } status = WdfDeviceConfigureRequestDispatching(device, fdoContext->Queues[queueIndex], WdfRequestTypeWrite); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeWrite failed with %!status!.", status); goto exit; } ++queueIndex; ASSERT(queueIndex == QUEUE_COUNT); status = AssignS0IdleSettings(device); if (!NT_SUCCESS(status)) { goto exit; } // // If you need to talk to hardware to figure out what F-states are // applicable this can be done in EvtSelfManagedIoInit // (but no later than that). EvtSelfManagedIoInit gets invoked after // EvtPrepareHardware so you'd have chance to initialize your hardware. // status = AssignPowerFrameworkSettings(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; }
/*++ 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. All the software resources should be allocated in this callback. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ NTSTATUS PSDrv_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { WDF_FILEOBJECT_CONFIG fileConfig; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDF_OBJECT_ATTRIBUTES fileObjectAttributes; WDF_OBJECT_ATTRIBUTES requestAttributes; NTSTATUS status; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_CONTEXT pDevContext; WDFQUEUE queue; ULONG maximumTransferSize; UNREFERENCED_PARAMETER(Driver); PSDrv_DbgPrint (3, ("PSDrv_EvtDeviceAdd - begins\n")); PAGED_CODE(); // 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); pnpPowerCallbacks.EvtDevicePrepareHardware = PSDrv_EvtDevicePrepareHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // Initialize the request attributes to specify the context size and type // for every request created by framework for this device. WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes); // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the // framework whether you are interested in handle Create, Close and // Cleanup requests that gets generate when an application or another // kernel component opens an handle to the device. If you don't register // the framework default behaviour would be complete these requests // with STATUS_SUCCESS. A driver might be interested in registering these // events if it wants to do security validation and also wants to maintain // per handle (fileobject) context. WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PSDrv_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK); // Specify a context for FileObject. If you register FILE_EVENT callbacks, // the framework by default creates a framework FILEOBJECT corresponding // to the WDM fileobject. If you want to track any per handle context, // use the context for FileObject. Driver that typically use FsContext // field should instead use Framework FileObject context. WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes, FILE_CONTEXT); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes); // We can do iso transfer only if the io type is directio. WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); // Now specify the size of device extension where we track per device // context.DeviceInit is completely initialized. So call the framework // to create the device and attach it to the lower stack. WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfDeviceCreate failed! (Status = %x)\n", status)); return status; } // Get the DeviceObject context by using accessory function specified in // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT. pDevContext = GetDeviceContext(device); //Get MaximumTransferSize from registry maximumTransferSize=0; status = ReadFdoRegistryKeyValue(Driver, L"MaximumTransferSize", &maximumTransferSize); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("ReadFdoRegistryKeyValue failed with Status code %!STATUS!\n", status)); return status; } if (maximumTransferSize) { pDevContext->MaximumTransferSize = maximumTransferSize; } else { pDevContext->MaximumTransferSize = DEFAULT_REGISTRY_TRANSFER_SIZE; } // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so // that you don't get the popup in usermode (on Win2K) when you surprise // remove the device. WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); // Do not show the little green remove icon pnpCaps.SurpriseRemovalOK = WdfTrue; /* // Show the little green remove icon... pnpCaps.SurpriseRemovalOK = WdfFalse; pnpCaps.Removable = WdfTrue; */ WdfDeviceSetPnpCapabilities(device, &pnpCaps); // Register I/O callbacks to tell the framework that you are interested // in handling WdfRequestTypeRead, WdfRequestTypeWrite, and IRP_MJ_DEVICE_CONTROL requests. // WdfIoQueueDispatchParallel means that we are capable of handling // all the I/O request simultaneously and we are responsible for protecting // data that could be accessed by these callbacks simultaneously. // This queue will be, by default, auto managed by the framework with // respect to PNP and Power events. That is, framework will take care // of queuing, failing, dispatching incoming requests based on the current // pnp/power state of the device. WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoRead = PSDrv_EvtIoRead; ioQueueConfig.EvtIoWrite = PSDrv_EvtIoWrite; ioQueueConfig.EvtIoDeviceControl = PSDrv_EvtIoDeviceControl; ioQueueConfig.EvtIoStop = PSDrvEvtIoStop; ioQueueConfig.EvtIoResume = PSDrvEvtIoResume; status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfIoQueueCreate failed! (Status = %x)\n", status)); return status; } // Register a device interface so that app can find our device and talk to it. status = WdfDeviceCreateDeviceInterface(device, (LPGUID)&GUID_CLASS_PSDRV_USB, NULL); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfDeviceCreateDeviceInterface failed! (Status = %x)\n", status)); return status; } PSDrv_DbgPrint(3, ("PSDrv_EvtDeviceAdd - ends\n")); return status; }
/* ** Driver TODO: Complete the implementation of EvtDriverDeviceAdd for your specific device. ** ** WDF calls this callback when a device instance is added to the driver. Good drivers will do a lot of ** work here to set up everything necessary, such as adding callbacks for PNP power state changes. ** This function defines an IO queue for handling DeviceIoControl and file read requests, both of which are ** important to the POS barcode scanner model. ** ** Note that this is not a complete device add implementation, as the PNP power callbacks are not handled. ** Additionally, driver writers may wish to set up additional queues to serialize device property requests ** (see Ioctl.cpp for more info). */ NTSTATUS EvtDriverDeviceAdd(_In_ WDFDRIVER /* UnusedDriver */, _Inout_ PWDFDEVICE_INIT DeviceInit) { NTSTATUS status = STATUS_SUCCESS; WDF_FILEOBJECT_CONFIG fileConfig; WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES fileAttributes; WDFDEVICE device; // Handle file events WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, EvtDeviceFileCreate, EvtFileClose, WDF_NO_EVENT_CALLBACK ); WDF_OBJECT_ATTRIBUTES_INIT(&fileAttributes); WdfDeviceInitSetFileObjectConfig( DeviceInit, &fileConfig, &fileAttributes ); // Create Device WDF_OBJECT_ATTRIBUTES_INIT(&deviceAttributes); status = WdfDeviceCreate( &DeviceInit, &deviceAttributes, &device ); if (!NT_SUCCESS(status)) { return status; } // Create a device interface for POS Barcode Scanner so that the device can be enumerated status = WdfDeviceCreateDeviceInterface( device, &GUID_DEVINTERFACE_POS_SCANNER, NULL ); if (!NT_SUCCESS(status)) { return status; } // Initialize the POS library POS_CX_ATTRIBUTES posCxAttributes; POS_CX_ATTRIBUTES_INIT(&posCxAttributes); posCxAttributes.EvtDeviceOwnershipChange = EvtDeviceOwnershipChange; status = PosCxInit(device, &posCxAttributes); if (!NT_SUCCESS(status)) { return status; } // Set up an IO queue to handle DeviceIoControl and ReadFile WDF_IO_QUEUE_CONFIG queueConfig; WDF_OBJECT_ATTRIBUTES attributes; WDFQUEUE queue; WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoDeviceControl = EvtIoDeviceControl; queueConfig.EvtIoRead = EvtIoRead; // Call us in PASSIVE_LEVEL WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfIoQueueCreate( device, &queueConfig, &attributes, &queue ); return status; }