Reactos
at master 741 lines 23 kB view raw
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 &parametersPath, 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}