1 // 2 // Copyright (C) Microsoft. All rights reserved. 3 // 4 #include <ntverp.h> 5 #include <strsafe.h> 6 #include <driverspecs.h> 7 8 extern "C" { 9 #include "mx.h" 10 } 11 #include "fxmin.hpp" 12 #include <fxldrUm.h> 13 14 #include <wdfcxbase.h> 15 #include "wdf20.h" 16 #include "wdf215.h" 17 18 // 19 // This will cause inclusion of VfWdfFunctions table implementation from header 20 // 21 #define VF_FX_DYNAMICS_GENERATE_TABLE 1 22 23 24 25 26 27 #include "..\version\FxDynamics.h" 28 #include "..\version\vffxdynamics.h" 29 #include "FxLibraryCommon.h" 30 31 #include "FxTelemetry.hpp" 32 33 extern "C" { 34 // 35 // Global triage Info for dbgeng and 0x9F work 36 // 37 static WDFOBJECT_TRIAGE_INFO _WdfObjectTriageInfo = {0}; 38 static WDFCONTEXT_TRIAGE_INFO _WdfContextTriageInfo = {0}; 39 static WDFCONTEXTTYPE_TRIAGE_INFO _WdfContextTypeTriageInfo = {0}; 40 static WDFQUEUE_TRIAGE_INFO _WdfQueueTriageInfo = {0}; 41 static WDFIRPQUEUE_TRIAGE_INFO _WdfIrpQueueTriageInfo = {0}; 42 static WDFREQUEST_TRIAGE_INFO _WdfRequestTriageInfo = {0}; 43 static WDFDEVICE_TRIAGE_INFO _WdfDeviceTriageInfo = {0}; 44 static WDFIRP_TRIAGE_INFO _WdfIrpTriageInfo = {0}; 45 static WDFFWDPROGRESS_TRIAGE_INFO _WdfFwdProgressTriageInfo = {0}; 46 47 WDF_TRIAGE_INFO g_WdfTriageInfo = { 48 // 49 // UMDF Version. 50 // 51 __WUDF_MAJOR_VERSION, 52 __WUDF_MINOR_VERSION, 53 54 // 55 // Table Version. 56 // 57 WDF_01_TRIAGE_INFO_MAJOR_VERSION, 58 WDF_01_TRIAGE_INFO_MINOR_VERSION, 59 60 // 61 // Reserved ptr (set to NULL). 62 // 63 NULL, 64 65 // 66 // WDF objects triage info. 67 // 68 &_WdfObjectTriageInfo, 69 &_WdfContextTriageInfo, 70 &_WdfContextTypeTriageInfo, 71 &_WdfQueueTriageInfo, 72 &_WdfFwdProgressTriageInfo, 73 &_WdfIrpQueueTriageInfo, 74 &_WdfRequestTriageInfo, 75 &_WdfDeviceTriageInfo, 76 &_WdfIrpTriageInfo, 77 }; 78 } // extern "C" 79 80 VOID 81 GetTriageInfo( 82 VOID 83 ) 84 { 85 // Object 86 _WdfObjectTriageInfo.RawObjectSize = sizeof(FxObject); 87 _WdfObjectTriageInfo.ObjectType = FIELD_OFFSET(FxObject, m_Type); 88 _WdfObjectTriageInfo.TotalObjectSize = FIELD_OFFSET(FxObject, m_ObjectSize); 89 _WdfObjectTriageInfo.ChildListHead = FIELD_OFFSET(FxObject, m_ChildListHead); 90 _WdfObjectTriageInfo.ChildEntry = FIELD_OFFSET(FxObject, m_ChildEntry); 91 _WdfObjectTriageInfo.Globals = FIELD_OFFSET(FxObject, m_Globals); 92 _WdfObjectTriageInfo.ParentObject = FIELD_OFFSET(FxObject, m_ParentObject); 93 94 // Context Triage Info 95 _WdfContextTriageInfo.HeaderSize = sizeof(FxContextHeader); 96 _WdfContextTriageInfo.NextHeader = FIELD_OFFSET(FxContextHeader, NextHeader); 97 _WdfContextTriageInfo.Object = FIELD_OFFSET(FxContextHeader, Object); 98 _WdfContextTriageInfo.TypeInfoPtr = FIELD_OFFSET(FxContextHeader, ContextTypeInfo); 99 _WdfContextTriageInfo.Context = FIELD_OFFSET(FxContextHeader, Context); 100 101 // Context type Triage info 102 _WdfContextTypeTriageInfo.TypeInfoSize = sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO); 103 _WdfContextTypeTriageInfo.ContextSize = FIELD_OFFSET(WDF_OBJECT_CONTEXT_TYPE_INFO, ContextSize); 104 _WdfContextTypeTriageInfo.ContextName = FIELD_OFFSET(WDF_OBJECT_CONTEXT_TYPE_INFO, ContextName); 105 106 // WdfRequest Queue 107 _WdfQueueTriageInfo.QueueSize = sizeof(FxIoQueue); 108 _WdfQueueTriageInfo.IrpQueue1 = FIELD_OFFSET(FxIoQueue, m_Queue); 109 _WdfQueueTriageInfo.IrpQueue2 = FIELD_OFFSET(FxIoQueue, m_DriverCancelable); 110 _WdfQueueTriageInfo.RequestList1 = FIELD_OFFSET(FxIoQueue, m_Cancelled); 111 _WdfQueueTriageInfo.RequestList2 = FIELD_OFFSET(FxIoQueue, m_CanceledOnQueueList); 112 _WdfQueueTriageInfo.FwdProgressContext = FIELD_OFFSET(FxIoQueue, m_FwdProgContext); 113 _WdfQueueTriageInfo.PkgIo = FIELD_OFFSET(FxIoQueue, m_PkgIo); 114 115 // Forward Progress 116 _WdfFwdProgressTriageInfo.ReservedRequestList = 117 FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_ReservedRequestList); 118 _WdfFwdProgressTriageInfo.ReservedRequestInUseList = 119 FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_ReservedRequestInUseList); 120 _WdfFwdProgressTriageInfo.PendedIrpList = 121 FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_PendedIrpList); 122 123 // Irp Queue 124 _WdfIrpQueueTriageInfo.IrpQueueSize = sizeof(FxIrpQueue); 125 _WdfIrpQueueTriageInfo.IrpListHeader = FIELD_OFFSET(FxIrpQueue, m_Queue); 126 127 128 129 130 131 132 133 134 135 _WdfIrpQueueTriageInfo.IrpListEntry = 0; 136 _WdfIrpQueueTriageInfo.IrpContext = 0; 137 138 // WdfRequest 139 _WdfRequestTriageInfo.RequestSize = sizeof(FxRequest); 140 _WdfRequestTriageInfo.CsqContext = FIELD_OFFSET(FxRequest, m_CsqContext); 141 _WdfRequestTriageInfo.FxIrp = FIELD_OFFSET(FxRequest, m_Irp); 142 _WdfRequestTriageInfo.ListEntryQueueOwned = 143 FIELD_OFFSET(FxRequest, m_OwnerListEntry); 144 _WdfRequestTriageInfo.ListEntryQueueOwned2 = 145 FIELD_OFFSET(FxRequest, m_OwnerListEntry2); 146 _WdfRequestTriageInfo.RequestListEntry = 147 FIELD_OFFSET(FxRequest, m_ListEntry); 148 _WdfRequestTriageInfo.FwdProgressList = 149 FIELD_OFFSET(FxRequest, m_ForwardProgressList); 150 151 // WdfDevice 152 _WdfDeviceTriageInfo.DeviceInitSize = sizeof(WDFDEVICE_INIT); 153 _WdfDeviceTriageInfo.DeviceDriver = FIELD_OFFSET(FxDevice, m_Driver); 154 155 // FxIrp 156 _WdfIrpTriageInfo.FxIrpSize = sizeof(FxIrp); 157 _WdfIrpTriageInfo.IrpPtr = FIELD_OFFSET(FxIrp, m_Irp); 158 } 159 160 NTSTATUS 161 FxLibraryCommonCommission( 162 VOID 163 ) 164 { 165 NTSTATUS status; 166 167 __Print((LITERAL(WDF_LIBRARY_COMMISSION) "\n")); 168 169 // 170 // Commission this version's DLL globals. 171 // 172 status = FxLibraryGlobalsCommission(); 173 if (!NT_SUCCESS(status)) { 174 __Print(("FxLibraryGlobalsCommission failed %X\n", status)); 175 return status; 176 } 177 178 // 179 // register for ETW tracing. 180 // 181 RegisterTelemetryProvider(); 182 183 // 184 // Initialize internal WPP tracing. 185 // 186 status = FxTraceInitialize(); 187 if (NT_SUCCESS(status)) { 188 FxLibraryGlobals.InternalTracingInitialized = TRUE; 189 } 190 else { 191 __Print(("Failed to initialize tracing for WDF\n")); 192 193 // 194 // Failure to initialize is not critical enough to fail driver load. 195 // 196 status = STATUS_SUCCESS; 197 } 198 199 return status; 200 } 201 202 NTSTATUS 203 FxLibraryCommonDecommission( 204 VOID 205 ) 206 { 207 __Print((LITERAL(WDF_LIBRARY_DECOMMISSION) ": enter\n")); 208 209 // 210 // Uninitialize WPP tracing. 211 // 212 if (FxLibraryGlobals.InternalTracingInitialized) { 213 TraceUninitialize(); 214 FxLibraryGlobals.InternalTracingInitialized = FALSE; 215 } 216 217 // 218 // Unregister telemetry provider. 219 // 220 UnregisterTelemetryProvider(); 221 222 EventUnregisterMicrosoft_Windows_DriverFrameworks_UserMode_Performance(); 223 224 // 225 // Decommission this version's DLL globals. 226 // 227 FxLibraryGlobalsDecommission(); 228 229 // 230 // Note: This is the absolute last action from WDF library (dynamic or static). 231 // The image is likely to be deleted after returning. 232 // 233 __Print((LITERAL(WDF_LIBRARY_DECOMMISSION) ": exit\n")); 234 235 return STATUS_SUCCESS; 236 } 237 238 239 NTSTATUS 240 FxLibraryCommonRegisterClient( 241 PWDF_BIND_INFO Info, 242 PWDF_DRIVER_GLOBALS * WdfDriverGlobals, 243 PCLIENT_INFO ClientInfo 244 ) 245 { 246 NTSTATUS status; 247 248 status = STATUS_INVALID_PARAMETER; 249 250 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n")); 251 252 ASSERT(Info != NULL && Info->FuncCount != 0); 253 ASSERT(WdfDriverGlobals != 0); 254 255 if (Info == NULL || WdfDriverGlobals == NULL || Info->FuncTable == NULL) { 256 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) 257 ": NULL parameter -- %s\n", 258 (Info == NULL) ? "PWDF_BIND_INFO" : 259 (WdfDriverGlobals == NULL) ? "PWDF_DRIVER_GLOBALS *" : 260 (Info->FuncTable == NULL) ? "PWDF_BIND_INFO->FuncTable" : 261 "unknown" )); 262 goto Done; 263 } 264 265 *WdfDriverGlobals = NULL; 266 267 ASSERT(Info->FuncCount <= WdfVersion.FuncCount); 268 269 // 270 // WdfVersion.Count is initialized in FxDynamics.h and is never changed. 271 // Prefast is unable to make that determination. 272 // 273 __assume(WdfVersion.FuncCount == sizeof(WDFFUNCTIONS)/sizeof(PVOID)); 274 275 if (Info->FuncCount > WdfVersion.FuncCount) { 276 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) 277 ": version mismatch detected in function table count: client" 278 "has 0x%x, library has 0x%x\n", 279 Info->FuncCount, WdfVersion.FuncCount)); 280 goto Done; 281 } 282 283 if (Info->FuncCount <= WdfFunctionTableNumEntries_V2_15) { 284 285 switch (Info->FuncCount) { 286 287 case WdfFunctionTableNumEntries_V2_15: 288 case WdfFunctionTableNumEntries_V2_0: 289 break; 290 291 default: 292 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) 293 ": Function table count 0x%x doesn't match any previously " 294 "released framework version table size\n", 295 Info->FuncCount)); 296 goto Done; 297 } 298 } 299 else { 300 // 301 // Client version is same as framework version. Make 302 // sure table count is exact. 303 // 304 // Note that in order for build-to-build upgrade to work, the following 305 // check should be commented out during active development. 306 // 307 // DO CHANGE it to a real failure towards the tail end of release to 308 // prevent cases where a driver sneaks out into public after being built 309 // with a non-RTM version of WDF and has a function count less than the 310 // final count. An HCK test has been added to ensure such drivers are 311 // caught early. This check is an additional prevention. 312 // 313 if (Info->FuncCount != WdfFunctionTableNumEntries) { 314 __Print(("Framework function table size (%d) doesn't match " 315 "with client (%d). Rebuild the client driver.", 316 WdfFunctionTableNumEntries, Info->FuncCount)); 317 318 ASSERT(FALSE); 319 goto Done; 320 } 321 } 322 323 // 324 // Allocate an new FxDriverGlobals area for this driver. 325 // 326 *WdfDriverGlobals = FxAllocateDriverGlobals(); 327 328 if (*WdfDriverGlobals) { 329 BOOLEAN isFunctinTableHookingOn = FALSE; 330 BOOLEAN isPerformanceAnalysisOn = FALSE; 331 PFX_DRIVER_GLOBALS fxDriverGlobals = NULL; 332 // 333 // Check the registry to see if Enhanced verifier is on for this driver. 334 // if registry read fails, options value remains unchanged. 335 // store enhanced verifier options in driver globals 336 // 337 fxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals); 338 GetEnhancedVerifierOptions(ClientInfo, &fxDriverGlobals->FxEnhancedVerifierOptions); 339 isFunctinTableHookingOn = IsFxVerifierFunctionTableHooking(fxDriverGlobals); 340 isPerformanceAnalysisOn = IsFxPerformanceAnalysis(fxDriverGlobals); 341 342 // 343 // Set-up the function table. Enhanced verifier and Performance analysis is off by default. 344 // 345 if (isFunctinTableHookingOn == FALSE && isPerformanceAnalysisOn == FALSE) { 346 // 347 // Set-up the function table 348 // 349 // Starting in 2.15 we reference a copy of the DDI table in WDF01000, 350 // prior to that we copy the entire table to local memory. 351 // 352 if (Info->FuncCount <= WdfFunctionTableNumEntries_V2_0) { 353 RtlCopyMemory( Info->FuncTable, 354 &WdfVersion.Functions, 355 Info->FuncCount * sizeof(PVOID) ); 356 } 357 else { 358 // 359 // FuncTable arrives with a ptr to &WdfFunctions, so we update 360 // what WdfFunctions points to 361 // 362 *((WDFFUNC**) Info->FuncTable) = (WDFFUNC*) &WdfVersion.Functions; 363 } 364 } 365 else { 366 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) 367 ": Enhanced Verification is ON \n")); 368 369 if (Microsoft_Windows_DriverFrameworks_UserMode_PerformanceHandle == NULL) 370 { 371 EventRegisterMicrosoft_Windows_DriverFrameworks_UserMode_Performance(); 372 } 373 374 // 375 // Enhanced verification is on. Return verifier function table 376 // 377 // Starting in 1.15 we reference a copy of the DDI table in WDF01000, 378 // prior to that we copy the entire table to local memory. 379 // 380 if (Info->FuncCount <= WdfFunctionTableNumEntries_V2_0) { 381 RtlCopyMemory( Info->FuncTable, 382 &VfWdfVersion.Functions, 383 Info->FuncCount * sizeof(PVOID) ); 384 } 385 else { 386 // 387 // FuncTable arrives with a ptr to &WdfFunctions, so we update 388 // what WdfFunctions points to. 389 // 390 *((WDFFUNC**) Info->FuncTable) = (WDFFUNC*) &VfWdfVersion.Functions; 391 } 392 } 393 394 status = STATUS_SUCCESS; 395 396 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) 397 ": WdfFunctions %p\n", Info->FuncTable)); 398 } 399 400 Done: 401 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) 402 ": exit: status %X\n", status)); 403 404 if (!NT_SUCCESS(status)) { 405 FX_VERIFY(DRIVER(BadArgument, TODO), 406 TRAPMSG("Version mismatch detected in function table count. Recompile" 407 " driver with correct headers")); 408 } 409 410 return status; 411 } 412 413 NTSTATUS 414 FxLibraryCommonUnregisterClient( 415 PWDF_BIND_INFO Info, 416 PWDF_DRIVER_GLOBALS WdfDriverGlobals 417 ) 418 { 419 NTSTATUS status; 420 421 __Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT) ": enter\n")); 422 423 ASSERT(Info != NULL); 424 ASSERT(WdfDriverGlobals != NULL); 425 426 if (Info != NULL && WdfDriverGlobals != NULL) { 427 PFX_DRIVER_GLOBALS pFxDriverGlobals; 428 429 status = STATUS_SUCCESS; 430 431 pFxDriverGlobals = GetFxDriverGlobals(WdfDriverGlobals); 432 433 // 434 // Destroy this FxDriver instance, if its still indicated. 435 // 436 if (pFxDriverGlobals->Driver != NULL) { 437 // 438 // Association support, we are a root with no parent 439 // 440 pFxDriverGlobals->Driver->DeleteObject(); 441 442 FxDestroy(pFxDriverGlobals); 443 } 444 445 // 446 // Stop IFR logging 447 // 448 FxIFRStop(pFxDriverGlobals); 449 450 // 451 // This will free the client's FxDriverGlobals area 452 // 453 FxFreeDriverGlobals(WdfDriverGlobals); 454 } 455 else { 456 status = STATUS_UNSUCCESSFUL; 457 } 458 459 __Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT) 460 ": exit: status %X\n", status)); 461 462 return status; 463 } 464 465 VOID 466 GetEnhancedVerifierOptions( 467 PCLIENT_INFO ClientInfo, 468 PULONG Options 469 ) 470 { 471 NTSTATUS status; 472 ULONG value; 473 FxAutoRegKey hWdf; 474 DECLARE_CONST_UNICODE_STRING(valueName, WDF_ENHANCED_VERIFIER_OPTIONS_VALUE_NAME); 475 476 *Options = 0; 477 if (ClientInfo == NULL || 478 ClientInfo->Size != sizeof(CLIENT_INFO) || 479 ClientInfo->RegistryPath == NULL || 480 ClientInfo->RegistryPath->Length == 0 || 481 ClientInfo->RegistryPath->Buffer == NULL || 482 Options == NULL) { 483 484 __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) 485 ": Invalid ClientInfo received from wudfldr \n")); 486 return; 487 } 488 489 status = FxRegKey::_OpenKey(NULL, 490 ClientInfo->RegistryPath, 491 &hWdf.m_Key, 492 KEY_READ); 493 if (!NT_SUCCESS(status)) { 494 return; 495 } 496 497 status = FxRegKey::_QueryULong( 498 hWdf.m_Key, &valueName, &value); 499 500 // 501 // Examine key values and set Options only on success. 502 // 503 if (NT_SUCCESS(status)) { 504 if (value) { 505 *Options = value; 506 } 507 } 508 } 509