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