1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxDevice.cpp 8 9 Abstract: 10 11 This is the class implementation for the base Device class. 12 13 Author: 14 15 16 17 Environment: 18 19 Both kernel and user mode 20 21 Revision History: 22 23 --*/ 24 25 #include "coreprivshared.hpp" 26 27 extern "C" { 28 // #include "FxDevice.tmh" 29 } 30 31 // 32 // This table contains the mapping between device type and the 33 // default priority boost used by the the framework when 34 // an I/O request is completed. The DeviceObject->DeviceType 35 // is used as an index into this table. 36 // 37 const CHAR FxDevice::m_PriorityBoosts[] = { 38 IO_NO_INCREMENT, // FILE_DEVICE_UNDEFINED 0x00000000 39 IO_NO_INCREMENT, // FILE_DEVICE_BEEP 0x00000001 40 IO_CD_ROM_INCREMENT, // FILE_DEVICE_CD_ROM 0x00000002 41 IO_CD_ROM_INCREMENT, // FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 42 IO_NO_INCREMENT, // FILE_DEVICE_CONTROLLER 0x00000004 43 IO_NO_INCREMENT, // FILE_DEVICE_DATALINK 0x00000005 44 IO_NO_INCREMENT, // FILE_DEVICE_DFS 0x00000006 45 IO_DISK_INCREMENT, // FILE_DEVICE_DISK 0x00000007 46 IO_DISK_INCREMENT, // FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 47 IO_NO_INCREMENT, // FILE_DEVICE_FILE_SYSTEM 0x00000009 48 IO_NO_INCREMENT, // FILE_DEVICE_INPORT_PORT 0x0000000a 49 IO_KEYBOARD_INCREMENT, // FILE_DEVICE_KEYBOARD 0x0000000b 50 IO_MAILSLOT_INCREMENT, // FILE_DEVICE_MAILSLOT 0x0000000c 51 IO_SOUND_INCREMENT, // FILE_DEVICE_MIDI_IN 0x0000000d 52 IO_SOUND_INCREMENT, // FILE_DEVICE_MIDI_OUT 0x0000000e 53 IO_MOUSE_INCREMENT, // FILE_DEVICE_MOUSE 0x0000000f 54 IO_NO_INCREMENT, // FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 55 IO_NAMED_PIPE_INCREMENT,// FILE_DEVICE_NAMED_PIPE 0x00000011 56 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK 0x00000012 57 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK_BROWSER 0x00000013 58 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 59 IO_NO_INCREMENT, // FILE_DEVICE_NULL 0x00000015 60 IO_PARALLEL_INCREMENT, // FILE_DEVICE_PARALLEL_PORT 0x00000016 61 IO_NETWORK_INCREMENT, // FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 62 IO_NO_INCREMENT, // FILE_DEVICE_PRINTER 0x00000018 63 IO_NO_INCREMENT, // FILE_DEVICE_SCANNER 0x00000019 64 IO_SERIAL_INCREMENT, // FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a 65 IO_SERIAL_INCREMENT, // FILE_DEVICE_SERIAL_PORT 0x0000001b 66 IO_VIDEO_INCREMENT, // FILE_DEVICE_SCREEN 0x0000001c 67 IO_SOUND_INCREMENT, // FILE_DEVICE_SOUND 0x0000001d 68 IO_SOUND_INCREMENT, // FILE_DEVICE_STREAMS 0x0000001e 69 IO_NO_INCREMENT, // FILE_DEVICE_TAPE 0x0000001f 70 IO_NO_INCREMENT, // FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 71 IO_NO_INCREMENT, // FILE_DEVICE_TRANSPORT 0x00000021 72 IO_NO_INCREMENT, // FILE_DEVICE_UNKNOWN 0x00000022 73 IO_VIDEO_INCREMENT, // FILE_DEVICE_VIDEO 0x00000023 74 IO_DISK_INCREMENT, // FILE_DEVICE_VIRTUAL_DISK 0x00000024 75 IO_SOUND_INCREMENT, // FILE_DEVICE_WAVE_IN 0x00000025 76 IO_SOUND_INCREMENT, // FILE_DEVICE_WAVE_OUT 0x00000026 77 IO_KEYBOARD_INCREMENT, // FILE_DEVICE_8042_PORT 0x00000027 78 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 79 IO_NO_INCREMENT, // FILE_DEVICE_BATTERY 0x00000029 80 IO_NO_INCREMENT, // FILE_DEVICE_BUS_EXTENDER 0x0000002a 81 IO_SERIAL_INCREMENT, // FILE_DEVICE_MODEM 0x0000002b 82 IO_NO_INCREMENT, // FILE_DEVICE_VDM 0x0000002c 83 IO_DISK_INCREMENT, // FILE_DEVICE_MASS_STORAGE 0x0000002d 84 IO_NETWORK_INCREMENT, // FILE_DEVICE_SMB 0x0000002e 85 IO_SOUND_INCREMENT, // FILE_DEVICE_KS 0x0000002f 86 IO_NO_INCREMENT, // FILE_DEVICE_CHANGER 0x00000030 87 IO_NO_INCREMENT, // FILE_DEVICE_SMARTCARD 0x00000031 88 IO_NO_INCREMENT, // FILE_DEVICE_ACPI 0x00000032 89 IO_NO_INCREMENT, // FILE_DEVICE_DVD 0x00000033 90 IO_VIDEO_INCREMENT, // FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 91 IO_NO_INCREMENT, // FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 92 IO_NO_INCREMENT, // FILE_DEVICE_DFS_VOLUME 0x00000036 93 IO_SERIAL_INCREMENT, // FILE_DEVICE_SERENUM 0x00000037 94 IO_NO_INCREMENT, // FILE_DEVICE_TERMSRV 0x00000038 95 IO_NO_INCREMENT, // FILE_DEVICE_KSEC 0x00000039 96 IO_NO_INCREMENT, // FILE_DEVICE_FIPS 0x0000003A 97 IO_NO_INCREMENT, // FILE_DEVICE_INFINIBAND 0x0000003B 98 }; 99 100 NTSTATUS 101 FxDevice::_CompletionRoutineForRemlockMaintenance( 102 __in MdDeviceObject DeviceObject, 103 __in MdIrp Irp, 104 __in PVOID Context 105 ) 106 /*++ 107 108 Routine Description: 109 110 A completion routine for the IRPs for which we acquired opt-in remove lock. 111 112 Arguments: 113 DeviceObject - Pointer to deviceobject 114 Irp - Pointer to the Irp for which we acquired opt-in remove lock. 115 Context - NULL 116 Return Value: 117 118 NT Status is returned. 119 120 --*/ 121 122 { 123 FxIrp irp(Irp); 124 125 UNREFERENCED_PARAMETER(Context); 126 127 // 128 // Let the irp continue on its way. 129 // 130 irp.PropagatePendingReturned(); 131 132 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 133 Mx::MxReleaseRemoveLock(&((FxDevice::_GetFxWdmExtension( 134 DeviceObject))->IoRemoveLock), Irp); 135 #else 136 UNREFERENCED_PARAMETER(DeviceObject); 137 #endif 138 139 return STATUS_CONTINUE_COMPLETION; 140 } 141 142 143 FxDevice::FxDevice( 144 __in FxDriver *ArgDriver 145 ) : 146 FxDeviceBase(ArgDriver->GetDriverGlobals(), ArgDriver, FX_TYPE_DEVICE, sizeof(FxDevice)), 147 m_ParentDevice(NULL) 148 { 149 SetInitialState(); 150 } 151 152 VOID 153 FxDevice::SetInitialState( 154 VOID 155 ) 156 { 157 // 158 // Set the initial device state 159 // 160 m_CurrentPnpState = WdfDevStatePnpObjectCreated; 161 m_CurrentPowerState = WdfDevStatePowerObjectCreated; 162 m_CurrentPowerPolicyState = WdfDevStatePwrPolObjectCreated; 163 164 // 165 // Set the default IO type to "buffered" 166 // 167 m_ReadWriteIoType = WdfDeviceIoBuffered; 168 169 RtlZeroMemory(&m_DeviceName, sizeof(m_DeviceName)); 170 RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName)); 171 RtlZeroMemory(&m_MofResourceName, sizeof(m_MofResourceName)); 172 173 m_Filter = FALSE; 174 m_Exclusive = FALSE; 175 m_PowerPageableCapable = FALSE; 176 m_ParentWaitingOnChild = FALSE; 177 m_Legacy = FALSE; 178 m_DeviceObjectDeleted = FALSE; 179 m_PdoKnown = FALSE; 180 m_Legacy = FALSE; 181 m_AutoForwardCleanupClose = FALSE; 182 m_SelfIoTargetNeeded = FALSE; 183 m_DeviceTelemetryInfoFlags = 0; 184 185 // 186 // Clear all packages by default 187 // 188 189 m_PkgIo = NULL; 190 m_PkgPnp = NULL; 191 m_PkgGeneral = NULL; 192 m_PkgWmi = NULL; 193 m_PkgDefault = NULL; 194 195 InitializeListHead(&m_PreprocessInfoListHead); 196 InitializeListHead(&m_CxDeviceInfoListHead); 197 198 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 199 m_FileObjectClass = WdfFileObjectNotRequired; 200 #else // UMDF 201 // 202 // In UMDF file object is always required. So indicate that now. 203 // 204 m_FileObjectClass = WdfFileObjectWdfCannotUseFsContexts; 205 #endif 206 207 m_DefaultPriorityBoost = IO_NO_INCREMENT; 208 209 InitializeListHead(&m_FileObjectListHead); 210 211 m_RequestLookasideListElementSize = 0; 212 RtlZeroMemory(&m_RequestLookasideList, sizeof(m_RequestLookasideList)); 213 RtlZeroMemory(&m_RequestAttributes, sizeof(m_RequestAttributes)); 214 215 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 216 // 217 // Init UMDF specific members 218 // 219 m_CleanupFromFailedCreate = FALSE; 220 m_Dispatcher = NULL; 221 m_DevStack = NULL; 222 m_PdoDevKey = NULL; 223 m_DeviceKeyPath = NULL; 224 m_KernelDeviceName = NULL; 225 m_DeviceInstanceId = NULL; 226 227 m_RetrievalMode = UMINT::WdfDeviceIoBufferRetrievalDeferred; 228 m_IoctlIoType = WdfDeviceIoBuffered; 229 m_DirectTransferThreshold = 0; 230 231 m_DirectHardwareAccess = FX_DIRECT_HARDWARE_ACCESS_DEFAULT; 232 m_RegisterAccessMode = FX_REGISTER_ACCESS_MODE_DEFAULT; 233 m_FileObjectPolicy = FX_FILE_OBJECT_POLICY_DEFAULT; 234 m_FsContextUsePolicy = FX_FS_CONTEXT_USE_POLICY_DEFAULT; 235 m_InteruptThreadpool = NULL; 236 #endif 237 } 238 239 FxDevice::~FxDevice() 240 { 241 PLIST_ENTRY next; 242 243 // Make it always present right now even on free builds 244 if (IsDisposed() == FALSE) { 245 DoTraceLevelMessage( 246 GetDriverGlobals(), TRACE_LEVEL_FATAL, TRACINGDEVICE, 247 "FxDevice 0x%p not disposed: this maybe a driver reference count " 248 "problem with WDFDEVICE %p", this, GetObjectHandleUnchecked()); 249 250 FxVerifierBugCheck(GetDriverGlobals(), 251 WDF_OBJECT_ERROR, 252 (ULONG_PTR) GetObjectHandleUnchecked(), 253 (ULONG_PTR) this); 254 } 255 256 // 257 // Execute mode-specific destructor. Noop for KMDF, but does 258 // does detach and delete of UM device object for UMDF. Therefore 259 // can be done before other cleanup. 260 // 261 DestructorInternal(); 262 263 // 264 // If the device has been initialized but hasn't yet been 265 // destroyed, destroy it now. 266 // 267 268 269 270 271 272 273 274 ASSERT(m_DeviceObject.GetObject() == NULL); 275 276 ASSERT(m_DeviceName.Buffer == NULL); 277 278 #if FX_CORE_MODE == FX_CORE_KERNEL_MODE 279 // 280 // Assert only applicable to KM because FxDevice can get destroyed in UMDF 281 // without going through normal pnp remove path, for example, when an 282 // AddDevice failure is done in reflector, after all um drivers have 283 // succeeded AddDevice. KMDF and host use fake remove irp to handle 284 // AddDevice failure in KMDF and host respectively, but reflector does not 285 // do that for AddDevice failure that happens in reflector. 286 // Note that symbolicName buffer will anyway be deleted in this destructor 287 // later on so the symbolic link buffer doesn't leak out. 288 // 289 ASSERT(m_SymbolicLinkName.Buffer == NULL); 290 #endif 291 292 ASSERT(m_MofResourceName.Buffer == NULL); 293 294 if (m_PkgIo != NULL) { 295 m_PkgIo->RELEASE(NULL); 296 m_PkgIo = NULL; 297 } 298 299 if (m_PkgPnp != NULL) { 300 m_PkgPnp->RELEASE(NULL); 301 m_PkgPnp = NULL; 302 } 303 304 if (m_PkgGeneral != NULL) { 305 m_PkgGeneral->RELEASE(NULL); 306 m_PkgGeneral = NULL; 307 } 308 309 if (m_PkgWmi != NULL) { 310 m_PkgWmi->RELEASE(NULL); 311 m_PkgWmi = NULL; 312 } 313 314 if (m_PkgDefault != NULL) { 315 m_PkgDefault->RELEASE(NULL); 316 m_PkgDefault = NULL; 317 } 318 319 while (!IsListEmpty(&m_PreprocessInfoListHead)) { 320 next = RemoveHeadList(&m_PreprocessInfoListHead); 321 FxIrpPreprocessInfo* info; 322 info = CONTAINING_RECORD(next, FxIrpPreprocessInfo, ListEntry); 323 InitializeListHead(next); 324 delete info; 325 } 326 327 while (!IsListEmpty(&m_CxDeviceInfoListHead)) { 328 next = RemoveHeadList(&m_CxDeviceInfoListHead); 329 FxCxDeviceInfo* info; 330 info = CONTAINING_RECORD(next, FxCxDeviceInfo, ListEntry); 331 InitializeListHead(next); 332 delete info; 333 } 334 335 // 336 // Clean up any referenced objects 337 // 338 if (m_DeviceName.Buffer != NULL) { 339 FxPoolFree(m_DeviceName.Buffer); 340 RtlZeroMemory(&m_DeviceName, sizeof(m_DeviceName)); 341 } 342 343 DeleteSymbolicLink(); 344 345 if (m_MofResourceName.Buffer != NULL) { 346 FxPoolFree(m_MofResourceName.Buffer); 347 RtlZeroMemory(&m_MofResourceName, sizeof(m_DeviceName)); 348 } 349 350 // 351 // m_RequestLookasideListElementSize will be set to non zero if we have 352 // initialized the request lookaside list. 353 // 354 if (m_RequestLookasideListElementSize != 0) { 355 Mx::MxDeleteNPagedLookasideList(&m_RequestLookasideList); 356 m_RequestLookasideListElementSize = 0; 357 } 358 359 if (m_ParentDevice != NULL) { 360 m_ParentDevice->RELEASE(this); 361 } 362 } 363 364 _Must_inspect_result_ 365 NTSTATUS 366 FxDevice::_Create( 367 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 368 __in PWDFDEVICE_INIT* DeviceInit, 369 __in_opt PWDF_OBJECT_ATTRIBUTES DeviceAttributes, 370 __out FxDevice** Device 371 ) 372 { 373 PWDFDEVICE_INIT pInit; 374 FxDevice* pDevice; 375 NTSTATUS status; 376 WDFOBJECT object; 377 PLIST_ENTRY pNext; 378 PWDFCXDEVICE_INIT pCxInit; 379 FxWdmDeviceExtension* wdmDeviceExtension; 380 381 *Device = NULL; 382 pInit = *DeviceInit; 383 384 pDevice = new (FxDriverGlobals, DeviceAttributes) 385 FxDevice(pInit->Driver); 386 387 if (pDevice == NULL) { 388 status = STATUS_INSUFFICIENT_RESOURCES; 389 goto Done; 390 } 391 392 status = pDevice->Initialize(pInit, DeviceAttributes); 393 if (!NT_SUCCESS(status)) { 394 goto Done; 395 } 396 397 switch (pInit->InitType) { 398 case FxDeviceInitTypeFdo: 399 status = pDevice->FdoInitialize(pInit); 400 break; 401 402 case FxDeviceInitTypePdo: 403 status = pDevice->PdoInitialize(pInit); 404 break; 405 406 case FxDeviceInitTypeControlDevice: 407 status = pDevice->ControlDeviceInitialize(pInit); 408 break; 409 410 default: 411 // 412 // Should not drop here 413 // 414 ASSERT(FALSE); 415 break; 416 } 417 if (!NT_SUCCESS(status)) { 418 goto Done; 419 } 420 421 // 422 // Ok, we have created the device. Now lets create a handle for it. 423 // 424 status = pDevice->PostInitialize(); 425 if (!NT_SUCCESS(status)) { 426 goto Done; 427 } 428 429 // 430 // Can't use the PDO's FxDevice m_Parent as the object hierarchy parent 431 // because the Fx object hierarchy lifetime rules do not match the 432 // rules for a pnp PDO lifetime vs its FDO. 433 // 434 status = pDevice->Commit(DeviceAttributes, 435 &object, 436 pDevice->GetDriver()); 437 if (!NT_SUCCESS(status)) { 438 goto Done; 439 } 440 441 // 442 // NOTE: ---> DO NOT FAIL FROM HERE FORWARD <--- 443 // 444 445 // 446 // Up until now we have not reassigned any of the allocations in pInit 447 // and assigned them to the underlying objects. We are now at the point 448 // of "no return", ie we cannot fail. If we reassigned the allocations 449 // before this point and the driver retried to create the device (let's 450 // say with a different name), we would have freed those allocations 451 // and the driver writer would have thought that particular settings 452 // we valid, but were not b/c we freed them on error. So, to avoid a 453 // huge tracking mess, we only grab the allocations once we know for 454 // *sure* we are going to return success. 455 // 456 if (pInit->DeviceName != NULL) { 457 pInit->DeviceName->ReleaseString(&pDevice->m_DeviceName); 458 } 459 460 // 461 // Check for driver preprocess requirements. 462 // 463 if (pInit->PreprocessInfo != NULL) { 464 ASSERT( pInit->PreprocessInfo->ClassExtension == FALSE); 465 ASSERT(IsListEmpty(&pDevice->m_PreprocessInfoListHead)); 466 InsertTailList(&pDevice->m_PreprocessInfoListHead, 467 &pInit->PreprocessInfo->ListEntry); 468 pInit->PreprocessInfo = NULL; 469 470 // 471 // If the driver is preprocessing requests on this device, they need 472 // their own stack location so that they can set their own completion 473 // routine. 474 // 475 pDevice->SetStackSize(pDevice->GetStackSize()+1); 476 } 477 478 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 479 wdmDeviceExtension = _GetFxWdmExtension(pDevice->GetDeviceObject()); 480 if (wdmDeviceExtension->RemoveLockOptionFlags & 481 WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO) { 482 // 483 // We will use a completion routine for remlock maintenance 484 // 485 pDevice->SetStackSize(pDevice->GetStackSize()+1); 486 } 487 488 // 489 // Note: In case of UMDF StackSize is incremented prior to attaching 490 // the device to stack. See the comment in FxDeviceUm.cpp 491 // 492 if (pDevice->m_SelfIoTargetNeeded) { 493 pDevice->SetStackSize(pDevice->GetStackSize()+1); 494 } 495 496 #else 497 UNREFERENCED_PARAMETER(wdmDeviceExtension); 498 #endif 499 500 // 501 // Check for any class-extensions' preprocess requirements. 502 // 503 for (pNext = pInit->CxDeviceInitListHead.Flink; 504 pNext != &pInit->CxDeviceInitListHead; 505 pNext = pNext->Flink) { 506 507 pCxInit = CONTAINING_RECORD(pNext, WDFCXDEVICE_INIT, ListEntry); 508 509 if (pCxInit->PreprocessInfo != NULL) { 510 ASSERT(pCxInit->PreprocessInfo->ClassExtension); 511 InsertTailList(&pDevice->m_PreprocessInfoListHead, 512 &pCxInit->PreprocessInfo->ListEntry); 513 pCxInit->PreprocessInfo = NULL; 514 515 // 516 // If the class extension is preprocessing requests on this 517 // device, it needs its own stack location so that it can 518 // set its own completion routine. 519 // 520 pDevice->SetStackSize(pDevice->GetStackSize()+1); 521 } 522 } 523 524 if (pDevice->IsPnp()) { 525 // 526 // Take all of the allocations out of pInit related to pnp. This 527 // will also transition the pnp state machine into the added state. 528 // 529 pDevice->m_PkgPnp->FinishInitialize(pInit); 530 } 531 532 pInit->CreatedDevice = pDevice; 533 534 // 535 // Clear out the pointer, we freed it on behalf of the caller 536 // 537 *DeviceInit = NULL; 538 539 if (pInit->CreatedOnStack == FALSE) { 540 delete pInit; 541 } 542 543 Done: 544 if (!NT_SUCCESS(status) && pDevice != NULL) { 545 // 546 // We want to propagate the original error code 547 // 548 (void) pDevice->DeleteDeviceFromFailedCreate(status, FALSE); 549 pDevice = NULL; 550 } 551 552 *Device = pDevice; 553 554 return status; 555 } 556 557 _Must_inspect_result_ 558 NTSTATUS 559 FxDevice::DeleteDeviceFromFailedCreateNoDelete( 560 __in NTSTATUS FailedStatus, 561 __in BOOLEAN UseStateMachine 562 ) 563 { 564 // 565 // Cleanup the device, the driver may have allocated resources 566 // associated with the WDFDEVICE 567 // 568 DoTraceLevelMessage( 569 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP, 570 "WDFDEVICE %p !devobj %p created, but EvtDriverDeviceAdd returned " 571 "status %!STATUS! or failure in creation", 572 GetObjectHandleUnchecked(), GetDeviceObject(), FailedStatus); 573 574 // 575 // We do not let filters affect the building of the rest of the stack. 576 // If they return error, we convert it to STATUS_SUCCESS, remove the 577 // attached device from the stack, and cleanup. 578 // 579 if (IsFilter()) { 580 DoTraceLevelMessage( 581 GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP, 582 "WDFDEVICE %p, !devobj %p is a filter, converting %!STATUS! to" 583 " STATUS_SUCCESS", GetObjectHandleUnchecked(), GetDeviceObject(), 584 FailedStatus); 585 FailedStatus = STATUS_SUCCESS; 586 } 587 588 if (UseStateMachine) { 589 MxEvent waitEvent; 590 591 // 592 // See comments for m_CleanupFromFailedCreate in class definition file 593 // for use of this statement. 594 // 595 SetCleanupFromFailedCreate(TRUE); 596 597 598 599 600 601 waitEvent.Initialize(SynchronizationEvent, FALSE); 602 m_PkgPnp->CleanupDeviceFromFailedCreate(waitEvent.GetSelfPointer()); 603 } 604 else { 605 // 606 // Upon certain types of failure, like STATUS_OBJECT_NAME_COLLISION, we 607 // could keep the pDevice around and the caller retry after changing 608 // a property, but the simpler route for now is to just recreate 609 // everything from scratch on the retry. 610 // 611 // Usually the pnp state machine will do this and the FxDevice destructor 612 // relies on it running b/c it does some cleanup. 613 // 614 EarlyDispose(); 615 DestroyChildren(); 616 617 // 618 // Wait for all children to drain out and cleanup. 619 // 620 if (m_DisposeList != NULL) { 621 m_DisposeList->WaitForEmpty(); 622 } 623 624 // 625 // We keep a reference on m_PkgPnp which is released in the destructor 626 // so we can safely touch m_PkgPnp after destroying all of the child 627 // objects. 628 // 629 if (m_PkgPnp != NULL) { 630 m_PkgPnp->CleanupStateMachines(TRUE); 631 } 632 } 633 634 // 635 // This will detach and delete the device object 636 // 637 Destroy(); 638 639 return FailedStatus; 640 } 641 642 _Must_inspect_result_ 643 NTSTATUS 644 FxDevice::DeleteDeviceFromFailedCreate( 645 __in NTSTATUS FailedStatus, 646 __in BOOLEAN UseStateMachine 647 ) 648 { 649 NTSTATUS status; 650 651 status = DeleteDeviceFromFailedCreateNoDelete(FailedStatus, UseStateMachine); 652 653 // 654 // Delete the Fx object now 655 // 656 DeleteObject(); 657 658 return status; 659 } 660 661 _Must_inspect_result_ 662 NTSTATUS 663 FxDevice::Initialize( 664 __in PWDFDEVICE_INIT DeviceInit, 665 __in_opt PWDF_OBJECT_ATTRIBUTES DeviceAttributes 666 ) 667 /*++ 668 669 Routine Description: 670 Generic initialization for an FxDevice regardless of role (pdo, fdo, control). 671 672 Arguments: 673 674 675 Return Value: 676 677 678 --*/ 679 680 { 681 PFX_DRIVER_GLOBALS pGlobals; 682 PLIST_ENTRY next; 683 NTSTATUS status; 684 size_t reqCtxSize; 685 PWDFCXDEVICE_INIT cxInit; 686 CCHAR cxIndex; 687 FxCxDeviceInfo* cxDeviceInfo; 688 689 pGlobals = GetDriverGlobals(); 690 m_Exclusive = DeviceInit->Exclusive; 691 cxIndex = 0; 692 693 MarkDisposeOverride(ObjectDoNotLock); 694 695 // 696 // Configure device constraints. 697 // 698 status = ConfigureConstraints(DeviceAttributes); 699 if (!NT_SUCCESS(status)) { 700 return status; 701 } 702 703 // 704 // Generic catch all 705 // 706 m_PkgDefault = new (pGlobals) FxDefaultIrpHandler(pGlobals, (CfxDevice*)this); 707 if (m_PkgDefault == NULL) { 708 return STATUS_INSUFFICIENT_RESOURCES; 709 } 710 711 InstallPackage(m_PkgDefault); 712 713 if (DeviceInit->InitType == FxDeviceInitTypeControlDevice) { 714 m_Legacy = TRUE; 715 } 716 717 // 718 // Size will be set to a non zero if the driver wants request attributes 719 // associated with each created request. 720 // 721 if (DeviceInit->RequestAttributes.Size != 0) { 722 ASSERT(DeviceInit->RequestAttributes.Size == sizeof(WDF_OBJECT_ATTRIBUTES)); 723 RtlCopyMemory(&m_RequestAttributes, 724 &DeviceInit->RequestAttributes, 725 sizeof(DeviceInit->RequestAttributes)); 726 } 727 728 reqCtxSize = FxGetContextSize(&m_RequestAttributes); 729 730 // 731 // If present, setup a I/O class extensions info chain. 732 // 733 for (next = DeviceInit->CxDeviceInitListHead.Flink; 734 next != &DeviceInit->CxDeviceInitListHead; 735 next = next->Flink) { 736 737 cxInit = CONTAINING_RECORD(next, WDFCXDEVICE_INIT, ListEntry); 738 739 cxDeviceInfo = new(pGlobals) FxCxDeviceInfo(pGlobals); 740 if (NULL == cxDeviceInfo) { 741 return STATUS_INSUFFICIENT_RESOURCES; 742 } 743 744 cxDeviceInfo->Index = ++cxIndex; // 1-based. 745 cxDeviceInfo->Driver = cxInit->CxDriverGlobals->Driver; 746 cxDeviceInfo->IoInCallerContextCallback.m_Method = 747 cxInit->IoInCallerContextCallback; 748 cxDeviceInfo->RequestAttributes = cxInit->RequestAttributes; 749 750 InsertTailList(&m_CxDeviceInfoListHead, &cxDeviceInfo->ListEntry); 751 752 // 753 // Set weak ref to this run-time cx struct to help file-object logic later on. 754 // 755 cxInit->CxDeviceInfo = cxDeviceInfo; 756 757 // 758 // Find the max size for the request context. Used below. 759 // 760 ASSERT(cxInit->RequestAttributes.Size == 0 || 761 cxInit->RequestAttributes.Size == sizeof(WDF_OBJECT_ATTRIBUTES)); 762 763 reqCtxSize = MAX(FxGetContextSize(&cxInit->RequestAttributes), 764 reqCtxSize); 765 } 766 767 // 768 // Memory layout for memory backing FxRequest which is allocated from the 769 // lookaside list: 770 // 771 // If we are tracking memory, the allocation layout is 772 // 0x0 - FX_POOL_TRACKER 773 // 0x0 + sizeof(FX_POOL_TRACKER) - FX_POOL_HEADER 774 // 0x0 + sizeof(FX_POOL_TRACKER) + FX_POOL_HEADER_SIZE - start of FxRequest 775 // 776 // if no tracking is occuring, the allocation layout is 777 // 0x0 - FX_POOL_HEADER 778 // 0x0 + FX_POOL_HEADER_SIZE - start of FxRequest 779 // 780 // NOTE: If the computation of m_RequestLookasideListElementSize changes, 781 // FxDevice::AllocateRequestMemory and FxDevice::FreeRequestMemory will also 782 // need to be updated to reflect the changes made. 783 // 784 status = FxCalculateObjectTotalSize2(pGlobals, 785 sizeof(FxRequest), 786 0, 787 reqCtxSize, 788 &m_RequestLookasideListElementSize); 789 if (!NT_SUCCESS(status)) { 790 return status; 791 } 792 793 status = FxPoolAddHeaderSize(pGlobals, 794 m_RequestLookasideListElementSize, 795 &m_RequestLookasideListElementSize); 796 797 if (!NT_SUCCESS(status)) { 798 // 799 // FxPoolAddHeaderSize will log to the IFR on error 800 // 801 return status; 802 } 803 804 Mx::MxInitializeNPagedLookasideList(&m_RequestLookasideList, 805 NULL, 806 NULL, 807 0, 808 m_RequestLookasideListElementSize, 809 pGlobals->Tag, 810 0); 811 // 812 // Init device's auto_forward_cleanup_close. 813 // 814 ConfigureAutoForwardCleanupClose(DeviceInit); 815 816 // 817 // Create, close, cleanup, shutdown 818 // 819 m_PkgGeneral = new(pGlobals) FxPkgGeneral(pGlobals, this); 820 if (m_PkgGeneral == NULL) { 821 return STATUS_INSUFFICIENT_RESOURCES; 822 } 823 824 InstallPackage(m_PkgGeneral); 825 826 #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE) 827 828 829 830 831 832 833 // m_PkgWmi = new(pGlobals) FxWmiIrpHandler(pGlobals, this); __REACTOS__ 834 // if (m_PkgWmi == NULL) { 835 // return STATUS_INSUFFICIENT_RESOURCES; 836 // } 837 // InstallPackage(m_PkgWmi); 838 #endif 839 840 // 841 // IO package handles reads, writes, internal and external IOCTLs 842 // 843 m_PkgIo = new(pGlobals) FxPkgIo(pGlobals, (CfxDevice*) this); 844 845 if (m_PkgIo == NULL) { 846 return STATUS_INSUFFICIENT_RESOURCES; 847 } 848 849 InstallPackage(m_PkgIo); 850 851 // 852 // Configure I/O package. 853 // 854 m_PkgIo->SetIoInCallerContextCallback(DeviceInit->IoInCallerContextCallback); 855 856 if (DeviceInit->RequiresSelfIoTarget) { 857 m_SelfIoTargetNeeded = TRUE; 858 } 859 860 return STATUS_SUCCESS; 861 } 862 863 VOID 864 FxDevice::ConfigureAutoForwardCleanupClose( 865 __in PWDFDEVICE_INIT DeviceInit 866 ) 867 { 868 WDF_TRI_STATE autoForwardCleanupClose; 869 PLIST_ENTRY next; 870 BOOLEAN checkClientDriver; 871 872 autoForwardCleanupClose = WdfUseDefault; 873 checkClientDriver = TRUE; 874 875 // 876 // Device-wide configuration for auto forwarding cleanup and close requests: 877 // . Use WdfFalse if one of the devices in the chain use this setting with a create 878 // callback (this means it will complete all create IRPs). 879 // . Else use lowest driver's setting in the chain (order of cx chain: lower to higher). 880 // . If no settings are present, use default. 881 // 882 for (next = DeviceInit->CxDeviceInitListHead.Blink; 883 next != &DeviceInit->CxDeviceInitListHead; 884 next = next->Blink) { 885 886 PWDFCXDEVICE_INIT cxInit; 887 888 cxInit = CONTAINING_RECORD(next, WDFCXDEVICE_INIT, ListEntry); 889 890 if (cxInit->FileObject.Set) { 891 autoForwardCleanupClose = cxInit->FileObject.AutoForwardCleanupClose; 892 893 if (autoForwardCleanupClose == WdfFalse && 894 cxInit->FileObject.Callbacks.EvtCxDeviceFileCreate != NULL) { 895 896 checkClientDriver = FALSE; 897 break; 898 } 899 } 900 } 901 902 if (checkClientDriver && DeviceInit->FileObject.Set) { 903 autoForwardCleanupClose = DeviceInit->FileObject.AutoForwardCleanupClose; 904 } 905 906 switch (autoForwardCleanupClose) { 907 case WdfTrue: 908 909 m_AutoForwardCleanupClose = TRUE; 910 // 911 // If the device is legacy then set it to false because you can't forward 912 // requests. 913 // 914 if(m_Legacy) { 915 m_AutoForwardCleanupClose = FALSE; 916 } 917 break; 918 919 case WdfFalse: 920 m_AutoForwardCleanupClose = FALSE; 921 break; 922 923 case WdfUseDefault: 924 // 925 // For filters (which must be FDOs), we default to TRUE. All other 926 // device roles (FDO, PDO, control) default to FALSE. We cannot check 927 // m_Filter yet because it is set in FdoInitialize which occurs later. 928 // 929 if (DeviceInit->IsFdoInit() && DeviceInit->Fdo.Filter) { 930 m_AutoForwardCleanupClose = TRUE; 931 } 932 else { 933 m_AutoForwardCleanupClose = FALSE; 934 } 935 } 936 } 937 938 _Must_inspect_result_ 939 NTSTATUS 940 FxDevice::PostInitialize( 941 VOID 942 ) 943 { 944 NTSTATUS status; 945 946 status = FxDisposeList::_Create(GetDriverGlobals(), 947 m_DeviceObject.GetObject(), 948 &m_DisposeList); 949 950 return status; 951 } 952 953 954 955 956 957 958 959 960 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 961 962 _Must_inspect_result_ 963 NTSTATUS 964 FxDevice::CreateDevice( 965 __in PWDFDEVICE_INIT DeviceInit 966 ) 967 { 968 MdDeviceObject pNewDeviceObject; 969 ULONG characteristics; 970 NTSTATUS status; 971 DEVICE_TYPE devType; 972 973 status = m_PkgGeneral->Initialize(DeviceInit); 974 if (!NT_SUCCESS(status)) { 975 return status; 976 } 977 978 devType = DeviceInit->DeviceType; 979 if (devType < ARRAY_SIZE(m_PriorityBoosts)) { 980 m_DefaultPriorityBoost= m_PriorityBoosts[devType]; 981 } 982 983 characteristics = DeviceInit->Characteristics; 984 985 // 986 // You can only create secure device objects which have a name. All other 987 // device objects rely on the PDO's security 988 // 989 if (DeviceInit->ShouldCreateSecure()) { 990 PUNICODE_STRING pName, pSddl; 991 LPGUID pGuid; 992 993 if (DeviceInit->DeviceName != NULL) { 994 pName = DeviceInit->DeviceName->GetUnicodeString(); 995 } 996 else { 997 pName = NULL; 998 } 999 1000 if (DeviceInit->Security.DeviceClassSet) { 1001 pGuid = &DeviceInit->Security.DeviceClass; 1002 } 1003 else { 1004 pGuid = NULL; 1005 } 1006 1007 if (DeviceInit->Security.Sddl != NULL) { 1008 pSddl = DeviceInit->Security.Sddl->GetUnicodeString(); 1009 } 1010 else { 1011 // 1012 // Always provide an SDDL if one is not supplied. 1013 // 1014 // SDDL_DEVOBJ_SYS_ALL_ADM_ALL = "D:P(A;;GA;;;SY)(A;;GA;;;BA)" 1015 // 1016 // SDDL_DEVOBJ_SYS_ALL_ADM_ALL allows the kernel, system, and 1017 // administrator complete control over the device. No other users 1018 // may access the device. 1019 // 1020 // pSddl = (PUNICODE_STRING) &SDDL_DEVOBJ_SYS_ALL_ADM_ALL; 1021 pSddl = NULL; // __REACTOS__ : wdmsec.lib is not supported 1022 } 1023 1024 status = Mx::MxCreateDeviceSecure( 1025 m_Driver->m_DriverObject.GetObject(), 1026 sizeof(FxWdmDeviceExtension), 1027 pName, 1028 devType, 1029 characteristics, 1030 m_Exclusive, 1031 pSddl, 1032 pGuid, 1033 &pNewDeviceObject); 1034 } 1035 else { 1036 status = Mx::MxCreateDevice( 1037 m_Driver->m_DriverObject.GetObject(), 1038 sizeof(FxWdmDeviceExtension), 1039 NULL, 1040 devType, 1041 characteristics, 1042 m_Exclusive, 1043 &pNewDeviceObject); 1044 } 1045 1046 if (NT_SUCCESS(status)) { 1047 FxWdmDeviceExtension* pWdmExt; 1048 1049 pWdmExt = _GetFxWdmExtension(pNewDeviceObject); 1050 1051 // 1052 // We reassign DeviceExtension below and then use the knowledge that 1053 // we can always retrieve DeviceExtension by adding sizeof(DEVICE_OBJECT) 1054 // to pNewDeviceObject. ASSERT that this assumption is correct. 1055 // 1056 MxDeviceObject newDeviceObject(pNewDeviceObject); 1057 ASSERT(pWdmExt == newDeviceObject.GetDeviceExtension()); 1058 1059 Mx::MxInitializeRemoveLock(&pWdmExt->IoRemoveLock, 1060 GetDriverGlobals()->Tag, 1061 0, // max min 1062 0 // highwater mark 1063 ); 1064 1065 // 1066 // Option for remove lock is stored in device extension 1067 // since this option may be examined after FxDevice is destroyed 1068 // (if an Irp is sent after removal of device). 1069 // We combine the flags from DeviceInit with what's set through registry 1070 // 1071 pWdmExt->RemoveLockOptionFlags = DeviceInit->RemoveLockOptionFlags | 1072 GetDriverGlobals()->RemoveLockOptionFlags; 1073 1074 // 1075 // We assign the first context assigned to this object as the 1076 // DeviceExtension for compatibility reasons. This allows existing 1077 // WDM extensions to work as well as any stack which exports a known 1078 // structure for the extension (ie the FDO knows the extension of its 1079 // PDO and casts it and accesses it directly). 1080 // 1081 newDeviceObject.SetDeviceExtension(&GetContextHeader()->Context[0]); 1082 m_DeviceObject.SetObject(pNewDeviceObject); 1083 1084 // 1085 // Set some device object flags based on properties of DeviceInit. 1086 // 1087 // If we are a filter, we will set these flags later 1088 // (in FxDevice::FdoInitialize) based on the device we are attached to. 1089 // 1090 if (m_Filter == FALSE) { 1091 if (DeviceInit->ReadWriteIoType == WdfDeviceIoBuffered) { 1092 m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_BUFFERED_IO); 1093 } 1094 else if (DeviceInit->ReadWriteIoType == WdfDeviceIoDirect) { 1095 m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_DIRECT_IO); 1096 } 1097 1098 m_ReadWriteIoType = DeviceInit->ReadWriteIoType; 1099 m_PowerPageableCapable = DeviceInit->PowerPageable; 1100 } 1101 } 1102 1103 return status; 1104 } 1105 1106 #endif // (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 1107 1108 VOID 1109 FxDevice::FinishInitializing( 1110 VOID 1111 ) 1112 1113 /*++ 1114 1115 Routine Description: 1116 1117 This routine is called when the device is completely initialized. 1118 1119 Arguments: 1120 1121 none. 1122 1123 Returns: 1124 1125 none. 1126 1127 --*/ 1128 1129 { 1130 1131 m_DeviceObject.SetFlags( m_DeviceObject.GetFlags() & ~DO_DEVICE_INITIALIZING); 1132 } 1133 1134 VOID 1135 FxDevice::DeleteObject( 1136 VOID 1137 ) 1138 /*++ 1139 1140 Routine Description: 1141 Virtual override of an FxObject::DeleteObject. For PDOs which are created 1142 statically and then deleted before being reported to WDF, we must simulate 1143 a pnp remove event to trigger cleanup. 1144 1145 Arguments: 1146 None 1147 1148 Return Value: 1149 None 1150 1151 --*/ 1152 { 1153 if (IsPnp() && IsPdo()) { 1154 FxPkgPdo* pPkgPdo; 1155 KIRQL irql; 1156 BOOLEAN remove; 1157 1158 remove = FALSE; 1159 1160 pPkgPdo = GetPdoPkg(); 1161 1162 pPkgPdo->Lock(&irql); 1163 1164 if (pPkgPdo->m_Static && pPkgPdo->m_AddedToStaticList == FALSE) { 1165 // 1166 // Since no pnp action has been taken since the child was created, we 1167 // should be in the initial state. 1168 // 1169 if (m_CurrentPnpState == WdfDevStatePnpInit) { 1170 // 1171 // A PDO in this state should be deletable 1172 // 1173 ASSERT(IsNoDeleteDDI() == FALSE); 1174 1175 remove = TRUE; 1176 } 1177 else { 1178 // 1179 // If we are not in the init state, we should be in the created 1180 // state. This means we are failing from FxDevice::CreateDevice. 1181 // 1182 ASSERT(m_CurrentPnpState == WdfDevStatePnpObjectCreated); 1183 } 1184 } 1185 1186 pPkgPdo->Unlock(irql); 1187 1188 if (remove) { 1189 // 1190 // Cleanup the device and then let the super class delete the object. 1191 // 1192 (void) DeleteDeviceFromFailedCreateNoDelete( 1193 STATUS_UNSUCCESSFUL, TRUE); 1194 } 1195 } 1196 else if (IsLegacy() && m_PkgGeneral != NULL && m_DeviceObject.GetObject() != NULL) { 1197 // 1198 // We allow tracing devices to go through a normal DeleteObject() path 1199 // where we do not prematurely delete the device object. 1200 // 1201 (void) FxVerifierCheckIrqlLevel(GetDriverGlobals(), PASSIVE_LEVEL); 1202 1203 m_DeviceObjectDeleted = TRUE; 1204 1205 // 1206 // This reference will be released in Destroy(). 1207 // 1208 Mx::MxReferenceObject(m_DeviceObject.GetObject()); 1209 1210 if (m_PkgWmi != NULL) { 1211 // 1212 // Since a legacy NT4 driver does not have an explicit WMI 1213 // deregistration DDI, we do it for them on deletion. 1214 // 1215 // This is done in DeleteObject because we need to deregister before 1216 // we delete the device object, otherwise we can bugcheck when 1217 // running under driver verifier. 1218 // 1219 // m_PkgWmi->Deregister(); __REACTOS__ 1220 } 1221 1222 // 1223 // By deleting the device object now, we prevent any new creates from 1224 // being sent to the device (the io manager enforces this). 1225 // 1226 Mx::MxDeleteDevice(m_DeviceObject.GetObject()); 1227 1228 if (m_PkgGeneral->CanDestroyControlDevice() == FALSE) { 1229 // 1230 // Delay the actual destruction of the device until the last open 1231 // handle has been closed. ControlDeviceDelete() will perform the 1232 // destruction later. 1233 // 1234 return; 1235 } 1236 } 1237 1238 FxDeviceBase::DeleteObject(); // __super call 1239 } 1240 1241 BOOLEAN 1242 FxDevice::Dispose( 1243 VOID 1244 ) 1245 { 1246 ASSERT(Mx::MxGetCurrentIrql() == PASSIVE_LEVEL); 1247 1248 if (m_Legacy) { 1249 if (m_PkgWmi != NULL) { 1250 // 1251 // We deregister in Dispose() (as well as DeleteObject()) for 1252 // control devices which are implicitly destroyed when the driver 1253 // unloads and FxDriver is being deleted. 1254 // 1255 // Since a legacy NT4 driver does not have an explicit WMI 1256 // deregistration DDI, we do it for them on destruction. 1257 // 1258 // This is done in Dispose because we are guaranteed to be at 1259 // passive level here. Even though m_PkgWmi was already 1260 // Dispose()'ed (because it is a child of this object), it is still 1261 // valid to reference the pointer because there is an explicit 1262 // reference on the object that was taken when we created this object. 1263 // 1264 // m_PkgWmi->Deregister(); __REACTOS__ 1265 } 1266 1267 // 1268 // Important that the cleanup routine be called while the PDEVICE_OBJECT 1269 // is valid! 1270 // 1271 CallCleanup(); 1272 1273 // 1274 // Manually destroy the children now so that by the time we wait on the 1275 // dispose empty out, all of the children will have been added to it. 1276 // 1277 DestroyChildren(); 1278 1279 if (m_DisposeList != NULL) { 1280 m_DisposeList->WaitForEmpty(); 1281 } 1282 1283 // 1284 // Now delete the device object 1285 // 1286 Destroy(); 1287 1288 return FALSE; 1289 } 1290 1291 return FxDeviceBase::Dispose(); // __super call 1292 } 1293 1294 _Must_inspect_result_ 1295 NTSTATUS 1296 FxDevice::_AcquireOptinRemoveLock( 1297 __in MdDeviceObject DeviceObject, 1298 __in MdIrp Irp 1299 ) 1300 { 1301 NTSTATUS status; 1302 FxIrp irp(Irp); 1303 1304 FxWdmDeviceExtension * wdmDeviceExtension = 1305 FxDevice::_GetFxWdmExtension(DeviceObject); 1306 1307 if (wdmDeviceExtension->RemoveLockOptionFlags & 1308 WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO) { 1309 1310 status = Mx::MxAcquireRemoveLock(&(wdmDeviceExtension->IoRemoveLock), Irp); 1311 1312 if (!NT_SUCCESS(status)) { 1313 return status; 1314 } 1315 1316 irp.CopyCurrentIrpStackLocationToNext(); 1317 1318 irp.SetCompletionRoutineEx( 1319 DeviceObject, 1320 _CompletionRoutineForRemlockMaintenance, 1321 DeviceObject, 1322 TRUE, 1323 TRUE, 1324 TRUE 1325 ); 1326 1327 irp.SetNextIrpStackLocation(); 1328 } 1329 1330 return STATUS_SUCCESS; 1331 } 1332 1333 _Must_inspect_result_ 1334 NTSTATUS 1335 STDCALL 1336 FxDevice::DispatchWithLock( 1337 __in MdDeviceObject DeviceObject, 1338 __in MdIrp Irp 1339 ) 1340 { 1341 NTSTATUS status; 1342 FxIrp irp(Irp); 1343 1344 switch (_RequiresRemLock(irp.GetMajorFunction(), 1345 irp.GetMinorFunction())) { 1346 1347 case FxDeviceRemLockRequired: 1348 status = Mx::MxAcquireRemoveLock( 1349 &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, 1350 Irp 1351 ); 1352 1353 if (!NT_SUCCESS(status)) { 1354 irp.SetStatus(status); 1355 irp.CompleteRequest(IO_NO_INCREMENT); 1356 1357 return status; 1358 } 1359 1360 break; 1361 1362 case FxDeviceRemLockOptIn: 1363 status = _AcquireOptinRemoveLock( 1364 DeviceObject, 1365 Irp 1366 ); 1367 1368 if (!NT_SUCCESS(status)) { 1369 irp.SetStatus(status); 1370 irp.CompleteRequest(IO_NO_INCREMENT); 1371 1372 return status; 1373 } 1374 1375 break; 1376 1377 case FxDeviceRemLockTestValid: 1378 // 1379 // Try to Acquire and Release the RemLock. If acquiring the lock 1380 // fails then it is not safe to process the IRP and the IRP should 1381 // be completed immediately. 1382 // 1383 status = Mx::MxAcquireRemoveLock( 1384 &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, 1385 Irp 1386 ); 1387 1388 if (!NT_SUCCESS(status)) { 1389 irp.SetStatus(status); 1390 irp.CompleteRequest(IO_NO_INCREMENT); 1391 1392 return status; 1393 } 1394 1395 Mx::MxReleaseRemoveLock( 1396 &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, 1397 Irp 1398 ); 1399 break; 1400 } 1401 1402 return Dispatch(DeviceObject, Irp); 1403 } 1404 1405 _Must_inspect_result_ 1406 __inline 1407 BOOLEAN 1408 IsPreprocessIrp( 1409 __in MdIrp Irp, 1410 __in FxIrpPreprocessInfo* Info 1411 ) 1412 { 1413 UCHAR major, minor; 1414 BOOLEAN preprocess; 1415 FxIrp irp(Irp); 1416 1417 major = irp.GetMajorFunction(); 1418 minor = irp.GetMinorFunction(); 1419 1420 preprocess = FALSE; 1421 1422 if (Info->Dispatch[major].EvtDevicePreprocess != NULL) { 1423 if (Info->Dispatch[major].NumMinorFunctions == 0) { 1424 // 1425 // If the driver is not interested in particular minor codes, 1426 // just give the irp to it. 1427 // 1428 preprocess = TRUE; 1429 } 1430 else { 1431 ULONG i; 1432 1433 // 1434 // Try to match up to a minor code. 1435 // 1436 for (i = 0; i < Info->Dispatch[major].NumMinorFunctions; i++) { 1437 if (Info->Dispatch[major].MinorFunctions[i] == minor) { 1438 preprocess = TRUE; 1439 break; 1440 } 1441 } 1442 } 1443 } 1444 1445 return preprocess; 1446 } 1447 1448 _Must_inspect_result_ 1449 __inline 1450 NTSTATUS 1451 PreprocessIrp( 1452 __in FxDevice* Device, 1453 __in MdIrp Irp, 1454 __in FxIrpPreprocessInfo* Info, 1455 __in PVOID DispatchContext 1456 ) 1457 { 1458 NTSTATUS status; 1459 UCHAR major, minor; 1460 FxIrp irp(Irp); 1461 1462 major = irp.GetMajorFunction(); 1463 minor = irp.GetMinorFunction(); 1464 1465 // 1466 // If this is a pnp remove irp, this object could be deleted by the time 1467 // EvtDevicePreprocess returns. To not touch freed pool, capture all 1468 // values we will need before preprocessing. 1469 // 1470 1471 if (Info->ClassExtension == FALSE) { 1472 status = Info->Dispatch[major].EvtDevicePreprocess( Device->GetHandle(), 1473 Irp); 1474 } 1475 else { 1476 status = Info->Dispatch[major].EvtCxDevicePreprocess( 1477 Device->GetHandle(), 1478 Irp, 1479 DispatchContext); 1480 } 1481 1482 // 1483 // If we got this far, we handed the irp off to EvtDevicePreprocess, so we 1484 // must now do our remlock maintainance if necessary. 1485 // 1486 if (FxDevice::_RequiresRemLock(major, minor) == FxDeviceRemLockRequired) { 1487 // 1488 // Keep the remove lock active until after we call into the driver. 1489 // If the driver redispatches the irp to the framework, we will 1490 // reacquire the remove lock at that point in time. 1491 // 1492 // Touching pDevObj after sending the pnp remove irp to the framework 1493 // is OK b/c we have acquired the remlock previously and that will 1494 // prevent this irp's processing racing with the pnp remove irp 1495 // processing. 1496 // 1497 Mx::MxReleaseRemoveLock(Device->GetRemoveLock(), 1498 Irp); 1499 } 1500 1501 return status; 1502 } 1503 1504 _Must_inspect_result_ 1505 __inline 1506 NTSTATUS 1507 DispatchWorker( 1508 __in FxDevice* Device, 1509 __in MdIrp Irp, 1510 __in WDFCONTEXT DispatchContext 1511 ) 1512 { 1513 PLIST_ENTRY next; 1514 FxIrp irp(Irp); 1515 1516 next = (PLIST_ENTRY)DispatchContext; 1517 1518 ASSERT(NULL != DispatchContext && 1519 ((UCHAR)(ULONG_PTR)DispatchContext & FX_IN_DISPATCH_CALLBACK) == 0); 1520 1521 // 1522 // Check for any driver/class-extensions' preprocess requirements. 1523 // 1524 while (next != &Device->m_PreprocessInfoListHead) { 1525 FxIrpPreprocessInfo* info; 1526 1527 info = CONTAINING_RECORD(next, FxIrpPreprocessInfo, ListEntry); 1528 1529 // 1530 // Advance to next node. 1531 // 1532 next = next->Flink; 1533 1534 if (IsPreprocessIrp(Irp, info)) { 1535 return PreprocessIrp(Device, Irp, info, next); 1536 } 1537 } 1538 1539 // 1540 // No preprocess requirements, directly dispatch the IRP. 1541 // 1542 return Device->GetDispatchPackage( 1543 irp.GetMajorFunction() 1544 )->Dispatch(Irp); 1545 } 1546 1547 1548 _Must_inspect_result_ 1549 NTSTATUS 1550 STDCALL 1551 FxDevice::Dispatch( 1552 __in MdDeviceObject DeviceObject, 1553 __in MdIrp Irp 1554 ) 1555 { 1556 FxDevice* device = FxDevice::GetFxDevice(DeviceObject); 1557 return DispatchWorker(device, 1558 Irp, 1559 device->m_PreprocessInfoListHead.Flink); 1560 } 1561 1562 _Must_inspect_result_ 1563 NTSTATUS 1564 FxDevice::DispatchPreprocessedIrp( 1565 __in MdIrp Irp, 1566 __in WDFCONTEXT DispatchContext 1567 ) 1568 { 1569 NTSTATUS status; 1570 UCHAR major, minor; 1571 FxIrp irp(Irp); 1572 1573 // 1574 // The contract for this DDI is just like IoCallDriver. The caller sets up 1575 // their stack location and then the DDI advances to the next stack location. 1576 // This means that the caller either has to call IoSkipCurrentIrpStackLocation 1577 // or IoCopyCurrentIrpStackLocationToNext before calling this DDI. 1578 // 1579 irp.SetNextIrpStackLocation(); 1580 1581 major = irp.GetMajorFunction(); 1582 minor = irp.GetMinorFunction(); 1583 1584 // 1585 // FxPkgPnp and FxWmiIrpHandler expect that there will be a remove lock 1586 // acquired for all power irps. We release the remlock when we called 1587 // Evt(Ext)DevicePreprocessIrp. 1588 // 1589 if (_RequiresRemLock(major, minor) == FxDeviceRemLockRequired) { 1590 status = Mx::MxAcquireRemoveLock( 1591 GetRemoveLock(), 1592 Irp 1593 ); 1594 1595 if (!NT_SUCCESS(status)) { 1596 goto Done; 1597 } 1598 } 1599 1600 return DispatchWorker(this, Irp, DispatchContext); 1601 1602 Done: 1603 irp.SetStatus(status); 1604 irp.SetInformation(0); 1605 irp.CompleteRequest(IO_NO_INCREMENT); 1606 1607 return status; 1608 } 1609 1610 VOID 1611 FxDevice::InstallPackage( 1612 __inout FxPackage *Package 1613 ) 1614 1615 { 1616 // 1617 // Add this package as an association on FxDevice 1618 // so its children get Dispose notifications. 1619 // 1620 // Note: This assumes a transfer of the controlling reference 1621 // count which it will dereference on FxDevice teardown. 1622 // We need to add an extra one here since packages have 1623 // an existing reference count model. 1624 // 1625 Package->AddRef(); 1626 Package->AssignParentObject(this); 1627 } 1628 1629 PVOID 1630 FxDevice::AllocateRequestMemory( 1631 __in_opt PWDF_OBJECT_ATTRIBUTES RequestAttributes 1632 ) 1633 /*++ 1634 1635 Routine Description: 1636 Allocates enough memory for an FxRequest* plus any additonal memory required 1637 for the device's specific context memory. 1638 1639 If we are tracking memory, the allocation layout is 1640 0x0 - FX_POOL_TRACKER 1641 0x0 + sizeof(FX_POOL_TRACKER) - FX_POOL_HEADER 1642 0x0 + sizeof(FX_POOL_TRACKER) + FX_POOL_HEADER_SIZE - start of FxRequest 1643 1644 if no tracking is occuring, the allocation layout is 1645 0x0 - FX_POOL_HEADER 1646 0x0 + FX_POOL_HEADER_SIZE - start of FxRequest 1647 1648 the total size is precomputed in m_RequestLookasideListElementSize during 1649 FxDevice::Initialize 1650 1651 Arguments: 1652 RequestAttributes - Attributes setting for the request. 1653 1654 Return Value: 1655 valid ptr or NULL 1656 1657 --*/ 1658 1659 { 1660 PFX_DRIVER_GLOBALS pGlobals; 1661 PFX_POOL_TRACKER pTracker; 1662 PFX_POOL_HEADER pHeader; 1663 PVOID ptr, pTrueBase; 1664 1665 pGlobals = GetDriverGlobals(); 1666 ptr = NULL; 1667 1668 if (IsPdo() && GetPdoPkg()->IsForwardRequestToParentEnabled()) { 1669 pTrueBase = FxAllocateFromNPagedLookasideListNoTracking(&m_RequestLookasideList); 1670 } 1671 else { 1672 pTrueBase = FxAllocateFromNPagedLookasideList(&m_RequestLookasideList, 1673 m_RequestLookasideListElementSize); 1674 } 1675 1676 if (pTrueBase != NULL) { 1677 if (pGlobals->IsPoolTrackingOn()) { 1678 pTracker = (PFX_POOL_TRACKER) pTrueBase; 1679 pHeader = WDF_PTR_ADD_OFFSET_TYPE(pTrueBase, 1680 sizeof(FX_POOL_TRACKER), 1681 PFX_POOL_HEADER); 1682 1683 // 1684 // Format and insert the Tracker in the NonPagedHeader list. 1685 // 1686 FxPoolInsertNonPagedAllocateTracker(&pGlobals->FxPoolFrameworks, 1687 pTracker, 1688 m_RequestLookasideListElementSize, 1689 pGlobals->Tag, 1690 _ReturnAddress()); 1691 } 1692 else { 1693 pHeader = (PFX_POOL_HEADER) pTrueBase; 1694 } 1695 1696 // 1697 // Common init 1698 // 1699 pHeader->Base = pTrueBase; 1700 pHeader->FxDriverGlobals = pGlobals; 1701 1702 ptr = &pHeader->AllocationStart[0]; 1703 1704 if (RequestAttributes == NULL) { 1705 RequestAttributes = &m_RequestAttributes; 1706 } 1707 1708 ptr = FxObjectAndHandleHeaderInit( 1709 pGlobals, 1710 ptr, 1711 COMPUTE_OBJECT_SIZE(sizeof(FxRequest), 0), 1712 RequestAttributes, 1713 FxObjectTypeExternal 1714 ); 1715 1716 #if FX_VERBOSE_TRACE 1717 DoTraceLevelMessage(pGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1718 "Allocating FxRequest* %p, WDFREQUEST %p", 1719 ptr, _ToHandle((FxObject*) ptr)); 1720 #endif 1721 return ptr; 1722 } 1723 1724 return NULL; 1725 } 1726 1727 VOID 1728 FxDevice::FreeRequestMemory( 1729 __in FxRequest* Request 1730 ) 1731 { 1732 PFX_POOL_HEADER pHeader; 1733 1734 #if FX_VERBOSE_TRACE 1735 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1736 "Free FxRequest* %p memory", Request); 1737 #endif 1738 1739 // 1740 // Remove the request from the list of outstanding requests against this 1741 // driver. 1742 // 1743 pHeader = FxObject::_CleanupPointer(GetDriverGlobals(), Request); 1744 if (IsPdo() && GetPdoPkg()->IsForwardRequestToParentEnabled()) { 1745 FxFreeToNPagedLookasideListNoTracking(&m_RequestLookasideList, pHeader->Base); 1746 } 1747 else { 1748 FxFreeToNPagedLookasideList(&m_RequestLookasideList, pHeader->Base); 1749 } 1750 } 1751 1752 _Must_inspect_result_ 1753 NTSTATUS 1754 FxDevice::QueryInterface( 1755 __inout FxQueryInterfaceParams* Params 1756 ) 1757 { 1758 switch (Params->Type) { 1759 case FX_TYPE_DEVICE: 1760 *Params->Object = (FxDevice*) this; 1761 break; 1762 1763 default: 1764 return FxDeviceBase::QueryInterface(Params); // __super call 1765 } 1766 1767 return STATUS_SUCCESS; 1768 } 1769 1770 _Must_inspect_result_ 1771 NTSTATUS 1772 FxDevice::AddIoTarget( 1773 __inout FxIoTarget* IoTarget 1774 ) 1775 { 1776 NTSTATUS status; 1777 1778 status = m_IoTargetsList.Add(GetDriverGlobals(), 1779 &IoTarget->m_TransactionedEntry); 1780 1781 if (NT_SUCCESS(status)) { 1782 IoTarget->m_AddedToDeviceList = TRUE; 1783 IoTarget->ADDREF(this); 1784 } 1785 1786 return status; 1787 } 1788 1789 VOID 1790 FxDevice::RemoveIoTarget( 1791 __inout FxIoTarget* IoTarget 1792 ) 1793 { 1794 m_IoTargetsList.Remove(GetDriverGlobals(), 1795 &IoTarget->m_TransactionedEntry); 1796 1797 // 1798 // Assumes that the caller has its own reference on the IoTarget 1799 // 1800 IoTarget->RELEASE(this); 1801 } 1802 1803 _Must_inspect_result_ 1804 NTSTATUS 1805 FxDevice::AllocateEnumInfo( 1806 VOID 1807 ) 1808 { 1809 if (IsPnp()) { 1810 return m_PkgPnp->AllocateEnumInfo(); 1811 } 1812 else { 1813 return STATUS_SUCCESS; 1814 } 1815 } 1816 1817 FxIoTarget* 1818 FxDevice::GetDefaultIoTarget( 1819 VOID 1820 ) 1821 { 1822 if (IsPnp() && IsFdo()) { 1823 return GetFdoPkg()->m_DefaultTarget; 1824 } 1825 else { 1826 return NULL; 1827 } 1828 } 1829 1830 FxIoTargetSelf* 1831 FxDevice::GetSelfIoTarget( 1832 VOID 1833 ) 1834 /*++ 1835 Routine Description: 1836 Returns the Self IO target for this FxDevice. 1837 Currently Self IO Target is supported only for a Pnp FDO. 1838 If the Self IO Target has not been established, it returns NULL. 1839 --*/ 1840 { 1841 if (IsPnp() && IsFdo()) { 1842 return GetFdoPkg()->m_SelfTarget; 1843 } 1844 else { 1845 return NULL; 1846 } 1847 } 1848 1849 _Must_inspect_result_ 1850 NTSTATUS 1851 FxDevice::SetFilter( 1852 __in BOOLEAN Value 1853 ) 1854 { 1855 NTSTATUS status; 1856 1857 ASSERT(IsFdo()); 1858 1859 status = m_PkgIo->SetFilter(Value); 1860 1861 if (NT_SUCCESS(status) && m_PkgPnp != NULL) { 1862 status = GetFdoPkg()->SetFilter(Value); 1863 } 1864 1865 if (NT_SUCCESS(status)) { 1866 m_Filter = Value; 1867 } 1868 1869 return status; 1870 } 1871 1872 VOID 1873 FxDevice::SetFilterIoType( 1874 VOID 1875 ) 1876 { 1877 FxIoTarget * ioTarget; 1878 FxTransactionedEntry * targetsList = NULL; 1879 1880 ASSERT(IsFilter()); 1881 1882 m_DeviceObject.SetFlags( m_DeviceObject.GetFlags() & ~(DO_BUFFERED_IO | DO_DIRECT_IO)); 1883 1884 // 1885 // m_AttachedDevice can be NULL for UMDF, so check for NULL 1886 // 1887 if (m_AttachedDevice.GetObject() != NULL) { 1888 m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | 1889 (m_AttachedDevice.GetFlags() & (DO_BUFFERED_IO | DO_DIRECT_IO))); 1890 } 1891 1892 if (m_DeviceObject.GetFlags() & DO_BUFFERED_IO) { 1893 m_ReadWriteIoType = WdfDeviceIoBuffered; 1894 } 1895 else if (m_DeviceObject.GetFlags() & DO_DIRECT_IO) { 1896 m_ReadWriteIoType = WdfDeviceIoDirect; 1897 } 1898 else { 1899 m_ReadWriteIoType = WdfDeviceIoNeither; 1900 } 1901 1902 // 1903 // We also need to propagate these settings to any io targets that 1904 // have already been created 1905 // 1906 1907 m_IoTargetsList.LockForEnum(GetDriverGlobals()); 1908 1909 targetsList = m_IoTargetsList.GetNextEntry(targetsList); 1910 1911 while (targetsList != NULL) { 1912 1913 ioTarget = (FxIoTarget *) targetsList->GetTransactionedObject(); 1914 1915 if (ioTarget->GetTargetPDO() == GetPhysicalDevice()) { 1916 ioTarget->UpdateTargetIoType(); 1917 } 1918 1919 targetsList = m_IoTargetsList.GetNextEntry(targetsList); 1920 } 1921 1922 m_IoTargetsList.UnlockFromEnum(GetDriverGlobals()); 1923 } 1924 1925 BOOLEAN 1926 FxDevice::IsInterfaceRegistered( 1927 _In_ const GUID* InterfaceClassGUID, 1928 _In_opt_ PCUNICODE_STRING RefString 1929 ) 1930 { 1931 PSINGLE_LIST_ENTRY ple; 1932 BOOLEAN found = FALSE; 1933 1934 m_PkgPnp->m_DeviceInterfaceLock.AcquireLock(GetDriverGlobals()); 1935 1936 // 1937 // Iterate over the interfaces and see if we have a match 1938 // 1939 for (ple = m_PkgPnp->m_DeviceInterfaceHead.Next; ple != NULL; ple = ple->Next) { 1940 FxDeviceInterface *pDI; 1941 1942 pDI = FxDeviceInterface::_FromEntry(ple); 1943 1944 if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) { 1945 if (RefString != NULL) { 1946 if ((RefString->Length == pDI->m_ReferenceString.Length) 1947 && 1948 (RtlCompareMemory(RefString->Buffer, 1949 pDI->m_ReferenceString.Buffer, 1950 RefString->Length) == RefString->Length)) { 1951 // 1952 // They match, carry on 1953 // 1954 DO_NOTHING(); 1955 } 1956 else { 1957 // 1958 // The ref strings do not match, continue on in the search 1959 // of the collection. 1960 // 1961 continue; 1962 } 1963 } 1964 else if (pDI->m_ReferenceString.Length > 0) { 1965 // 1966 // Caller didn't specify a ref string but this interface has 1967 // one, continue on in the search through the collection. 1968 // 1969 continue; 1970 } 1971 1972 // 1973 // Set the state and break out of the loop because we found our 1974 // interface. 1975 // 1976 found = TRUE; 1977 break; 1978 } 1979 } 1980 1981 m_PkgPnp->m_DeviceInterfaceLock.ReleaseLock(GetDriverGlobals()); 1982 1983 return found; 1984 } 1985 1986 _Must_inspect_result_ 1987 NTSTATUS 1988 FxDevice::_AllocAndQueryProperty( 1989 _In_ PFX_DRIVER_GLOBALS Globals, 1990 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1991 _In_opt_ FxDevice* Device, 1992 _In_opt_ MdDeviceObject RemotePdo, 1993 _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty, 1994 _In_ POOL_TYPE PoolType, 1995 _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 1996 _Out_ WDFMEMORY* PropertyMemory 1997 ) 1998 { 1999 FxMemoryObject* pMemory; 2000 NTSTATUS status; 2001 ULONG length = 0; 2002 2003 status = FxDevice::_QueryProperty(Globals, 2004 DeviceInit, 2005 Device, 2006 RemotePdo, 2007 DeviceProperty, 2008 0, 2009 NULL, 2010 &length); 2011 if (status != STATUS_BUFFER_TOO_SMALL) { 2012 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2013 "Could not retrieve property %d length, %!STATUS!", 2014 DeviceProperty, status); 2015 _Analysis_assume_(!NT_SUCCESS(status)); 2016 return status; 2017 } 2018 2019 status = FxMemoryObject::_Create(Globals, 2020 PropertyMemoryAttributes, 2021 PoolType, 2022 Globals->Tag, 2023 length, 2024 &pMemory); 2025 if (!NT_SUCCESS(status)) { 2026 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2027 "Could not allocate WDFMEMORY, %!STATUS!", status); 2028 return status; 2029 } 2030 2031 status = FxDevice::_QueryProperty(Globals, 2032 DeviceInit, 2033 Device, 2034 RemotePdo, 2035 DeviceProperty, 2036 length, 2037 pMemory->GetBuffer(), 2038 &length); 2039 if (!NT_SUCCESS(status)) { 2040 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2041 "Could not query for full buffer, size %d, for " 2042 "property %d, %!STATUS!", 2043 length, DeviceProperty, status); 2044 pMemory->DeleteObject(); 2045 return status; 2046 } 2047 2048 status = pMemory->Commit(PropertyMemoryAttributes, 2049 (WDFOBJECT*)PropertyMemory); 2050 2051 if (!NT_SUCCESS(status)) { 2052 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2053 "Could not commit memory object, %!STATUS!", 2054 status); 2055 pMemory->DeleteObject(); 2056 } 2057 2058 return status; 2059 } 2060 2061 _Must_inspect_result_ 2062 NTSTATUS 2063 FxDevice::_AllocAndQueryPropertyEx( 2064 _In_ PFX_DRIVER_GLOBALS DriverGlobals, 2065 _In_opt_ PWDFDEVICE_INIT DeviceInit, 2066 _In_opt_ FxDevice* Device, 2067 _In_ PVOID PropertyData, 2068 _In_ FxPropertyType FxPropertyType, 2069 _In_ POOL_TYPE PoolType, 2070 _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 2071 _Out_ WDFMEMORY* PropertyMemory, 2072 _Out_ PDEVPROPTYPE PropertyType 2073 ) 2074 { 2075 FxMemoryObject* pMemory; 2076 NTSTATUS status; 2077 ULONG length = 0; 2078 DEVPROPTYPE propType; 2079 ULONG requiredLength; 2080 2081 status = FxDevice::_QueryPropertyEx(DriverGlobals, 2082 DeviceInit, 2083 Device, 2084 PropertyData, 2085 FxPropertyType, 2086 0, 2087 NULL, 2088 &requiredLength, 2089 &propType); 2090 if (status != STATUS_BUFFER_TOO_SMALL) { 2091 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2092 "Could not retrieve property, %!STATUS!", 2093 status); 2094 _Analysis_assume_(!NT_SUCCESS(status)); 2095 return status; 2096 } 2097 2098 *PropertyMemory = NULL; 2099 *PropertyType = 0; 2100 2101 length = requiredLength; 2102 status = FxMemoryObject::_Create(DriverGlobals, 2103 PropertyMemoryAttributes, 2104 PoolType, 2105 DriverGlobals->Tag, 2106 length, 2107 &pMemory); 2108 if (!NT_SUCCESS(status)) { 2109 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2110 "Could not allocate WDFMEMORY, %!STATUS!", status); 2111 return status; 2112 } 2113 2114 status = FxDevice::_QueryPropertyEx(DriverGlobals, 2115 DeviceInit, 2116 Device, 2117 PropertyData, 2118 FxPropertyType, 2119 length, 2120 pMemory->GetBuffer(), 2121 &requiredLength, 2122 &propType); 2123 if (!NT_SUCCESS(status)) { 2124 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2125 "Could not query for full buffer, size %d, for " 2126 "property, %!STATUS!", 2127 length, status); 2128 pMemory->DeleteObject(); 2129 return status; 2130 } 2131 2132 status = pMemory->Commit(PropertyMemoryAttributes, 2133 (WDFOBJECT*)PropertyMemory); 2134 2135 if (!NT_SUCCESS(status)) { 2136 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2137 "Could not commit memory object, %!STATUS!", 2138 status); 2139 pMemory->DeleteObject(); 2140 } 2141 else { 2142 *PropertyMemory = pMemory->GetHandle(); 2143 *PropertyType = propType; 2144 } 2145 2146 return status; 2147 } 2148 2149 _Must_inspect_result_ 2150 NTSTATUS 2151 FxDevice::_ValidateOpenKeyParams( 2152 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 2153 _In_opt_ PWDFDEVICE_INIT DeviceInit, 2154 _In_opt_ FxDevice* Device 2155 ) 2156 { 2157 NTSTATUS status = STATUS_SUCCESS; 2158 2159 // 2160 // This function should be called with exactly one valid WDFDEVICE_INIT 2161 // or one valid FxDevice object. Supplying neither or both is an error. 2162 // 2163 if ((DeviceInit == NULL && Device == NULL) || 2164 (DeviceInit != NULL && Device != NULL)) { 2165 2166 status = STATUS_INVALID_PARAMETER; 2167 DoTraceLevelMessage( 2168 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2169 "Device OpenKey/QueryProperty was called with invalid " 2170 "DeviceInit and Device parameters, %!STATUS!", status); 2171 FxVerifierDbgBreakPoint(FxDriverGlobals); 2172 } 2173 2174 return status; 2175 } 2176 2177