18a978a17SVictor Perevertkin /*++
28a978a17SVictor Perevertkin
38a978a17SVictor Perevertkin Copyright (c) Microsoft Corporation
48a978a17SVictor Perevertkin
58a978a17SVictor Perevertkin Module Name:
68a978a17SVictor Perevertkin
78a978a17SVictor Perevertkin FxDeviceBase.cpp
88a978a17SVictor Perevertkin
98a978a17SVictor Perevertkin Abstract:
108a978a17SVictor Perevertkin
118a978a17SVictor Perevertkin This is the class implementation for the base device class.
128a978a17SVictor Perevertkin
138a978a17SVictor Perevertkin Author:
148a978a17SVictor Perevertkin
158a978a17SVictor Perevertkin
168a978a17SVictor Perevertkin
178a978a17SVictor Perevertkin Environment:
188a978a17SVictor Perevertkin
198a978a17SVictor Perevertkin Both kernel and user mode
208a978a17SVictor Perevertkin
218a978a17SVictor Perevertkin Revision History:
228a978a17SVictor Perevertkin
238a978a17SVictor Perevertkin --*/
248a978a17SVictor Perevertkin
258a978a17SVictor Perevertkin #include "coreprivshared.hpp"
268a978a17SVictor Perevertkin
278a978a17SVictor Perevertkin extern "C" {
28*1f377076SVictor Perevertkin // #include "FxDeviceBase.tmh"
298a978a17SVictor Perevertkin }
308a978a17SVictor Perevertkin
FxDeviceBase(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in FxDriver * Driver,__in WDFTYPE Type,__in USHORT Size)318a978a17SVictor Perevertkin FxDeviceBase::FxDeviceBase(
328a978a17SVictor Perevertkin __in PFX_DRIVER_GLOBALS FxDriverGlobals,
338a978a17SVictor Perevertkin __in FxDriver* Driver,
348a978a17SVictor Perevertkin __in WDFTYPE Type,
358a978a17SVictor Perevertkin __in USHORT Size
368a978a17SVictor Perevertkin ) :
378a978a17SVictor Perevertkin FxNonPagedObject(Type, Size, FxDriverGlobals)
388a978a17SVictor Perevertkin {
398a978a17SVictor Perevertkin m_Driver = Driver;
408a978a17SVictor Perevertkin
418a978a17SVictor Perevertkin m_CallbackLockPtr = NULL;
428a978a17SVictor Perevertkin m_CallbackLockObjectPtr = NULL;
438a978a17SVictor Perevertkin
448a978a17SVictor Perevertkin m_DisposeList = NULL;
458a978a17SVictor Perevertkin
468a978a17SVictor Perevertkin m_DmaPacketTransactionStatus = FxDmaPacketTransactionCompleted;
478a978a17SVictor Perevertkin
488a978a17SVictor Perevertkin m_ExecutionLevel = WdfExecutionLevelInheritFromParent;
498a978a17SVictor Perevertkin m_SynchronizationScope = WdfSynchronizationScopeInheritFromParent;
508a978a17SVictor Perevertkin
518a978a17SVictor Perevertkin MarkPassiveDispose(ObjectDoNotLock);
528a978a17SVictor Perevertkin SetDeviceBase(this);
538a978a17SVictor Perevertkin }
548a978a17SVictor Perevertkin
~FxDeviceBase(VOID)558a978a17SVictor Perevertkin FxDeviceBase::~FxDeviceBase(
568a978a17SVictor Perevertkin VOID
578a978a17SVictor Perevertkin )
588a978a17SVictor Perevertkin {
598a978a17SVictor Perevertkin if (m_DisposeList != NULL) {
608a978a17SVictor Perevertkin m_DisposeList->DeleteObject();
618a978a17SVictor Perevertkin m_DisposeList = NULL;
628a978a17SVictor Perevertkin }
638a978a17SVictor Perevertkin
648a978a17SVictor Perevertkin if (m_CallbackLockPtr != NULL) {
658a978a17SVictor Perevertkin delete m_CallbackLockPtr;
668a978a17SVictor Perevertkin m_CallbackLockPtr = NULL;
678a978a17SVictor Perevertkin }
688a978a17SVictor Perevertkin }
698a978a17SVictor Perevertkin
708a978a17SVictor Perevertkin _Must_inspect_result_
718a978a17SVictor Perevertkin NTSTATUS
QueryInterface(__inout FxQueryInterfaceParams * Params)728a978a17SVictor Perevertkin FxDeviceBase::QueryInterface(
738a978a17SVictor Perevertkin __inout FxQueryInterfaceParams* Params
748a978a17SVictor Perevertkin )
758a978a17SVictor Perevertkin {
768a978a17SVictor Perevertkin switch (Params->Type) {
778a978a17SVictor Perevertkin case FX_TYPE_DEVICE_BASE:
788a978a17SVictor Perevertkin *Params->Object = this;
798a978a17SVictor Perevertkin break;
808a978a17SVictor Perevertkin
818a978a17SVictor Perevertkin case FX_TYPE_IHASCALLBACKS:
828a978a17SVictor Perevertkin *Params->Object = (IFxHasCallbacks*) this;
838a978a17SVictor Perevertkin break;
848a978a17SVictor Perevertkin
858a978a17SVictor Perevertkin default:
86*1f377076SVictor Perevertkin return FxNonPagedObject::QueryInterface(Params); // __super call
878a978a17SVictor Perevertkin }
888a978a17SVictor Perevertkin
898a978a17SVictor Perevertkin return STATUS_SUCCESS;
908a978a17SVictor Perevertkin }
918a978a17SVictor Perevertkin
928a978a17SVictor Perevertkin NTSTATUS
ConfigureConstraints(__in_opt PWDF_OBJECT_ATTRIBUTES ObjectAttributes)938a978a17SVictor Perevertkin FxDeviceBase::ConfigureConstraints(
948a978a17SVictor Perevertkin __in_opt PWDF_OBJECT_ATTRIBUTES ObjectAttributes
958a978a17SVictor Perevertkin )
968a978a17SVictor Perevertkin {
978a978a17SVictor Perevertkin NTSTATUS status;
988a978a17SVictor Perevertkin WDF_EXECUTION_LEVEL driverLevel;
998a978a17SVictor Perevertkin WDF_SYNCHRONIZATION_SCOPE driverScope;
1008a978a17SVictor Perevertkin
1018a978a17SVictor Perevertkin ASSERT(m_Driver != NULL);
1028a978a17SVictor Perevertkin
1038a978a17SVictor Perevertkin //
1048a978a17SVictor Perevertkin // If WDF_OBJECT_ATTRIBUTES is specified, these override any
1058a978a17SVictor Perevertkin // default settings.
1068a978a17SVictor Perevertkin //
1078a978a17SVictor Perevertkin if (ObjectAttributes != NULL) {
1088a978a17SVictor Perevertkin m_ExecutionLevel = ObjectAttributes->ExecutionLevel;
1098a978a17SVictor Perevertkin m_SynchronizationScope = ObjectAttributes->SynchronizationScope;
1108a978a17SVictor Perevertkin }
1118a978a17SVictor Perevertkin
1128a978a17SVictor Perevertkin //
1138a978a17SVictor Perevertkin // If no WDFDEVICE specific attributes are specified, we
1148a978a17SVictor Perevertkin // get them from WDFDRIVER, which allows WDFDRIVER to
1158a978a17SVictor Perevertkin // provide a default for all WDFDEVICE's created.
1168a978a17SVictor Perevertkin //
1178a978a17SVictor Perevertkin m_Driver->GetConstraints(&driverLevel, &driverScope);
1188a978a17SVictor Perevertkin
1198a978a17SVictor Perevertkin if (m_ExecutionLevel == WdfExecutionLevelInheritFromParent) {
1208a978a17SVictor Perevertkin m_ExecutionLevel = driverLevel;
1218a978a17SVictor Perevertkin }
1228a978a17SVictor Perevertkin
1238a978a17SVictor Perevertkin if (m_SynchronizationScope == WdfSynchronizationScopeInheritFromParent) {
1248a978a17SVictor Perevertkin m_SynchronizationScope = driverScope;
1258a978a17SVictor Perevertkin }
1268a978a17SVictor Perevertkin
1278a978a17SVictor Perevertkin //
1288a978a17SVictor Perevertkin // Configure The Execution Level Constraint
1298a978a17SVictor Perevertkin //
1308a978a17SVictor Perevertkin if (m_ExecutionLevel == WdfExecutionLevelPassive) {
1318a978a17SVictor Perevertkin m_CallbackLockPtr = new(GetDriverGlobals())
1328a978a17SVictor Perevertkin FxCallbackMutexLock(GetDriverGlobals());
1338a978a17SVictor Perevertkin //
1348a978a17SVictor Perevertkin // Currently, all event callbacks from FxDevice into the driver
1358a978a17SVictor Perevertkin // are from PASSIVE_LEVEL threads, and there is no need to defer
1368a978a17SVictor Perevertkin // to a system workitem like IoQueue. So we don't allocate and
1378a978a17SVictor Perevertkin // setup an FxSystemWorkItem here.
1388a978a17SVictor Perevertkin //
1398a978a17SVictor Perevertkin // If the FxDevice starts raising events to the device driver
1408a978a17SVictor Perevertkin // whose thread starts out above PASSIVE_LEVEL, then an FxSystemWorkItem
1418a978a17SVictor Perevertkin // would need to be allocated when WdfExecutionLevelPassive is specified.
1428a978a17SVictor Perevertkin //
1438a978a17SVictor Perevertkin // (FDO and PDO variants of FxDevice may own their own event dispatch
1448a978a17SVictor Perevertkin // and deferral logic separate from FxDevice.)
1458a978a17SVictor Perevertkin //
1468a978a17SVictor Perevertkin }
1478a978a17SVictor Perevertkin else {
1488a978a17SVictor Perevertkin m_CallbackLockPtr = new(GetDriverGlobals())
1498a978a17SVictor Perevertkin FxCallbackSpinLock(GetDriverGlobals());
1508a978a17SVictor Perevertkin }
1518a978a17SVictor Perevertkin
1528a978a17SVictor Perevertkin //
1538a978a17SVictor Perevertkin // Finish initializing the spin/mutex lock.
1548a978a17SVictor Perevertkin //
1558a978a17SVictor Perevertkin if (NULL == m_CallbackLockPtr) {
1568a978a17SVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
1578a978a17SVictor Perevertkin DoTraceLevelMessage(
1588a978a17SVictor Perevertkin GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGOBJECT,
1598a978a17SVictor Perevertkin "WDFDEVICE %p, could not allocate callback lock, %!STATUS!",
1608a978a17SVictor Perevertkin GetHandle(), status);
1618a978a17SVictor Perevertkin goto Done;
1628a978a17SVictor Perevertkin }
1638a978a17SVictor Perevertkin
1648a978a17SVictor Perevertkin m_CallbackLockPtr->Initialize(this);
1658a978a17SVictor Perevertkin m_CallbackLockObjectPtr = this;
1668a978a17SVictor Perevertkin
1678a978a17SVictor Perevertkin status = STATUS_SUCCESS;
1688a978a17SVictor Perevertkin
1698a978a17SVictor Perevertkin Done:
1708a978a17SVictor Perevertkin return status;
1718a978a17SVictor Perevertkin }
1728a978a17SVictor Perevertkin
1738a978a17SVictor Perevertkin VOID
GetConstraints(__out_opt WDF_EXECUTION_LEVEL * ExecutionLevel,__out_opt WDF_SYNCHRONIZATION_SCOPE * SynchronizationScope)1748a978a17SVictor Perevertkin FxDeviceBase::GetConstraints(
1758a978a17SVictor Perevertkin __out_opt WDF_EXECUTION_LEVEL* ExecutionLevel,
1768a978a17SVictor Perevertkin __out_opt WDF_SYNCHRONIZATION_SCOPE* SynchronizationScope
1778a978a17SVictor Perevertkin )
1788a978a17SVictor Perevertkin {
1798a978a17SVictor Perevertkin if (ExecutionLevel != NULL) {
1808a978a17SVictor Perevertkin *ExecutionLevel = m_ExecutionLevel;
1818a978a17SVictor Perevertkin }
1828a978a17SVictor Perevertkin
1838a978a17SVictor Perevertkin if (SynchronizationScope != NULL) {
1848a978a17SVictor Perevertkin *SynchronizationScope = m_SynchronizationScope;
1858a978a17SVictor Perevertkin }
1868a978a17SVictor Perevertkin }
1878a978a17SVictor Perevertkin
1888a978a17SVictor Perevertkin FxCallbackLock*
GetCallbackLockPtr(__out_opt FxObject ** LockObject)1898a978a17SVictor Perevertkin FxDeviceBase::GetCallbackLockPtr(
1908a978a17SVictor Perevertkin __out_opt FxObject** LockObject
1918a978a17SVictor Perevertkin )
1928a978a17SVictor Perevertkin {
1938a978a17SVictor Perevertkin if (LockObject != NULL) {
1948a978a17SVictor Perevertkin *LockObject = m_CallbackLockObjectPtr;
1958a978a17SVictor Perevertkin }
1968a978a17SVictor Perevertkin
1978a978a17SVictor Perevertkin return m_CallbackLockPtr;
1988a978a17SVictor Perevertkin }
1998a978a17SVictor Perevertkin
2008a978a17SVictor Perevertkin
2018a978a17SVictor Perevertkin VOID
Init(__in MdDeviceObject DeviceObject,__in MdDeviceObject AttachedDevice,__in MdDeviceObject PhysicalDevice)2028a978a17SVictor Perevertkin FxDeviceBase::Init(
2038a978a17SVictor Perevertkin __in MdDeviceObject DeviceObject,
2048a978a17SVictor Perevertkin __in MdDeviceObject AttachedDevice,
2058a978a17SVictor Perevertkin __in MdDeviceObject PhysicalDevice
2068a978a17SVictor Perevertkin )
2078a978a17SVictor Perevertkin {
2088a978a17SVictor Perevertkin m_DeviceObject.SetObject(DeviceObject);
2098a978a17SVictor Perevertkin m_AttachedDevice.SetObject(AttachedDevice);
2108a978a17SVictor Perevertkin m_PhysicalDevice.SetObject(PhysicalDevice);
2118a978a17SVictor Perevertkin }
2128a978a17SVictor Perevertkin
2138a978a17SVictor Perevertkin FxDeviceBase*
_SearchForDevice(__in FxObject * Object,__out_opt IFxHasCallbacks ** Callbacks)2148a978a17SVictor Perevertkin FxDeviceBase::_SearchForDevice(
2158a978a17SVictor Perevertkin __in FxObject* Object,
2168a978a17SVictor Perevertkin __out_opt IFxHasCallbacks** Callbacks
2178a978a17SVictor Perevertkin )
2188a978a17SVictor Perevertkin {
2198a978a17SVictor Perevertkin FxObject* pParent, *pOrigParent;
2208a978a17SVictor Perevertkin FxDeviceBase* pDeviceBase;
2218a978a17SVictor Perevertkin FxQueryInterfaceParams cbParams = { (PVOID*) Callbacks, FX_TYPE_IHASCALLBACKS, 0 };
2228a978a17SVictor Perevertkin PVOID pTag;
2238a978a17SVictor Perevertkin
2248a978a17SVictor Perevertkin pDeviceBase = Object->GetDeviceBase();
2258a978a17SVictor Perevertkin if (pDeviceBase == NULL) {
2268a978a17SVictor Perevertkin DoTraceLevelMessage(
2278a978a17SVictor Perevertkin Object->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGOBJECT,
2288a978a17SVictor Perevertkin "WDFHANDLE %p does not have a WDFDEVICE as an ancestor",
2298a978a17SVictor Perevertkin Object->GetObjectHandle());
2308a978a17SVictor Perevertkin return NULL;
2318a978a17SVictor Perevertkin }
2328a978a17SVictor Perevertkin
2338a978a17SVictor Perevertkin if (Callbacks == NULL) {
2348a978a17SVictor Perevertkin //
2358a978a17SVictor Perevertkin // Caller is not interested in the callbacks interface, just return
2368a978a17SVictor Perevertkin // now without searching for it.
2378a978a17SVictor Perevertkin //
2388a978a17SVictor Perevertkin return pDeviceBase;
2398a978a17SVictor Perevertkin }
2408a978a17SVictor Perevertkin
2418a978a17SVictor Perevertkin //
2428a978a17SVictor Perevertkin // Init out parameter.
2438a978a17SVictor Perevertkin //
2448a978a17SVictor Perevertkin *Callbacks = NULL;
2458a978a17SVictor Perevertkin
2468a978a17SVictor Perevertkin pOrigParent = Object;
2478a978a17SVictor Perevertkin pTag = pOrigParent;
2488a978a17SVictor Perevertkin
2498a978a17SVictor Perevertkin //
2508a978a17SVictor Perevertkin // By adding a reference now, we simulate what GetParentObjectReferenced
2518a978a17SVictor Perevertkin // does later, thus allowing simple logic on when/how to release the
2528a978a17SVictor Perevertkin // reference on exit.
2538a978a17SVictor Perevertkin //
2548a978a17SVictor Perevertkin Object->ADDREF(pTag);
2558a978a17SVictor Perevertkin
2568a978a17SVictor Perevertkin do {
2578a978a17SVictor Perevertkin //
2588a978a17SVictor Perevertkin // If successful, Callbacks will be != NULL
2598a978a17SVictor Perevertkin //
2608a978a17SVictor Perevertkin if (NT_SUCCESS(Object->QueryInterface(&cbParams))) {
2618a978a17SVictor Perevertkin ASSERT(*Callbacks != NULL);
2628a978a17SVictor Perevertkin //
2638a978a17SVictor Perevertkin // Release the reference previously taken by the top of the function
2648a978a17SVictor Perevertkin // or GetParentObjectReferenced in a previous pass in the loop.
2658a978a17SVictor Perevertkin //
2668a978a17SVictor Perevertkin Object->RELEASE(pTag);
2678a978a17SVictor Perevertkin return pDeviceBase;
2688a978a17SVictor Perevertkin }
2698a978a17SVictor Perevertkin
2708a978a17SVictor Perevertkin pParent = Object->GetParentObjectReferenced(pTag);
2718a978a17SVictor Perevertkin
2728a978a17SVictor Perevertkin //
2738a978a17SVictor Perevertkin // Release the reference previously taken by the top of the function
2748a978a17SVictor Perevertkin // or GetParentObjectReferenced in a previous pass in the loop.
2758a978a17SVictor Perevertkin //
2768a978a17SVictor Perevertkin Object->RELEASE(pTag);
2778a978a17SVictor Perevertkin
2788a978a17SVictor Perevertkin Object = pParent;
2798a978a17SVictor Perevertkin } while (Object != NULL);
2808a978a17SVictor Perevertkin
2818a978a17SVictor Perevertkin ASSERT(Object == NULL);
2828a978a17SVictor Perevertkin
2838a978a17SVictor Perevertkin //
2848a978a17SVictor Perevertkin // Queue presented requests do not have parents (to increase performance).
2858a978a17SVictor Perevertkin // Try to find the callback interface on this object's device base.
2868a978a17SVictor Perevertkin //
2878a978a17SVictor Perevertkin if (NT_SUCCESS(pDeviceBase->QueryInterface(&cbParams))) {
2888a978a17SVictor Perevertkin ASSERT(*Callbacks != NULL);
2898a978a17SVictor Perevertkin //
2908a978a17SVictor Perevertkin // Success, we got a callback interface.
2918a978a17SVictor Perevertkin //
2928a978a17SVictor Perevertkin return pDeviceBase;
2938a978a17SVictor Perevertkin }
2948a978a17SVictor Perevertkin
2958a978a17SVictor Perevertkin DoTraceLevelMessage(
2968a978a17SVictor Perevertkin pOrigParent->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGOBJECT,
2978a978a17SVictor Perevertkin "WDFHANDLE %p does not have a callbacks interface in its object tree"
2988a978a17SVictor Perevertkin "(WDFDEVICE %p)", pOrigParent->GetObjectHandle(),
2998a978a17SVictor Perevertkin pDeviceBase->GetHandle());
3008a978a17SVictor Perevertkin
3018a978a17SVictor Perevertkin return pDeviceBase;
3028a978a17SVictor Perevertkin }
3038a978a17SVictor Perevertkin
3048a978a17SVictor Perevertkin FxDeviceBase*
_SearchForDevice(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in_opt PWDF_OBJECT_ATTRIBUTES Attributes)3058a978a17SVictor Perevertkin FxDeviceBase::_SearchForDevice(
3068a978a17SVictor Perevertkin __in PFX_DRIVER_GLOBALS FxDriverGlobals,
3078a978a17SVictor Perevertkin __in_opt PWDF_OBJECT_ATTRIBUTES Attributes
3088a978a17SVictor Perevertkin )
3098a978a17SVictor Perevertkin {
3108a978a17SVictor Perevertkin FxObject* pParentObject;
3118a978a17SVictor Perevertkin FxDeviceBase* pDeviceBase;
3128a978a17SVictor Perevertkin
3138a978a17SVictor Perevertkin if (Attributes == NULL || Attributes->ParentObject == NULL) {
3148a978a17SVictor Perevertkin return NULL;
3158a978a17SVictor Perevertkin }
3168a978a17SVictor Perevertkin
3178a978a17SVictor Perevertkin FxObjectHandleGetPtr(FxDriverGlobals,
3188a978a17SVictor Perevertkin Attributes->ParentObject,
3198a978a17SVictor Perevertkin FX_TYPE_OBJECT,
3208a978a17SVictor Perevertkin (PVOID*) &pParentObject);
3218a978a17SVictor Perevertkin
3228a978a17SVictor Perevertkin pDeviceBase = _SearchForDevice(pParentObject, NULL);
3238a978a17SVictor Perevertkin
3248a978a17SVictor Perevertkin return pDeviceBase;
3258a978a17SVictor Perevertkin }
3268a978a17SVictor Perevertkin
3278a978a17SVictor Perevertkin _Must_inspect_result_
3288a978a17SVictor Perevertkin NTSTATUS
AllocateTarget(_Out_ FxIoTarget ** Target,_In_ BOOLEAN SelfTarget)3298a978a17SVictor Perevertkin FxDeviceBase::AllocateTarget(
3308a978a17SVictor Perevertkin _Out_ FxIoTarget** Target,
3318a978a17SVictor Perevertkin _In_ BOOLEAN SelfTarget
3328a978a17SVictor Perevertkin )
3338a978a17SVictor Perevertkin /*++
3348a978a17SVictor Perevertkin
3358a978a17SVictor Perevertkin Routine Description:
3368a978a17SVictor Perevertkin
3378a978a17SVictor Perevertkin Allocates an IO Target or an Self IO target for the FxDevice.
3388a978a17SVictor Perevertkin
3398a978a17SVictor Perevertkin Arguments:
3408a978a17SVictor Perevertkin
3418a978a17SVictor Perevertkin Target - Out - returns the pointer to the allocated IO target.
3428a978a17SVictor Perevertkin
3438a978a17SVictor Perevertkin SelfTarget - If TRUE allocates an Self IO Target, if FALSE allocates
3448a978a17SVictor Perevertkin a regular IO target.
3458a978a17SVictor Perevertkin
3468a978a17SVictor Perevertkin Returns:
3478a978a17SVictor Perevertkin
3488a978a17SVictor Perevertkin NTSTATUS
3498a978a17SVictor Perevertkin
3508a978a17SVictor Perevertkin --*/
3518a978a17SVictor Perevertkin {
3528a978a17SVictor Perevertkin FxIoTarget* pTarget;
3538a978a17SVictor Perevertkin NTSTATUS status;
3548a978a17SVictor Perevertkin
3558a978a17SVictor Perevertkin if (SelfTarget) {
3568a978a17SVictor Perevertkin pTarget = (FxIoTarget*) new(GetDriverGlobals(), WDF_NO_OBJECT_ATTRIBUTES)
3578a978a17SVictor Perevertkin FxIoTargetSelf(GetDriverGlobals(), sizeof(FxIoTargetSelf));
3588a978a17SVictor Perevertkin } else {
3598a978a17SVictor Perevertkin pTarget = new(GetDriverGlobals(), WDF_NO_OBJECT_ATTRIBUTES)
3608a978a17SVictor Perevertkin FxIoTarget(GetDriverGlobals(), sizeof(FxIoTarget));
3618a978a17SVictor Perevertkin }
3628a978a17SVictor Perevertkin
3638a978a17SVictor Perevertkin if (pTarget == NULL) {
3648a978a17SVictor Perevertkin status = STATUS_INSUFFICIENT_RESOURCES;
3658a978a17SVictor Perevertkin
3668a978a17SVictor Perevertkin DoTraceLevelMessage(
3678a978a17SVictor Perevertkin GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
3688a978a17SVictor Perevertkin "WDFDEVICE %p could not allocate a WDFIOTARGET, %!STATUS!",
3698a978a17SVictor Perevertkin GetHandle(), status);
3708a978a17SVictor Perevertkin
3718a978a17SVictor Perevertkin goto Done;
3728a978a17SVictor Perevertkin }
3738a978a17SVictor Perevertkin
3748a978a17SVictor Perevertkin status = AddIoTarget(pTarget);
3758a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
3768a978a17SVictor Perevertkin DoTraceLevelMessage(
3778a978a17SVictor Perevertkin GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
3788a978a17SVictor Perevertkin "WDFDEVICE %p failed to initialize (add) a WDFIOTARGET, %!STATUS!",
3798a978a17SVictor Perevertkin GetHandle(), status);
3808a978a17SVictor Perevertkin
3818a978a17SVictor Perevertkin goto Done;
3828a978a17SVictor Perevertkin }
3838a978a17SVictor Perevertkin
3848a978a17SVictor Perevertkin status = pTarget->Init(this);
3858a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
3868a978a17SVictor Perevertkin DoTraceLevelMessage(
3878a978a17SVictor Perevertkin GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
3888a978a17SVictor Perevertkin "WDFDEVICE %p failed to initialize a WDFIOTARGET, %!STATUS!",
3898a978a17SVictor Perevertkin GetHandle(), status);
3908a978a17SVictor Perevertkin
3918a978a17SVictor Perevertkin goto Done;
3928a978a17SVictor Perevertkin }
3938a978a17SVictor Perevertkin
3948a978a17SVictor Perevertkin status = pTarget->Commit(WDF_NO_OBJECT_ATTRIBUTES, NULL, this);
3958a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
3968a978a17SVictor Perevertkin DoTraceLevelMessage(
3978a978a17SVictor Perevertkin GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
3988a978a17SVictor Perevertkin "WDFDEVICE %p failed to initialize (commit) a WDFIOTARGET, %!STATUS!",
3998a978a17SVictor Perevertkin GetHandle(), status);
4008a978a17SVictor Perevertkin
4018a978a17SVictor Perevertkin goto Done;
4028a978a17SVictor Perevertkin }
4038a978a17SVictor Perevertkin
4048a978a17SVictor Perevertkin status = STATUS_SUCCESS;
4058a978a17SVictor Perevertkin
4068a978a17SVictor Perevertkin Done:
4078a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
4088a978a17SVictor Perevertkin if (pTarget != NULL) {
4098a978a17SVictor Perevertkin pTarget->DeleteFromFailedCreate();
4108a978a17SVictor Perevertkin pTarget = NULL;
4118a978a17SVictor Perevertkin }
4128a978a17SVictor Perevertkin }
4138a978a17SVictor Perevertkin
4148a978a17SVictor Perevertkin *Target = pTarget;
4158a978a17SVictor Perevertkin
4168a978a17SVictor Perevertkin return status;
4178a978a17SVictor Perevertkin }
418