1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDriverApi.cpp
8 
9 Abstract:
10 
11     This module contains the "C" interface for the FxDriver object.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Both kernel and user mode
20 
21 Revision History:
22 
23 --*/
24 
25 #include "coreprivshared.hpp"
26 
27 // Tracing support
28 extern "C" {
29 #include <ntverp.h>
30 // #include "FxDriverApi.tmh"
31 }
32 
33 #include "fxtelemetry.hpp"
34 
35 //
36 // extern the whole file
37 //
38 extern "C" {
39 
40 //
41 // Driver Pool Allocations
42 //
43 
44 
45 __drv_maxIRQL(PASSIVE_LEVEL)
46 PWSTR
47 STDCALL
48 WDFEXPORT(WdfDriverGetRegistryPath)(
49     __in
50     PWDF_DRIVER_GLOBALS DriverGlobals,
51     __in
52     WDFDRIVER Driver
53     )
54 {
55     DDI_ENTRY();
56 
57     PFX_DRIVER_GLOBALS pFxDriverGlobals;
58     NTSTATUS status;
59     FxDriver *pDriver;
60 
61     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
62                                    Driver,
63                                    FX_TYPE_DRIVER,
64                                    (PVOID *)&pDriver,
65                                    &pFxDriverGlobals);
66 
67     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
68     if (!NT_SUCCESS(status)) {
69         return NULL;
70     }
71 
72     return pDriver->GetRegistryPathUnicodeString()->Buffer;
73 }
74 
75 VOID
76 RosInitWdf();
77 
78 _Must_inspect_result_
79 __drv_maxIRQL(PASSIVE_LEVEL)
80 NTSTATUS
81 STDCALL
82 WDFEXPORT(WdfDriverCreate)(
83     __in
84     PWDF_DRIVER_GLOBALS DriverGlobals,
85     __in
86     MdDriverObject DriverObject,
87     __in
88     PCUNICODE_STRING RegistryPath,
89     __in_opt
90     PWDF_OBJECT_ATTRIBUTES DriverAttributes,
91     __in
92     PWDF_DRIVER_CONFIG DriverConfig,
93     __out_opt
94     WDFDRIVER* Driver
95     )
96 {
97     DDI_ENTRY();
98 
99     PFX_DRIVER_GLOBALS pFxDriverGlobals;
100     FxDriver *pDriver;
101     NTSTATUS status;
102     WDFDRIVER hDriver;
103     const LONG validFlags = WdfDriverInitNonPnpDriver |
104                             WdfDriverInitNoDispatchOverride;
105 
106     RosInitWdf();
107     DriverGlobals = WdfDriverGlobals;
108 
109     hDriver = NULL;
110     pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
111 
112     FxPointerNotNull(pFxDriverGlobals, DriverObject);
113     FxPointerNotNull(pFxDriverGlobals, RegistryPath);
114     FxPointerNotNull(pFxDriverGlobals, DriverConfig);
115 
116     //
117     // Validate the size of the input Driver Config structure.  The size changed
118     // after v1.1.  The size is the same for v1.1 and v1.0, verify that.
119     //
120     WDFCASSERT(sizeof(WDF_DRIVER_CONFIG_V1_0) == sizeof(WDF_DRIVER_CONFIG_V1_1));
121 
122     if (DriverConfig->Size != sizeof(WDF_DRIVER_CONFIG)
123         &&
124         DriverConfig->Size != sizeof(WDF_DRIVER_CONFIG_V1_1)) {
125 
126         status = STATUS_INFO_LENGTH_MISMATCH;
127         DoTraceLevelMessage(
128             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
129             "WDF_DRIVER_CONFIG got Size %d, expected v1.1 size %d or cur ver size %d, %!STATUS!",
130             DriverConfig->Size,
131             sizeof(WDF_DRIVER_CONFIG_V1_1), sizeof(WDF_DRIVER_CONFIG), status);
132 
133         return status;
134     }
135 
136     //
137     // Validate the DriverInitFlags value in the Driver Config.
138     //
139     if ((DriverConfig->DriverInitFlags & ~validFlags) != 0) {
140         status = STATUS_INVALID_PARAMETER;
141         DoTraceLevelMessage(
142             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
143             "DriverInitFlags 0x%x invalid, valid flags are 0x%x, %!STATUS!",
144             DriverConfig->DriverInitFlags, validFlags, status);
145         return status;
146     }
147 
148     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
149     if (!NT_SUCCESS(status)) {
150         return status;
151     }
152 
153     status = FxValidateUnicodeString(pFxDriverGlobals, RegistryPath);
154     if (!NT_SUCCESS(status)) {
155         return status;
156     }
157 
158     //
159     // Driver and Public.Driver are set once WdfDriverCreate returns successfully.
160     // If they are set, that means this DDI has already been called for this
161     // client.  Return an error if this occurrs.
162     //
163     if (pFxDriverGlobals->Driver != NULL ||
164         pFxDriverGlobals->Public.Driver != NULL) {
165 
166         status = STATUS_DRIVER_INTERNAL_ERROR;
167 
168         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
169                             "WdfDriverCreate can only be called one time per "
170                             "WDM PDRIVER_OBJECT %p, %!STATUS!",
171                             DriverObject, status);
172 
173         return status;
174     }
175 
176     if (Driver != NULL) {
177         *Driver = NULL;
178     }
179 
180     //
181     // Initializing the tag requires initializing the driver name first.
182     //
183     FxDriver::_InitializeDriverName(pFxDriverGlobals, RegistryPath);
184 
185     //
186     // Initialize the tag before any allocation so that we can use the correct
187     // tag value when allocating on behalf of the driver (for all allocations,
188     // including FxDriver).
189     //
190     // Use the client's driver tag value if they specified one.  First check
191     // to make sure the size of the structure is the new size (vs the old size
192     // in v1.1).
193     //
194     // ' kdD' - was the default tag in many DDKs, don't allow its use.
195     //
196     if (DriverConfig->Size == sizeof(WDF_DRIVER_CONFIG) &&
197         DriverConfig->DriverPoolTag != 0x0 &&
198         DriverConfig->DriverPoolTag != ' kdD') {
199         //
200         // Copy directly using the driver's value
201         //
202         pFxDriverGlobals->Tag = DriverConfig->DriverPoolTag;
203         pFxDriverGlobals->Public.DriverTag = DriverConfig->DriverPoolTag;
204     }
205     else {
206         //
207         // Derive the value from the driver's service name
208         //
209         FxDriver::_InitializeTag(pFxDriverGlobals, DriverConfig);
210     }
211 
212     //
213     // Check to see if this is an NT4 style device driver.  If so, fail if they
214     // specified an AddDevice routine.  If no dispatch override is set,
215     // do not do any checking at all.
216     //
217     if (DriverConfig->DriverInitFlags & WdfDriverInitNoDispatchOverride) {
218         DO_NOTHING();
219     }
220     else if ((DriverConfig->DriverInitFlags & WdfDriverInitNonPnpDriver) &&
221              DriverConfig->EvtDriverDeviceAdd != NULL) {
222 
223          DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
224                             "Invalid Driver flags or EvtDriverDeviceAdd callback already added"
225                               "STATUS_INVALID_PARAMETER");
226 
227         return STATUS_INVALID_PARAMETER;
228     }
229 
230     status = FxValidateObjectAttributes(pFxDriverGlobals, DriverAttributes,
231                                         (FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED |
232                                         FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED |
233                                         FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED)
234                                         );
235 
236     if (!NT_SUCCESS(status)) {
237         return status;
238     }
239 
240     //
241     // FxDriver stores the driver wide configuration
242     //
243     FxInitialize(pFxDriverGlobals, DriverObject, RegistryPath, DriverConfig);
244 
245     //
246     // FxDriver stores the driver wide configuration
247     //
248     pDriver = new(pFxDriverGlobals, DriverAttributes)
249         FxDriver(DriverObject, DriverConfig, pFxDriverGlobals);
250 
251     if (pDriver != NULL) {
252 
253         if (NT_SUCCESS(status)) {
254 
255             status = pDriver->Initialize(RegistryPath, DriverConfig, DriverAttributes);
256 
257             if (NT_SUCCESS(status)) {
258                 status = pDriver->Commit(DriverAttributes, (WDFOBJECT*)&hDriver, FALSE);
259             }
260         }
261     }
262     else {
263         status =  STATUS_INSUFFICIENT_RESOURCES;
264     }
265 
266     //
267     // Only return a valid handle on success.  Upon error, release any memory
268     // and do not rely on any other function (like the driver unload routine) to
269     // be called.
270     //
271     if (NT_SUCCESS(status)) {
272         //
273         // **** Note ****
274         // Do not introduce failures after this point without ensuring
275         // FxObject::DeleteFromFailedCreate has a chance to clear out any
276         // assigned callbacks on the object.
277         //
278 
279         //
280         // Store the WDFDRIVER and FxDriver* globally so the driver can retrieve
281         // it anytime.
282         //
283         pFxDriverGlobals->Driver = pDriver;
284         pFxDriverGlobals->Public.Driver = hDriver;
285 
286         //
287         // Record the flags so that diagnostics knows what type of driver it is.
288         //
289         pFxDriverGlobals->Public.DriverFlags |= DriverConfig->DriverInitFlags;
290 
291         if (DriverConfig->DriverInitFlags &
292                 (WdfDriverInitNoDispatchOverride | WdfDriverInitNonPnpDriver)) {
293             //
294             // If there is no dispatch override or if it is an NT4 legacy style
295             // driver then we will not displace unload in the stub if one was not
296             // specified.
297             //
298             if (DriverConfig->EvtDriverUnload != NULL) {
299                 pFxDriverGlobals->Public.DisplaceDriverUnload = TRUE;
300             }
301             else {
302                 pFxDriverGlobals->Public.DisplaceDriverUnload = FALSE;
303             }
304         }
305         else {
306             pFxDriverGlobals->Public.DisplaceDriverUnload = TRUE;
307         }
308 
309         if (Driver != NULL) {
310             *Driver = hDriver;
311         }
312 
313 #ifndef __REACTOS__
314         if (FX_TELEMETRY_ENABLED(g_TelemetryProvider, pFxDriverGlobals)) {
315             FxAutoString imageName;
316 
317 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
318         const PWCHAR pVersionStr =
319             FX_MAKE_WSTR(__WDF_MAJOR_VERSION_STRING) L"."
320             FX_MAKE_WSTR(__WDF_MINOR_VERSION_STRING) L"."
321             FX_MAKE_WSTR(__WDF_BUILD_NUMBER) ;
322 #else // USER_MODE
323         const PWCHAR pVersionStr =
324             FX_MAKE_WSTR(__WUDF_MAJOR_VERSION_STRING) L"."
325             FX_MAKE_WSTR(__WUDF_MINOR_VERSION_STRING) L"."
326             FX_MAKE_WSTR(__WUDF_SERVICE_VERSION) ;
327 #endif
328 
329             //
330             // GetImageName can fail if the registry cannot be accessed. This
331             // can happen during system shutdown. Since the image name is only
332             // used for telemetry the failure can be ignored.
333             //
334             (VOID) GetImageName(pFxDriverGlobals, &imageName.m_UnicodeString);
335 
336             WDF_CENSUS_EVT_WRITE_DRIVER_LOAD(g_TelemetryProvider,
337                                     pFxDriverGlobals,
338                                     imageName.m_UnicodeString.Buffer,
339                                     pVersionStr);
340         }
341 #endif // __REACTOS__
342     }
343     else {
344         if (pDriver != NULL) {
345             pDriver->DeleteFromFailedCreate();
346         }
347 
348         FxDestroy(pFxDriverGlobals);
349     }
350 
351     return status;
352 }
353 
354 _Must_inspect_result_
355 __drv_maxIRQL(PASSIVE_LEVEL)
356 NTSTATUS
357 STDCALL
358 WDFEXPORT(WdfDriverRegisterTraceInfo)(
359     __in
360     PWDF_DRIVER_GLOBALS DriverGlobals,
361     __in
362     PDRIVER_OBJECT DriverObject,
363     __in
364     PFN_WDF_TRACE_CALLBACK EvtTraceCallback,
365     __in
366     PVOID ControlBlock
367     )
368 {
369     DDI_ENTRY();
370 
371     UNREFERENCED_PARAMETER(DriverGlobals);
372     UNREFERENCED_PARAMETER(DriverObject);
373     UNREFERENCED_PARAMETER(EvtTraceCallback);
374     UNREFERENCED_PARAMETER(ControlBlock);
375 
376     return STATUS_NOT_SUPPORTED;
377 }
378 
379 _Must_inspect_result_
380 __drv_maxIRQL(PASSIVE_LEVEL)
381 NTSTATUS
382 STDCALL
383 WDFEXPORT(WdfDriverRetrieveVersionString)(
384     __in
385     PWDF_DRIVER_GLOBALS DriverGlobals,
386     __in
387     WDFDRIVER Driver,
388     __in
389     WDFSTRING String
390     )
391 {
392     DDI_ENTRY();
393 
394     PFX_DRIVER_GLOBALS pFxDriverGlobals;
395     FxDriver* pDriver;
396     FxString* pString;
397     NTSTATUS status;
398 
399 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
400     const PWCHAR pVersionStr =
401         L"Kernel Mode Driver Framework version "
402         FX_MAKE_WSTR(__WDF_MAJOR_VERSION_STRING) L"."
403         FX_MAKE_WSTR(__WDF_MINOR_VERSION_STRING) L"."
404         FX_MAKE_WSTR(__WDF_BUILD_NUMBER) ;
405 
406     const PWCHAR pVersionStrVerifier =
407         L"Kernel Mode Driver Framework (verifier on) version "
408         FX_MAKE_WSTR(__WDF_MAJOR_VERSION_STRING) L"."
409         FX_MAKE_WSTR(__WDF_MINOR_VERSION_STRING) L"."
410         FX_MAKE_WSTR(__WDF_BUILD_NUMBER);
411 #else // USER_MODE
412     const PWCHAR pVersionStr =
413         L"User Mode Driver Framework version "
414         FX_MAKE_WSTR(__WUDF_MAJOR_VERSION_STRING) L"."
415         FX_MAKE_WSTR(__WUDF_MINOR_VERSION_STRING) L"."
416         FX_MAKE_WSTR(__WUDF_SERVICE_VERSION) ;
417 
418     const PWCHAR pVersionStrVerifier =
419         L"User Mode Driver Framework (verifier on) version "
420         FX_MAKE_WSTR(__WUDF_MAJOR_VERSION_STRING) L"."
421         FX_MAKE_WSTR(__WUDF_MINOR_VERSION_STRING) L"."
422         FX_MAKE_WSTR(__WUDF_SERVICE_VERSION);
423 #endif
424 
425     //
426     // Even though it is unused, still convert it to make sure a valid handle is
427     // being passed in.
428     //
429     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
430                                    Driver,
431                                    FX_TYPE_DRIVER,
432                                    (PVOID *)&pDriver,
433                                    &pFxDriverGlobals);
434 
435     FxPointerNotNull(pFxDriverGlobals, String);
436 
437     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
438     if (!NT_SUCCESS(status)) {
439         return status;
440     }
441 
442     FxObjectHandleGetPtr(pFxDriverGlobals,
443                          String,
444                          FX_TYPE_STRING,
445                          (PVOID *)&pString);
446 
447     status = pString->Assign(
448         pFxDriverGlobals->FxVerifierOn ? pVersionStrVerifier : pVersionStr
449         );
450 
451     return status;
452 }
453 
454 _Must_inspect_result_
455 __drv_maxIRQL(PASSIVE_LEVEL)
456 BOOLEAN
457 STDCALL
458 WDFEXPORT(WdfDriverIsVersionAvailable)(
459     __in
460     PWDF_DRIVER_GLOBALS DriverGlobals,
461     __in
462     WDFDRIVER Driver,
463     __in
464     PWDF_DRIVER_VERSION_AVAILABLE_PARAMS VersionAvailableParams
465     )
466 {
467     DDI_ENTRY();
468 
469     PFX_DRIVER_GLOBALS pFxDriverGlobals;
470     FxDriver* pDriver;
471     NTSTATUS status;
472     ULONG major, minor;
473 
474 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
475     major = __WDF_MAJOR_VERSION;
476     minor = __WDF_MINOR_VERSION;
477 #else
478     major = __WUDF_MAJOR_VERSION;
479     minor = __WUDF_MINOR_VERSION;
480 #endif
481 
482     //
483     // Even though it is unused, still convert it to make sure a valid handle is
484     // being passed in.
485     //
486     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
487                                    Driver,
488                                    FX_TYPE_DRIVER,
489                                    (PVOID *)&pDriver,
490                                    &pFxDriverGlobals);
491 
492     FxPointerNotNull(pFxDriverGlobals, VersionAvailableParams);
493 
494     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
495     if (!NT_SUCCESS(status)) {
496         return FALSE;
497     }
498 
499     if (VersionAvailableParams->Size != sizeof(WDF_DRIVER_VERSION_AVAILABLE_PARAMS)) {
500         status = STATUS_INFO_LENGTH_MISMATCH;
501 
502         DoTraceLevelMessage(
503             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
504             "VersionAvailableParams Size 0x%x, expected 0x%x, %!STATUS!",
505             VersionAvailableParams->Size, sizeof(WDF_DRIVER_VERSION_AVAILABLE_PARAMS),
506             status);
507 
508         return FALSE;
509     }
510 
511     //
512     // We log at TRACE_LEVEL_INFORMATION so that we know it gets into the IFR at
513     // all times.  This will make it easier to debug drivers which fail to load
514     // when a new minor version of WDF is installed b/c they are failing
515     // version checks.
516     //
517     DoTraceLevelMessage(
518         pFxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER,
519         "IsVersionAvailable, current WDF ver major %d, minor %d, caller asking "
520         "about major %d, minor %d", major, minor,
521         VersionAvailableParams->MajorVersion, VersionAvailableParams->MinorVersion);
522 
523     //
524     // Currently we only support one major version per KMDF binary and we support
525     // all minor versions of that major version down to 0x0.
526     //
527     if (VersionAvailableParams->MajorVersion == major &&
528         VersionAvailableParams->MinorVersion <= minor) {
529         return TRUE;
530     }
531 
532     return FALSE;
533 }
534 
535 } // extern "C"
536