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