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