WDFOBJECT WDFEXPORT(WdfDpcGetParentObject)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDPC Dpc ) /*++ Routine Description: Return the parent parent object supplied to WdfDpcCreate. Arguments: WDFDPC - Handle to WDFDPC object created with WdfDpcCreate. Returns: --*/ { FxDpc* pFxDpc; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Dpc, FX_TYPE_DPC, (PVOID*)&pFxDpc); return pFxDpc->GetObject(); }
KDPC* WDFEXPORT(WdfDpcWdmGetDpc)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDPC Dpc ) /*++ Routine Description: Return the KDPC* object pointer so that it may be linked into a DPC list. Arguments: WDFDPC - Handle to WDFDPC object created with WdfDpcCreate. Returns: KDPC* --*/ { FxDpc* pFxDpc; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Dpc, FX_TYPE_DPC, (PVOID*)&pFxDpc); return pFxDpc->GetDpcPtr(); }
BOOLEAN WDFEXPORT(WdfDpcEnqueue)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDPC Dpc ) /*++ Routine Description: Enqueue the DPC to run at a system determined time Arguments: WDFDPC - Handle to WDFDPC object created with WdfDpcCreate. Returns: --*/ { FxDpc* pFxDpc; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Dpc, FX_TYPE_DPC, (PVOID*)&pFxDpc); return KeInsertQueueDpc(pFxDpc->GetDpcPtr(), NULL, NULL); }
WDFOBJECT WDFEXPORT(WdfCollectionGetLastItem)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFCOLLECTION Collection ) { DDI_ENTRY(); FxCollection *pCollection; FxObject* pObject; KIRQL irql; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Collection, FX_TYPE_COLLECTION, (PVOID*) &pCollection); pCollection->Lock(&irql); pObject = pCollection->GetLastItem(); pCollection->Unlock(irql); if (pObject != NULL) { return pObject->GetObjectHandle(); } else { return NULL; } }
ULONG WDFEXPORT(WdfCollectionGetCount)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFCOLLECTION Collection ) { DDI_ENTRY(); FxCollection *pCollection; KIRQL irql; ULONG count; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Collection, FX_TYPE_COLLECTION, (PVOID *)&pCollection); pCollection->Lock(&irql); count = pCollection->Count(); pCollection->Unlock(irql); return count; }
NTSTATUS WDFEXPORT(WdfCollectionAdd)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFCOLLECTION Collection, __in WDFOBJECT Object ) { DDI_ENTRY(); PFX_DRIVER_GLOBALS pFxDriverGlobals; FxCollection *pCollection; FxObject *pObject; NTSTATUS status; KIRQL irql; FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), Collection, FX_TYPE_COLLECTION, (PVOID*) &pCollection, &pFxDriverGlobals); FxObjectHandleGetPtr(pFxDriverGlobals, Object, FX_TYPE_OBJECT, (PVOID*) &pObject); pCollection->Lock(&irql); status = pCollection->Add(pObject) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; pCollection->Unlock(irql); return status; }
VOID WDFEXPORT(WdfDeviceClearRemovalRelationsDevices)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device ) /*++ Routine Description: Deregisters all PDOs to not be reported as also requiring removal when this PDO is removed. Arguments: Device - this driver's PDO Return Value: None --*/ { FxDevice* pDevice; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID*) &pDevice); pDevice->m_PkgPnp->ClearRemovalDevicesList(); }
NTSTATUS WDFEXPORT(WdfWmiProviderCreate)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in PWDF_WMI_PROVIDER_CONFIG WmiProviderConfig, __in_opt PWDF_OBJECT_ATTRIBUTES ProviderAttributes, __out WDFWMIPROVIDER* WmiProvider ) { FxDevice* pDevice; FxPowerPolicyOwnerSettings* ownerSettings; FxWmiProvider* pProvider; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID*) &pDevice); FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), WmiProviderConfig); FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), WmiProvider); // // If the Device is a power policy owner then do not allow client drivers // to register for GUID_POWER_DEVICE_ENABLE or GUID_POWER_DEVICE_WAKE_ENABLE // if the framework has already register a provider for those guids. // if (pDevice->m_PkgPnp->IsPowerPolicyOwner()) { ownerSettings = pDevice->m_PkgPnp->m_PowerPolicyMachine.m_Owner; if ((FxIsEqualGuid(&WmiProviderConfig->Guid, &GUID_POWER_DEVICE_ENABLE) && ownerSettings->m_IdleSettings.WmiInstance != NULL) || (FxIsEqualGuid(&WmiProviderConfig->Guid, &GUID_POWER_DEVICE_WAKE_ENABLE) && ownerSettings->m_WakeSettings.WmiInstance != NULL)) { DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR, TRACINGDEVICE, "WMI Guid already registered by " "framework"); return STATUS_WMI_GUID_DISCONNECTED; } } return FxWmiProvider::_Create(GetFxDriverGlobals(DriverGlobals), Device, ProviderAttributes, WmiProviderConfig, WmiProvider, &pProvider); }
VOID WDFEXPORT(WdfCollectionRemove)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFCOLLECTION Collection, __in WDFOBJECT Item ) { DDI_ENTRY(); PFX_DRIVER_GLOBALS pFxDriverGlobals; FxCollection *pCollection; FxCollectionEntry *pEntry; FxObject* pObject; NTSTATUS status; KIRQL irql; FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), Collection, FX_TYPE_COLLECTION, (PVOID*) &pCollection, &pFxDriverGlobals); FxObjectHandleGetPtr(pFxDriverGlobals, Item, FX_TYPE_OBJECT, (PVOID*) &pObject); pCollection->Lock(&irql); pEntry = pCollection->FindEntryByObject(pObject); if (pEntry != NULL) { pCollection->CleanupEntry(pEntry); status = STATUS_SUCCESS; } else { pObject = NULL; status = STATUS_NOT_FOUND; } pCollection->Unlock(irql); if (pObject != NULL) { pCollection->CleanupEntryObject(pObject); } if (!NT_SUCCESS(status)) { DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR, "WDFOBJECT %p not in WDFCOLLECTION %p, %!STATUS!", Item, Collection, status); FxVerifierDbgBreakPoint(pFxDriverGlobals); } }
ULONGLONG WDFEXPORT(WdfWmiProviderGetTracingHandle)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFWMIPROVIDER WmiProvider ) { FxWmiProvider *pProvider; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), WmiProvider, FX_TYPE_WMI_PROVIDER, (PVOID*) &pProvider); return pProvider->GetTracingHandle(); }
PDEVICE_OBJECT WDFEXPORT(WdfDeviceWdmGetAttachedDevice)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device ) { FxDeviceBase *pDevice; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE_BASE, (PVOID*) &pDevice); return pDevice->GetAttachedDevice(); }
WDFWMIPROVIDER WDFEXPORT(WdfWmiInstanceGetProvider)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFWMIINSTANCE WmiInstance ) { FxWmiInstanceExternal *pInstance; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), WmiInstance, FX_TYPE_WMI_INSTANCE, (PVOID*) &pInstance); return pInstance->GetProvider()->GetHandle(); }
VOID WDFEXPORT(WdfWmiInstanceDeregister)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFWMIINSTANCE WmiInstance ) { FxWmiInstanceExternal* pInstance; FxWmiProvider* pProvider; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), WmiInstance, FX_TYPE_WMI_INSTANCE, (PVOID*) &pInstance); pProvider = pInstance->GetProvider(); pProvider->RemoveInstance(pInstance); }
BOOLEAN WDFEXPORT(WdfWmiProviderIsEnabled)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFWMIPROVIDER WmiProvider, __in WDF_WMI_PROVIDER_CONTROL ProviderControl ) { FxWmiProvider *pProvider; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), WmiProvider, FX_TYPE_WMI_PROVIDER, (PVOID*) &pProvider); return pProvider->IsEnabled(ProviderControl); }
BOOLEAN WDFAPI WDFEXPORT(WdfUsbTargetPipeIsOutEndpoint)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFUSBPIPE Pipe ) { DDI_ENTRY(); FxUsbPipe* pUsbPipe; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Pipe, FX_TYPE_IO_TARGET_USB_PIPE, (PVOID*) &pUsbPipe); return pUsbPipe->IsOutEndpoint(); }
VOID WDFEXPORT(WdfDeviceSetBusInformationForChildren)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in PPNP_BUS_INFORMATION BusInformation ) { FxDevice* pDevice; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID*) &pDevice); FxPointerNotNull(pDevice->GetDriverGlobals(), BusInformation); pDevice->m_PkgPnp->SetChildBusInformation(BusInformation); }
NTSTATUS WDFAPI WDFEXPORT(WdfUsbTargetPipeFormatRequestForReset)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFUSBPIPE Pipe, __in WDFREQUEST Request ) { DDI_ENTRY(); PFX_DRIVER_GLOBALS pFxDriverGlobals; FxRequest* pRequest; FxUsbPipe* pUsbPipe; NTSTATUS status; FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), Pipe, FX_TYPE_IO_TARGET_USB_PIPE, (PVOID*) &pUsbPipe, &pFxDriverGlobals); DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, "Pipe %p, Request %p", Pipe, Request); FxObjectHandleGetPtr(pFxDriverGlobals, Request, FX_TYPE_REQUEST, (PVOID*) &pRequest); status = pUsbPipe->FormatResetRequest(pRequest); DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, "Pipe %p, Request %p = 0x%x", Pipe, Request, status); return status; }
VOID WDFEXPORT(WdfDeviceRemoveRemovalRelationsPhysicalDevice)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in PDEVICE_OBJECT PhysicalDevice ) /*++ Routine Description: Deregisters a PDO from another non descendant (not verifiable though) pnp stack to not be reported as also requiring removal when this PDO is removed. The PDO could be another device enumerated by this driver. Arguments: Device - this driver's PDO PhysicalDevice - PDO for another stack Return Value: None --*/ { FxDevice* pDevice; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID*) &pDevice); FxPointerNotNull(pDevice->GetDriverGlobals(), PhysicalDevice); pDevice->m_PkgPnp->RemoveRemovalDevice(PhysicalDevice); }
VOID WDFEXPORT(WdfDeviceSetSpecialFileSupport)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in WDF_SPECIAL_FILE_TYPE FileType, __in BOOLEAN Supported ) { FxDevice* pDevice; PFX_DRIVER_GLOBALS pFxDriverGlobals; FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID *) &pDevice, &pFxDriverGlobals); if (FileType < WdfSpecialFilePaging || FileType >= WdfSpecialFileMax) { DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "WDFDEVICE 0x%p FileType %d specified is not in valid range", Device, FileType); FxVerifierDbgBreakPoint(pFxDriverGlobals); return; } FxObjectHandleGetPtr(pFxDriverGlobals, Device, FX_TYPE_DEVICE, (PVOID*) &pDevice); pDevice->m_PkgPnp->SetSpecialFileSupport(FileType, Supported); }
NTSTATUS WDFEXPORT(WdfDeviceWdmDispatchIrpToIoQueue)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in MdIrp Irp, __in WDFQUEUE Queue, __in ULONG Flags ) { FxIoQueue *queue; FxDevice *device; PFX_DRIVER_GLOBALS fxDriverGlobals; PIO_STACK_LOCATION stack; NTSTATUS status; FxIoInCallerContext* ioInCallerCtx; queue = NULL; ioInCallerCtx = NULL; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID*) &device); fxDriverGlobals = device->GetDriverGlobals(); FX_TRACK_DRIVER(fxDriverGlobals); FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Queue, FX_TYPE_QUEUE, (PVOID*)&queue); FxPointerNotNull(fxDriverGlobals, Irp); // // If the caller is a preprocess routine, the contract for this DDI is just like IoCallDriver. // The caller sets up their stack location and then the DDI advances to the next stack // location. This means that the caller either has to call IoSkipCurrentIrpStackLocation // or IoCopyCurrentIrpStackLocationToNext before calling this DDI. // if (Flags & WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP) { IoSetNextIrpStackLocation(Irp); } // // Verifier checks. // status = VerifyWdfDeviceWdmDispatchIrpToIoQueue(fxDriverGlobals, device, Irp, queue, Flags); if(!NT_SUCCESS(status)) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } // // Adjust stack if IRP needs to be forwarded to parent device. // if (device->m_ParentDevice == queue->GetDevice()) { IoCopyCurrentIrpStackLocationToNext(Irp); IoSetNextIrpStackLocation(Irp); // // From now on use new device. // device = device->m_ParentDevice; // // Save a pointer to the device object for this request so that it can // be used later in completion. // stack = IoGetCurrentIrpStackLocation(Irp); stack->DeviceObject = device->GetDeviceObject(); } // // Get in-context caller callback if required. // if (Flags & WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK) { ioInCallerCtx = device->m_PkgIo->GetIoInCallerContextCallback( queue->GetCxDeviceInfo()); } // // DispatchStep2 will convert the IRP into a WDFREQUEST, queue it and if // possible dispatch the request to the driver. // return device->m_PkgIo->DispatchStep2(Irp, ioInCallerCtx, queue); }
NTSTATUS WDFEXPORT(WdfDeviceWdmDispatchIrp)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in MdIrp Irp, __in WDFCONTEXT DispatchContext ) /*++ Routine Description: Client driver calls this API from its dispatch callback when it decides to hand the IRP back to framework. Cx calls this API from (a) its pre-process callback or (b) its dispatch callback when it decides to hand the IRP back to the framework. Arguments: Device - WDF Device handle. IRP - WDM request. DispatchContext - WDF's context (input arg to callback). Returns: IRP's status. --*/ { FxDevice *device; NTSTATUS status; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID*) &device); FxPointerNotNull(device->GetDriverGlobals(), Irp); FxPointerNotNull(device->GetDriverGlobals(), DispatchContext); if ((UCHAR)DispatchContext & FX_IN_DISPATCH_CALLBACK) { // // Called from a dispach irp callback. // DispatchContext = (WDFCONTEXT)((ULONG_PTR)DispatchContext & ~FX_IN_DISPATCH_CALLBACK); // // DispatchContext is validated by DispatchStep1. // status = device->m_PkgIo->DispatchStep1(Irp, DispatchContext); } else { // // Called from a pre-process irp callback. // // // Verifier checks. // VerifyWdfDeviceWdmDispatchIrp(device->GetDriverGlobals(), DriverGlobals, device, DispatchContext); status = device->DispatchPreprocessedIrp(Irp, DispatchContext); } return status; }
WDFFILEOBJECT WDFEXPORT(WdfDeviceGetFileObject)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in MdFileObject FileObject ) /*++ Routine Description: This functions returns the WDFFILEOBJECT corresponding to the WDM fileobject. Arguments: Device - Handle to the device to which the WDM fileobject is related to. FileObject - WDM FILE_OBJECT structure. Return Value: --*/ { PFX_DRIVER_GLOBALS pFxDriverGlobals; NTSTATUS status; FxFileObject* pFxFO; FxDevice *pDevice; pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); pFxFO = NULL; // // Validate the Device object handle, and get its FxDevice* // FxObjectHandleGetPtr(pFxDriverGlobals, Device, FX_TYPE_DEVICE, (PVOID*)&pDevice); // // Call the static GetFileObjectFromWdm function. This will return an error if the // WDM fileObject is NULL and the device is not exclusive or the device is // configured to have a WDFFILEOBJECT for every open handle. // status = FxFileObject::_GetFileObjectFromWdm( pDevice, pDevice->GetFileObjectClass(), FileObject, &pFxFO ); if (!NT_SUCCESS(status)) { DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "FxFileObject::_GetFileObjectFromWdm returned an error %!STATUS!", status); return NULL; } // // pFxFO can be NULL if the device is configured with FileObjectClass WdfFileObjectNotRequired. // return pFxFO != NULL ? pFxFO->GetHandle() : NULL; }
NTSTATUS WDFEXPORT(WdfDmaTransactionInitializeUsingRequest)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDMATRANSACTION DmaTransaction, __in WDFREQUEST Request, __in PFN_WDF_PROGRAM_DMA EvtProgramDmaFunction, __in WDF_DMA_DIRECTION DmaDirection ) { NTSTATUS status; FxDmaTransactionBase* pDmaTrans; FxRequest* pReqObj; MDL* mdl = NULL; PIO_STACK_LOCATION stack; ULONG reqLength; PFX_DRIVER_GLOBALS pFxDriverGlobals; FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), DmaTransaction, FX_TYPE_DMA_TRANSACTION, (PVOID *) &pDmaTrans, &pFxDriverGlobals); FxPointerNotNull(pFxDriverGlobals, EvtProgramDmaFunction); if (DmaDirection != WdfDmaDirectionReadFromDevice && DmaDirection != WdfDmaDirectionWriteToDevice) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Initialization of WDFDMATRANSACTION 0x%p using WDFREQUEST %p, " "DmaDirection 0x%x is an invalid value, %!STATUS!", DmaTransaction, Request, DmaDirection, status); return status; } FxObjectHandleGetPtr(pFxDriverGlobals, Request, FX_TYPE_REQUEST, (PVOID *) &pReqObj); reqLength = 0; stack = pReqObj->GetFxIrp()->GetCurrentIrpStackLocation(); // // Get the MDL and Length from the request. // switch (stack->MajorFunction) { case IRP_MJ_READ: if (DmaDirection != WdfDmaDirectionReadFromDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with the WDFREQUEST 0x%p type " "%!WDF_REQUEST_TYPE! %!STATUS!", DmaDirection, DmaTransaction, Request, stack->MajorFunction, status); return status; } reqLength = stack->Parameters.Read.Length; status = pReqObj->GetMdl(&mdl); break; case IRP_MJ_WRITE: if (DmaDirection != WdfDmaDirectionWriteToDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with the WDFREQUEST 0x%p type " "%!WDF_REQUEST_TYPE! %!STATUS!", DmaDirection, DmaTransaction, Request, stack->MajorFunction, status); return status; } reqLength = stack->Parameters.Write.Length; status = pReqObj->GetMdl(&mdl); break; case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_INTERNAL_DEVICE_CONTROL: switch (METHOD_FROM_CTL_CODE(stack->Parameters.DeviceIoControl.IoControlCode)) { case METHOD_BUFFERED: if (DmaDirection == WdfDmaDirectionWriteToDevice) { reqLength = stack->Parameters.DeviceIoControl.InputBufferLength; } else { reqLength = stack->Parameters.DeviceIoControl.OutputBufferLength; } // // In this case both input buffer and output buffer map // to the same MDL and it's probed for read & write access. // So it's okay for DMA transfer in either direction. // status = pReqObj->GetMdl(&mdl); break; case METHOD_IN_DIRECT: // // For this type, the output buffer is probed for read access. // So the direction of DMA transfer is WdfDmaDirectionWriteToDevice. // if (DmaDirection != WdfDmaDirectionWriteToDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with WDFREQUEST 0x%p ioctl type " "METHOD_IN_DIRECT %!STATUS!", DmaDirection, DmaTransaction, Request, status); return status; } reqLength = stack->Parameters.DeviceIoControl.OutputBufferLength; status = pReqObj->GetDeviceControlOutputMdl(&mdl); break; case METHOD_OUT_DIRECT: // // For this type, the output buffer is probed for write access. // So the direction of DMA transfer is WdfDmaDirectionReadFromDevice. // if (DmaDirection != WdfDmaDirectionReadFromDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with WDFREQUEST 0x%p ioctl type " "METHOD_OUT_DIRECT %!STATUS!", DmaDirection, DmaTransaction, Request, status); return status; } reqLength = stack->Parameters.DeviceIoControl.OutputBufferLength; status = pReqObj->GetDeviceControlOutputMdl(&mdl); break; default: status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Invalid ioctl code in WDFREQUEST 0x%p %!STATUS!", Request, status); FxVerifierDbgBreakPoint(pFxDriverGlobals); break; }// End of switch(ioctType) break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } if (!NT_SUCCESS(status)) { DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Couldn't retrieve mdl from WDFREQUEST 0x%p for " "WDFTRANSACTION 0x%p %!STATUS!", Request, DmaTransaction, status); return status; } if (reqLength == 0) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Zero length request, %!STATUS!", status); return status; } // // If the DMA enabler is packet based, make sure the virtual address and // the length of transfer are within bounds. Basically, we are checking // to see if the length of data to be transferred doesn't span multiple // MDLs, because packet based DMA doesn't support chained MDLs. // if (pDmaTrans->GetDmaEnabler()->SupportsChainedMdls() == FALSE) { ULONG length; length = MmGetMdlByteCount(mdl); if (reqLength > length) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "WDFREQUEST %p transfer length (%d) is out of bounds of MDL " "Byte count (%d), %!STATUS!", Request, reqLength, length, status); return status; } } // // Parms appear OK, so initialize this instance. // status = pDmaTrans->Initialize(EvtProgramDmaFunction, DmaDirection, mdl, 0, reqLength); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "WDFTANSACTION 0x%p initialization failed: " "%!STATUS!", DmaTransaction, status); return status; } // // Set this Request in the new DmaTransaction. The request will // take a reference on this request when it starts executing. // pDmaTrans->SetRequest(pReqObj); return STATUS_SUCCESS; }
NTSTATUS WDFEXPORT(WdfWmiInstanceCreate)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in PWDF_WMI_INSTANCE_CONFIG InstanceConfig, __in_opt PWDF_OBJECT_ATTRIBUTES InstanceAttributes, __out_opt WDFWMIINSTANCE* Instance ) { PFX_DRIVER_GLOBALS pFxDriverGlobals; FxWmiProvider* pProvider; FxWmiInstanceExternal* pInstance; WDFWMIINSTANCE hInstance; NTSTATUS status; pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals); pInstance = NULL; FxPointerNotNull(pFxDriverGlobals, InstanceConfig); if (InstanceConfig->Size != sizeof(WDF_WMI_INSTANCE_CONFIG)) { status = STATUS_INFO_LENGTH_MISMATCH; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Expected InstanceConfig Size %d, got %d, %!STATUS!", InstanceConfig->Size, sizeof(*InstanceConfig), status); return status; } if (InstanceConfig->Provider == NULL && InstanceConfig->ProviderConfig == NULL) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "InstanceConfig %p Provider and ProviderConfig are both NULL, only " "one can be, %!STATUS!", InstanceConfig, status); return status; } else if (InstanceConfig->Provider != NULL && InstanceConfig->ProviderConfig != NULL) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "InstanceConfig %p Provider %p and ProviderConfig %p are both not " "NULL, only one can be, %!STATUS!", InstanceConfig, InstanceConfig->Provider, InstanceConfig->ProviderConfig, status); return status; } if (InstanceConfig->Provider != NULL) { FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals, InstanceConfig->Provider, FX_TYPE_WMI_PROVIDER, (PVOID*) &pProvider, &pFxDriverGlobals); } else { FxDevice* pDevice; FxPowerPolicyOwnerSettings* ownerSettings; WDFWMIPROVIDER hProvider; hProvider = NULL; FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID*) &pDevice); // // If the Device is a power policy owner then do not allow client drivers // to register for GUID_POWER_DEVICE_ENABLE or GUID_POWER_DEVICE_WAKE_ENABLE // if the framework has already register a provider for those guids. // if (pDevice->m_PkgPnp->IsPowerPolicyOwner()) { ownerSettings = pDevice->m_PkgPnp->m_PowerPolicyMachine.m_Owner; if ((FxIsEqualGuid(&InstanceConfig->ProviderConfig->Guid, &GUID_POWER_DEVICE_ENABLE) && ownerSettings->m_IdleSettings.WmiInstance != NULL) || (FxIsEqualGuid(&InstanceConfig->ProviderConfig->Guid, &GUID_POWER_DEVICE_WAKE_ENABLE) && ownerSettings->m_WakeSettings.WmiInstance != NULL)) { status = STATUS_WMI_GUID_DISCONNECTED; DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR, TRACINGDEVICE, "WMI Guid already registered by " "framework"); return status; } } status = FxWmiProvider::_Create(pFxDriverGlobals, Device, NULL, InstanceConfig->ProviderConfig, &hProvider, &pProvider); if (!NT_SUCCESS(status)) { return status; } // // Use the object's globals and not the caller's // pFxDriverGlobals = pProvider->GetDriverGlobals(); } status = FxWmiInstanceExternal::_Create(pFxDriverGlobals, pProvider, InstanceConfig, InstanceAttributes, &hInstance, &pInstance); if (NT_SUCCESS(status) && InstanceConfig->Register) { status = pProvider->AddInstance(pInstance); } if (NT_SUCCESS(status)) { if (Instance != NULL) { *Instance = hInstance; } } else { // // Something went wrong, cleanup // if (pInstance != NULL) { // // This will remove the instance from the provider's list as well. // pInstance->DeleteFromFailedCreate(); } // // Only remove the provider if we created it in this function // if (InstanceConfig->ProviderConfig != NULL) { pProvider->DeleteFromFailedCreate(); } } return status; }
_Must_inspect_result_ NTSTATUS FxIoTargetRemote::_Create( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in CfxDeviceBase* Device, __out FxIoTargetRemote** Target ) { FxIoTargetRemote* pTarget; FxObject* pParent; WDFOBJECT hTarget; NTSTATUS status; *Target = NULL; if (Attributes == NULL || Attributes->ParentObject == NULL) { pParent = Device; } else { CfxDeviceBase* pSearchDevice; FxObjectHandleGetPtr(FxDriverGlobals, Attributes->ParentObject, FX_TYPE_OBJECT, (PVOID*) &pParent); pSearchDevice = FxDeviceBase::_SearchForDevice(pParent, NULL); if (pSearchDevice == NULL) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, "Attributes->ParentObject 0x%p must have WDFDEVICE as an " "eventual ancestor, %!STATUS!", Attributes->ParentObject, status); return status; } else if (pSearchDevice != Device) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, "Attributes->ParentObject 0x%p ancestor is WDFDEVICE %p, but " "not the same WDFDEVICE 0x%p passed to WdfIoTargetCreate, " "%!STATUS!", Attributes->ParentObject, pSearchDevice->GetHandle(), Device->GetHandle(), status); return status; } } pTarget = new (FxDriverGlobals, Attributes) FxIoTargetRemote(FxDriverGlobals); if (pTarget == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, "Could not allocate memory for target, %!STATUS!", status); return status; } // // initialize the new target // status = pTarget->InitRemote(Device); if (!NT_SUCCESS(status)) { return status; } // // Commit and apply the attributes // status = pTarget->Commit(Attributes, &hTarget, pParent); if (NT_SUCCESS(status)) { *Target = pTarget; } else { // // This will properly clean up the target's state and free it // DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, "Commit failed for target, %!STATUS!", status); pTarget->DeleteFromFailedCreate(); } return status; }
WDFAPI NTSTATUS WDFEXPORT(WdfDeviceConfigureWdmIrpDispatchCallback)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDEVICE Device, __in_opt WDFDRIVER Driver, __in UCHAR MajorFunction, __in PFN_WDFDEVICE_WDM_IRP_DISPATCH EvtDeviceWdmIrpDispatch, __in_opt WDFCONTEXT DriverContext ) /*++ Routine Description: Configure callbacks for read, write, ctrl and internal_ctrl. By default the I/O package sends all requests to the devices default queue or to the queues configured with WdfDeviceConfigureRequestDispatching. This API allows a driver specified callback to select the target queue dynamically. Arguments: Device - The device which is handling the IO. Driver - Optional Driver, used to associate callback with a specific class extension. RequestType - WDF Request type to be forwarded to the callback EvtDeviceWdmIrpDispatch - Driver's callback. DriverContext - Callback's context. Returns: NTSTATUS --*/ { PFX_DRIVER_GLOBALS fxDriverGlobals; NTSTATUS status; FxDevice* device; FxCxDeviceInfo* cxDeviceInfo; device = NULL; cxDeviceInfo = NULL; FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), Device, FX_TYPE_DEVICE, (PVOID *) &device, &fxDriverGlobals); // // Validate the driver handle and get (if present) the associated cx info. // if (Driver != NULL) { FxDriver* driver; FxObjectHandleGetPtr(fxDriverGlobals, Driver, FX_TYPE_DRIVER, (PVOID*)&driver); // // Find the driver's cx info if it's not the main driver for this device. // cx struct info can be NULL if cx acts as client driver. // cxDeviceInfo = device->GetCxDeviceInfo(driver); } // // Make sure callback is not null. // FxPointerNotNull(fxDriverGlobals, EvtDeviceWdmIrpDispatch); // // This callback can only be called during initialization. // if (device->IsLegacy()) { // // This is a controldevice. Make sure the create is called after the device // is initialized and ready to accept I/O. // if ((device->GetDeviceObject()->Flags & DO_DEVICE_INITIALIZING) == 0x0) { status = STATUS_INVALID_DEVICE_STATE; DoTraceLevelMessage( fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, "Driver cannot set IRP dispatch callback " "after WdfControlDeviceFinishInitializing " "is called on the WDFDEVICE %p, %!STATUS!", device, status); goto Done; } } else { // // This is either FDO or PDO. Make sure it's not started yet. // if (device->GetDevicePnpState() != WdfDevStatePnpInit) { status = STATUS_INVALID_DEVICE_STATE; DoTraceLevelMessage( fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, "Driver cannot set IRP dispatch callback " "after the WDFDEVICE %p is started, %!STATUS!", device, status); goto Done; } } // // Let I/O package do the rest. // status = device->m_PkgIo->ConfigureDynamicDispatching(MajorFunction, cxDeviceInfo, EvtDeviceWdmIrpDispatch, DriverContext); Done: return status; }
_Must_inspect_result_ NTSTATUS FxPkgIo::CreateQueue( __in PWDF_IO_QUEUE_CONFIG Config, __in PWDF_OBJECT_ATTRIBUTES QueueAttributes, __in_opt FxDriver* Caller, __deref_out FxIoQueue** ppQueue ) { PFX_DRIVER_GLOBALS pFxDriverGlobals; FxObject* pParent; FxIoQueue* pQueue; NTSTATUS status; FxDriver* pDriver; pParent = NULL; pQueue = NULL; pDriver = NULL; pFxDriverGlobals = GetDriverGlobals(); if (QueueAttributes != NULL && QueueAttributes->ParentObject != NULL) { CfxDeviceBase* pSearchDevice; FxObjectHandleGetPtr(pFxDriverGlobals, QueueAttributes->ParentObject, FX_TYPE_OBJECT, (PVOID*)&pParent); pSearchDevice = FxDeviceBase::_SearchForDevice(pParent, NULL); if (pSearchDevice == NULL) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, "QueueAttributes->ParentObject 0x%p must have WDFDEVICE as an " "eventual ancestor, %!STATUS!", QueueAttributes->ParentObject, status); return status; } else if (pSearchDevice != m_DeviceBase) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO, "Attributes->ParentObject 0x%p ancestor is WDFDEVICE %p, but " "not the same WDFDEVICE 0x%p passed to WdfIoQueueCreate, " "%!STATUS!", QueueAttributes->ParentObject, pSearchDevice->GetHandle(), m_Device->GetHandle(), status); return status; } } else { // // By default, use the package as the parent // pParent = this; } // // v1.11 and up: get driver object if driver handle is specified. // Client driver can also specify a driver handle, the end result in this case is // a PkgIoContext that is NULL (see below), i.e., the same as if driver handle // was NULL. // if (Config->Size > sizeof(WDF_IO_QUEUE_CONFIG_V1_9) && Config->Driver != NULL) { FxObjectHandleGetPtr(GetDriverGlobals(), Config->Driver, FX_TYPE_DRIVER, (PVOID*)&pDriver); } status = FxIoQueue::_Create(pFxDriverGlobals, QueueAttributes, Config, Caller, this, m_PowerStateOn, &pQueue ); if (!NT_SUCCESS(status)) { ASSERT(pQueue == NULL); return status; } // // Class extension support: associate queue with a specific cx layer. // if (pDriver != NULL) { pQueue->SetCxDeviceInfo(m_Device->GetCxDeviceInfo(pDriver)); } status = pQueue->Commit(QueueAttributes, NULL, pParent); if (!NT_SUCCESS(status)) { pQueue->DeleteFromFailedCreate(); return status; } AddIoQueue(pQueue); *ppQueue = pQueue; return status; }