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 FxDevice::DispatchWithLock( 1336 __in MdDeviceObject DeviceObject, 1337 __in MdIrp Irp 1338 ) 1339 { 1340 NTSTATUS status; 1341 FxIrp irp(Irp); 1342 1343 switch (_RequiresRemLock(irp.GetMajorFunction(), 1344 irp.GetMinorFunction())) { 1345 1346 case FxDeviceRemLockRequired: 1347 status = Mx::MxAcquireRemoveLock( 1348 &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, 1349 Irp 1350 ); 1351 1352 if (!NT_SUCCESS(status)) { 1353 irp.SetStatus(status); 1354 irp.CompleteRequest(IO_NO_INCREMENT); 1355 1356 return status; 1357 } 1358 1359 break; 1360 1361 case FxDeviceRemLockOptIn: 1362 status = _AcquireOptinRemoveLock( 1363 DeviceObject, 1364 Irp 1365 ); 1366 1367 if (!NT_SUCCESS(status)) { 1368 irp.SetStatus(status); 1369 irp.CompleteRequest(IO_NO_INCREMENT); 1370 1371 return status; 1372 } 1373 1374 break; 1375 1376 case FxDeviceRemLockTestValid: 1377 // 1378 // Try to Acquire and Release the RemLock. If acquiring the lock 1379 // fails then it is not safe to process the IRP and the IRP should 1380 // be completed immediately. 1381 // 1382 status = Mx::MxAcquireRemoveLock( 1383 &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, 1384 Irp 1385 ); 1386 1387 if (!NT_SUCCESS(status)) { 1388 irp.SetStatus(status); 1389 irp.CompleteRequest(IO_NO_INCREMENT); 1390 1391 return status; 1392 } 1393 1394 Mx::MxReleaseRemoveLock( 1395 &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, 1396 Irp 1397 ); 1398 break; 1399 } 1400 1401 return Dispatch(DeviceObject, Irp); 1402 } 1403 1404 _Must_inspect_result_ 1405 __inline 1406 BOOLEAN 1407 IsPreprocessIrp( 1408 __in MdIrp Irp, 1409 __in FxIrpPreprocessInfo* Info 1410 ) 1411 { 1412 UCHAR major, minor; 1413 BOOLEAN preprocess; 1414 FxIrp irp(Irp); 1415 1416 major = irp.GetMajorFunction(); 1417 minor = irp.GetMinorFunction(); 1418 1419 preprocess = FALSE; 1420 1421 if (Info->Dispatch[major].EvtDevicePreprocess != NULL) { 1422 if (Info->Dispatch[major].NumMinorFunctions == 0) { 1423 // 1424 // If the driver is not interested in particular minor codes, 1425 // just give the irp to it. 1426 // 1427 preprocess = TRUE; 1428 } 1429 else { 1430 ULONG i; 1431 1432 // 1433 // Try to match up to a minor code. 1434 // 1435 for (i = 0; i < Info->Dispatch[major].NumMinorFunctions; i++) { 1436 if (Info->Dispatch[major].MinorFunctions[i] == minor) { 1437 preprocess = TRUE; 1438 break; 1439 } 1440 } 1441 } 1442 } 1443 1444 return preprocess; 1445 } 1446 1447 _Must_inspect_result_ 1448 __inline 1449 NTSTATUS 1450 PreprocessIrp( 1451 __in FxDevice* Device, 1452 __in MdIrp Irp, 1453 __in FxIrpPreprocessInfo* Info, 1454 __in PVOID DispatchContext 1455 ) 1456 { 1457 NTSTATUS status; 1458 UCHAR major, minor; 1459 FxIrp irp(Irp); 1460 1461 major = irp.GetMajorFunction(); 1462 minor = irp.GetMinorFunction(); 1463 1464 // 1465 // If this is a pnp remove irp, this object could be deleted by the time 1466 // EvtDevicePreprocess returns. To not touch freed pool, capture all 1467 // values we will need before preprocessing. 1468 // 1469 1470 if (Info->ClassExtension == FALSE) { 1471 status = Info->Dispatch[major].EvtDevicePreprocess( Device->GetHandle(), 1472 Irp); 1473 } 1474 else { 1475 status = Info->Dispatch[major].EvtCxDevicePreprocess( 1476 Device->GetHandle(), 1477 Irp, 1478 DispatchContext); 1479 } 1480 1481 // 1482 // If we got this far, we handed the irp off to EvtDevicePreprocess, so we 1483 // must now do our remlock maintainance if necessary. 1484 // 1485 if (FxDevice::_RequiresRemLock(major, minor) == FxDeviceRemLockRequired) { 1486 // 1487 // Keep the remove lock active until after we call into the driver. 1488 // If the driver redispatches the irp to the framework, we will 1489 // reacquire the remove lock at that point in time. 1490 // 1491 // Touching pDevObj after sending the pnp remove irp to the framework 1492 // is OK b/c we have acquired the remlock previously and that will 1493 // prevent this irp's processing racing with the pnp remove irp 1494 // processing. 1495 // 1496 Mx::MxReleaseRemoveLock(Device->GetRemoveLock(), 1497 Irp); 1498 } 1499 1500 return status; 1501 } 1502 1503 _Must_inspect_result_ 1504 __inline 1505 NTSTATUS 1506 DispatchWorker( 1507 __in FxDevice* Device, 1508 __in MdIrp Irp, 1509 __in WDFCONTEXT DispatchContext 1510 ) 1511 { 1512 PLIST_ENTRY next; 1513 FxIrp irp(Irp); 1514 1515 next = (PLIST_ENTRY)DispatchContext; 1516 1517 ASSERT(NULL != DispatchContext && 1518 ((UCHAR)(ULONG_PTR)DispatchContext & FX_IN_DISPATCH_CALLBACK) == 0); 1519 1520 // 1521 // Check for any driver/class-extensions' preprocess requirements. 1522 // 1523 while (next != &Device->m_PreprocessInfoListHead) { 1524 FxIrpPreprocessInfo* info; 1525 1526 info = CONTAINING_RECORD(next, FxIrpPreprocessInfo, ListEntry); 1527 1528 // 1529 // Advance to next node. 1530 // 1531 next = next->Flink; 1532 1533 if (IsPreprocessIrp(Irp, info)) { 1534 return PreprocessIrp(Device, Irp, info, next); 1535 } 1536 } 1537 1538 // 1539 // No preprocess requirements, directly dispatch the IRP. 1540 // 1541 return Device->GetDispatchPackage( 1542 irp.GetMajorFunction() 1543 )->Dispatch(Irp); 1544 } 1545 1546 1547 _Must_inspect_result_ 1548 NTSTATUS 1549 FxDevice::Dispatch( 1550 __in MdDeviceObject DeviceObject, 1551 __in MdIrp Irp 1552 ) 1553 { 1554 FxDevice* device = FxDevice::GetFxDevice(DeviceObject); 1555 return DispatchWorker(device, 1556 Irp, 1557 device->m_PreprocessInfoListHead.Flink); 1558 } 1559 1560 _Must_inspect_result_ 1561 NTSTATUS 1562 FxDevice::DispatchPreprocessedIrp( 1563 __in MdIrp Irp, 1564 __in WDFCONTEXT DispatchContext 1565 ) 1566 { 1567 NTSTATUS status; 1568 UCHAR major, minor; 1569 FxIrp irp(Irp); 1570 1571 // 1572 // The contract for this DDI is just like IoCallDriver. The caller sets up 1573 // their stack location and then the DDI advances to the next stack location. 1574 // This means that the caller either has to call IoSkipCurrentIrpStackLocation 1575 // or IoCopyCurrentIrpStackLocationToNext before calling this DDI. 1576 // 1577 irp.SetNextIrpStackLocation(); 1578 1579 major = irp.GetMajorFunction(); 1580 minor = irp.GetMinorFunction(); 1581 1582 // 1583 // FxPkgPnp and FxWmiIrpHandler expect that there will be a remove lock 1584 // acquired for all power irps. We release the remlock when we called 1585 // Evt(Ext)DevicePreprocessIrp. 1586 // 1587 if (_RequiresRemLock(major, minor) == FxDeviceRemLockRequired) { 1588 status = Mx::MxAcquireRemoveLock( 1589 GetRemoveLock(), 1590 Irp 1591 ); 1592 1593 if (!NT_SUCCESS(status)) { 1594 goto Done; 1595 } 1596 } 1597 1598 return DispatchWorker(this, Irp, DispatchContext); 1599 1600 Done: 1601 irp.SetStatus(status); 1602 irp.SetInformation(0); 1603 irp.CompleteRequest(IO_NO_INCREMENT); 1604 1605 return status; 1606 } 1607 1608 VOID 1609 FxDevice::InstallPackage( 1610 __inout FxPackage *Package 1611 ) 1612 1613 { 1614 // 1615 // Add this package as an association on FxDevice 1616 // so its children get Dispose notifications. 1617 // 1618 // Note: This assumes a transfer of the controlling reference 1619 // count which it will dereference on FxDevice teardown. 1620 // We need to add an extra one here since packages have 1621 // an existing reference count model. 1622 // 1623 Package->AddRef(); 1624 Package->AssignParentObject(this); 1625 } 1626 1627 PVOID 1628 FxDevice::AllocateRequestMemory( 1629 __in_opt PWDF_OBJECT_ATTRIBUTES RequestAttributes 1630 ) 1631 /*++ 1632 1633 Routine Description: 1634 Allocates enough memory for an FxRequest* plus any additonal memory required 1635 for the device's specific context memory. 1636 1637 If we are tracking memory, the allocation layout is 1638 0x0 - FX_POOL_TRACKER 1639 0x0 + sizeof(FX_POOL_TRACKER) - FX_POOL_HEADER 1640 0x0 + sizeof(FX_POOL_TRACKER) + FX_POOL_HEADER_SIZE - start of FxRequest 1641 1642 if no tracking is occuring, the allocation layout is 1643 0x0 - FX_POOL_HEADER 1644 0x0 + FX_POOL_HEADER_SIZE - start of FxRequest 1645 1646 the total size is precomputed in m_RequestLookasideListElementSize during 1647 FxDevice::Initialize 1648 1649 Arguments: 1650 RequestAttributes - Attributes setting for the request. 1651 1652 Return Value: 1653 valid ptr or NULL 1654 1655 --*/ 1656 1657 { 1658 PFX_DRIVER_GLOBALS pGlobals; 1659 PFX_POOL_TRACKER pTracker; 1660 PFX_POOL_HEADER pHeader; 1661 PVOID ptr, pTrueBase; 1662 1663 pGlobals = GetDriverGlobals(); 1664 ptr = NULL; 1665 1666 if (IsPdo() && GetPdoPkg()->IsForwardRequestToParentEnabled()) { 1667 pTrueBase = FxAllocateFromNPagedLookasideListNoTracking(&m_RequestLookasideList); 1668 } 1669 else { 1670 pTrueBase = FxAllocateFromNPagedLookasideList(&m_RequestLookasideList, 1671 m_RequestLookasideListElementSize); 1672 } 1673 1674 if (pTrueBase != NULL) { 1675 if (pGlobals->IsPoolTrackingOn()) { 1676 pTracker = (PFX_POOL_TRACKER) pTrueBase; 1677 pHeader = WDF_PTR_ADD_OFFSET_TYPE(pTrueBase, 1678 sizeof(FX_POOL_TRACKER), 1679 PFX_POOL_HEADER); 1680 1681 // 1682 // Format and insert the Tracker in the NonPagedHeader list. 1683 // 1684 FxPoolInsertNonPagedAllocateTracker(&pGlobals->FxPoolFrameworks, 1685 pTracker, 1686 m_RequestLookasideListElementSize, 1687 pGlobals->Tag, 1688 _ReturnAddress()); 1689 } 1690 else { 1691 pHeader = (PFX_POOL_HEADER) pTrueBase; 1692 } 1693 1694 // 1695 // Common init 1696 // 1697 pHeader->Base = pTrueBase; 1698 pHeader->FxDriverGlobals = pGlobals; 1699 1700 ptr = &pHeader->AllocationStart[0]; 1701 1702 if (RequestAttributes == NULL) { 1703 RequestAttributes = &m_RequestAttributes; 1704 } 1705 1706 ptr = FxObjectAndHandleHeaderInit( 1707 pGlobals, 1708 ptr, 1709 COMPUTE_OBJECT_SIZE(sizeof(FxRequest), 0), 1710 RequestAttributes, 1711 FxObjectTypeExternal 1712 ); 1713 1714 #if FX_VERBOSE_TRACE 1715 DoTraceLevelMessage(pGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1716 "Allocating FxRequest* %p, WDFREQUEST %p", 1717 ptr, _ToHandle((FxObject*) ptr)); 1718 #endif 1719 return ptr; 1720 } 1721 1722 return NULL; 1723 } 1724 1725 VOID 1726 FxDevice::FreeRequestMemory( 1727 __in FxRequest* Request 1728 ) 1729 { 1730 PFX_POOL_HEADER pHeader; 1731 1732 #if FX_VERBOSE_TRACE 1733 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, 1734 "Free FxRequest* %p memory", Request); 1735 #endif 1736 1737 // 1738 // Remove the request from the list of outstanding requests against this 1739 // driver. 1740 // 1741 pHeader = FxObject::_CleanupPointer(GetDriverGlobals(), Request); 1742 if (IsPdo() && GetPdoPkg()->IsForwardRequestToParentEnabled()) { 1743 FxFreeToNPagedLookasideListNoTracking(&m_RequestLookasideList, pHeader->Base); 1744 } 1745 else { 1746 FxFreeToNPagedLookasideList(&m_RequestLookasideList, pHeader->Base); 1747 } 1748 } 1749 1750 _Must_inspect_result_ 1751 NTSTATUS 1752 FxDevice::QueryInterface( 1753 __inout FxQueryInterfaceParams* Params 1754 ) 1755 { 1756 switch (Params->Type) { 1757 case FX_TYPE_DEVICE: 1758 *Params->Object = (FxDevice*) this; 1759 break; 1760 1761 default: 1762 return FxDeviceBase::QueryInterface(Params); // __super call 1763 } 1764 1765 return STATUS_SUCCESS; 1766 } 1767 1768 _Must_inspect_result_ 1769 NTSTATUS 1770 FxDevice::AddIoTarget( 1771 __inout FxIoTarget* IoTarget 1772 ) 1773 { 1774 NTSTATUS status; 1775 1776 status = m_IoTargetsList.Add(GetDriverGlobals(), 1777 &IoTarget->m_TransactionedEntry); 1778 1779 if (NT_SUCCESS(status)) { 1780 IoTarget->m_AddedToDeviceList = TRUE; 1781 IoTarget->ADDREF(this); 1782 } 1783 1784 return status; 1785 } 1786 1787 VOID 1788 FxDevice::RemoveIoTarget( 1789 __inout FxIoTarget* IoTarget 1790 ) 1791 { 1792 m_IoTargetsList.Remove(GetDriverGlobals(), 1793 &IoTarget->m_TransactionedEntry); 1794 1795 // 1796 // Assumes that the caller has its own reference on the IoTarget 1797 // 1798 IoTarget->RELEASE(this); 1799 } 1800 1801 _Must_inspect_result_ 1802 NTSTATUS 1803 FxDevice::AllocateEnumInfo( 1804 VOID 1805 ) 1806 { 1807 if (IsPnp()) { 1808 return m_PkgPnp->AllocateEnumInfo(); 1809 } 1810 else { 1811 return STATUS_SUCCESS; 1812 } 1813 } 1814 1815 FxIoTarget* 1816 FxDevice::GetDefaultIoTarget( 1817 VOID 1818 ) 1819 { 1820 if (IsPnp() && IsFdo()) { 1821 return GetFdoPkg()->m_DefaultTarget; 1822 } 1823 else { 1824 return NULL; 1825 } 1826 } 1827 1828 FxIoTargetSelf* 1829 FxDevice::GetSelfIoTarget( 1830 VOID 1831 ) 1832 /*++ 1833 Routine Description: 1834 Returns the Self IO target for this FxDevice. 1835 Currently Self IO Target is supported only for a Pnp FDO. 1836 If the Self IO Target has not been established, it returns NULL. 1837 --*/ 1838 { 1839 if (IsPnp() && IsFdo()) { 1840 return GetFdoPkg()->m_SelfTarget; 1841 } 1842 else { 1843 return NULL; 1844 } 1845 } 1846 1847 _Must_inspect_result_ 1848 NTSTATUS 1849 FxDevice::SetFilter( 1850 __in BOOLEAN Value 1851 ) 1852 { 1853 NTSTATUS status; 1854 1855 ASSERT(IsFdo()); 1856 1857 status = m_PkgIo->SetFilter(Value); 1858 1859 if (NT_SUCCESS(status) && m_PkgPnp != NULL) { 1860 status = GetFdoPkg()->SetFilter(Value); 1861 } 1862 1863 if (NT_SUCCESS(status)) { 1864 m_Filter = Value; 1865 } 1866 1867 return status; 1868 } 1869 1870 VOID 1871 FxDevice::SetFilterIoType( 1872 VOID 1873 ) 1874 { 1875 FxIoTarget * ioTarget; 1876 FxTransactionedEntry * targetsList = NULL; 1877 1878 ASSERT(IsFilter()); 1879 1880 m_DeviceObject.SetFlags( m_DeviceObject.GetFlags() & ~(DO_BUFFERED_IO | DO_DIRECT_IO)); 1881 1882 // 1883 // m_AttachedDevice can be NULL for UMDF, so check for NULL 1884 // 1885 if (m_AttachedDevice.GetObject() != NULL) { 1886 m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | 1887 (m_AttachedDevice.GetFlags() & (DO_BUFFERED_IO | DO_DIRECT_IO))); 1888 } 1889 1890 if (m_DeviceObject.GetFlags() & DO_BUFFERED_IO) { 1891 m_ReadWriteIoType = WdfDeviceIoBuffered; 1892 } 1893 else if (m_DeviceObject.GetFlags() & DO_DIRECT_IO) { 1894 m_ReadWriteIoType = WdfDeviceIoDirect; 1895 } 1896 else { 1897 m_ReadWriteIoType = WdfDeviceIoNeither; 1898 } 1899 1900 // 1901 // We also need to propagate these settings to any io targets that 1902 // have already been created 1903 // 1904 1905 m_IoTargetsList.LockForEnum(GetDriverGlobals()); 1906 1907 targetsList = m_IoTargetsList.GetNextEntry(targetsList); 1908 1909 while (targetsList != NULL) { 1910 1911 ioTarget = (FxIoTarget *) targetsList->GetTransactionedObject(); 1912 1913 if (ioTarget->GetTargetPDO() == GetPhysicalDevice()) { 1914 ioTarget->UpdateTargetIoType(); 1915 } 1916 1917 targetsList = m_IoTargetsList.GetNextEntry(targetsList); 1918 } 1919 1920 m_IoTargetsList.UnlockFromEnum(GetDriverGlobals()); 1921 } 1922 1923 BOOLEAN 1924 FxDevice::IsInterfaceRegistered( 1925 _In_ const GUID* InterfaceClassGUID, 1926 _In_opt_ PCUNICODE_STRING RefString 1927 ) 1928 { 1929 PSINGLE_LIST_ENTRY ple; 1930 BOOLEAN found = FALSE; 1931 1932 m_PkgPnp->m_DeviceInterfaceLock.AcquireLock(GetDriverGlobals()); 1933 1934 // 1935 // Iterate over the interfaces and see if we have a match 1936 // 1937 for (ple = m_PkgPnp->m_DeviceInterfaceHead.Next; ple != NULL; ple = ple->Next) { 1938 FxDeviceInterface *pDI; 1939 1940 pDI = FxDeviceInterface::_FromEntry(ple); 1941 1942 if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) { 1943 if (RefString != NULL) { 1944 if ((RefString->Length == pDI->m_ReferenceString.Length) 1945 && 1946 (RtlCompareMemory(RefString->Buffer, 1947 pDI->m_ReferenceString.Buffer, 1948 RefString->Length) == RefString->Length)) { 1949 // 1950 // They match, carry on 1951 // 1952 DO_NOTHING(); 1953 } 1954 else { 1955 // 1956 // The ref strings do not match, continue on in the search 1957 // of the collection. 1958 // 1959 continue; 1960 } 1961 } 1962 else if (pDI->m_ReferenceString.Length > 0) { 1963 // 1964 // Caller didn't specify a ref string but this interface has 1965 // one, continue on in the search through the collection. 1966 // 1967 continue; 1968 } 1969 1970 // 1971 // Set the state and break out of the loop because we found our 1972 // interface. 1973 // 1974 found = TRUE; 1975 break; 1976 } 1977 } 1978 1979 m_PkgPnp->m_DeviceInterfaceLock.ReleaseLock(GetDriverGlobals()); 1980 1981 return found; 1982 } 1983 1984 _Must_inspect_result_ 1985 NTSTATUS 1986 FxDevice::_AllocAndQueryProperty( 1987 _In_ PFX_DRIVER_GLOBALS Globals, 1988 _In_opt_ PWDFDEVICE_INIT DeviceInit, 1989 _In_opt_ FxDevice* Device, 1990 _In_opt_ MdDeviceObject RemotePdo, 1991 _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty, 1992 _In_ POOL_TYPE PoolType, 1993 _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 1994 _Out_ WDFMEMORY* PropertyMemory 1995 ) 1996 { 1997 FxMemoryObject* pMemory; 1998 NTSTATUS status; 1999 ULONG length = 0; 2000 2001 status = FxDevice::_QueryProperty(Globals, 2002 DeviceInit, 2003 Device, 2004 RemotePdo, 2005 DeviceProperty, 2006 0, 2007 NULL, 2008 &length); 2009 if (status != STATUS_BUFFER_TOO_SMALL) { 2010 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2011 "Could not retrieve property %d length, %!STATUS!", 2012 DeviceProperty, status); 2013 _Analysis_assume_(!NT_SUCCESS(status)); 2014 return status; 2015 } 2016 2017 status = FxMemoryObject::_Create(Globals, 2018 PropertyMemoryAttributes, 2019 PoolType, 2020 Globals->Tag, 2021 length, 2022 &pMemory); 2023 if (!NT_SUCCESS(status)) { 2024 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2025 "Could not allocate WDFMEMORY, %!STATUS!", status); 2026 return status; 2027 } 2028 2029 status = FxDevice::_QueryProperty(Globals, 2030 DeviceInit, 2031 Device, 2032 RemotePdo, 2033 DeviceProperty, 2034 length, 2035 pMemory->GetBuffer(), 2036 &length); 2037 if (!NT_SUCCESS(status)) { 2038 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2039 "Could not query for full buffer, size %d, for " 2040 "property %d, %!STATUS!", 2041 length, DeviceProperty, status); 2042 pMemory->DeleteObject(); 2043 return status; 2044 } 2045 2046 status = pMemory->Commit(PropertyMemoryAttributes, 2047 (WDFOBJECT*)PropertyMemory); 2048 2049 if (!NT_SUCCESS(status)) { 2050 DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2051 "Could not commit memory object, %!STATUS!", 2052 status); 2053 pMemory->DeleteObject(); 2054 } 2055 2056 return status; 2057 } 2058 2059 _Must_inspect_result_ 2060 NTSTATUS 2061 FxDevice::_AllocAndQueryPropertyEx( 2062 _In_ PFX_DRIVER_GLOBALS DriverGlobals, 2063 _In_opt_ PWDFDEVICE_INIT DeviceInit, 2064 _In_opt_ FxDevice* Device, 2065 _In_ PVOID PropertyData, 2066 _In_ FxPropertyType FxPropertyType, 2067 _In_ POOL_TYPE PoolType, 2068 _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, 2069 _Out_ WDFMEMORY* PropertyMemory, 2070 _Out_ PDEVPROPTYPE PropertyType 2071 ) 2072 { 2073 FxMemoryObject* pMemory; 2074 NTSTATUS status; 2075 ULONG length = 0; 2076 DEVPROPTYPE propType; 2077 ULONG requiredLength; 2078 2079 status = FxDevice::_QueryPropertyEx(DriverGlobals, 2080 DeviceInit, 2081 Device, 2082 PropertyData, 2083 FxPropertyType, 2084 0, 2085 NULL, 2086 &requiredLength, 2087 &propType); 2088 if (status != STATUS_BUFFER_TOO_SMALL) { 2089 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2090 "Could not retrieve property, %!STATUS!", 2091 status); 2092 _Analysis_assume_(!NT_SUCCESS(status)); 2093 return status; 2094 } 2095 2096 *PropertyMemory = NULL; 2097 *PropertyType = 0; 2098 2099 length = requiredLength; 2100 status = FxMemoryObject::_Create(DriverGlobals, 2101 PropertyMemoryAttributes, 2102 PoolType, 2103 DriverGlobals->Tag, 2104 length, 2105 &pMemory); 2106 if (!NT_SUCCESS(status)) { 2107 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2108 "Could not allocate WDFMEMORY, %!STATUS!", status); 2109 return status; 2110 } 2111 2112 status = FxDevice::_QueryPropertyEx(DriverGlobals, 2113 DeviceInit, 2114 Device, 2115 PropertyData, 2116 FxPropertyType, 2117 length, 2118 pMemory->GetBuffer(), 2119 &requiredLength, 2120 &propType); 2121 if (!NT_SUCCESS(status)) { 2122 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2123 "Could not query for full buffer, size %d, for " 2124 "property, %!STATUS!", 2125 length, status); 2126 pMemory->DeleteObject(); 2127 return status; 2128 } 2129 2130 status = pMemory->Commit(PropertyMemoryAttributes, 2131 (WDFOBJECT*)PropertyMemory); 2132 2133 if (!NT_SUCCESS(status)) { 2134 DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, 2135 "Could not commit memory object, %!STATUS!", 2136 status); 2137 pMemory->DeleteObject(); 2138 } 2139 else { 2140 *PropertyMemory = pMemory->GetHandle(); 2141 *PropertyType = propType; 2142 } 2143 2144 return status; 2145 } 2146 2147 _Must_inspect_result_ 2148 NTSTATUS 2149 FxDevice::_ValidateOpenKeyParams( 2150 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, 2151 _In_opt_ PWDFDEVICE_INIT DeviceInit, 2152 _In_opt_ FxDevice* Device 2153 ) 2154 { 2155 NTSTATUS status = STATUS_SUCCESS; 2156 2157 // 2158 // This function should be called with exactly one valid WDFDEVICE_INIT 2159 // or one valid FxDevice object. Supplying neither or both is an error. 2160 // 2161 if ((DeviceInit == NULL && Device == NULL) || 2162 (DeviceInit != NULL && Device != NULL)) { 2163 2164 status = STATUS_INVALID_PARAMETER; 2165 DoTraceLevelMessage( 2166 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, 2167 "Device OpenKey/QueryProperty was called with invalid " 2168 "DeviceInit and Device parameters, %!STATUS!", status); 2169 FxVerifierDbgBreakPoint(FxDriverGlobals); 2170 } 2171 2172 return status; 2173 } 2174 2175