Reactos
1//
2// Copyright (C) Microsoft. All rights reserved.
3//
4
5extern "C" {
6#include <ntddk.h>
7}
8
9//
10// This will cause inclusion of VfWdfFunctions table implementation from header
11//
12// TODO: Uncomment when implement verified functions table
13//#define VF_FX_DYNAMICS_GENERATE_TABLE 1
14
15//
16// Compute the length based on the max. service name length and the rest of the
17// error string as seen in ReportDdiFunctionCountMismatch
18//
19// TODO: Fix this !!!
20#ifndef MAX_PATH
21#define MAX_PATH 260
22#endif
23#define EVTLOG_DDI_COUNT_ERROR_MAX_LEN (53 + MAX_PATH)
24
25#include "fx.hpp"
26#include "fxldr.h"
27#include "fxlibrarycommon.h"
28#include "fxtelemetry.hpp"
29#ifndef __REACTOS__
30#include "wdfversionlog.h"
31#include "minwindef.h"
32#else
33#include "reactos_special.h"
34#endif
35
36extern "C" {
37//
38// Global triage Info for dbgeng and 0x9F work
39//
40static WDFOBJECT_TRIAGE_INFO _WdfObjectTriageInfo = {0};
41static WDFCONTEXT_TRIAGE_INFO _WdfContextTriageInfo = {0};
42static WDFCONTEXTTYPE_TRIAGE_INFO _WdfContextTypeTriageInfo = {0};
43static WDFQUEUE_TRIAGE_INFO _WdfQueueTriageInfo = {0};
44static WDFIRPQUEUE_TRIAGE_INFO _WdfIrpQueueTriageInfo = {0};
45static WDFREQUEST_TRIAGE_INFO _WdfRequestTriageInfo = {0};
46static WDFDEVICE_TRIAGE_INFO _WdfDeviceTriageInfo = {0};
47static WDFIRP_TRIAGE_INFO _WdfIrpTriageInfo = {0};
48static WDFFWDPROGRESS_TRIAGE_INFO _WdfFwdProgressTriageInfo = {0};
49
50WDF_TRIAGE_INFO g_WdfTriageInfo = {
51 //
52 // KMDF Version.
53 //
54 __WDF_MAJOR_VERSION,
55 __WDF_MINOR_VERSION,
56
57 //
58 // Table Version.
59 //
60 WDF_01_TRIAGE_INFO_MAJOR_VERSION,
61 WDF_01_TRIAGE_INFO_MINOR_VERSION,
62
63 //
64 // Reserved ptr (set to NULL).
65 //
66 NULL,
67
68 //
69 // WDF objects triage info.
70 //
71 &_WdfObjectTriageInfo,
72 &_WdfContextTriageInfo,
73 &_WdfContextTypeTriageInfo,
74 &_WdfQueueTriageInfo,
75 &_WdfFwdProgressTriageInfo,
76 &_WdfIrpQueueTriageInfo,
77 &_WdfRequestTriageInfo,
78 &_WdfDeviceTriageInfo,
79 &_WdfIrpTriageInfo,
80};
81} // extern "C"
82
83VOID
84GetTriageInfo(
85 VOID
86 )
87{
88 // Object
89 _WdfObjectTriageInfo.RawObjectSize = sizeof(FxObject);
90 _WdfObjectTriageInfo.ObjectType = FIELD_OFFSET(FxObject, m_Type);
91 _WdfObjectTriageInfo.TotalObjectSize = FIELD_OFFSET(FxObject, m_ObjectSize);
92 _WdfObjectTriageInfo.ChildListHead = FIELD_OFFSET(FxObject, m_ChildListHead);
93 _WdfObjectTriageInfo.ChildEntry = FIELD_OFFSET(FxObject, m_ChildEntry);
94 _WdfObjectTriageInfo.Globals = FIELD_OFFSET(FxObject, m_Globals);
95 _WdfObjectTriageInfo.ParentObject = FIELD_OFFSET(FxObject, m_ParentObject);
96
97 // Context Triage Info
98 _WdfContextTriageInfo.HeaderSize = sizeof(FxContextHeader);
99 _WdfContextTriageInfo.NextHeader = FIELD_OFFSET(FxContextHeader, NextHeader);
100 _WdfContextTriageInfo.Object = FIELD_OFFSET(FxContextHeader, Object);
101 _WdfContextTriageInfo.TypeInfoPtr = FIELD_OFFSET(FxContextHeader, ContextTypeInfo);
102 _WdfContextTriageInfo.Context = FIELD_OFFSET(FxContextHeader, Context);
103
104 // Context type Triage info
105 _WdfContextTypeTriageInfo.TypeInfoSize = sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO);
106 _WdfContextTypeTriageInfo.ContextSize = FIELD_OFFSET(WDF_OBJECT_CONTEXT_TYPE_INFO, ContextSize);
107 _WdfContextTypeTriageInfo.ContextName = FIELD_OFFSET(WDF_OBJECT_CONTEXT_TYPE_INFO, ContextName);
108
109 // WdfRequest Queue
110 _WdfQueueTriageInfo.QueueSize = sizeof(FxIoQueue);
111 _WdfQueueTriageInfo.IrpQueue1 = FIELD_OFFSET(FxIoQueue, m_Queue);
112 _WdfQueueTriageInfo.IrpQueue2 = FIELD_OFFSET(FxIoQueue, m_DriverCancelable);
113 _WdfQueueTriageInfo.RequestList1 = FIELD_OFFSET(FxIoQueue, m_Cancelled);
114 _WdfQueueTriageInfo.RequestList2 = FIELD_OFFSET(FxIoQueue, m_CanceledOnQueueList);
115 _WdfQueueTriageInfo.FwdProgressContext = FIELD_OFFSET(FxIoQueue, m_FwdProgContext);
116 _WdfQueueTriageInfo.PkgIo = FIELD_OFFSET(FxIoQueue, m_PkgIo);
117
118 // Forward Progress
119 _WdfFwdProgressTriageInfo.ReservedRequestList =
120 FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_ReservedRequestList);
121 _WdfFwdProgressTriageInfo.ReservedRequestInUseList =
122 FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_ReservedRequestInUseList);
123 _WdfFwdProgressTriageInfo.PendedIrpList =
124 FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_PendedIrpList);
125
126 // Irp Queue
127 _WdfIrpQueueTriageInfo.IrpQueueSize = sizeof(FxIrpQueue);
128 _WdfIrpQueueTriageInfo.IrpListHeader = FIELD_OFFSET(FxIrpQueue, m_Queue);
129 _WdfIrpQueueTriageInfo.IrpListEntry = FIELD_OFFSET(IRP, Tail.Overlay.ListEntry);
130 _WdfIrpQueueTriageInfo.IrpContext = FIELD_OFFSET(IRP,
131 Tail.Overlay.DriverContext[FX_IRP_QUEUE_CSQ_CONTEXT_ENTRY]);
132
133 // WdfRequest
134 _WdfRequestTriageInfo.RequestSize = sizeof(FxRequest);
135 _WdfRequestTriageInfo.CsqContext = FIELD_OFFSET(FxRequest, m_CsqContext);
136 _WdfRequestTriageInfo.FxIrp = FIELD_OFFSET(FxRequest, m_Irp);
137 _WdfRequestTriageInfo.ListEntryQueueOwned =
138 FIELD_OFFSET(FxRequest, m_OwnerListEntry);
139 _WdfRequestTriageInfo.ListEntryQueueOwned2 =
140 FIELD_OFFSET(FxRequest, m_OwnerListEntry2);
141 _WdfRequestTriageInfo.RequestListEntry =
142 FIELD_OFFSET(FxRequest, m_ListEntry);
143 _WdfRequestTriageInfo.FwdProgressList =
144 FIELD_OFFSET(FxRequest, m_ForwardProgressList);
145
146 // WdfDevice
147 _WdfDeviceTriageInfo.DeviceInitSize = sizeof(WDFDEVICE_INIT);
148 _WdfDeviceTriageInfo.DeviceDriver = FIELD_OFFSET(FxDevice, m_Driver);
149
150 // FxIrp
151 _WdfIrpTriageInfo.FxIrpSize = sizeof(FxIrp);
152 _WdfIrpTriageInfo.IrpPtr = FIELD_OFFSET(FxIrp, m_Irp);
153}
154
155BOOLEAN
156IsClientInfoValid(
157 _In_ PCLIENT_INFO ClientInfo
158 )
159{
160 if (ClientInfo == NULL ||
161 ClientInfo->Size != sizeof(CLIENT_INFO) ||
162 ClientInfo->RegistryPath == NULL ||
163 ClientInfo->RegistryPath->Length == 0 ||
164 ClientInfo->RegistryPath->Buffer == NULL) {
165 return FALSE;
166 }
167 return TRUE;
168}
169
170VOID
171ReportDdiFunctionCountMismatch(
172 _In_ PCUNICODE_STRING ServiceName,
173 _In_ ULONG ActualFunctionCount,
174 _In_ ULONG ExpectedFunctionCount
175 )
176{
177 WCHAR insertString[EVTLOG_DDI_COUNT_ERROR_MAX_LEN] = { 0 };
178 NTSTATUS status;
179
180 //
181 // NOTE: Any single call to DbgPrintEx will only transmit 512 bytes of
182 // information.
183 //
184 DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL,
185 "\n\n************************* \n"
186 "* DDI function table mismatch detected in KMDF driver. The \n"
187 "* driver will not load until it is re-compiled using a \n"
188 "* newer version of the Windows Driver Kit (WDK). \n"
189 );
190
191 DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL,
192 "* Service name : %wZ\n"
193 "* Actual function table count : %d \n"
194 "* Expected function table count: %d \n"
195 "*************************** \n\n",
196 ServiceName,
197 ActualFunctionCount,
198 ExpectedFunctionCount
199 );
200
201 //
202 // Report a warning level ETW event to the system event log. "Wdf01000" is
203 // the listed event provider.
204 //
205 status = RtlStringCchPrintfW(insertString,
206 RTL_NUMBER_OF(insertString),
207 L"Service:%wZ Count:Actual %d Expected %d",
208 ServiceName,
209 ActualFunctionCount,
210 ExpectedFunctionCount);
211 if (NT_SUCCESS(status)) {
212 LibraryLogEvent(FxLibraryGlobals.DriverObject,
213 WDFVER_CLIENT_INVALID_DDI_COUNT,
214 STATUS_INVALID_PARAMETER,
215 insertString,
216 NULL,
217 0);
218 }
219
220 //
221 // Report a telemetry event that can be used to proactively fix drivers
222 //
223#ifndef __REACTOS__
224 TraceLoggingWrite(g_TelemetryProvider,
225 "KmdfClientFunctionCountMismatch",
226 WDF_TELEMETRY_EVT_KEYWORDS,
227 TraceLoggingUnicodeString(ServiceName, "ServiceName"),
228 TraceLoggingUInt32(ActualFunctionCount, "FunctionCount"),
229 TraceLoggingUInt32(ExpectedFunctionCount, "ExpectedCount"));
230#endif
231}
232
233_Must_inspect_result_
234NTSTATUS
235NTAPI
236FxLibraryCommonCommission(
237 VOID
238 )
239{
240 DECLARE_CONST_UNICODE_STRING(usName, L"RtlGetVersion");
241 PFN_RTL_GET_VERSION pRtlGetVersion = NULL;
242 NTSTATUS status;
243
244 __Print((LITERAL(WDF_LIBRARY_COMMISSION) "\n"));
245
246 //
247 // Commission this version's DLL globals.
248 //
249 status = FxLibraryGlobalsCommission();
250
251 if (!NT_SUCCESS(status)) {
252 __Print(("FxLibraryGlobalsCommission failed %X\n", status));
253 return status;
254 }
255
256 //
257 // register telemetry provider.
258 //
259#ifndef __REACTOS__
260 RegisterTelemetryProvider();
261
262 //
263 // Initialize internal WPP tracing.
264 //
265 status = FxTraceInitialize();
266 if (NT_SUCCESS(status)) {
267 FxLibraryGlobals.InternalTracingInitialized = TRUE;
268 }
269 else {
270 __Print(("Failed to initialize tracing for WDF\n"));
271
272 //
273 // Failure to initialize is not critical enough to fail driver load.
274 //
275 status = STATUS_SUCCESS;
276 }
277#endif
278 //
279 // Attempt to load RtlGetVersion (works for > w2k).
280 //
281 pRtlGetVersion = (PFN_RTL_GET_VERSION) MmGetSystemRoutineAddress(
282 (PUNICODE_STRING) &usName
283 );
284
285 //
286 // Now attempt to get this OS's version.
287 //
288 if (pRtlGetVersion != NULL) {
289 pRtlGetVersion(&gOsVersion);
290 }
291
292 __Print(("OsVersion(%d.%d)\n",
293 gOsVersion.dwMajorVersion,
294 gOsVersion.dwMinorVersion ));
295
296 //
297 // Init triage info for 9f bugcheck analysis.
298 //
299 GetTriageInfo();
300
301 return STATUS_SUCCESS;
302}
303
304_Must_inspect_result_
305NTSTATUS
306NTAPI
307FxLibraryCommonDecommission(
308 VOID
309 )
310{
311 __Print((LITERAL(WDF_LIBRARY_DECOMMISSION) ": enter\n"));
312
313 //
314 // Uninitialize WPP tracing.
315 //
316 if (FxLibraryGlobals.InternalTracingInitialized) {
317 //TraceUninitialize(); __REACTOS__ : not compiled
318 FxLibraryGlobals.InternalTracingInitialized = FALSE;
319 }
320
321 //
322 // Unregister telemetry provider.
323 //
324 //UnregisterTelemetryProvider(); __REACTOS__ : not compiled
325
326#ifndef __REACTOS__
327 EventUnregisterMicrosoft_Windows_DriverFrameworks_KernelMode_Performance();
328#endif // __REACTOS__
329 //
330 // Decommission this version's DLL globals.
331 //
332 FxLibraryGlobalsDecommission();
333
334 //
335 // Note: This is the absolute last action from WDF library (dynamic or static).
336 // The image is likely to be deleted after returning.
337 //
338 __Print((LITERAL(WDF_LIBRARY_DECOMMISSION) ": exit\n"));
339
340 return STATUS_SUCCESS;
341}
342
343_Must_inspect_result_
344NTSTATUS
345NTAPI
346FxLibraryCommonRegisterClient(
347 __inout PWDF_BIND_INFO Info,
348 __deref_out PWDF_DRIVER_GLOBALS *WdfDriverGlobals,
349 __in_opt PCLIENT_INFO ClientInfo
350 )
351{
352 NTSTATUS status;
353 UNICODE_STRING serviceName = { 0 };
354
355 status = STATUS_INVALID_PARAMETER;
356
357 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n"));
358
359 if (Info == NULL || WdfDriverGlobals == NULL || Info->FuncTable == NULL) {
360 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
361 ": NULL parameter -- %s\n",
362 (Info == NULL) ? "PWDF_BIND_INFO" :
363 (WdfDriverGlobals == NULL) ? "PWDF_DRIVER_GLOBALS *" :
364 (Info->FuncTable == NULL) ? "PWDF_BIND_INFO->FuncTable" :
365 "unknown" ));
366 goto Done;
367 }
368
369 ASSERT(Info->FuncCount);
370
371
372 *WdfDriverGlobals = NULL;
373
374 //
375 // WdfVersion.Count is initialized in FxDynamics.h and is never changed.
376 // Prefast is unable to make that determination.
377 //
378 __assume(WdfVersion.FuncCount == sizeof(WDFFUNCTIONS)/sizeof(PVOID));
379
380 if (Info->FuncCount > WdfVersion.FuncCount) {
381 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
382 ": version mismatch detected in function table count: client"
383 "has 0x%x, library has 0x%x\n",
384 Info->FuncCount, WdfVersion.FuncCount));
385 goto Done;
386 }
387
388 if (Info->FuncCount <= WdfFunctionTableNumEntries_V1_15) {
389 //
390 // Make sure table count matches exactly with previously
391 // released framework version table sizes.
392 //
393 switch (Info->FuncCount) {
394
395 case WdfFunctionTableNumEntries_V1_15:
396 case WdfFunctionTableNumEntries_V1_13:
397 case WdfFunctionTableNumEntries_V1_11:
398 case WdfFunctionTableNumEntries_V1_9:
399 // case WdfFunctionTableNumEntries_V1_7: // both 1.7 and 1.5 have 387 functions
400 case WdfFunctionTableNumEntries_V1_5:
401 case WdfFunctionTableNumEntries_V1_1:
402 case WdfFunctionTableNumEntries_V1_0:
403 break;
404
405 default:
406 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
407 ": Function table count 0x%x doesn't match any previously "
408 "released framework version table size\n",
409 Info->FuncCount));
410 goto Done;
411 }
412 }
413 else {
414
415
416
417
418
419
420
421
422 // Client version is same as framework version. Make
423 // sure table count is exact.
424 if (Info->FuncCount != WdfFunctionTableNumEntries) {
425 RtlZeroMemory(&serviceName, sizeof(UNICODE_STRING));
426
427 if (IsClientInfoValid(ClientInfo)) {
428 GetNameFromPath(ClientInfo->RegistryPath, &serviceName);
429 }
430 else {
431 RtlInitUnicodeString(&serviceName, L"Unknown");
432 }
433
434 //
435 // Report a DbgPrint message, telemetry event and an ETW event that
436 // will serve as diagnostic aid.
437 //
438 ReportDdiFunctionCountMismatch((PCUNICODE_STRING)&serviceName,
439 Info->FuncCount,
440 WdfFunctionTableNumEntries);
441
442 //
443 // If loader diagnostics are enabled and KD is connected, break-in
444 //
445 if (WdfLdrDbgPrintOn && KD_DEBUGGER_ENABLED &&
446 !KD_DEBUGGER_NOT_PRESENT) {
447 DbgBreakPoint();
448 }
449 goto Done;
450 }
451 }
452
453 //
454 // Allocate an new FxDriverGlobals area for this driver.
455 //
456 *WdfDriverGlobals = FxAllocateDriverGlobals();
457
458 if (*WdfDriverGlobals) {
459 BOOLEAN isFunctinTableHookingOn = FALSE;
460 BOOLEAN isPerformanceAnalysisOn = FALSE;
461 PFX_DRIVER_GLOBALS fxDriverGlobals = NULL;
462
463 //
464 // Check the registry to see if Enhanced verifier is on for this driver.
465 // if registry read fails, options value remains unchanged.
466 // store enhanced verifier options in driver globals
467 //
468 fxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals);
469 GetEnhancedVerifierOptions(ClientInfo, &fxDriverGlobals->FxEnhancedVerifierOptions);
470 isFunctinTableHookingOn = IsFxVerifierFunctionTableHooking(fxDriverGlobals);
471 isPerformanceAnalysisOn = IsFxPerformanceAnalysis(fxDriverGlobals);
472
473 //
474 // Set-up the function table. Enhanced verifier and Performance analysis is off by default.
475 //
476 if (isFunctinTableHookingOn == FALSE && isPerformanceAnalysisOn == FALSE) {
477
478 //
479 // Starting in 1.15 we reference a copy of the DDI table in WDF01000,
480 // prior to that we copy the entire table to local memory.
481 //
482 if (Info->FuncCount <= WdfFunctionTableNumEntries_V1_13) {
483 RtlCopyMemory( Info->FuncTable,
484 &WdfVersion.Functions,
485 Info->FuncCount * sizeof(PVOID) );
486 }
487 else {
488 //
489 // FuncTable arrives with a ptr to &WdfFunctions, so we update
490 // what WdfFunctions points to.
491 //
492 *((WDFFUNC**) Info->FuncTable) = (WDFFUNC*) &WdfVersion.Functions;
493 }
494 }
495 else {
496 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
497 "Verifier functions table NOT IMPLEMENTED\n"));
498
499 DbgBreakPoint();
500
501 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
502 ": Enhanced Verification is ON\n"));
503
504#ifndef __REACTOS__
505 LockVerifierSection(fxDriverGlobals, ClientInfo->RegistryPath);
506
507 if (Microsoft_Windows_DriverFrameworks_KernelMode_PerformanceHandle == NULL) {
508 EventRegisterMicrosoft_Windows_DriverFrameworks_KernelMode_Performance();
509 }
510
511 //
512 // Enhanced verification is on. Return verifier function table
513 //
514 // Starting in 1.15 we reference a copy of the DDI table in WDF01000,
515 // prior to that we copy the entire table to local memory.
516 //
517 if (Info->FuncCount <= WdfFunctionTableNumEntries_V1_13) {
518 RtlCopyMemory( Info->FuncTable,
519 &VfWdfVersion.Functions,
520 Info->FuncCount * sizeof(PVOID) );
521 }
522 else {
523 //
524 // FuncTable arrives with a ptr to &WdfFunctions, so we update
525 // what WdfFunctions points to.
526 //
527 *((WDFFUNC**) Info->FuncTable) = (WDFFUNC*) &VfWdfVersion.Functions;
528 }
529#endif // __REACTOS__
530 }
531
532 status = STATUS_SUCCESS;
533
534 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
535 ": WdfFunctions %p\n", Info->FuncTable));
536 }
537
538Done:
539 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
540 ": exit: status %X\n", status));
541
542 return status;
543}
544
545_Must_inspect_result_
546NTSTATUS
547NTAPI
548FxLibraryCommonUnregisterClient(
549 __in PWDF_BIND_INFO Info,
550 __in PWDF_DRIVER_GLOBALS WdfDriverGlobals
551 )
552{
553 NTSTATUS status;
554
555 __Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT) ": enter\n"));
556
557 ASSERT(Info);
558 ASSERT(WdfDriverGlobals);
559
560 if (Info != NULL && WdfDriverGlobals != NULL) {
561 PFX_DRIVER_GLOBALS pFxDriverGlobals;
562
563 status = STATUS_SUCCESS;
564
565 pFxDriverGlobals = GetFxDriverGlobals(WdfDriverGlobals);
566
567 //
568 // Destroy this FxDriver instance, if its still indicated.
569 //
570 if (pFxDriverGlobals->Driver != NULL) {
571 //
572 // Association support, we are a root with no parent
573 //
574 pFxDriverGlobals->Driver->DeleteObject();
575
576 FxDestroy(pFxDriverGlobals);
577 }
578
579 //
580 // Stop IFR logging
581 //
582 FxIFRStop(pFxDriverGlobals);
583
584 //
585 // unlock enhanced-verifier image sections
586 //
587 if (IsFxVerifierFunctionTableHooking(pFxDriverGlobals)) {
588 UnlockVerifierSection(pFxDriverGlobals);
589 }
590
591 //
592 // This will free the client's FxDriverGlobals area
593 //
594 FxFreeDriverGlobals(WdfDriverGlobals);
595 }
596 else {
597 status = STATUS_UNSUCCESSFUL;
598 }
599
600 __Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT)
601 ": exit: status %X\n", status));
602
603 return status;
604}
605
606VOID
607GetEnhancedVerifierOptions(
608 __in PCLIENT_INFO ClientInfo,
609 __out PULONG Options
610 )
611{
612 NTSTATUS status;
613 ULONG value;
614 FxAutoRegKey hKey, hWdf;
615 DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf");
616 DECLARE_CONST_UNICODE_STRING(valueName, WDF_ENHANCED_VERIFIER_OPTIONS_VALUE_NAME);
617
618 *Options = 0;
619 if (!IsClientInfoValid(ClientInfo) ||
620 Options == NULL) {
621
622 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
623 ": Invalid ClientInfo received from wdfldr \n"));
624 return;
625 }
626
627 status = FxRegKey::_OpenKey(NULL,
628 ClientInfo->RegistryPath,
629 &hWdf.m_Key,
630 KEY_READ);
631 if (!NT_SUCCESS(status)) {
632 return;
633 }
634
635 status = FxRegKey::_OpenKey(hWdf.m_Key,
636 ¶metersPath,
637 &hKey.m_Key,
638 KEY_READ);
639 if (!NT_SUCCESS(status)) {
640 return;
641 }
642
643 status = FxRegKey::_QueryULong(
644 hKey.m_Key, &valueName, &value);
645
646 //
647 // Examine key values and set Options only on success.
648 //
649 if (NT_SUCCESS(status)) {
650 if (value) {
651 *Options = value;
652 }
653 }
654}
655
656VOID
657LibraryLogEvent(
658 __in PDRIVER_OBJECT DriverObject,
659 __in NTSTATUS ErrorCode,
660 __in NTSTATUS FinalStatus,
661 __in PWSTR ErrorInsertionString,
662 __in_bcount(RawDataLen) PVOID RawDataBuf,
663 __in USHORT RawDataLen
664 )
665/*++
666
667
668Routine Description:
669
670 Logs an error to the system event log.
671
672 Arguments:
673
674 DriverObject - Pointer to driver object reporting the error.
675
676 ErrorCode - Indicates the type of error, system or driver-defined.
677
678 ErrorInsertionString - Null-terminated Unicode string inserted into error
679 description, as defined by error code.
680
681Return Value:
682
683None.
684
685--*/
686{
687 PIO_ERROR_LOG_PACKET errorLogEntry;
688 size_t errorLogEntrySize; // [including null]
689 size_t errorInsertionStringByteSize = 0;
690
691 if (ErrorInsertionString) {
692 errorInsertionStringByteSize = wcslen(ErrorInsertionString) * sizeof(WCHAR);
693 errorInsertionStringByteSize += sizeof(UNICODE_NULL);
694 }
695
696 errorLogEntrySize = sizeof(IO_ERROR_LOG_PACKET) + RawDataLen + errorInsertionStringByteSize;
697
698 //
699 // Log an error.
700 //
701 //
702 // prefast complains about comparison of constant with constant here
703 //
704#pragma prefast(suppress:__WARNING_CONST_CONST_COMP, "If ErrorInsertionString is not null then this is not a constant")
705 if (errorLogEntrySize <= ERROR_LOG_MAXIMUM_SIZE) {
706
707 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DriverObject,
708 (UCHAR)errorLogEntrySize);
709
710 if (errorLogEntry != NULL) {
711
712 RtlZeroMemory(errorLogEntry, errorLogEntrySize);
713
714 errorLogEntry->ErrorCode = ErrorCode;
715 errorLogEntry->FinalStatus = FinalStatus;
716 errorLogEntry->NumberOfStrings = (ErrorInsertionString) ? 1 : 0;
717 errorLogEntry->DumpDataSize = RawDataLen;
718 errorLogEntry->StringOffset = (FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)) + errorLogEntry->DumpDataSize;
719
720 //
721 // Insertion strings follow dumpdata and since there is no dumpdata we place the
722 // insertion string at the start offset of the dumpdata.
723 //
724 if (RawDataBuf) {
725 RtlCopyMemory(errorLogEntry->DumpData,
726 RawDataBuf,
727 RawDataLen);
728 }
729
730 if (ErrorInsertionString) {
731 RtlCopyMemory(((PCHAR)errorLogEntry->DumpData) + RawDataLen,
732 ErrorInsertionString,
733 errorInsertionStringByteSize);
734 }
735
736 IoWriteErrorLogEntry(errorLogEntry);
737 }
738 }
739
740 return;
741}