1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDriverUm.cpp
8 
9 Abstract:
10 
11     This is the main driver framework.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     User mode only
20 
21 Revision History:
22 
23 
24 
25 --*/
26 
27 #include "coreprivshared.hpp"
28 #include "fxiotarget.hpp"
29 #include "fxldrum.h"
30 
31 // Tracing support
32 extern "C" {
33 #include "FxDriverUm.tmh"
34 }
35 
36 
37 _Must_inspect_result_
38 NTSTATUS
AddDevice(_In_ PDRIVER_OBJECT_UM DriverObject,_In_ PVOID Context,_In_ IWudfDeviceStack * DevStack,_In_ LPCWSTR KernelDeviceName,_In_opt_ HKEY PdoKey,_In_ LPCWSTR ServiceName,_In_ LPCWSTR DevInstanceID,_In_ ULONG DriverID)39 FxDriver::AddDevice (
40     _In_  PDRIVER_OBJECT_UM         DriverObject,
41     _In_  PVOID                     Context,
42     _In_  IWudfDeviceStack *        DevStack,
43     _In_  LPCWSTR                   KernelDeviceName,
44     _In_opt_ HKEY                   PdoKey,
45     _In_  LPCWSTR                   ServiceName,
46     _In_  LPCWSTR                   DevInstanceID,
47     _In_  ULONG                     DriverID
48     )
49 {
50     FxDriver *pDriver;
51 
52     //
53     // Context parameter is CWudfDriverGlobals in legacy UMDF. Not used in
54     // UMDF 2.0
55     //
56     UNREFERENCED_PARAMETER(Context);
57 
58     pDriver = FxDriver::GetFxDriver(DriverObject);
59 
60 
61 
62     if (pDriver != NULL) {
63         return pDriver->AddDevice(DevStack,
64                                   KernelDeviceName,
65                                   PdoKey,
66                                   ServiceName,
67                                   DevInstanceID,
68                                   DriverID
69                                   );
70     }
71 
72     return STATUS_UNSUCCESSFUL;
73 }
74 
75 _Must_inspect_result_
76 NTSTATUS
AddDevice(_In_ IWudfDeviceStack * DevStack,_In_ LPCWSTR KernelDeviceName,_In_opt_ HKEY PdoKey,_In_ LPCWSTR ServiceName,_In_ LPCWSTR DevInstanceID,_In_ ULONG DriverID)77 FxDriver::AddDevice(
78     _In_  IWudfDeviceStack *        DevStack,
79     _In_  LPCWSTR                   KernelDeviceName,
80     _In_opt_ HKEY                   PdoKey,
81     _In_  LPCWSTR                   ServiceName,
82     _In_  LPCWSTR                   DevInstanceID,
83     _In_  ULONG                     DriverID
84     )
85 {
86     WDFDEVICE_INIT init(this);
87     FxDevice* pDevice;
88     NTSTATUS status;
89     HRESULT hr = S_OK;
90     LONG lRetVal = -1;
91 
92     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
93                         "Enter AddDevice DevStack %p", DevStack);
94 
95     //FX_VERIFY(INTERNAL, CHECK_NOT_NULL(DevStack));
96     //FX_VERIFY(INTERNAL, CHECK_NOT_NULL(KernelDeviceName));
97     //FX_VERIFY(INTERNAL, CHECK_HANDLE(PdoKey));
98     //FX_VERIFY(INTERNAL, CHECK_NOT_NULL(ServiceName));
99     //FX_VERIFY(INTERNAL, CHECK_NOT_NULL(DevInstanceID));
100 
101     pDevice = NULL;
102     init.CreatedOnStack = TRUE;
103     init.InitType = FxDeviceInitTypeFdo;
104     init.Fdo.PhysicalDevice = NULL;
105 
106     //
107     // Capture the input parameters
108     //
109     init.DevStack = DevStack;
110     init.DriverID = DriverID;
111 
112     lRetVal = RegOpenKeyEx(
113         PdoKey,
114         NULL,
115         0,
116         KEY_READ,
117         &init.PdoKey
118         );
119 
120     if (ERROR_SUCCESS != lRetVal) {
121         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
122                             "Registry key open failed for the PDO key, "
123                             "winerror %!WINERROR!", lRetVal);
124 
125         hr = HRESULT_FROM_WIN32(lRetVal);
126         return FxDevice::NtStatusFromHr(DevStack, hr);
127     }
128 
129     size_t len = 0;
130     hr = StringCchLengthW(ServiceName, STRSAFE_MAX_CCH, &len);
131     if (FAILED(hr)) {
132         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
133                             "Registry path string too long or badly formed "
134                             "path. Invalid configuration HRESULT %!hresult!",
135                             hr);
136         return FxDevice::NtStatusFromHr(DevStack, hr);
137     }
138 
139     len += 1;    // Add one for the string termination character
140     init.ConfigRegistryPath = new WCHAR[len];
141     if (NULL == init.ConfigRegistryPath) {
142         hr = E_OUTOFMEMORY;
143         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
144                             "Failed to allocate memory for Config path"
145                             " HRESULT %!hresult!", hr);
146 
147         return FxDevice::NtStatusFromHr(DevStack, hr);
148     }
149 
150     hr = StringCchCopyW(init.ConfigRegistryPath, len, ServiceName);
151     if (FAILED(hr)) {
152         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
153                             "Failed to copy the configuration path status "
154                             "%!hresult!", hr);
155         return FxDevice::NtStatusFromHr(DevStack, hr);
156     }
157 
158     //
159     // Capture the PDO device instance ID.
160     //
161     len = 0;
162     hr = StringCchLengthW(DevInstanceID, STRSAFE_MAX_CCH, &len);
163     if (FAILED(hr)) {
164         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
165                             "Device Instance ID string too long or badly formed"
166                             " path. Invalid configuration %!hresult!", hr);
167         return FxDevice::NtStatusFromHr(DevStack, hr);
168     }
169 
170     len += 1; // Add one for the string termination character
171     init.DevInstanceID = new WCHAR[len];
172     if (NULL == init.DevInstanceID) {
173         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
174                             "Failed to allocate memory for DevInstanceID "
175                             "%!hresult!", hr);
176         hr = E_OUTOFMEMORY;
177         return FxDevice::NtStatusFromHr(DevStack, hr);
178     }
179 
180     hr = StringCchCopyW(init.DevInstanceID, len, DevInstanceID);
181     if (FAILED(hr)) {
182         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
183                             "Unable to copy DevInstanceID %!hresult!", hr);
184         return FxDevice::NtStatusFromHr(DevStack, hr);
185     }
186 
187     //
188     // Capture Kernel device name.
189     //
190     len = 0;
191     hr = StringCchLengthW(KernelDeviceName, STRSAFE_MAX_CCH, &len);
192     if (FAILED(hr)) {
193         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
194                             "Unable to determine KernelDeviceName length"
195                             "%!hresult!", hr);
196         return FxDevice::NtStatusFromHr(DevStack, hr);
197     }
198 
199     len += 1; // Add one for string termination character.
200     init.KernelDeviceName = new WCHAR[len];
201     if (init.KernelDeviceName == NULL) {
202         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
203                             "Failed to allocate memory for KernelDeviceName "
204                             "%!hresult!", hr);
205         hr = E_OUTOFMEMORY;
206         return FxDevice::NtStatusFromHr(DevStack, hr);
207     }
208 
209     hr = StringCchCopyW(init.KernelDeviceName, len, KernelDeviceName);
210     if (FAILED(hr)) {
211         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
212                             "Unable to copy kernel device name KernelDeviceName"
213                             " %!hresult!", hr);
214         return FxDevice::NtStatusFromHr(DevStack, hr);
215     }
216 
217     //
218     // Invoke driver's AddDevice callback
219     //
220     status = m_DriverDeviceAdd.Invoke(GetHandle(), &init);
221 
222     //
223     // Caller returned w/out creating a device, we are done.  Returning
224     // STATUS_SUCCESS w/out creating a device and attaching to the stack is OK,
225     // especially for filter drivers which selectively attach to devices.
226     //
227     if (init.CreatedDevice == NULL) {
228         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGPNP,
229                             "Driver did not create a device in "
230                             "EvtDriverAddDevice, status %!STATUS!", status);
231 
232         //
233         // We do not let filters affect the building of the rest of the stack.
234         // If they return error, we convert it to STATUS_SUCCESS.
235         //
236         if (init.Fdo.Filter && !NT_SUCCESS(status)) {
237             DoTraceLevelMessage(
238                 GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
239                 "Filter returned %!STATUS! without creating a WDFDEVICE, "
240                 "converting to STATUS_SUCCESS", status);
241             status = STATUS_SUCCESS;
242         }
243 
244         return status;
245     }
246 
247     pDevice = init.CreatedDevice;
248 
249     if (NT_SUCCESS(status)) {
250         //
251         // Make sure that DO_DEVICE_INITIALIZING is cleared.
252         // FxDevice::FdoInitialize does not do this b/c the driver writer may
253         // want the bit set until sometime after WdfDeviceCreate returns
254         //
255         pDevice->FinishInitializing();
256     }
257     else {
258         //
259         // Created a device, but returned error.
260         //
261         ASSERT(pDevice->IsPnp());
262         ASSERT(pDevice->m_CurrentPnpState == WdfDevStatePnpInit);
263 
264         status = pDevice->DeleteDeviceFromFailedCreate(status, TRUE);
265         pDevice = NULL;
266     }
267 
268     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
269                         "Exit, status %!STATUS!", status);
270 
271     return status;
272 }
273 
274 _Must_inspect_result_
275 NTSTATUS
AllocateDriverObjectExtensionAndStoreFxDriver(VOID)276 FxDriver::AllocateDriverObjectExtensionAndStoreFxDriver(
277     VOID
278     )
279 {
280     //
281     // No allocation needed for user-mode, just store FxDriver in driver object.
282     //
283     m_DriverObject.GetObject()->FxDriver = this;
284 
285     return STATUS_SUCCESS;
286 }
287 
288 FxDriver*
GetFxDriver(__in MdDriverObject DriverObject)289 FxDriver::GetFxDriver(
290     __in MdDriverObject DriverObject
291     )
292 {
293     return DriverObject->FxDriver;
294 }
295 
296 VOID
ClearDriverObjectFxDriver(VOID)297 FxDriver::ClearDriverObjectFxDriver(
298     VOID
299     )
300 {
301     PDRIVER_OBJECT_UM pDriverObj = m_DriverObject.GetObject();
302 
303     if (pDriverObj != NULL) {
304         pDriverObj->FxDriver = NULL;
305     }
306 }
307 
308 NTSTATUS
OpenParametersKey(VOID)309 FxDriver::OpenParametersKey(
310     VOID
311     )
312 {
313     HRESULT hr;
314     NTSTATUS status;
315 
316     PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
317     PDRIVER_OBJECT_UM pDrvObj = GetDriverObject();
318     IWudfDeviceStack* pDevStack = (IWudfDeviceStack*)pDrvObj->WudfDevStack;
319 
320     UMINT::WDF_PROPERTY_STORE_ROOT rootSpecifier;
321     UMINT::WDF_PROPERTY_STORE_RETRIEVE_FLAGS flags;
322     CANSI_STRING serviceNameA;
323     DECLARE_UNICODE_STRING_SIZE(serviceNameW, WDF_DRIVER_GLOBALS_NAME_LEN);
324     HKEY hKey;
325 
326     RtlInitAnsiString(&serviceNameA, FxDriverGlobals->Public.DriverName);
327     status = RtlAnsiStringToUnicodeString(&serviceNameW,
328                                           &serviceNameA,
329                                           FALSE);
330     if (NT_SUCCESS(status)) {
331         rootSpecifier.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
332         rootSpecifier.RootClass = UMINT::WdfPropertyStoreRootDriverParametersKey;
333         rootSpecifier.Qualifier.ParametersKey.ServiceName = serviceNameW.Buffer;
334 
335         flags = UMINT::WdfPropertyStoreCreateIfMissing;
336 
337         hr = pDevStack->CreateRegistryEntry(&rootSpecifier,
338                                             flags,
339                                             GENERIC_ALL & ~(GENERIC_WRITE | KEY_CREATE_SUB_KEY | WRITE_DAC),
340                                             NULL,
341                                             &hKey,
342                                             NULL);
343         status = FxDevice::NtStatusFromHr(pDevStack, hr);
344         if (NT_SUCCESS(status)) {
345             m_DriverParametersKey = hKey;
346         }
347     }
348 
349     return status;
350 }
351 
352 
353