1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxSyncRequest.cpp 8 9 Abstract: 10 11 This module implements FxSyncRequest object 12 13 Author: 14 15 Environment: 16 17 Both kernel and user mode 18 19 Revision History: 20 21 22 23 --*/ 24 25 #include "coreprivshared.hpp" 26 27 // Tracing support 28 extern "C" { 29 // #include "FxSyncRequest.tmh" 30 } 31 32 FxSyncRequest::FxSyncRequest( 33 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 34 __in_opt FxRequestContext* Context, 35 __in_opt WDFREQUEST Request 36 ) : 37 FxRequestBase(FxDriverGlobals, 38 0, // no handle for this object 39 NULL, // No PIRP 40 FxRequestDoesNotOwnIrp, 41 FxRequestConstructorCallerIsFx, 42 FxObjectTypeEmbedded) 43 /*++ 44 45 Routine Description: 46 Constructs an FxSyncRequest 47 48 Arguments: 49 Context - Context to associate with this object 50 51 Request - (opt) real Request object. 52 53 Return Value: 54 None. 55 56 --*/ 57 { 58 // 59 // If m_CleanContextOnDestroy is TRUE, m_RequestContext is cleared in the 60 // destructor so that the base class destructor does not free the context. 61 // This is useful if the context is also stack based. 62 // 63 if (Context != NULL) { 64 m_ClearContextOnDestroy = TRUE; 65 } 66 67 else { 68 m_ClearContextOnDestroy = FALSE; 69 } 70 71 m_RequestContext = Context; 72 73 if (Request == NULL) { 74 m_TrueRequest = this; 75 m_RequestBaseFlags |= FxRequestBaseSyncCleanupContext; 76 } 77 else { 78 FxRequest* pRequest; 79 80 FxObjectHandleGetPtr(FxDriverGlobals, 81 Request, 82 FX_TYPE_REQUEST, 83 (PVOID*) &pRequest); 84 m_TrueRequest = pRequest; 85 86 // 87 // pRequest could be currently formatted and the caller has not reused the request 88 // in between the format and the sync. send. This will place pRequest into the 89 // correct state. 90 // 91 if (pRequest->m_RequestContext != NULL) { 92 pRequest->m_RequestContext->ReleaseAndRestore(pRequest); 93 } 94 pRequest->SetContext(Context); 95 pRequest->m_RequestBaseFlags |= FxRequestBaseSyncCleanupContext; 96 } 97 98 // 99 // Indicate that there is no object header so when FxObject::Release is 100 // called on the final ref count removal, it doesn't try to touch hyperspace. 101 // 102 SetNoContextHeader(); 103 } 104 105 FxSyncRequest::~FxSyncRequest( 106 VOID 107 ) 108 /*++ 109 110 Routine Description: 111 Destroys an FxSyncRequest. Releases the initial reference taken during the 112 creation of this object. If there are any outstanding references to the 113 object, the destructor will not exit they are released. 114 115 Arguments: 116 None. 117 118 Return Value: 119 None. 120 121 --*/ 122 { 123 ULONG count; 124 125 // 126 // Release the initial reference taken on create. Use the base release call 127 // so that we don't unnecessarily set the event unless we have to. 128 // 129 count = FxRequestBase::RELEASE(NULL); // __super call 130 131 // 132 // For a driver supplied request(m_TrueRequest) the request context is 133 // allocated on the stack so clear it. 134 // 135 if (m_TrueRequest != this && m_ClearContextOnDestroy) { 136 m_TrueRequest->m_RequestContext = NULL; 137 m_TrueRequest->m_RequestBaseFlags &= ~FxRequestBaseSyncCleanupContext; 138 } 139 140 // 141 // Clear the context so that it is not automatically deleted. Useful 142 // if the caller's context is also allocated on the stack and does not 143 // need to be freed (as does not have to rememeber to clear the context 144 // before this object goes out of scope). 145 // 146 if (m_ClearContextOnDestroy) { 147 m_RequestContext = NULL; 148 } 149 150 if (count > 0) { 151 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIO, 152 "Request %p, waiting on event %p", 153 this, m_DestroyedEvent.GetEvent()); 154 155 m_DestroyedEvent.EnterCRAndWaitAndLeave(); 156 157 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIO, 158 "Request %p, wait on event %p done", 159 this, m_DestroyedEvent.GetEvent()); 160 } 161 } 162 163 VOID 164 FxSyncRequest::SelfDestruct( 165 VOID 166 ) 167 /*++ 168 169 Routine Description: 170 Override of base class SelfDestruct. Since this is a stack based object, 171 we must delay the stack caused destruction until all outstanding references 172 have been released. SelfDestruct is called when the last reference has been 173 removed from the object. 174 175 Since this is a stack based object, do nothing to free our memory (going out 176 of scope will do the trick). 177 178 Arguments: 179 None. 180 181 Return Value: 182 None. 183 184 --*/ 185 { 186 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGIO, 187 "SyncRequest %p, signaling event %p on SelfDestruct", 188 this, m_DestroyedEvent.GetEvent()); 189 190 m_DestroyedEvent.Set(); 191 } 192