1 /* 2 * PROJECT: ReactOS Kernel 3 * COPYRIGHT: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/io/pnpmgr/plugplay.c 5 * PURPOSE: Plug-and-play interface routines 6 * PROGRAMMERS: Eric Kohl <eric.kohl@t-online.de> 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 typedef struct _PNP_EVENT_ENTRY 16 { 17 LIST_ENTRY ListEntry; 18 PLUGPLAY_EVENT_BLOCK Event; 19 } PNP_EVENT_ENTRY, *PPNP_EVENT_ENTRY; 20 21 22 /* GLOBALS *******************************************************************/ 23 24 static LIST_ENTRY IopPnpEventQueueHead; 25 static KEVENT IopPnpNotifyEvent; 26 27 /* FUNCTIONS *****************************************************************/ 28 29 CODE_SEG("INIT") 30 NTSTATUS 31 IopInitPlugPlayEvents(VOID) 32 { 33 InitializeListHead(&IopPnpEventQueueHead); 34 35 KeInitializeEvent(&IopPnpNotifyEvent, 36 SynchronizationEvent, 37 FALSE); 38 39 return STATUS_SUCCESS; 40 } 41 42 NTSTATUS 43 IopQueueTargetDeviceEvent(const GUID *Guid, 44 PUNICODE_STRING DeviceIds) 45 { 46 PPNP_EVENT_ENTRY EventEntry; 47 UNICODE_STRING Copy; 48 ULONG TotalSize; 49 NTSTATUS Status; 50 51 ASSERT(DeviceIds); 52 53 /* Allocate a big enough buffer */ 54 Copy.Length = 0; 55 Copy.MaximumLength = DeviceIds->Length + sizeof(UNICODE_NULL); 56 TotalSize = 57 FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK, TargetDevice.DeviceIds) + 58 Copy.MaximumLength; 59 60 EventEntry = ExAllocatePool(NonPagedPool, 61 TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event)); 62 if (!EventEntry) 63 return STATUS_INSUFFICIENT_RESOURCES; 64 RtlZeroMemory(EventEntry, TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event)); 65 66 /* Fill the buffer with the event GUID */ 67 RtlCopyMemory(&EventEntry->Event.EventGuid, 68 Guid, 69 sizeof(GUID)); 70 EventEntry->Event.EventCategory = TargetDeviceChangeEvent; 71 EventEntry->Event.TotalSize = TotalSize; 72 73 /* Fill the device id */ 74 Copy.Buffer = EventEntry->Event.TargetDevice.DeviceIds; 75 Status = RtlAppendUnicodeStringToString(&Copy, DeviceIds); 76 if (!NT_SUCCESS(Status)) 77 { 78 ExFreePool(EventEntry); 79 return Status; 80 } 81 82 InsertHeadList(&IopPnpEventQueueHead, 83 &EventEntry->ListEntry); 84 KeSetEvent(&IopPnpNotifyEvent, 85 0, 86 FALSE); 87 88 return STATUS_SUCCESS; 89 } 90 91 92 static PDEVICE_OBJECT 93 IopTraverseDeviceNode(PDEVICE_NODE Node, PUNICODE_STRING DeviceInstance) 94 { 95 PDEVICE_OBJECT DeviceObject; 96 PDEVICE_NODE ChildNode; 97 98 if (RtlEqualUnicodeString(&Node->InstancePath, 99 DeviceInstance, TRUE)) 100 { 101 ObReferenceObject(Node->PhysicalDeviceObject); 102 return Node->PhysicalDeviceObject; 103 } 104 105 /* Traversal of all children nodes */ 106 for (ChildNode = Node->Child; 107 ChildNode != NULL; 108 ChildNode = ChildNode->Sibling) 109 { 110 DeviceObject = IopTraverseDeviceNode(ChildNode, DeviceInstance); 111 if (DeviceObject != NULL) 112 { 113 return DeviceObject; 114 } 115 } 116 117 return NULL; 118 } 119 120 121 PDEVICE_OBJECT 122 IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance) 123 { 124 if (IopRootDeviceNode == NULL) 125 return NULL; 126 127 if (DeviceInstance == NULL || 128 DeviceInstance->Length == 0) 129 { 130 if (IopRootDeviceNode->PhysicalDeviceObject) 131 { 132 ObReferenceObject(IopRootDeviceNode->PhysicalDeviceObject); 133 return IopRootDeviceNode->PhysicalDeviceObject; 134 } 135 else 136 return NULL; 137 } 138 139 return IopTraverseDeviceNode(IopRootDeviceNode, DeviceInstance); 140 } 141 142 static NTSTATUS 143 IopCaptureUnicodeString(PUNICODE_STRING DstName, PUNICODE_STRING SrcName) 144 { 145 NTSTATUS Status = STATUS_SUCCESS; 146 volatile UNICODE_STRING Name; 147 148 Name.Buffer = NULL; 149 _SEH2_TRY 150 { 151 Name.Length = SrcName->Length; 152 Name.MaximumLength = SrcName->MaximumLength; 153 if (Name.Length > Name.MaximumLength) 154 { 155 Status = STATUS_INVALID_PARAMETER; 156 _SEH2_LEAVE; 157 } 158 159 if (Name.MaximumLength) 160 { 161 ProbeForRead(SrcName->Buffer, 162 Name.MaximumLength, 163 sizeof(WCHAR)); 164 Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength); 165 if (Name.Buffer == NULL) 166 { 167 Status = STATUS_INSUFFICIENT_RESOURCES; 168 _SEH2_LEAVE; 169 } 170 171 memcpy(Name.Buffer, SrcName->Buffer, Name.MaximumLength); 172 } 173 174 *DstName = Name; 175 } 176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 177 { 178 if (Name.Buffer) 179 { 180 ExFreePool(Name.Buffer); 181 } 182 Status = _SEH2_GetExceptionCode(); 183 } 184 _SEH2_END; 185 186 return Status; 187 } 188 189 /* 190 * Remove the current PnP event from the tail of the event queue 191 * and signal IopPnpNotifyEvent if there is yet another event in the queue. 192 */ 193 static 194 NTSTATUS 195 IopRemovePlugPlayEvent( 196 _In_ PPLUGPLAY_CONTROL_USER_RESPONSE_DATA ResponseData) 197 { 198 /* Remove a pnp event entry from the tail of the queue */ 199 if (!IsListEmpty(&IopPnpEventQueueHead)) 200 { 201 ExFreePool(CONTAINING_RECORD(RemoveTailList(&IopPnpEventQueueHead), PNP_EVENT_ENTRY, ListEntry)); 202 } 203 204 /* Signal the next pnp event in the queue */ 205 if (!IsListEmpty(&IopPnpEventQueueHead)) 206 { 207 KeSetEvent(&IopPnpNotifyEvent, 208 0, 209 FALSE); 210 } 211 212 return STATUS_SUCCESS; 213 } 214 215 216 static NTSTATUS 217 IopGetInterfaceDeviceList(PPLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA DeviceList) 218 { 219 NTSTATUS Status; 220 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA StackList; 221 UNICODE_STRING DeviceInstance; 222 PDEVICE_OBJECT DeviceObject = NULL; 223 GUID FilterGuid; 224 PZZWSTR SymbolicLinkList = NULL, LinkList; 225 SIZE_T TotalLength; 226 227 _SEH2_TRY 228 { 229 RtlCopyMemory(&StackList, DeviceList, sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); 230 231 ProbeForRead(StackList.FilterGuid, sizeof(GUID), sizeof(UCHAR)); 232 RtlCopyMemory(&FilterGuid, StackList.FilterGuid, sizeof(GUID)); 233 234 if (StackList.Buffer != NULL && StackList.BufferSize != 0) 235 { 236 ProbeForWrite(StackList.Buffer, StackList.BufferSize, sizeof(UCHAR)); 237 } 238 } 239 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 240 { 241 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 242 } 243 _SEH2_END; 244 245 Status = IopCaptureUnicodeString(&DeviceInstance, &StackList.DeviceInstance); 246 if (NT_SUCCESS(Status)) 247 { 248 /* Get the device object */ 249 DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); 250 if (DeviceInstance.Buffer != NULL) 251 { 252 ExFreePool(DeviceInstance.Buffer); 253 } 254 } 255 256 Status = IoGetDeviceInterfaces(&FilterGuid, DeviceObject, StackList.Flags, &SymbolicLinkList); 257 ObDereferenceObject(DeviceObject); 258 259 if (!NT_SUCCESS(Status)) 260 { 261 /* failed */ 262 return Status; 263 } 264 265 LinkList = SymbolicLinkList; 266 while (*SymbolicLinkList != UNICODE_NULL) 267 { 268 SymbolicLinkList += wcslen(SymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); 269 } 270 TotalLength = ((SymbolicLinkList - LinkList + 1) * sizeof(WCHAR)); 271 272 _SEH2_TRY 273 { 274 if (StackList.Buffer != NULL && 275 StackList.BufferSize >= TotalLength) 276 { 277 // We've already probed the buffer for writing above. 278 RtlCopyMemory(StackList.Buffer, LinkList, TotalLength); 279 } 280 281 DeviceList->BufferSize = TotalLength; 282 } 283 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 284 { 285 ExFreePool(LinkList); 286 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 287 } 288 _SEH2_END; 289 290 ExFreePool(LinkList); 291 return STATUS_SUCCESS; 292 } 293 294 static NTSTATUS 295 IopGetDeviceProperty(PPLUGPLAY_CONTROL_PROPERTY_DATA PropertyData) 296 { 297 PDEVICE_OBJECT DeviceObject = NULL; 298 PDEVICE_NODE DeviceNode; 299 UNICODE_STRING DeviceInstance; 300 ULONG BufferSize; 301 ULONG Property; 302 DEVICE_REGISTRY_PROPERTY DeviceProperty; 303 PVOID Buffer; 304 NTSTATUS Status; 305 306 DPRINT("IopGetDeviceProperty() called\n"); 307 DPRINT("Device name: %wZ\n", &PropertyData->DeviceInstance); 308 309 Status = IopCaptureUnicodeString(&DeviceInstance, &PropertyData->DeviceInstance); 310 if (!NT_SUCCESS(Status)) 311 { 312 return Status; 313 } 314 315 _SEH2_TRY 316 { 317 Property = PropertyData->Property; 318 BufferSize = PropertyData->BufferSize; 319 ProbeForWrite(PropertyData->Buffer, 320 BufferSize, 321 sizeof(UCHAR)); 322 } 323 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 324 { 325 if (DeviceInstance.Buffer != NULL) 326 { 327 ExFreePool(DeviceInstance.Buffer); 328 } 329 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 330 } 331 _SEH2_END; 332 333 /* Get the device object */ 334 DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); 335 if (DeviceInstance.Buffer != NULL) 336 { 337 ExFreePool(DeviceInstance.Buffer); 338 } 339 if (DeviceObject == NULL) 340 { 341 return STATUS_NO_SUCH_DEVICE; 342 } 343 344 Buffer = ExAllocatePool(NonPagedPool, BufferSize); 345 if (Buffer == NULL) 346 { 347 ObDereferenceObject(DeviceObject); 348 return STATUS_INSUFFICIENT_RESOURCES; 349 } 350 351 352 DeviceNode = ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode; 353 354 if (Property == PNP_PROPERTY_POWER_DATA) 355 { 356 if (BufferSize < sizeof(CM_POWER_DATA)) 357 { 358 BufferSize = 0; 359 Status = STATUS_BUFFER_TOO_SMALL; 360 } 361 else 362 { 363 DEVICE_CAPABILITIES DeviceCapabilities; 364 PCM_POWER_DATA PowerData; 365 IO_STACK_LOCATION Stack; 366 IO_STATUS_BLOCK IoStatusBlock; 367 368 PowerData = (PCM_POWER_DATA)Buffer; 369 RtlZeroMemory(PowerData, sizeof(CM_POWER_DATA)); 370 PowerData->PD_Size = sizeof(CM_POWER_DATA); 371 372 RtlZeroMemory(&DeviceCapabilities, sizeof(DEVICE_CAPABILITIES)); 373 DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES); 374 DeviceCapabilities.Version = 1; 375 DeviceCapabilities.Address = -1; 376 DeviceCapabilities.UINumber = -1; 377 378 Stack.Parameters.DeviceCapabilities.Capabilities = &DeviceCapabilities; 379 380 Status = IopInitiatePnpIrp(DeviceObject, 381 &IoStatusBlock, 382 IRP_MN_QUERY_CAPABILITIES, 383 &Stack); 384 if (NT_SUCCESS(Status)) 385 { 386 DPRINT("Got device capabiliities\n"); 387 388 PowerData->PD_MostRecentPowerState = PowerDeviceD0; // FIXME 389 if (DeviceCapabilities.DeviceD1) 390 PowerData->PD_Capabilities |= PDCAP_D1_SUPPORTED; 391 if (DeviceCapabilities.DeviceD2) 392 PowerData->PD_Capabilities |= PDCAP_D2_SUPPORTED; 393 if (DeviceCapabilities.WakeFromD0) 394 PowerData->PD_Capabilities |= PDCAP_WAKE_FROM_D0_SUPPORTED; 395 if (DeviceCapabilities.WakeFromD1) 396 PowerData->PD_Capabilities |= PDCAP_WAKE_FROM_D1_SUPPORTED; 397 if (DeviceCapabilities.WakeFromD2) 398 PowerData->PD_Capabilities |= PDCAP_WAKE_FROM_D2_SUPPORTED; 399 if (DeviceCapabilities.WakeFromD3) 400 PowerData->PD_Capabilities |= PDCAP_WAKE_FROM_D3_SUPPORTED; 401 if (DeviceCapabilities.WarmEjectSupported) 402 PowerData->PD_Capabilities |= PDCAP_WARM_EJECT_SUPPORTED; 403 PowerData->PD_D1Latency = DeviceCapabilities.D1Latency; 404 PowerData->PD_D2Latency = DeviceCapabilities.D2Latency; 405 PowerData->PD_D3Latency = DeviceCapabilities.D3Latency; 406 RtlCopyMemory(&PowerData->PD_PowerStateMapping, 407 &DeviceCapabilities.DeviceState, 408 sizeof(DeviceCapabilities.DeviceState)); 409 PowerData->PD_DeepestSystemWake = DeviceCapabilities.SystemWake; 410 } 411 else 412 { 413 DPRINT("IRP_MN_QUERY_CAPABILITIES failed (Status 0x%08lx)\n", Status); 414 415 PowerData->PD_Capabilities = PDCAP_D0_SUPPORTED | PDCAP_D3_SUPPORTED; 416 PowerData->PD_MostRecentPowerState = PowerDeviceD0; 417 } 418 } 419 } 420 else if (Property == PNP_PROPERTY_REMOVAL_POLICY_OVERRIDE) 421 { 422 UNIMPLEMENTED; 423 BufferSize = 0; 424 Status = STATUS_NOT_IMPLEMENTED; 425 } 426 else if (Property == PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT) 427 { 428 if (BufferSize < sizeof(DeviceNode->HardwareRemovalPolicy)) 429 { 430 BufferSize = 0; 431 Status = STATUS_BUFFER_TOO_SMALL; 432 } 433 else 434 { 435 BufferSize = sizeof(DeviceNode->HardwareRemovalPolicy); 436 RtlCopyMemory(Buffer, 437 &DeviceNode->HardwareRemovalPolicy, 438 BufferSize); 439 } 440 } 441 else 442 { 443 switch (Property) 444 { 445 case PNP_PROPERTY_UI_NUMBER: 446 DeviceProperty = DevicePropertyUINumber; 447 break; 448 449 case PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME: 450 DeviceProperty = DevicePropertyPhysicalDeviceObjectName; 451 break; 452 453 case PNP_PROPERTY_BUSTYPEGUID: 454 DeviceProperty = DevicePropertyBusTypeGuid; 455 break; 456 457 case PNP_PROPERTY_LEGACYBUSTYPE: 458 DeviceProperty = DevicePropertyLegacyBusType; 459 break; 460 461 case PNP_PROPERTY_BUSNUMBER: 462 DeviceProperty = DevicePropertyBusNumber; 463 break; 464 465 case PNP_PROPERTY_REMOVAL_POLICY: 466 DeviceProperty = DevicePropertyRemovalPolicy; 467 break; 468 469 case PNP_PROPERTY_ADDRESS: 470 DeviceProperty = DevicePropertyAddress; 471 break; 472 473 case PNP_PROPERTY_ENUMERATOR_NAME: 474 DeviceProperty = DevicePropertyEnumeratorName; 475 break; 476 477 case PNP_PROPERTY_INSTALL_STATE: 478 DeviceProperty = DevicePropertyInstallState; 479 break; 480 481 #if (WINVER >= _WIN32_WINNT_WS03) 482 case PNP_PROPERTY_LOCATION_PATHS: 483 UNIMPLEMENTED; 484 BufferSize = 0; 485 Status = STATUS_NOT_IMPLEMENTED; 486 break; 487 #endif 488 489 #if (WINVER >= _WIN32_WINNT_WIN7) 490 case PNP_PROPERTY_CONTAINERID: 491 DeviceProperty = DevicePropertyContainerID; 492 break; 493 #endif 494 495 default: 496 BufferSize = 0; 497 Status = STATUS_INVALID_PARAMETER; 498 break; 499 } 500 501 if (Status == STATUS_SUCCESS) 502 { 503 Status = IoGetDeviceProperty(DeviceObject, 504 DeviceProperty, 505 BufferSize, 506 Buffer, 507 &BufferSize); 508 } 509 } 510 511 ObDereferenceObject(DeviceObject); 512 513 if (NT_SUCCESS(Status)) 514 { 515 _SEH2_TRY 516 { 517 RtlCopyMemory(PropertyData->Buffer, Buffer, BufferSize); 518 PropertyData->BufferSize = BufferSize; 519 } 520 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 521 { 522 Status = _SEH2_GetExceptionCode(); 523 } 524 _SEH2_END; 525 } 526 527 ExFreePool(Buffer); 528 return Status; 529 } 530 531 532 static NTSTATUS 533 IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData) 534 { 535 UNICODE_STRING RootDeviceName; 536 PDEVICE_OBJECT DeviceObject = NULL; 537 PDEVICE_NODE DeviceNode = NULL; 538 PDEVICE_NODE RelatedDeviceNode; 539 UNICODE_STRING TargetDeviceInstance; 540 NTSTATUS Status = STATUS_SUCCESS; 541 ULONG Relation = 0; 542 ULONG MaximumLength = 0; 543 544 DPRINT("IopGetRelatedDevice() called\n"); 545 DPRINT("Device name: %wZ\n", &RelatedDeviceData->TargetDeviceInstance); 546 547 Status = IopCaptureUnicodeString(&TargetDeviceInstance, &RelatedDeviceData->TargetDeviceInstance); 548 if (!NT_SUCCESS(Status)) 549 { 550 return Status; 551 } 552 553 _SEH2_TRY 554 { 555 Relation = RelatedDeviceData->Relation; 556 MaximumLength = RelatedDeviceData->RelatedDeviceInstanceLength; 557 ProbeForWrite(RelatedDeviceData->RelatedDeviceInstance, 558 MaximumLength, 559 sizeof(WCHAR)); 560 } 561 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 562 { 563 if (TargetDeviceInstance.Buffer != NULL) 564 { 565 ExFreePool(TargetDeviceInstance.Buffer); 566 } 567 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 568 } 569 _SEH2_END; 570 571 RtlInitUnicodeString(&RootDeviceName, 572 L"HTREE\\ROOT\\0"); 573 if (RtlEqualUnicodeString(&TargetDeviceInstance, 574 &RootDeviceName, 575 TRUE)) 576 { 577 DeviceNode = IopRootDeviceNode; 578 if (TargetDeviceInstance.Buffer != NULL) 579 { 580 ExFreePool(TargetDeviceInstance.Buffer); 581 } 582 } 583 else 584 { 585 /* Get the device object */ 586 DeviceObject = IopGetDeviceObjectFromDeviceInstance(&TargetDeviceInstance); 587 if (TargetDeviceInstance.Buffer != NULL) 588 { 589 ExFreePool(TargetDeviceInstance.Buffer); 590 } 591 if (DeviceObject == NULL) 592 return STATUS_NO_SUCH_DEVICE; 593 594 DeviceNode = ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode; 595 } 596 597 switch (Relation) 598 { 599 case PNP_GET_PARENT_DEVICE: 600 RelatedDeviceNode = DeviceNode->Parent; 601 break; 602 603 case PNP_GET_CHILD_DEVICE: 604 RelatedDeviceNode = DeviceNode->Child; 605 break; 606 607 case PNP_GET_SIBLING_DEVICE: 608 RelatedDeviceNode = DeviceNode->Sibling; 609 break; 610 611 default: 612 if (DeviceObject != NULL) 613 { 614 ObDereferenceObject(DeviceObject); 615 } 616 617 return STATUS_INVALID_PARAMETER; 618 } 619 620 if (RelatedDeviceNode == NULL) 621 { 622 if (DeviceObject) 623 { 624 ObDereferenceObject(DeviceObject); 625 } 626 627 return STATUS_NO_SUCH_DEVICE; 628 } 629 630 if (RelatedDeviceNode->InstancePath.Length > MaximumLength) 631 { 632 if (DeviceObject) 633 { 634 ObDereferenceObject(DeviceObject); 635 } 636 637 return STATUS_BUFFER_TOO_SMALL; 638 } 639 640 /* Copy related device instance name */ 641 _SEH2_TRY 642 { 643 RtlCopyMemory(RelatedDeviceData->RelatedDeviceInstance, 644 RelatedDeviceNode->InstancePath.Buffer, 645 RelatedDeviceNode->InstancePath.Length); 646 RelatedDeviceData->RelatedDeviceInstanceLength = RelatedDeviceNode->InstancePath.Length; 647 } 648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 649 { 650 Status = _SEH2_GetExceptionCode(); 651 } 652 _SEH2_END; 653 654 if (DeviceObject != NULL) 655 { 656 ObDereferenceObject(DeviceObject); 657 } 658 659 DPRINT("IopGetRelatedDevice() done\n"); 660 661 return Status; 662 } 663 664 static 665 BOOLEAN 666 PiIsDevNodeStarted( 667 _In_ PDEVICE_NODE DeviceNode) 668 { 669 return (DeviceNode->State == DeviceNodeStartPending || 670 DeviceNode->State == DeviceNodeStartCompletion || 671 DeviceNode->State == DeviceNodeStartPostWork || 672 DeviceNode->State == DeviceNodeStarted || 673 DeviceNode->State == DeviceNodeQueryStopped || 674 DeviceNode->State == DeviceNodeEnumeratePending || 675 DeviceNode->State == DeviceNodeEnumerateCompletion || 676 DeviceNode->State == DeviceNodeStopped || 677 DeviceNode->State == DeviceNodeRestartCompletion); 678 } 679 680 static ULONG 681 IopGetDeviceNodeStatus(PDEVICE_NODE DeviceNode) 682 { 683 ULONG Output = DN_NT_ENUMERATOR | DN_NT_DRIVER; 684 685 if (DeviceNode->Parent == IopRootDeviceNode) 686 Output |= DN_ROOT_ENUMERATED; 687 688 // FIXME: review for deleted and removed states 689 if (DeviceNode->State >= DeviceNodeDriversAdded) 690 Output |= DN_DRIVER_LOADED; 691 692 if (PiIsDevNodeStarted(DeviceNode)) 693 Output |= DN_STARTED; 694 695 if (DeviceNode->UserFlags & DNUF_WILL_BE_REMOVED) 696 Output |= DN_WILL_BE_REMOVED; 697 698 if (DeviceNode->Flags & DNF_HAS_PROBLEM) 699 Output |= DN_HAS_PROBLEM; 700 701 if (DeviceNode->Flags & DNF_HAS_PRIVATE_PROBLEM) 702 Output |= DN_PRIVATE_PROBLEM; 703 704 if (DeviceNode->Flags & DNF_DRIVER_BLOCKED) 705 Output |= DN_DRIVER_BLOCKED; 706 707 if (DeviceNode->Flags & DNF_CHILD_WITH_INVALID_ID) 708 Output |= DN_CHILD_WITH_INVALID_ID; 709 710 if (DeviceNode->Flags & DNF_HAS_PRIVATE_PROBLEM) 711 Output |= DN_PRIVATE_PROBLEM; 712 713 if (DeviceNode->Flags & DNF_LEGACY_DRIVER) 714 Output |= DN_LEGACY_DRIVER; 715 716 if (DeviceNode->UserFlags & DNUF_DONT_SHOW_IN_UI) 717 Output |= DN_NO_SHOW_IN_DM; 718 719 if (!(DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE)) 720 Output |= DN_DISABLEABLE; 721 722 return Output; 723 } 724 725 static NTSTATUS 726 IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData) 727 { 728 PDEVICE_OBJECT DeviceObject; 729 PDEVICE_NODE DeviceNode; 730 ULONG Operation = 0; 731 ULONG DeviceStatus = 0; 732 ULONG DeviceProblem = 0; 733 UNICODE_STRING DeviceInstance; 734 NTSTATUS Status; 735 736 DPRINT("IopDeviceStatus() called\n"); 737 738 Status = IopCaptureUnicodeString(&DeviceInstance, &StatusData->DeviceInstance); 739 if (!NT_SUCCESS(Status)) 740 { 741 return Status; 742 } 743 744 DPRINT("Device name: '%wZ'\n", &DeviceInstance); 745 746 _SEH2_TRY 747 { 748 Operation = StatusData->Operation; 749 if (Operation == PNP_SET_DEVICE_STATUS) 750 { 751 DeviceStatus = StatusData->DeviceStatus; 752 DeviceProblem = StatusData->DeviceProblem; 753 } 754 } 755 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 756 { 757 if (DeviceInstance.Buffer != NULL) 758 { 759 ExFreePool(DeviceInstance.Buffer); 760 } 761 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 762 } 763 _SEH2_END; 764 765 /* Get the device object */ 766 DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); 767 if (DeviceInstance.Buffer != NULL) 768 { 769 ExFreePool(DeviceInstance.Buffer); 770 } 771 if (DeviceObject == NULL) 772 { 773 return STATUS_NO_SUCH_DEVICE; 774 } 775 776 DeviceNode = IopGetDeviceNode(DeviceObject); 777 778 switch (Operation) 779 { 780 case PNP_GET_DEVICE_STATUS: 781 DPRINT("Get status data\n"); 782 DeviceStatus = IopGetDeviceNodeStatus(DeviceNode); 783 DeviceProblem = DeviceNode->Problem; 784 break; 785 786 case PNP_SET_DEVICE_STATUS: 787 DPRINT1("Set status data is NOT SUPPORTED\n"); 788 break; 789 790 case PNP_CLEAR_DEVICE_STATUS: 791 DPRINT1("FIXME: Clear status data!\n"); 792 break; 793 } 794 795 ObDereferenceObject(DeviceObject); 796 797 if (Operation == PNP_GET_DEVICE_STATUS) 798 { 799 _SEH2_TRY 800 { 801 StatusData->DeviceStatus = DeviceStatus; 802 StatusData->DeviceProblem = DeviceProblem; 803 } 804 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 805 { 806 Status = _SEH2_GetExceptionCode(); 807 } 808 _SEH2_END; 809 } 810 811 return Status; 812 } 813 814 static 815 NTSTATUS 816 IopGetDeviceRelations(PPLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA RelationsData) 817 { 818 UNICODE_STRING DeviceInstance; 819 PDEVICE_OBJECT DeviceObject = NULL; 820 IO_STACK_LOCATION Stack; 821 IO_STATUS_BLOCK IoStatusBlock; 822 PDEVICE_RELATIONS DeviceRelations = NULL; 823 PDEVICE_OBJECT ChildDeviceObject; 824 PDEVICE_NODE ChildDeviceNode; 825 ULONG i; 826 ULONG Relations; 827 ULONG BufferSize, RequiredSize; 828 ULONG BufferLeft; 829 PWCHAR Buffer, Ptr; 830 NTSTATUS Status = STATUS_SUCCESS; 831 832 DPRINT("IopGetDeviceRelations() called\n"); 833 DPRINT("Device name: %wZ\n", &RelationsData->DeviceInstance); 834 DPRINT("Relations: %lu\n", RelationsData->Relations); 835 DPRINT("BufferSize: %lu\n", RelationsData->BufferSize); 836 DPRINT("Buffer: %p\n", RelationsData->Buffer); 837 838 _SEH2_TRY 839 { 840 Relations = RelationsData->Relations; 841 BufferSize = RelationsData->BufferSize; 842 Buffer = RelationsData->Buffer; 843 844 ProbeForWrite(Buffer, BufferSize, sizeof(CHAR)); 845 } 846 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 847 { 848 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 849 } 850 _SEH2_END; 851 852 Status = IopCaptureUnicodeString(&DeviceInstance, &RelationsData->DeviceInstance); 853 if (!NT_SUCCESS(Status)) 854 { 855 DPRINT1("IopCaptureUnicodeString() failed (Status 0x%08lx)\n", Status); 856 return Status; 857 } 858 859 /* Get the device object */ 860 DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); 861 if (DeviceObject == NULL) 862 { 863 DPRINT1("IopGetDeviceObjectFromDeviceInstance() returned NULL\n"); 864 Status = STATUS_NO_SUCH_DEVICE; 865 goto done; 866 } 867 868 switch (Relations) 869 { 870 case PNP_EJECT_RELATIONS: 871 Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations; 872 break; 873 874 case PNP_REMOVAL_RELATIONS: 875 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations; 876 break; 877 878 case PNP_POWER_RELATIONS: 879 Stack.Parameters.QueryDeviceRelations.Type = PowerRelations; 880 break; 881 882 case PNP_BUS_RELATIONS: 883 Stack.Parameters.QueryDeviceRelations.Type = BusRelations; 884 break; 885 886 default: 887 Status = STATUS_INVALID_PARAMETER; 888 goto done; 889 } 890 891 Status = IopInitiatePnpIrp(DeviceObject, 892 &IoStatusBlock, 893 IRP_MN_QUERY_DEVICE_RELATIONS, 894 &Stack); 895 if (!NT_SUCCESS(Status)) 896 { 897 DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status); 898 goto done; 899 } 900 901 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information; 902 903 DPRINT("Found %d device relations\n", DeviceRelations->Count); 904 905 _SEH2_TRY 906 { 907 RequiredSize = 0; 908 BufferLeft = BufferSize; 909 Ptr = Buffer; 910 911 for (i = 0; i < DeviceRelations->Count; i++) 912 { 913 ChildDeviceObject = DeviceRelations->Objects[i]; 914 915 ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject); 916 if (ChildDeviceNode) 917 { 918 DPRINT("Device instance: %wZ\n", &ChildDeviceNode->InstancePath); 919 DPRINT("RequiredSize: %hu\n", ChildDeviceNode->InstancePath.Length + sizeof(WCHAR)); 920 921 if (Ptr != NULL) 922 { 923 if (BufferLeft < ChildDeviceNode->InstancePath.Length + 2 * sizeof(WCHAR)) 924 { 925 Status = STATUS_BUFFER_TOO_SMALL; 926 break; 927 } 928 929 RtlCopyMemory(Ptr, 930 ChildDeviceNode->InstancePath.Buffer, 931 ChildDeviceNode->InstancePath.Length); 932 Ptr = (PWCHAR)((ULONG_PTR)Ptr + ChildDeviceNode->InstancePath.Length); 933 *Ptr = UNICODE_NULL; 934 Ptr = (PWCHAR)((ULONG_PTR)Ptr + sizeof(WCHAR)); 935 936 BufferLeft -= (ChildDeviceNode->InstancePath.Length + sizeof(WCHAR)); 937 } 938 939 RequiredSize += (ChildDeviceNode->InstancePath.Length + sizeof(WCHAR)); 940 } 941 } 942 943 if (Ptr != NULL && BufferLeft >= sizeof(WCHAR)) 944 *Ptr = UNICODE_NULL; 945 946 if (RequiredSize > 0) 947 RequiredSize += sizeof(WCHAR); 948 949 DPRINT("BufferSize: %lu RequiredSize: %lu\n", RelationsData->BufferSize, RequiredSize); 950 951 RelationsData->BufferSize = RequiredSize; 952 } 953 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 954 { 955 Status = _SEH2_GetExceptionCode(); 956 } 957 _SEH2_END; 958 959 done: 960 if (DeviceRelations != NULL) 961 ExFreePool(DeviceRelations); 962 963 if (DeviceObject != NULL) 964 ObDereferenceObject(DeviceObject); 965 966 if (DeviceInstance.Buffer != NULL) 967 ExFreePool(DeviceInstance.Buffer); 968 969 return Status; 970 } 971 972 static NTSTATUS 973 IopGetDeviceDepth(PPLUGPLAY_CONTROL_DEPTH_DATA DepthData) 974 { 975 PDEVICE_OBJECT DeviceObject; 976 PDEVICE_NODE DeviceNode; 977 UNICODE_STRING DeviceInstance; 978 NTSTATUS Status = STATUS_SUCCESS; 979 980 DPRINT("IopGetDeviceDepth() called\n"); 981 DPRINT("Device name: %wZ\n", &DepthData->DeviceInstance); 982 983 Status = IopCaptureUnicodeString(&DeviceInstance, &DepthData->DeviceInstance); 984 if (!NT_SUCCESS(Status)) 985 { 986 return Status; 987 } 988 989 /* Get the device object */ 990 DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); 991 if (DeviceInstance.Buffer != NULL) 992 { 993 ExFreePool(DeviceInstance.Buffer); 994 } 995 if (DeviceObject == NULL) 996 { 997 return STATUS_NO_SUCH_DEVICE; 998 } 999 1000 DeviceNode = IopGetDeviceNode(DeviceObject); 1001 1002 _SEH2_TRY 1003 { 1004 DepthData->Depth = DeviceNode->Level; 1005 } 1006 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1007 { 1008 Status = _SEH2_GetExceptionCode(); 1009 } 1010 _SEH2_END; 1011 1012 ObDereferenceObject(DeviceObject); 1013 1014 return Status; 1015 } 1016 1017 static 1018 NTSTATUS 1019 PiControlSyncDeviceAction( 1020 _In_ PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA DeviceData, 1021 _In_ PLUGPLAY_CONTROL_CLASS ControlClass) 1022 { 1023 PDEVICE_OBJECT DeviceObject; 1024 NTSTATUS Status; 1025 UNICODE_STRING DeviceInstance; 1026 1027 ASSERT(ControlClass == PlugPlayControlEnumerateDevice || 1028 ControlClass == PlugPlayControlStartDevice || 1029 ControlClass == PlugPlayControlResetDevice); 1030 1031 Status = IopCaptureUnicodeString(&DeviceInstance, &DeviceData->DeviceInstance); 1032 if (!NT_SUCCESS(Status)) 1033 { 1034 return Status; 1035 } 1036 1037 DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); 1038 if (DeviceInstance.Buffer != NULL) 1039 { 1040 ExFreePool(DeviceInstance.Buffer); 1041 } 1042 if (DeviceObject == NULL) 1043 { 1044 return STATUS_NO_SUCH_DEVICE; 1045 } 1046 1047 DEVICE_ACTION Action; 1048 1049 switch (ControlClass) 1050 { 1051 case PlugPlayControlEnumerateDevice: 1052 Action = PiActionEnumDeviceTree; 1053 break; 1054 case PlugPlayControlStartDevice: 1055 Action = PiActionStartDevice; 1056 break; 1057 case PlugPlayControlResetDevice: 1058 Action = PiActionResetDevice; 1059 break; 1060 default: 1061 UNREACHABLE; 1062 break; 1063 } 1064 1065 Status = PiPerformSyncDeviceAction(DeviceObject, Action); 1066 1067 ObDereferenceObject(DeviceObject); 1068 1069 return Status; 1070 } 1071 1072 /* PUBLIC FUNCTIONS **********************************************************/ 1073 1074 /* 1075 * Plug and Play event structure used by NtGetPlugPlayEvent. 1076 * 1077 * EventGuid 1078 * Can be one of the following values: 1079 * GUID_HWPROFILE_QUERY_CHANGE 1080 * GUID_HWPROFILE_CHANGE_CANCELLED 1081 * GUID_HWPROFILE_CHANGE_COMPLETE 1082 * GUID_TARGET_DEVICE_QUERY_REMOVE 1083 * GUID_TARGET_DEVICE_REMOVE_CANCELLED 1084 * GUID_TARGET_DEVICE_REMOVE_COMPLETE 1085 * GUID_PNP_CUSTOM_NOTIFICATION 1086 * GUID_PNP_POWER_NOTIFICATION 1087 * GUID_DEVICE_* (see above) 1088 * 1089 * EventCategory 1090 * Type of the event that happened. 1091 * 1092 * Result 1093 * ? 1094 * 1095 * Flags 1096 * ? 1097 * 1098 * TotalSize 1099 * Size of the event block including the device IDs and other 1100 * per category specific fields. 1101 */ 1102 1103 /* 1104 * NtGetPlugPlayEvent 1105 * 1106 * Returns one Plug & Play event from a global queue. 1107 * 1108 * Parameters 1109 * Reserved1 1110 * Reserved2 1111 * Always set to zero. 1112 * 1113 * Buffer 1114 * The buffer that will be filled with the event information on 1115 * successful return from the function. 1116 * 1117 * BufferSize 1118 * Size of the buffer pointed by the Buffer parameter. If the 1119 * buffer size is not large enough to hold the whole event 1120 * information, error STATUS_BUFFER_TOO_SMALL is returned and 1121 * the buffer remains untouched. 1122 * 1123 * Return Values 1124 * STATUS_PRIVILEGE_NOT_HELD 1125 * STATUS_BUFFER_TOO_SMALL 1126 * STATUS_SUCCESS 1127 * 1128 * Remarks 1129 * This function isn't multi-thread safe! 1130 * 1131 * @implemented 1132 */ 1133 NTSTATUS 1134 NTAPI 1135 NtGetPlugPlayEvent(IN ULONG Reserved1, 1136 IN ULONG Reserved2, 1137 OUT PPLUGPLAY_EVENT_BLOCK Buffer, 1138 IN ULONG BufferSize) 1139 { 1140 PPNP_EVENT_ENTRY Entry; 1141 NTSTATUS Status; 1142 1143 DPRINT("NtGetPlugPlayEvent() called\n"); 1144 1145 /* Function can only be called from user-mode */ 1146 if (KeGetPreviousMode() == KernelMode) 1147 { 1148 DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n"); 1149 return STATUS_ACCESS_DENIED; 1150 } 1151 1152 /* Check for Tcb privilege */ 1153 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, 1154 UserMode)) 1155 { 1156 DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n"); 1157 return STATUS_PRIVILEGE_NOT_HELD; 1158 } 1159 1160 /* Wait for a PnP event */ 1161 DPRINT("Waiting for pnp notification event\n"); 1162 Status = KeWaitForSingleObject(&IopPnpNotifyEvent, 1163 UserRequest, 1164 UserMode, 1165 FALSE, 1166 NULL); 1167 if (!NT_SUCCESS(Status) || Status == STATUS_USER_APC) 1168 { 1169 DPRINT("KeWaitForSingleObject() failed (Status %lx)\n", Status); 1170 ASSERT(Status == STATUS_USER_APC); 1171 return Status; 1172 } 1173 1174 /* Get entry from the tail of the queue */ 1175 Entry = CONTAINING_RECORD(IopPnpEventQueueHead.Blink, 1176 PNP_EVENT_ENTRY, 1177 ListEntry); 1178 1179 /* Check the buffer size */ 1180 if (BufferSize < Entry->Event.TotalSize) 1181 { 1182 DPRINT1("Buffer is too small for the pnp-event\n"); 1183 return STATUS_BUFFER_TOO_SMALL; 1184 } 1185 1186 /* Copy event data to the user buffer */ 1187 _SEH2_TRY 1188 { 1189 ProbeForWrite(Buffer, 1190 Entry->Event.TotalSize, 1191 sizeof(UCHAR)); 1192 RtlCopyMemory(Buffer, 1193 &Entry->Event, 1194 Entry->Event.TotalSize); 1195 } 1196 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1197 { 1198 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 1199 } 1200 _SEH2_END; 1201 1202 DPRINT("NtGetPlugPlayEvent() done\n"); 1203 1204 return STATUS_SUCCESS; 1205 } 1206 1207 /* 1208 * NtPlugPlayControl 1209 * 1210 * A function for doing various Plug & Play operations from user mode. 1211 * 1212 * Parameters 1213 * PlugPlayControlClass 1214 * 0x00 Reenumerate device tree 1215 * 1216 * Buffer points to UNICODE_STRING decribing the instance 1217 * path (like "HTREE\ROOT\0" or "Root\ACPI_HAL\0000"). For 1218 * more information about instance paths see !devnode command 1219 * in kernel debugger or look at "Inside Windows 2000" book, 1220 * chapter "Driver Loading, Initialization, and Installation". 1221 * 1222 * 0x01 Register new device 1223 * 0x02 Deregister device 1224 * 0x03 Initialize device 1225 * 0x04 Start device 1226 * 0x06 Query and remove device 1227 * 0x07 User response 1228 * 1229 * Called after processing the message from NtGetPlugPlayEvent. 1230 * 1231 * 0x08 Generate legacy device 1232 * 0x09 Get interface device list 1233 * 0x0A Get property data 1234 * 0x0B Device class association (Registration) 1235 * 0x0C Get related device 1236 * 0x0D Get device interface alias 1237 * 0x0E Get/set/clear device status 1238 * 0x0F Get device depth 1239 * 0x10 Query device relations 1240 * 0x11 Query target device relation 1241 * 0x12 Query conflict list 1242 * 0x13 Retrieve dock data 1243 * 0x14 Reset device 1244 * 0x15 Halt device 1245 * 0x16 Get blocked driver data 1246 * 1247 * Buffer 1248 * The buffer contains information that is specific to each control 1249 * code. The buffer is read-only. 1250 * 1251 * BufferSize 1252 * Size of the buffer pointed by the Buffer parameter. If the 1253 * buffer size specifies incorrect value for specified control 1254 * code, error ??? is returned. 1255 * 1256 * Return Values 1257 * STATUS_PRIVILEGE_NOT_HELD 1258 * STATUS_SUCCESS 1259 * ... 1260 * 1261 * @unimplemented 1262 */ 1263 NTSTATUS 1264 NTAPI 1265 NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, 1266 IN OUT PVOID Buffer, 1267 IN ULONG BufferLength) 1268 { 1269 DPRINT("NtPlugPlayControl(%d %p %lu) called\n", 1270 PlugPlayControlClass, Buffer, BufferLength); 1271 1272 /* Function can only be called from user-mode */ 1273 if (KeGetPreviousMode() == KernelMode) 1274 { 1275 DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n"); 1276 return STATUS_ACCESS_DENIED; 1277 } 1278 1279 /* Check for Tcb privilege */ 1280 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, 1281 UserMode)) 1282 { 1283 DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n"); 1284 return STATUS_PRIVILEGE_NOT_HELD; 1285 } 1286 1287 /* Probe the buffer */ 1288 _SEH2_TRY 1289 { 1290 ProbeForWrite(Buffer, 1291 BufferLength, 1292 sizeof(ULONG)); 1293 } 1294 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1295 { 1296 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 1297 } 1298 _SEH2_END; 1299 1300 switch (PlugPlayControlClass) 1301 { 1302 case PlugPlayControlEnumerateDevice: 1303 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA)) 1304 return STATUS_INVALID_PARAMETER; 1305 // the Flags field is not used anyway 1306 return PiControlSyncDeviceAction((PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)Buffer, 1307 PlugPlayControlClass); 1308 1309 // case PlugPlayControlRegisterNewDevice: 1310 // case PlugPlayControlDeregisterDevice: 1311 // case PlugPlayControlInitializeDevice: 1312 1313 case PlugPlayControlStartDevice: 1314 case PlugPlayControlResetDevice: 1315 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)) 1316 return STATUS_INVALID_PARAMETER; 1317 return PiControlSyncDeviceAction((PPLUGPLAY_CONTROL_DEVICE_CONTROL_DATA)Buffer, 1318 PlugPlayControlClass); 1319 1320 // case PlugPlayControlUnlockDevice: 1321 // case PlugPlayControlQueryAndRemoveDevice: 1322 1323 case PlugPlayControlUserResponse: 1324 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_USER_RESPONSE_DATA)) 1325 return STATUS_INVALID_PARAMETER; 1326 return IopRemovePlugPlayEvent((PPLUGPLAY_CONTROL_USER_RESPONSE_DATA)Buffer); 1327 1328 // case PlugPlayControlGenerateLegacyDevice: 1329 1330 case PlugPlayControlGetInterfaceDeviceList: 1331 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)) 1332 return STATUS_INVALID_PARAMETER; 1333 return IopGetInterfaceDeviceList((PPLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)Buffer); 1334 1335 case PlugPlayControlProperty: 1336 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA)) 1337 return STATUS_INVALID_PARAMETER; 1338 return IopGetDeviceProperty((PPLUGPLAY_CONTROL_PROPERTY_DATA)Buffer); 1339 1340 // case PlugPlayControlDeviceClassAssociation: 1341 1342 case PlugPlayControlGetRelatedDevice: 1343 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA)) 1344 return STATUS_INVALID_PARAMETER; 1345 return IopGetRelatedDevice((PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA)Buffer); 1346 1347 // case PlugPlayControlGetInterfaceDeviceAlias: 1348 1349 case PlugPlayControlDeviceStatus: 1350 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_STATUS_DATA)) 1351 return STATUS_INVALID_PARAMETER; 1352 return IopDeviceStatus((PPLUGPLAY_CONTROL_STATUS_DATA)Buffer); 1353 1354 case PlugPlayControlGetDeviceDepth: 1355 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEPTH_DATA)) 1356 return STATUS_INVALID_PARAMETER; 1357 return IopGetDeviceDepth((PPLUGPLAY_CONTROL_DEPTH_DATA)Buffer); 1358 1359 case PlugPlayControlQueryDeviceRelations: 1360 if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)) 1361 return STATUS_INVALID_PARAMETER; 1362 return IopGetDeviceRelations((PPLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA)Buffer); 1363 1364 // case PlugPlayControlTargetDeviceRelation: 1365 // case PlugPlayControlQueryConflictList: 1366 // case PlugPlayControlRetrieveDock: 1367 // case PlugPlayControlHaltDevice: 1368 // case PlugPlayControlGetBlockedDriverList: 1369 1370 default: 1371 return STATUS_NOT_IMPLEMENTED; 1372 } 1373 1374 return STATUS_NOT_IMPLEMENTED; 1375 } 1376