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