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