1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 Version.cpp
8
9 Abstract:
10
11 This module forms a loadable library from the WDF core libs
12
13 Revision History:
14
15 --*/
16
17 #include <stdarg.h>
18 #include <stddef.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <ntverp.h>
22
23 extern "C" {
24 #include <ntddk.h>
25 #include <ntstrsafe.h>
26 }
27
28 #define FX_DYNAMICS_GENERATE_TABLE 1
29
30 #include "fx.hpp"
31
32 #include <fxldr.h>
33 #include "fxbugcheck.h"
34 #include "wdfversionlog.h"
35
36 #define DRIVER_OBJECT_EXTENSION_IDENTIFIER DriverEntry
37 #define DRIVER_PARAMETERS L"Parameters"
38 #define REGISTRY_KMDF_MAJOR_VERSION L"MajorVersion"
39 #define REGISTRY_KMDF_MINOR_VERSION L"MinorVersion"
40 #define REGISTRY_KMDF_BUILD_NUMBER L"BuildNumber"
41
42 //-----------------------------------------------------------------------------
43 // These header files are referenced in order to make internal structures
44 // available in public symbols. Various WDFKD debug commands use these
45 // internal structures to provide information about WDF.
46 //-----------------------------------------------------------------------------
47 #include "fxifr.h"
48
49 extern "C" {
50
51 //
52 // This is the collection of all structure/types to be make public.
53 // This union forces the structure type-info into the PDB file.
54 //
55 union {
56
57 WDF_IFR_HEADER * typeWDF_IFR_HEADER;
58 WDF_IFR_RECORD * typeWDF_IFR_RECORD;
59 WDF_IFR_OFFSET * typeWDF_IFR_OFFSET;
60 WDF_BIND_INFO * typeWDF_BIND_INFO;
61 WDF_OBJECT_CONTEXT_TYPE_INFO * typeWDF_OBJECT_CONTEXT_TYPE_INFO;
62 WDF_POWER_ROUTINE_TIMED_OUT_DATA * typeWDF_POWER_ROUTINE_TIMED_OUT_DATA;
63 WDF_BUGCHECK_CODES * typeWDF_BUGCHECK_CODES;
64 WDF_REQUEST_FATAL_ERROR_CODES * typeWDF_REQUEST_FATAL_ERROR_CODES;
65 FX_OBJECT_INFO * typeFX_OBJECT_INFO;
66 FX_POOL_HEADER * typeFX_POOL_HEADER;
67 FX_POOL * typeFX_POOL;
68 FxObject * typeFxObject;
69 FxContextHeader * typeFxContextHeader;
70 FX_DUMP_DRIVER_INFO_ENTRY * typeFX_DUMP_DRIVER_INFO_ENTRY;
71 FxTargetSubmitSyncParams * typeFxTargetSubmitSyncParams;
72
73 } uAllPublicTypes;
74
75 } // extern "C" end
76
77 //----------------------------------------- ------------------------------------
78
79 extern "C" {
80
81 #include "fxdynamics.h"
82
83 #include "fxlibrarycommon.h"
84
85 #define KMDF_DEFAULT_NAME "Wdf" ## \
86 LITERAL(__WDF_MAJOR_VERSION_STRING) ## \
87 "000" //minor version
88
89 //-----------------------------------------------------------------------------
90 // local prototype definitions
91 //-----------------------------------------------------------------------------
92 extern "C"
93 DRIVER_UNLOAD DriverUnload;
94
95 extern "C"
96 DRIVER_INITIALIZE DriverEntry;
97
98 extern "C"
99 __drv_dispatchType(IRP_MJ_CREATE)
100 __drv_dispatchType(IRP_MJ_CLEANUP)
101 __drv_dispatchType(IRP_MJ_CLOSE)
102 DRIVER_DISPATCH FxLibraryDispatch;
103
104 RTL_OSVERSIONINFOW gOsVersion = { sizeof(RTL_OSVERSIONINFOW) };
105
106 ULONG WdfLdrDbgPrintOn = 0;
107
108 PCHAR WdfLdrType = KMDF_DEFAULT_NAME;
109
110 } // extern "C"
111
112
113 //-----------------------------------------------------------------------------
114 //
115 //-----------------------------------------------------------------------------
116 extern "C"
117 _Must_inspect_result_
118 NTSTATUS
119 WDF_LIBRARY_COMMISSION(
120 VOID
121 );
122
123 extern "C"
124 _Must_inspect_result_
125 NTSTATUS
126 WDF_LIBRARY_DECOMMISSION(
127 VOID
128 );
129
130 extern "C"
131 _Must_inspect_result_
132 NTSTATUS
133 WDF_LIBRARY_REGISTER_CLIENT(
134 __inout PWDF_BIND_INFO Info,
135 __deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals,
136 __deref_inout PVOID * Context
137 );
138
139 extern "C"
140 _Must_inspect_result_
141 NTSTATUS
142 WDF_LIBRARY_UNREGISTER_CLIENT(
143 __in PWDF_BIND_INFO Info,
144 __in PWDF_DRIVER_GLOBALS WdfDriverGlobals
145 );
146
147 extern "C"
148 VOID
149 FxLibraryDeleteDevice(
150 VOID
151 );
152
153 VOID
154 FxLibraryCleanup(
155 VOID
156 );
157
158 VOID
159 WdfWriteKmdfVersionToRegistry(
160 __in PDRIVER_OBJECT DriverObject,
161 __in PUNICODE_STRING RegistryPath
162 );
163
164 VOID
165 WdfDeleteKmdfVersionFromRegistry(
166 __in PDRIVER_OBJECT DriverObject
167 );
168
169 typedef struct _DRV_EXTENSION {
170 UNICODE_STRING ParametersRegistryPath;
171 } DRV_EXTENSION, *PDRV_EXTENSION;
172
173 //-----------------------------------------------------------------------------
174 // Library registeration information
175 //-----------------------------------------------------------------------------
176 extern "C" {
177 #pragma prefast(suppress:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "kernel component.");
178 WDF_LIBRARY_INFO WdfLibraryInfo = {
179 sizeof(WDF_LIBRARY_INFO),
180 (PFNLIBRARYCOMMISSION) WDF_LIBRARY_COMMISSION,
181 (PFNLIBRARYDECOMMISSION) WDF_LIBRARY_DECOMMISSION,
182 (PFNLIBRARYREGISTERCLIENT) WDF_LIBRARY_REGISTER_CLIENT,
183 (PFNLIBRARYUNREGISTERCLIENT) WDF_LIBRARY_UNREGISTER_CLIENT,
184 { __WDF_MAJOR_VERSION, __WDF_MINOR_VERSION, __WDF_BUILD_NUMBER }
185 };
186
187 } // extern "C" end
188
189 extern "C"
190 NTSTATUS
FxLibraryDispatch(__in struct _DEVICE_OBJECT * DeviceObject,__in PIRP Irp)191 FxLibraryDispatch (
192 __in struct _DEVICE_OBJECT * DeviceObject,
193 __in PIRP Irp
194 )
195 {
196 NTSTATUS status;
197
198 UNREFERENCED_PARAMETER(DeviceObject);
199 ASSERT(FxLibraryGlobals.LibraryDeviceObject == DeviceObject);
200
201 status = STATUS_INVALID_DEVICE_REQUEST;
202
203 switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) {
204 case IRP_MJ_CREATE:
205 //
206 // To limit our exposure for this device object, only allow kernel mode
207 // creates.
208 //
209 if (Irp->RequestorMode == KernelMode) {
210 status = STATUS_SUCCESS;
211 }
212 break;
213
214 case IRP_MJ_CLEANUP:
215 case IRP_MJ_CLOSE:
216 //
217 // Since we allowed a create to succeed, succeed the cleanup and close
218 //
219 status = STATUS_SUCCESS;
220 break;
221 }
222
223 Irp->IoStatus.Status = status;
224 Irp->IoStatus.Information = 0x0;
225 IoCompleteRequest(Irp, IO_NO_INCREMENT);
226
227 return status;
228 }
229
230 //-----------------------------------------------------------------------------
231 //
232 //-----------------------------------------------------------------------------
233
234 #define KMDF_DEVICE_NAME L"\\Device\\KMDF"
235
236 _Must_inspect_result_
237 NTSTATUS
FxLibraryCreateDevice(__in PUNICODE_STRING DeviceName)238 FxLibraryCreateDevice(
239 __in PUNICODE_STRING DeviceName
240 )
241 {
242 NTSTATUS status;
243 ULONG i;
244
245 i = 0;
246
247 //
248 // Repeatedly try to create a named device object until we run out of buffer
249 // space or we succeed.
250 //
251 do {
252 status = RtlUnicodeStringPrintf(DeviceName, L"%s%d", KMDF_DEVICE_NAME, i++);
253 if (!NT_SUCCESS(status)) {
254 return status;
255 }
256
257 //
258 // Create a device with no device extension
259 //
260 status = IoCreateDevice(
261 FxLibraryGlobals.DriverObject,
262 0,
263 DeviceName,
264 FILE_DEVICE_UNKNOWN,
265 0,
266 FALSE,
267 &FxLibraryGlobals.LibraryDeviceObject
268 );
269 } while (STATUS_OBJECT_NAME_COLLISION == status);
270
271 if (NT_SUCCESS(status)) {
272 //
273 // Clear the initializing bit now because the loader will attempt to
274 // open the device before we return from DriverEntry
275 //
276 ASSERT(FxLibraryGlobals.LibraryDeviceObject != NULL);
277 FxLibraryGlobals.LibraryDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
278 }
279
280 return status;
281 }
282
283 extern "C"
284 VOID
FxLibraryDeleteDevice(VOID)285 FxLibraryDeleteDevice(
286 VOID
287 )
288 {
289 FxLibraryCleanup();
290 }
291
292 VOID
FxLibraryCleanup(VOID)293 FxLibraryCleanup(
294 VOID
295 )
296 {
297 if (FxLibraryGlobals.LibraryDeviceObject != NULL) {
298 IoDeleteDevice(FxLibraryGlobals.LibraryDeviceObject);
299 FxLibraryGlobals.LibraryDeviceObject = NULL;
300 }
301 }
302
303 extern "C"
304 NTSTATUS
DriverEntry(__in PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath)305 DriverEntry(
306 __in PDRIVER_OBJECT DriverObject,
307 __in PUNICODE_STRING RegistryPath
308 )
309 {
310 UNICODE_STRING name;
311 UNICODE_STRING string;
312 NTSTATUS status;
313
314 //
315 // This creates a local buffer which is big enough to hold a copy of the
316 // constant string assigned to it. It does not point to the constant
317 // string. As such, it is a writeable buffer.
318 //
319 // NOTE: KMDF_DEVICE_NAME L"XXXX" creates a concatenated string of
320 // KMDF_DEVICE_NAME + L"XXXX". This is done to give us room for
321 // appending a number up to 4 digits long after KMDF_DEVICE_NAME if
322 // you want a null terminated string, 5 digits long if the string is
323 // not null terminated (as is the case for a UNICODE_STRING)
324 //
325 WCHAR buffer[] = KMDF_DEVICE_NAME L"XXXX";
326
327 //
328 // Initialize global to make NonPagedPool be treated as NxPool on Win8
329 // and NonPagedPool on down-level
330 //
331 ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
332
333 RtlInitUnicodeString(&string, WDF_REGISTRY_DBGPRINT_ON);
334
335 //
336 // Determine if debug prints are on.
337 //
338 (void) WdfLdrDiagnosticsValueByNameAsULONG(&string, &WdfLdrDbgPrintOn);
339
340 __Print(("DriverEntry\n"));
341
342 DriverObject->DriverUnload = DriverUnload;
343
344 FxLibraryGlobals.DriverObject = DriverObject;
345
346 DriverObject->MajorFunction[IRP_MJ_CREATE] = FxLibraryDispatch;
347 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FxLibraryDispatch;
348 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FxLibraryDispatch;
349
350 RtlZeroMemory(&name, sizeof(name));
351 name.Buffer = buffer;
352 name.Length = 0x0;
353 name.MaximumLength = sizeof(buffer);
354
355 //
356 // We use the string when we declare the buffer to get the right sized
357 // buffer. Now we want to make sure there are no contents before we
358 // use it to create a device object.
359 //
360 RtlZeroMemory(buffer, sizeof(buffer));
361
362 status = FxLibraryCreateDevice(&name);
363 if (!NT_SUCCESS(status)) {
364 __Print(("ERROR: FxLibraryCreateDevice failed with Status 0x%x\n", status));
365 return status;
366 }
367
368 //
369 // Register this library with WdfLdr
370 //
371 // NOTE: Once WdfRegisterLibrary returns NT_SUCCESS() we must return
372 // NT_SUCCESS from DriverEntry!
373 //
374 status = WdfRegisterLibrary( &WdfLibraryInfo, RegistryPath, &name );
375 if (!NT_SUCCESS(status)) {
376 __Print(("ERROR: WdfRegisterLibrary failed with Status 0x%x\n", status));
377 FxLibraryCleanup();
378 return status;
379 }
380
381 //
382 // Write KMDF version to registry
383 //
384 WdfWriteKmdfVersionToRegistry(DriverObject, RegistryPath);
385
386 return STATUS_SUCCESS;
387 }
388
389 //-----------------------------------------------------------------------------
390 //
391 //-----------------------------------------------------------------------------
392 extern "C"
393 VOID
DriverUnload(__in PDRIVER_OBJECT DriverObject)394 DriverUnload(
395 __in PDRIVER_OBJECT DriverObject
396 )
397 {
398 __Print(("DriverUnload\n"));
399
400 //
401 // Delete KMDF version from registry before destroying the Driver Object
402 //
403 WdfDeleteKmdfVersionFromRegistry(DriverObject);
404
405 //
406 // Make sure everything is deleted. Since the driver is considered a legacy
407 // driver, it can be unloaded while there are still outstanding device objects.
408 //
409 FxLibraryCleanup();
410 }
411
412 //-----------------------------------------------------------------------------
413 //
414 //-----------------------------------------------------------------------------
415 extern "C"
416 _Must_inspect_result_
417 NTSTATUS
WDF_LIBRARY_COMMISSION(VOID)418 WDF_LIBRARY_COMMISSION(
419 VOID
420 )
421 {
422 return FxLibraryCommonCommission();
423 }
424
425 //-----------------------------------------------------------------------------
426 //
427 //-----------------------------------------------------------------------------
428 extern "C"
429 _Must_inspect_result_
430 NTSTATUS
WDF_LIBRARY_DECOMMISSION(VOID)431 WDF_LIBRARY_DECOMMISSION(
432 VOID
433 )
434 {
435 return FxLibraryCommonDecommission();
436 }
437
438 #define EVTLOG_MESSAGE_SIZE 70
439 #define RAW_DATA_SIZE 4
440
441 extern "C"
442 _Must_inspect_result_
443 NTSTATUS
WDF_LIBRARY_REGISTER_CLIENT(__in PWDF_BIND_INFO Info,__deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals,__deref_inout PVOID * Context)444 WDF_LIBRARY_REGISTER_CLIENT(
445 __in PWDF_BIND_INFO Info,
446 __deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals,
447 __deref_inout PVOID * Context
448 )
449 {
450 NTSTATUS status = STATUS_INVALID_PARAMETER;
451 PFX_DRIVER_GLOBALS pFxDriverGlobals;
452 WCHAR insertString[EVTLOG_MESSAGE_SIZE];
453 ULONG rawData[RAW_DATA_SIZE];
454 PCLIENT_INFO clientInfo = NULL;
455
456 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n"));
457
458 clientInfo = (PCLIENT_INFO)*Context;
459 *Context = NULL;
460
461 ASSERT(Info->Version.Major == WdfLibraryInfo.Version.Major);
462
463 //
464 // NOTE: If the currently loaded library < drivers minor version fail the load
465 // instead of binding to a lower minor version. The reason for that if there
466 // is a newer API or new contract change made the driver shouldn't be using older
467 // API than it was compiled with.
468 //
469
470 if (Info->Version.Minor > WdfLibraryInfo.Version.Minor) {
471 status = RtlStringCchPrintfW(insertString,
472 RTL_NUMBER_OF(insertString),
473 L"Driver Version: %d.%d Kmdf Lib. Version: %d.%d",
474 Info->Version.Major,
475 Info->Version.Minor,
476 WdfLibraryInfo.Version.Major,
477 WdfLibraryInfo.Version.Minor);
478 if (!NT_SUCCESS(status)) {
479 __Print(("ERROR: RtlStringCchPrintfW failed with Status 0x%x\n", status));
480 return status;
481 }
482 rawData[0] = Info->Version.Major;
483 rawData[1] = Info->Version.Minor;
484 rawData[2] = WdfLibraryInfo.Version.Major;
485 rawData[3] = WdfLibraryInfo.Version.Minor;
486
487 LibraryLogEvent(FxLibraryGlobals.DriverObject,
488 WDFVER_MINOR_VERSION_NOT_SUPPORTED,
489 STATUS_OBJECT_TYPE_MISMATCH,
490 insertString,
491 rawData,
492 sizeof(rawData) );
493 //
494 // this looks like the best status to return
495 //
496 return STATUS_OBJECT_TYPE_MISMATCH;
497
498 }
499
500 status = FxLibraryCommonRegisterClient(Info,
501 WdfDriverGlobals,
502 clientInfo);
503
504 if (NT_SUCCESS(status)) {
505 //
506 // The context will be a pointer to FX_DRIVER_GLOBALS
507 //
508 *Context = GetFxDriverGlobals(*WdfDriverGlobals);
509
510 //
511 // Set the WDF_BIND_INFO structure pointer in FxDriverGlobals
512 //
513 pFxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals);
514 pFxDriverGlobals->WdfBindInfo = Info;
515 }
516
517 return status;
518 }
519
520
521 //-----------------------------------------------------------------------------
522 //
523 //-----------------------------------------------------------------------------
524 extern "C"
525 _Must_inspect_result_
526 NTSTATUS
WDF_LIBRARY_UNREGISTER_CLIENT(__in PWDF_BIND_INFO Info,__in PWDF_DRIVER_GLOBALS WdfDriverGlobals)527 WDF_LIBRARY_UNREGISTER_CLIENT(
528 __in PWDF_BIND_INFO Info,
529 __in PWDF_DRIVER_GLOBALS WdfDriverGlobals
530 )
531 {
532 return FxLibraryCommonUnregisterClient(Info, WdfDriverGlobals);
533 }
534
535 VOID
WdfWriteKmdfVersionToRegistry(__in PDRIVER_OBJECT DriverObject,__in PUNICODE_STRING RegistryPath)536 WdfWriteKmdfVersionToRegistry(
537 __in PDRIVER_OBJECT DriverObject,
538 __in PUNICODE_STRING RegistryPath
539 )
540 {
541 NTSTATUS status;
542 OBJECT_ATTRIBUTES objectAttributes;
543 HANDLE driverKey;
544 HANDLE parametersKey;
545 UNICODE_STRING valueName;
546 UNICODE_STRING parametersPath;
547 PDRV_EXTENSION driverExtension;
548
549 driverKey = NULL;
550 parametersKey = NULL;
551 driverExtension = NULL;
552
553 RtlInitUnicodeString(¶metersPath, DRIVER_PARAMETERS);
554
555 InitializeObjectAttributes(&objectAttributes,
556 RegistryPath,
557 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
558 NULL,
559 NULL);
560
561 status = ZwOpenKey(&driverKey, KEY_CREATE_SUB_KEY, &objectAttributes);
562 if (!NT_SUCCESS(status)) {
563 __Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\n",
564 RegistryPath->Buffer));
565 goto out;
566 }
567
568 InitializeObjectAttributes(&objectAttributes,
569 ¶metersPath,
570 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
571 driverKey,
572 NULL);
573
574 //
575 // Open or create key and get a handle
576 //
577 status = ZwCreateKey(¶metersKey,
578 KEY_SET_VALUE,
579 &objectAttributes,
580 0,
581 (PUNICODE_STRING) NULL,
582 REG_OPTION_VOLATILE,
583 NULL);
584
585 if (!NT_SUCCESS(status)) {
586 __Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\\%S\n",
587 RegistryPath->Buffer, parametersPath.Buffer));
588 goto out;
589 }
590
591 //
592 // Set Major Version
593 //
594 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION);
595
596 status = ZwSetValueKey(parametersKey,
597 &valueName,
598 0,
599 REG_DWORD,
600 &WdfLibraryInfo.Version.Major,
601 sizeof(WdfLibraryInfo.Version.Major));
602
603 if (!NT_SUCCESS(status)) {
604 __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Major Version\n"));
605 goto out;
606 }
607
608 //
609 // Set Minor Version
610 //
611 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION);
612
613 status = ZwSetValueKey(parametersKey,
614 &valueName,
615 0,
616 REG_DWORD,
617 &WdfLibraryInfo.Version.Minor,
618 sizeof(WdfLibraryInfo.Version.Minor));
619
620 if (!NT_SUCCESS(status)) {
621 __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Minor Version\n"));
622 goto out;
623 }
624
625
626 //
627 // Set Build Number
628 //
629 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER);
630
631 status = ZwSetValueKey(parametersKey,
632 &valueName,
633 0,
634 REG_DWORD,
635 &WdfLibraryInfo.Version.Build,
636 sizeof(WdfLibraryInfo.Version.Build));
637
638 if (!NT_SUCCESS(status)) {
639 __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Build Number\n"));
640 goto out;
641 }
642
643 //
644 // Create a Driver Extension to store the registry path, where we write the
645 // version of the wdf01000.sys that's loaded in memory
646 //
647 status = IoAllocateDriverObjectExtension(DriverObject,
648 (PVOID) DRIVER_OBJECT_EXTENSION_IDENTIFIER,
649 sizeof(DRV_EXTENSION),
650 (PVOID *)&driverExtension);
651
652 if (!NT_SUCCESS(status) || driverExtension == NULL) {
653 goto out;
654 }
655
656 driverExtension->ParametersRegistryPath.Buffer = (PWCHAR) ExAllocatePoolWithTag(
657 PagedPool,
658 RegistryPath->MaximumLength,
659 FX_TAG);
660 if (driverExtension->ParametersRegistryPath.Buffer == NULL) {
661 goto out;
662 }
663
664 driverExtension->ParametersRegistryPath.MaximumLength = RegistryPath->MaximumLength;
665 RtlCopyUnicodeString(&(driverExtension->ParametersRegistryPath), RegistryPath);
666
667 out:
668 if (driverKey != NULL) {
669 ZwClose(driverKey);
670 }
671
672 if (parametersKey != NULL) {
673 ZwClose(parametersKey);
674 }
675
676 return;
677 }
678
679 VOID
WdfDeleteKmdfVersionFromRegistry(__in PDRIVER_OBJECT DriverObject)680 WdfDeleteKmdfVersionFromRegistry(
681 __in PDRIVER_OBJECT DriverObject
682 )
683 {
684 PUNICODE_STRING registryPath;
685 OBJECT_ATTRIBUTES objectAttributes;
686 HANDLE driverKey;
687 HANDLE parametersKey;
688 UNICODE_STRING valueName;
689 NTSTATUS status;
690 UNICODE_STRING parametersPath;
691 PDRV_EXTENSION driverExtension;
692
693 RtlInitUnicodeString(¶metersPath, DRIVER_PARAMETERS);
694
695 driverKey = NULL;
696 parametersKey = NULL;
697
698 driverExtension = (PDRV_EXTENSION)IoGetDriverObjectExtension(DriverObject,
699 DRIVER_OBJECT_EXTENSION_IDENTIFIER);
700
701 if (driverExtension == NULL || driverExtension->ParametersRegistryPath.Buffer == NULL) {
702 return;
703 }
704
705 registryPath = &driverExtension->ParametersRegistryPath;
706
707 InitializeObjectAttributes(&objectAttributes,
708 registryPath,
709 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
710 NULL,
711 NULL);
712
713 status = ZwOpenKey(&driverKey, KEY_SET_VALUE, &objectAttributes);
714 if (!NT_SUCCESS(status)) {
715 goto out;
716 }
717
718 InitializeObjectAttributes(&objectAttributes,
719 ¶metersPath,
720 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
721 driverKey,
722 NULL);
723 //
724 // Open the key for deletion
725 //
726 status = ZwOpenKey(¶metersKey,
727 DELETE,
728 &objectAttributes);
729
730 if (!NT_SUCCESS(status)) {
731 goto out;
732 }
733
734 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION);
735 ZwDeleteValueKey(parametersKey, &valueName);
736
737 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION);
738 ZwDeleteValueKey(parametersKey, &valueName);
739
740 RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER);
741 ZwDeleteValueKey(parametersKey, &valueName);
742
743 ZwDeleteKey(parametersKey);
744
745 out:
746 if (driverExtension->ParametersRegistryPath.Buffer != NULL) {
747 ExFreePool(driverExtension->ParametersRegistryPath.Buffer);
748 }
749
750 if (driverKey != NULL) {
751 ZwClose(driverKey);
752 }
753
754 if (parametersKey != NULL) {
755 ZwClose(parametersKey);
756 }
757
758 return;
759 }
760
761