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