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