1 /*++
2 
3 Copyright (c) Microsoft. All rights reserved.
4 
5 Module Name:
6 
7     FxMessageDispatchUm.cpp
8 
9 Abstract:
10 
11     Implements the host process dispatcher object.  See header file for
12     details.
13 
14 Author:
15 
16 
17 
18 Environment:
19 
20     User mode only
21 
22 Revision History:
23 
24 
25 
26 --*/
27 
28 #include "fxmin.hpp"
29 #include "fxldrum.h"
30 
31 extern "C"
32 {
33 #include "FxMessageDispatchUm.tmh"
34 }
35 
36 // {cba20727-0910-4a8a-aada-c31d5cf5bf20}
37 extern const GUID IID_FxMessageDispatch =
38 {0xcba20727, 0x0910, 0x4a8a, { 0xaa, 0xda, 0xc3, 0x1d, 0x5c, 0xf5, 0xbf, 0x20 }};
39 
40 //
41 // Manager functions.
42 //
43 NTSTATUS
_CreateAndInitialize(_In_ PFX_DRIVER_GLOBALS DriverGlobals,_In_ FxDevice * Device,_Out_ FxMessageDispatch ** ppWudfDispatcher)44 FxMessageDispatch::_CreateAndInitialize(
45     _In_ PFX_DRIVER_GLOBALS DriverGlobals,
46     _In_ FxDevice* Device,
47     _Out_ FxMessageDispatch ** ppWudfDispatcher
48    )
49 {
50     HRESULT             hr = S_OK;
51     FxMessageDispatch *   pWudfDispatcher = NULL;
52     NTSTATUS status;
53 
54     *ppWudfDispatcher = NULL;
55 
56     pWudfDispatcher = new (DriverGlobals) FxMessageDispatch(Device);
57     if (NULL == pWudfDispatcher) {
58         hr = E_OUTOFMEMORY;
59         DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
60             "Memory allocation failure. Cannot create Dispatcher object.\n");
61         goto Done;
62     }
63 
64     *ppWudfDispatcher = pWudfDispatcher;
65 
66 Done:
67 
68     if (FAILED(hr)) {
69         status = Device->NtStatusFromHr(hr);
70     }
71     else {
72         status = STATUS_SUCCESS;
73     }
74 
75     return status;
76 }
77 
78 //
79 // IUnknown
80 //
81 ULONG
AddRef()82 FxMessageDispatch::AddRef()
83 {
84     LONG cRefs = InterlockedIncrement( &m_cRefs );
85 
86     //
87     // This allows host to manage the lifetime of FxDevice.
88     //
89     m_Device->ADDREF(this);
90 
91     return cRefs;
92 }
93 
94 
95 ULONG
Release()96 FxMessageDispatch::Release()
97 {
98     LONG cRefs = InterlockedDecrement( &m_cRefs );
99 
100     if (0 == cRefs) {
101         //
102         // The lifetime of this object is controlled by FxDevice
103         // object (the container object), and not by this ref count. FxDevice
104         // will delete this object in its destructior.
105         //
106         DO_NOTHING();
107     }
108 
109     //
110     // This allows host to manage the lifetime of FxDevice. If this is the last
111     // release on FxDevice, FxDevice will e deleted and this object will be
112     // deleted as part of FxDevice destructor.
113     //
114     m_Device->RELEASE(this);
115 
116     return cRefs;
117 }
118 
119 HRESULT
QueryInterface(_In_ const IID & iid,_Out_ void ** ppv)120 FxMessageDispatch::QueryInterface(
121     _In_ const IID&     iid,
122     _Out_ void **       ppv
123     )
124 {
125     if ( NULL == ppv ) {
126         return E_INVALIDARG;
127     }
128 
129     if ( iid == IID_IUnknown) {
130         *ppv = static_cast<IUnknown *> (this);
131     }
132     else if ( iid == IID_IFxMessageDispatch ) {
133         *ppv = static_cast<IFxMessageDispatch *> (this);
134     }
135     else if ( iid == IID_IFxMessageDispatch2 ) {
136         *ppv = static_cast<IFxMessageDispatch2 *> (this);
137     }
138     else if ( iid == IID_FxMessageDispatch ) {
139         *ppv = this;
140     }
141     else {
142         *ppv = NULL;
143         return E_NOINTERFACE;
144     }
145 
146     this->AddRef();
147     return S_OK;
148 }
149 
150 //
151 // IFxMessageDispatch
152 //
153 void
DispatchPnP(_In_ IWudfIrp * pIrp)154 FxMessageDispatch::DispatchPnP(
155     _In_ IWudfIrp *  pIrp
156     )
157 {
158     IWudfPnpIrp * pIPnpIrp = NULL;
159 
160     HRESULT hrQI = pIrp->QueryInterface(IID_IWudfPnpIrp, (PVOID*)&pIPnpIrp);
161     FX_VERIFY(INTERNAL, CHECK_QI(hrQI, pIPnpIrp));
162 
163     if (IRP_MJ_POWER == pIPnpIrp->GetMajorFunction()) {
164         GetDriverObject()->MajorFunction[IRP_MJ_POWER](GetDeviceObject(),
165                                                        pIrp,
166                                                        NULL);
167     }
168     else {
169         GetDriverObject()->MajorFunction[IRP_MJ_PNP](GetDeviceObject(),
170                                                      pIrp,
171                                                      NULL);
172     }
173 
174     SAFE_RELEASE(pIPnpIrp);
175 }
176 
177 void
CreateFile(_In_ IWudfIoIrp * pCreateIrp)178 FxMessageDispatch::CreateFile(
179     _In_ IWudfIoIrp *  pCreateIrp
180     )
181 {
182     GetDriverObject()->MajorFunction[IRP_MJ_CREATE](GetDeviceObject(),
183                                                     pCreateIrp,
184                                                     NULL);
185 }
186 
187 void
DeviceControl(_In_ IWudfIoIrp * pIrp,_In_opt_ IUnknown * pFxContext)188 FxMessageDispatch::DeviceControl(
189     _In_ IWudfIoIrp * pIrp,
190     _In_opt_ IUnknown * pFxContext
191     )
192 {
193     GetDriverObject()->MajorFunction[IRP_MJ_DEVICE_CONTROL](GetDeviceObject(),
194                                                             pIrp,
195                                                             pFxContext);
196 }
197 
198 void
ReadFile(_In_ IWudfIoIrp * pIrp,_In_opt_ IUnknown * pFxContext)199 FxMessageDispatch::ReadFile(
200     _In_ IWudfIoIrp * pIrp,
201     _In_opt_ IUnknown * pFxContext
202     )
203 {
204     GetDriverObject()->MajorFunction[IRP_MJ_READ](GetDeviceObject(), pIrp, pFxContext);
205 }
206 
207 void
WriteFile(_In_ IWudfIoIrp * pIrp,_In_opt_ IUnknown * pFxContext)208 FxMessageDispatch::WriteFile(
209     _In_ IWudfIoIrp * pIrp,
210     _In_opt_ IUnknown * pFxContext
211     )
212 {
213     GetDriverObject()->MajorFunction[IRP_MJ_WRITE](GetDeviceObject(), pIrp, pFxContext);
214 }
215 
216 void
CleanupFile(_In_ IWudfIoIrp * pIrp,_In_ IUnknown * pFxContext)217 FxMessageDispatch::CleanupFile(
218     _In_ IWudfIoIrp * pIrp,
219     _In_ IUnknown * pFxContext
220     )
221 {
222     GetDriverObject()->MajorFunction[IRP_MJ_CLEANUP](GetDeviceObject(), pIrp, pFxContext);
223 }
224 
225 void
CloseFile(_In_ IWudfIoIrp * pIrp,_In_ IUnknown * pFxContext)226 FxMessageDispatch::CloseFile(
227     _In_ IWudfIoIrp * pIrp,
228     _In_ IUnknown * pFxContext
229     )
230 {
231     GetDriverObject()->MajorFunction[IRP_MJ_CLOSE](GetDeviceObject(), pIrp, pFxContext);
232 }
233 
234 void
FlushBuffers(_In_ IWudfIoIrp * pIrp,_In_opt_ IUnknown * pFxContext)235 FxMessageDispatch::FlushBuffers(
236     _In_ IWudfIoIrp * pIrp,
237     _In_opt_ IUnknown * pFxContext
238     )
239 {
240     GetDriverObject()->MajorFunction[IRP_MJ_FLUSH_BUFFERS](GetDeviceObject(),
241                                                            pIrp,
242                                                            pFxContext);
243 }
244 
245 void
QueryInformationFile(_In_ IWudfIoIrp * pIrp,_In_opt_ IUnknown * pFxContext)246 FxMessageDispatch::QueryInformationFile(
247     _In_ IWudfIoIrp * pIrp,
248     _In_opt_ IUnknown * pFxContext
249     )
250 {
251     GetDriverObject()->MajorFunction[IRP_MJ_QUERY_INFORMATION](
252                                                     GetDeviceObject(),
253                                                     pIrp,
254                                                     pFxContext
255                                                     );
256 }
257 
258 void
SetInformationFile(_In_ IWudfIoIrp * pIrp,_In_opt_ IUnknown * pFxContext)259 FxMessageDispatch::SetInformationFile(
260     _In_ IWudfIoIrp * pIrp,
261     _In_opt_ IUnknown * pFxContext
262     )
263 {
264     GetDriverObject()->MajorFunction[IRP_MJ_SET_INFORMATION](GetDeviceObject(),
265                                                              pIrp,
266                                                              pFxContext);
267 }
268 
269 VOID
GetPreferredTransferMode(_Out_ UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL * RetrievalMode,_Out_ UMINT::WDF_DEVICE_IO_TYPE * RWPreference,_Out_ UMINT::WDF_DEVICE_IO_TYPE * IoctlPreference)270 FxMessageDispatch::GetPreferredTransferMode(
271     _Out_ UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL *RetrievalMode,
272     _Out_ UMINT::WDF_DEVICE_IO_TYPE *RWPreference,
273     _Out_ UMINT::WDF_DEVICE_IO_TYPE *IoctlPreference
274     )
275 {
276     FxDevice::GetPreferredTransferMode(GetDeviceObject(),
277                                        RetrievalMode,
278                                        (WDF_DEVICE_IO_TYPE*)RWPreference,
279                                        (WDF_DEVICE_IO_TYPE*)IoctlPreference);
280 }
281 
282 ULONG
GetDirectTransferThreshold(VOID)283 FxMessageDispatch::GetDirectTransferThreshold(
284     VOID
285     )
286 {
287     return m_Device->GetDirectTransferThreshold();
288 }
289 
290 NTSTATUS
ProcessWmiPowerQueryOrSetData(_In_ RdWmiPowerAction Action,_Out_ BOOLEAN * QueryResult)291 FxMessageDispatch::ProcessWmiPowerQueryOrSetData(
292     _In_ RdWmiPowerAction Action,
293     _Out_ BOOLEAN *QueryResult
294     )
295 {
296     return m_Device->ProcessWmiPowerQueryOrSetData(Action, QueryResult);
297 }
298 
299 WUDF_INTERFACE_CONTEXT
RemoteInterfaceArrival(_In_ LPCGUID pDeviceInterfaceGuid,_In_ PCWSTR pSymbolicLink)300 FxMessageDispatch::RemoteInterfaceArrival(
301     _In_    LPCGUID pDeviceInterfaceGuid,
302     _In_    PCWSTR  pSymbolicLink
303     )
304 {
305     return FxDevice::RemoteInterfaceArrival(GetDeviceObject(),
306                                             pDeviceInterfaceGuid,
307                                             pSymbolicLink);
308 }
309 
310 void
RemoteInterfaceRemoval(_In_ WUDF_INTERFACE_CONTEXT RemoteInterfaceID)311 FxMessageDispatch::RemoteInterfaceRemoval(
312     _In_    WUDF_INTERFACE_CONTEXT RemoteInterfaceID
313     )
314 {
315     FxDevice::RemoteInterfaceRemoval(GetDeviceObject(),
316                                      RemoteInterfaceID);
317 }
318 
319 BOOL
TransportQueryID(_In_ DWORD Id,_In_ PVOID DataBuffer,_In_ SIZE_T cbDataBufferSize)320 FxMessageDispatch::TransportQueryID(
321     _In_    DWORD  Id,
322     _In_    PVOID  DataBuffer,
323     _In_    SIZE_T cbDataBufferSize
324     )
325 {
326     return FxDevice::TransportQueryId(GetDeviceObject(),
327                                       Id,
328                                       DataBuffer,
329                                       cbDataBufferSize);
330 }
331 
332 void
PoFxDevicePowerRequired(void)333 FxMessageDispatch::PoFxDevicePowerRequired(
334     void
335     )
336 {
337     FxDevice::PoFxDevicePowerRequired(GetDeviceObject());
338 }
339 
340 void
PoFxDevicePowerNotRequired(void)341 FxMessageDispatch::PoFxDevicePowerNotRequired(
342     void
343     )
344 {
345     FxDevice::PoFxDevicePowerNotRequired(GetDeviceObject());
346 }
347 
348 //
349 // Additional public functions.
350 //
351 
352 //
353 // Returns the Dispatcher object from the given interface without
354 // incrementing the refcount.
355 //
356 FxMessageDispatch*
_GetObjFromItf(_In_ IFxMessageDispatch * pIFxMessageDispatch)357 FxMessageDispatch::_GetObjFromItf(
358     _In_ IFxMessageDispatch* pIFxMessageDispatch
359     )
360 {
361     FxMessageDispatch * pWudfDispatcher = NULL;
362     HRESULT hrQI = pIFxMessageDispatch->QueryInterface(
363                         IID_FxMessageDispatch,
364                         reinterpret_cast<void**>(&pWudfDispatcher)
365                         );
366     FX_VERIFY(INTERNAL, CHECK_QI(hrQI, pWudfDispatcher));
367     pWudfDispatcher->Release(); //release the reference taken by QI
368     return pWudfDispatcher;
369 }
370 
371 //
372 // Returns the specified interface from the given object without
373 // incrementing the refcount.
374 //
375 IFxMessageDispatch*
_GetDispatcherItf(_In_ FxMessageDispatch * pWudfDispatcher)376 FxMessageDispatch::_GetDispatcherItf(
377     _In_ FxMessageDispatch* pWudfDispatcher
378     )
379 {
380     IFxMessageDispatch * pIFxMessageDispatch = NULL;
381     HRESULT hrQI = pWudfDispatcher->QueryInterface(IID_IFxMessageDispatch,
382                                                   (PVOID*)&pIFxMessageDispatch);
383     FX_VERIFY(INTERNAL, CHECK_QI(hrQI, pIFxMessageDispatch));
384     pIFxMessageDispatch->Release(); //release the reference taken by QI
385     return pIFxMessageDispatch;
386 }
387