1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/ksfilter/ks/swenum.c 5 * PURPOSE: KS Software BUS functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "precomp.h" 10 11 #include <stdio.h> 12 #include <swenum.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 LONG KsDeviceCount = 0; 18 19 typedef NTSTATUS (NTAPI *PKSP_BUS_ENUM_CALLBACK)( 20 IN PHANDLE hKey, 21 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 22 IN PBUS_DEVICE_ENTRY DummyEntry, 23 IN LPWSTR RootName, 24 IN LPWSTR DirectoryName); 25 26 NTSTATUS 27 KspCreatePDO( 28 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 29 IN PBUS_DEVICE_ENTRY DeviceEntry, 30 OUT PDEVICE_OBJECT * OutDeviceObject) 31 { 32 PDEVICE_OBJECT DeviceObject; 33 WCHAR Buffer[50]; 34 ULONG CurDeviceId; 35 UNICODE_STRING DeviceName; 36 NTSTATUS Status; 37 PCOMMON_DEVICE_EXTENSION DeviceExtension; 38 39 /* increment device count */ 40 CurDeviceId = InterlockedIncrement(&KsDeviceCount); 41 42 /* generate new device id */ 43 swprintf(Buffer, L"\\Device\\KSENUM%08x", CurDeviceId); 44 45 /* initialize new device name */ 46 RtlInitUnicodeString(&DeviceName, Buffer); 47 48 /* create new device object */ 49 Status = IoCreateDevice(BusDeviceExtension->BusDeviceObject->DriverObject, sizeof(PVOID), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); 50 51 /* check for success */ 52 if (!NT_SUCCESS(Status)) 53 { 54 /* failed to create pdo */ 55 return Status; 56 } 57 58 /* now allocate device extension */ 59 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)AllocateItem(NonPagedPool, sizeof(COMMON_DEVICE_EXTENSION)); 60 if (!DeviceExtension) 61 { 62 /* no memory */ 63 IoDeleteDevice(DeviceObject); 64 return STATUS_INSUFFICIENT_RESOURCES; 65 } 66 67 /* store device extension */ 68 *((PVOID*)DeviceObject->DeviceExtension) = DeviceExtension; 69 70 /* initialize device extension */ 71 DeviceExtension->IsBus = FALSE; 72 DeviceExtension->DeviceObject = DeviceObject; 73 DeviceExtension->DeviceEntry = DeviceEntry; 74 DeviceExtension->BusDeviceExtension = BusDeviceExtension; 75 76 /* not started yet*/ 77 DeviceEntry->DeviceState = NotStarted; 78 79 /* get current time */ 80 KeQuerySystemTime(&DeviceEntry->TimeCreated); 81 82 /* setup flags */ 83 DeviceObject->Flags |= DO_POWER_PAGABLE; 84 DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; 85 /* TODO: fire time when expired */ 86 87 *OutDeviceObject = DeviceObject; 88 89 return STATUS_SUCCESS; 90 } 91 92 NTSTATUS 93 KspRegisterDeviceAssociation( 94 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 95 IN PBUS_DEVICE_ENTRY DeviceEntry, 96 IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry) 97 { 98 NTSTATUS Status; 99 UNICODE_STRING ReferenceString; 100 101 /* initialize reference string */ 102 RtlInitUnicodeString(&ReferenceString, DeviceEntry->DeviceName); 103 104 /* register device interface */ 105 Status = IoRegisterDeviceInterface(BusDeviceExtension->PhysicalDeviceObject, &BusInstanceEntry->InterfaceGuid, &ReferenceString, &BusInstanceEntry->SymbolicLink); 106 107 /* check for success */ 108 if (!NT_SUCCESS(Status)) 109 { 110 /* failed */ 111 return Status; 112 } 113 114 /* now enable the interface */ 115 Status = IoSetDeviceInterfaceState(&BusInstanceEntry->SymbolicLink, TRUE); 116 117 /* check for success */ 118 if (!NT_SUCCESS(Status)) 119 { 120 /* failed, free memory */ 121 FreeItem(BusInstanceEntry->SymbolicLink.Buffer); 122 return Status; 123 } 124 125 DPRINT("Registered DeviceInterface %wZ\n", &BusInstanceEntry->SymbolicLink); 126 127 128 /* done */ 129 return Status; 130 } 131 132 VOID 133 KspRemoveDeviceAssociations( 134 IN PBUS_DEVICE_ENTRY DeviceEntry) 135 { 136 PLIST_ENTRY Entry; 137 PBUS_INSTANCE_ENTRY CurEntry; 138 139 /* remove all entries */ 140 Entry = DeviceEntry->DeviceInterfaceList.Flink; 141 142 while(Entry != &DeviceEntry->DeviceInterfaceList) 143 { 144 /* get offset */ 145 CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); 146 147 /* sanity check */ 148 ASSERT(CurEntry->SymbolicLink.Buffer); 149 150 /* de-register interface */ 151 IoSetDeviceInterfaceState(&CurEntry->SymbolicLink, FALSE); 152 153 /* free symbolic link buffer */ 154 FreeItem(CurEntry->SymbolicLink.Buffer); 155 156 /* remove entry from list */ 157 RemoveEntryList(Entry); 158 159 /* move to next entry */ 160 Entry = Entry->Flink; 161 162 /* free entry */ 163 FreeItem(CurEntry); 164 } 165 } 166 167 NTSTATUS 168 KspEnumerateBusRegistryKeys( 169 IN HANDLE hKey, 170 IN LPWSTR ReferenceString, 171 IN PKSP_BUS_ENUM_CALLBACK Callback, 172 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 173 IN PBUS_DEVICE_ENTRY DeviceEntry) 174 { 175 UNICODE_STRING String; 176 OBJECT_ATTRIBUTES ObjectAttributes; 177 HANDLE hNewKey; 178 NTSTATUS Status; 179 ULONG ResultLength, Index, KeyInfoLength; 180 KEY_FULL_INFORMATION KeyInformation; 181 PKEY_BASIC_INFORMATION KeyInfo; 182 183 /* initialize key name */ 184 RtlInitUnicodeString(&String, ReferenceString); 185 186 /* initialize object attributes */ 187 InitializeObjectAttributes(&ObjectAttributes, &String, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); 188 189 /* open new key */ 190 Status = ZwOpenKey(&hNewKey, GENERIC_READ, &ObjectAttributes); 191 192 /* check for success */ 193 if (!NT_SUCCESS(Status)) 194 { 195 /* failed to open key */ 196 197 return Status; 198 } 199 200 /* query key stats */ 201 Status = ZwQueryKey(hNewKey, KeyFullInformation, &KeyInformation, sizeof(KeyInformation), &ResultLength); 202 203 if (!NT_SUCCESS(Status)) 204 { 205 /* close key */ 206 ZwClose(hNewKey); 207 208 /* done */ 209 return Status; 210 } 211 212 /* calculate key info length */ 213 KeyInfoLength = KeyInformation.MaxNameLen + sizeof(KEY_BASIC_INFORMATION) + 1 * sizeof(WCHAR); 214 215 /* allocate buffer */ 216 KeyInfo = (PKEY_BASIC_INFORMATION)AllocateItem(NonPagedPool, KeyInfoLength); 217 if (!KeyInfo) 218 { 219 220 /* no memory */ 221 ZwClose(hNewKey); 222 223 /* done */ 224 return STATUS_INSUFFICIENT_RESOURCES; 225 } 226 227 /* enumerate all keys */ 228 for(Index = 0; Index < KeyInformation.SubKeys; Index++) 229 { 230 231 /* query sub key */ 232 Status = ZwEnumerateKey(hNewKey, Index, KeyBasicInformation, (PVOID)KeyInfo, KeyInfoLength, &ResultLength); 233 234 /* check for success */ 235 if (NT_SUCCESS(Status)) 236 { 237 /* perform callback */ 238 Status = Callback(hNewKey, BusDeviceExtension, DeviceEntry, KeyInfo->Name, ReferenceString); 239 240 /* should enumeration stop */ 241 if (!NT_SUCCESS(Status)) 242 break; 243 } 244 } 245 246 /* free info buffer */ 247 FreeItem(KeyInfo); 248 249 /* close key */ 250 ZwClose(hNewKey); 251 252 /* done */ 253 return Status; 254 } 255 256 NTSTATUS 257 NTAPI 258 KspCreateDeviceAssociation( 259 IN PHANDLE hKey, 260 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 261 IN PBUS_DEVICE_ENTRY DeviceEntry, 262 IN LPWSTR InterfaceString, 263 IN LPWSTR ReferenceString) 264 { 265 GUID InterfaceGUID; 266 NTSTATUS Status; 267 PLIST_ENTRY Entry; 268 PBUS_INSTANCE_ENTRY CurEntry; 269 UNICODE_STRING DeviceName; 270 271 /* initialize interface string */ 272 RtlInitUnicodeString(&DeviceName, InterfaceString); 273 274 /* first convert device name to guid */ 275 RtlGUIDFromString(&DeviceName, &InterfaceGUID); 276 277 /* check if the device is already present */ 278 Entry = DeviceEntry->DeviceInterfaceList.Flink; 279 DPRINT("KspCreateDeviceAssociation ReferenceString %S\n", ReferenceString); 280 DPRINT("KspCreateDeviceAssociation InterfaceString %S\n", InterfaceString); 281 282 while(Entry != &DeviceEntry->DeviceInterfaceList) 283 { 284 /* get offset */ 285 CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); 286 287 if (IsEqualGUIDAligned(&CurEntry->InterfaceGuid, &InterfaceGUID)) 288 { 289 /* entry already exists */ 290 return STATUS_SUCCESS; 291 } 292 293 /* move to next entry */ 294 Entry = Entry->Flink; 295 } 296 297 /* time to allocate new entry */ 298 CurEntry = (PBUS_INSTANCE_ENTRY)AllocateItem(NonPagedPool, sizeof(BUS_INSTANCE_ENTRY)); 299 300 if (!CurEntry) 301 { 302 /* no memory */ 303 return STATUS_INSUFFICIENT_RESOURCES; 304 } 305 306 /* store guid */ 307 RtlMoveMemory(&CurEntry->InterfaceGuid, &InterfaceGUID, sizeof(GUID)); 308 309 /* now register the association */ 310 Status = KspRegisterDeviceAssociation(BusDeviceExtension, DeviceEntry, CurEntry); 311 312 /* check for success */ 313 if (NT_SUCCESS(Status)) 314 { 315 /* store entry */ 316 InsertTailList(&DeviceEntry->DeviceInterfaceList, &CurEntry->Entry); 317 } 318 else 319 { 320 /* failed to associated device */ 321 FreeItem(CurEntry); 322 } 323 324 /* done */ 325 return Status; 326 } 327 328 NTSTATUS 329 NTAPI 330 KspCreateDeviceReference( 331 IN PHANDLE hKey, 332 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 333 IN PBUS_DEVICE_ENTRY DummyEntry, 334 IN LPWSTR InterfaceId, 335 IN LPWSTR DeviceId) 336 { 337 LPWSTR DeviceName; 338 SIZE_T Length; 339 PLIST_ENTRY Entry; 340 PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */ 341 BOOLEAN ItemExists = FALSE; 342 UNICODE_STRING String; 343 NTSTATUS Status; 344 KIRQL OldLevel; 345 346 /* first construct device name & reference guid */ 347 Length = wcslen(DeviceId) + wcslen(InterfaceId); 348 349 /* append '&' and null byte */ 350 Length += 2; 351 352 /* allocate device name */ 353 DeviceName = AllocateItem(NonPagedPool, Length * sizeof(WCHAR)); 354 355 if (!DeviceName) 356 { 357 /* not enough memory */ 358 return STATUS_INSUFFICIENT_RESOURCES; 359 } 360 361 /* construct device name */ 362 wcscpy(DeviceName, DeviceId); 363 wcscat(DeviceName, L"&"); 364 wcscat(DeviceName, InterfaceId); 365 366 /* scan list and check if it is already present */ 367 Entry = BusDeviceExtension->Common.Entry.Flink; 368 369 while(Entry != &BusDeviceExtension->Common.Entry) 370 { 371 /* get real offset */ 372 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 373 374 /* check if name matches */ 375 if (!wcsicmp(DeviceEntry->DeviceName, DeviceName)) 376 { 377 /* item already exists */ 378 ItemExists = TRUE; 379 break; 380 } 381 382 /* move to next entry */ 383 Entry = Entry->Flink; 384 } 385 386 if (!ItemExists) 387 { 388 /* allocate new device entry */ 389 DeviceEntry = AllocateItem(NonPagedPool, sizeof(BUS_DEVICE_ENTRY)); 390 if (!DeviceEntry) 391 { 392 /* no memory */ 393 FreeItem(DeviceName); 394 return STATUS_INSUFFICIENT_RESOURCES; 395 } 396 397 /* initialize device entry */ 398 InitializeListHead(&DeviceEntry->DeviceInterfaceList); 399 InitializeListHead(&DeviceEntry->IrpPendingList); 400 401 /* copy device guid */ 402 RtlInitUnicodeString(&String, DeviceId); 403 RtlGUIDFromString(&String, &DeviceEntry->DeviceGuid); 404 405 /* copy device names */ 406 DeviceEntry->DeviceName = DeviceName; 407 DeviceEntry->Instance = (DeviceName + wcslen(DeviceId) + 1); 408 409 /* copy name */ 410 DeviceEntry->BusId = AllocateItem(NonPagedPool, (wcslen(DeviceId) + 1) * sizeof(WCHAR)); 411 if (!DeviceEntry->BusId) 412 { 413 /* no memory */ 414 FreeItem(DeviceName); 415 FreeItem(DeviceEntry); 416 return STATUS_INSUFFICIENT_RESOURCES; 417 } 418 wcscpy(DeviceEntry->BusId, DeviceId); 419 } 420 421 /* now enumerate the interfaces */ 422 Status = KspEnumerateBusRegistryKeys(hKey, InterfaceId, KspCreateDeviceAssociation, BusDeviceExtension, DeviceEntry); 423 424 /* check if list is empty */ 425 if (IsListEmpty(&DeviceEntry->DeviceInterfaceList)) 426 { 427 /* invalid device settings */ 428 FreeItem(DeviceEntry->BusId); 429 FreeItem(DeviceEntry->DeviceName); 430 FreeItem(DeviceEntry); 431 432 ASSERT(ItemExists == FALSE); 433 434 return STATUS_INVALID_DEVICE_STATE; 435 } 436 437 /* check if enumeration failed */ 438 if (!NT_SUCCESS(Status)) 439 { 440 /* failed */ 441 KspRemoveDeviceAssociations(DeviceEntry); 442 FreeItem(DeviceEntry->BusId); 443 FreeItem(DeviceEntry->DeviceName); 444 FreeItem(DeviceEntry); 445 446 ASSERT(ItemExists == FALSE); 447 448 /* done */ 449 return Status; 450 } 451 452 if (!ItemExists) 453 { 454 /* acquire lock */ 455 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 456 457 /* successfully initialized entry */ 458 InsertTailList(&BusDeviceExtension->Common.Entry, &DeviceEntry->Entry); 459 460 /* release lock */ 461 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 462 } 463 464 /* done */ 465 return Status; 466 } 467 468 NTSTATUS 469 NTAPI 470 KspCreateDeviceReferenceTrampoline( 471 IN PHANDLE hKey, 472 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 473 IN PBUS_DEVICE_ENTRY DummyEntry, 474 IN LPWSTR DeviceCategory, 475 IN LPWSTR ReferenceString) 476 { 477 return KspEnumerateBusRegistryKeys(hKey, DeviceCategory, KspCreateDeviceReference, BusDeviceExtension, DummyEntry); 478 } 479 480 481 NTSTATUS 482 KspOpenBusRegistryKey( 483 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 484 OUT PHANDLE hKey) 485 { 486 OBJECT_ATTRIBUTES ObjectAttributes; 487 488 /* initialize object attributes */ 489 InitializeObjectAttributes(&ObjectAttributes, &BusDeviceExtension->ServicePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 490 491 return ZwCreateKey(hKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 492 } 493 494 NTSTATUS 495 KspScanBus( 496 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension) 497 { 498 HANDLE hKey; 499 NTSTATUS Status; 500 501 /* first open key */ 502 Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); 503 504 /* check for success */ 505 if (!NT_SUCCESS(Status)) 506 { 507 /* no success */ 508 509 return Status; 510 } 511 512 /* TODO clear reference marks */ 513 514 /* construct device entries */ 515 Status = KspEnumerateBusRegistryKeys(hKey, NULL, KspCreateDeviceReferenceTrampoline, BusDeviceExtension, NULL); 516 517 /* TODO: delete unreferenced devices */ 518 519 /* close handle */ 520 ZwClose(hKey); 521 522 /* done */ 523 return Status; 524 } 525 526 527 NTSTATUS 528 NTAPI 529 KspBusQueryReferenceString( 530 IN PVOID Context, 531 IN OUT PWCHAR *String) 532 { 533 LPWSTR Name; 534 SIZE_T Length; 535 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context; 536 537 /* sanity checks */ 538 ASSERT(BusDeviceExtension); 539 ASSERT(BusDeviceExtension->BusIdentifier); 540 541 /* calculate length */ 542 Length = wcslen(BusDeviceExtension->BusIdentifier) + 1; 543 544 /* allocate buffer */ 545 Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); 546 547 if (!Name) 548 { 549 /* failed to allocate buffer */ 550 return STATUS_INSUFFICIENT_RESOURCES; 551 } 552 553 /* copy buffer */ 554 wcscpy(Name, BusDeviceExtension->BusIdentifier); 555 556 /* store result */ 557 *String = Name; 558 559 /* done */ 560 return STATUS_SUCCESS; 561 } 562 563 VOID 564 NTAPI 565 KspBusDeviceReference( 566 IN PVOID Context) 567 { 568 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 569 570 /* reference count */ 571 InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); 572 } 573 574 VOID 575 NTAPI 576 KspBusDeviceDereference( 577 IN PVOID Context) 578 { 579 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 580 581 /* reference count */ 582 InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); 583 } 584 585 VOID 586 NTAPI 587 KspBusReferenceDeviceObject( 588 IN PVOID Context) 589 { 590 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 591 592 /* reference count */ 593 InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); 594 } 595 596 VOID 597 NTAPI 598 KspBusDereferenceDeviceObject( 599 IN PVOID Context) 600 { 601 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 602 603 /* reference count */ 604 InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); 605 } 606 607 NTSTATUS 608 KspQueryBusDeviceInterface( 609 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 610 IN PIRP Irp) 611 { 612 PBUS_INTERFACE_SWENUM Interface; 613 PIO_STACK_LOCATION IoStack; 614 615 /* get current irp stack location */ 616 IoStack = IoGetCurrentIrpStackLocation(Irp); 617 618 /* sanity checks */ 619 ASSERT(IoStack->Parameters.QueryInterface.Size == sizeof(BUS_INTERFACE_SWENUM)); 620 ASSERT(IoStack->Parameters.QueryInterface.Interface); 621 622 /* fill in interface */ 623 Interface = (PBUS_INTERFACE_SWENUM)IoStack->Parameters.QueryInterface.Interface; 624 Interface->Interface.Size = sizeof(BUS_INTERFACE_SWENUM); 625 Interface->Interface.Version = BUS_INTERFACE_SWENUM_VERSION; 626 Interface->Interface.Context = ChildDeviceExtension; 627 Interface->Interface.InterfaceReference = KspBusDeviceReference; 628 Interface->Interface.InterfaceDereference = KspBusDeviceDereference; 629 Interface->ReferenceDeviceObject = KspBusReferenceDeviceObject; 630 Interface->DereferenceDeviceObject = KspBusDereferenceDeviceObject; 631 Interface->QueryReferenceString = KspBusQueryReferenceString; 632 633 return STATUS_SUCCESS; 634 } 635 636 NTSTATUS 637 KspEnableBusDeviceInterface( 638 PBUS_DEVICE_ENTRY DeviceEntry, 639 BOOLEAN bEnable) 640 { 641 PLIST_ENTRY Entry; 642 PBUS_INSTANCE_ENTRY InstanceEntry; 643 NTSTATUS Status = STATUS_SUCCESS; 644 645 /* enable now all interfaces */ 646 Entry = DeviceEntry->DeviceInterfaceList.Flink; 647 648 while(Entry != &DeviceEntry->DeviceInterfaceList) 649 { 650 /* get bus instance entry */ 651 InstanceEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); 652 DPRINT("Enabling %u %wZ Irql %u\n", bEnable, &InstanceEntry->SymbolicLink, KeGetCurrentIrql()); 653 654 /* set interface state */ 655 Status = IoSetDeviceInterfaceState(&InstanceEntry->SymbolicLink, bEnable); 656 657 if (!NT_SUCCESS(Status)) 658 { 659 /* failed to set interface */ 660 break; 661 } 662 663 /* move to next entry */ 664 Entry = Entry->Flink; 665 } 666 667 /* done */ 668 return Status; 669 } 670 671 NTSTATUS 672 KspDoReparseForIrp( 673 PIRP Irp, 674 PBUS_DEVICE_ENTRY DeviceEntry) 675 { 676 SIZE_T Length; 677 LPWSTR Buffer; 678 PIO_STACK_LOCATION IoStack; 679 680 /* get stack location */ 681 IoStack = IoGetCurrentIrpStackLocation(Irp); 682 683 /* sanity checks */ 684 ASSERT(DeviceEntry->PDODeviceName); 685 ASSERT(DeviceEntry->Instance); 686 ASSERT(IoStack->FileObject); 687 ASSERT(IoStack->FileObject->FileName.Buffer); 688 689 /* calculate length */ 690 Length = wcslen(DeviceEntry->PDODeviceName); 691 Length += wcslen(DeviceEntry->Instance); 692 693 /* zero byte and '\\' */ 694 Length += 2; 695 696 /* allocate buffer */ 697 Buffer = ExAllocatePoolWithTag(NonPagedPool, Length * sizeof(WCHAR), 'mNoI'); 698 if (!Buffer) 699 { 700 /* no resources */ 701 return STATUS_INSUFFICIENT_RESOURCES; 702 } 703 704 /* construct buffer */ 705 swprintf(Buffer, L"%s\\%s", DeviceEntry->PDODeviceName, DeviceEntry->Instance); 706 707 /* free old buffer*/ 708 ExFreePoolWithTag(IoStack->FileObject->FileName.Buffer, 'mNoI'); 709 710 /* store new file name */ 711 RtlInitUnicodeString(&IoStack->FileObject->FileName, Buffer); 712 713 /* done */ 714 return STATUS_REPARSE; 715 } 716 717 VOID 718 KspCompletePendingIrps( 719 IN PBUS_DEVICE_ENTRY DeviceEntry, 720 IN OUT NTSTATUS ResultCode) 721 { 722 PLIST_ENTRY Entry; 723 PIRP Irp; 724 NTSTATUS Status; 725 726 /* go through list */ 727 while(!IsListEmpty(&DeviceEntry->IrpPendingList)) 728 { 729 /* get first entry */ 730 Entry = RemoveHeadList(&DeviceEntry->IrpPendingList); 731 732 /* get irp */ 733 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); 734 735 if (ResultCode == STATUS_REPARSE) 736 { 737 /* construct reparse information */ 738 Status = KspDoReparseForIrp(Irp, DeviceEntry); 739 } 740 else 741 { 742 /* use default code */ 743 Status = ResultCode; 744 } 745 746 /* store result code */ 747 Irp->IoStatus.Status = Status; 748 749 DPRINT("Completing IRP %p Status %x\n", Irp, Status); 750 751 /* complete the request */ 752 CompleteRequest(Irp, IO_NO_INCREMENT); 753 } 754 755 } 756 757 758 759 NTSTATUS 760 KspStartBusDevice( 761 IN PDEVICE_OBJECT DeviceObject, 762 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 763 IN PIRP Irp) 764 { 765 WCHAR PDOName[256]; 766 NTSTATUS Status; 767 ULONG ResultLength; 768 LPWSTR Name; 769 ULONG NameLength; 770 PBUS_DEVICE_ENTRY DeviceEntry; 771 772 /* FIXME handle pending remove */ 773 774 /* get full device name */ 775 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyPhysicalDeviceObjectName, sizeof(PDOName), PDOName, &ResultLength); 776 777 if (!NT_SUCCESS(Status)) 778 { 779 /* failed to get device name */ 780 return Status; 781 } 782 783 /* allocate device name buffer */ 784 NameLength = ResultLength + sizeof(UNICODE_NULL); 785 Name = AllocateItem(NonPagedPool, NameLength); 786 if (!Name) 787 { 788 /* no memory */ 789 return STATUS_INSUFFICIENT_RESOURCES; 790 } 791 792 /* copy name */ 793 NT_VERIFY(NT_SUCCESS(RtlStringCbCopyW(Name, NameLength, PDOName))); 794 795 /* TODO: time stamp creation time */ 796 797 /* get device entry */ 798 DeviceEntry = (PBUS_DEVICE_ENTRY)ChildDeviceExtension->DeviceEntry; 799 800 /* sanity check */ 801 ASSERT(DeviceEntry); 802 803 /* store device name */ 804 DeviceEntry->PDODeviceName = Name; 805 806 /* mark device as started */ 807 DeviceEntry->DeviceState = Started; 808 809 /* reference start time */ 810 KeQuerySystemTime(&DeviceEntry->TimeCreated); 811 812 DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name, DeviceEntry->DeviceName, DeviceEntry->Instance); 813 814 /* enable device classes */ 815 //KspEnableBusDeviceInterface(DeviceEntry, TRUE); 816 817 /* done */ 818 return STATUS_SUCCESS; 819 } 820 821 NTSTATUS 822 KspQueryBusDeviceCapabilities( 823 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 824 IN PIRP Irp) 825 { 826 PDEVICE_CAPABILITIES Capabilities; 827 PIO_STACK_LOCATION IoStack; 828 829 /* get stack location */ 830 IoStack = IoGetCurrentIrpStackLocation(Irp); 831 832 /* get capabilities */ 833 Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; 834 835 RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES)); 836 837 /* setup capabilities */ 838 Capabilities->UniqueID = TRUE; 839 Capabilities->SilentInstall = TRUE; 840 Capabilities->SurpriseRemovalOK = TRUE; 841 Capabilities->Address = 0; 842 Capabilities->UINumber = 0; 843 Capabilities->SystemWake = PowerSystemWorking; /* FIXME common device extension */ 844 Capabilities->DeviceWake = PowerDeviceD0; 845 846 /* done */ 847 return STATUS_SUCCESS; 848 } 849 850 NTSTATUS 851 KspQueryBusInformation( 852 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 853 IN PIRP Irp) 854 { 855 PPNP_BUS_INFORMATION BusInformation; 856 857 /* allocate bus information */ 858 BusInformation = (PPNP_BUS_INFORMATION)AllocateItem(PagedPool, sizeof(PNP_BUS_INFORMATION)); 859 860 if (!BusInformation) 861 { 862 /* no memory */ 863 return STATUS_INSUFFICIENT_RESOURCES; 864 } 865 866 /* return info */ 867 BusInformation->BusNumber = 0; 868 BusInformation->LegacyBusType = InterfaceTypeUndefined; 869 RtlMoveMemory(&BusInformation->BusTypeGuid, &KSMEDIUMSETID_Standard, sizeof(GUID)); 870 871 /* store result */ 872 Irp->IoStatus.Information = (ULONG_PTR)BusInformation; 873 874 /* done */ 875 return STATUS_SUCCESS; 876 } 877 878 NTSTATUS 879 KspQueryBusDevicePnpState( 880 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 881 IN PIRP Irp) 882 { 883 /* set device flags */ 884 Irp->IoStatus.Information = PNP_DEVICE_DONT_DISPLAY_IN_UI | PNP_DEVICE_NOT_DISABLEABLE; 885 886 /* done */ 887 return STATUS_SUCCESS; 888 } 889 890 NTSTATUS 891 KspQueryId( 892 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 893 IN PIRP Irp) 894 { 895 PIO_STACK_LOCATION IoStack; 896 PBUS_DEVICE_ENTRY DeviceEntry; 897 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 898 LPWSTR Name; 899 SIZE_T Length; 900 901 /* get current irp stack location */ 902 IoStack = IoGetCurrentIrpStackLocation(Irp); 903 904 if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID) 905 { 906 /* get device entry */ 907 DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; 908 909 /* sanity check */ 910 ASSERT(DeviceEntry); 911 ASSERT(DeviceEntry->Instance); 912 913 /* calculate length */ 914 Length = wcslen(DeviceEntry->Instance) + 2; 915 916 /* allocate buffer */ 917 Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); 918 919 if (!Name) 920 { 921 /* failed to allocate buffer */ 922 return STATUS_INSUFFICIENT_RESOURCES; 923 } 924 925 /* copy buffer */ 926 wcscpy(Name, DeviceEntry->Instance); 927 928 /* store result */ 929 Irp->IoStatus.Information = (ULONG_PTR)Name; 930 931 /* done */ 932 return STATUS_SUCCESS; 933 } 934 else if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID || 935 IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) 936 { 937 /* get device entry */ 938 DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; 939 940 /* get bus device extension */ 941 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION) ChildDeviceExtension->BusDeviceExtension; 942 943 /* sanity check */ 944 ASSERT(DeviceEntry); 945 ASSERT(DeviceEntry->BusId); 946 ASSERT(BusDeviceExtension); 947 ASSERT(BusDeviceExtension->BusIdentifier); 948 949 /* calculate length */ 950 Length = wcslen(BusDeviceExtension->BusIdentifier); 951 Length += wcslen(DeviceEntry->BusId); 952 953 /* extra length for '\\' and 2 zero bytes */ 954 Length += 4; 955 956 /* allocate buffer */ 957 Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); 958 if (!Name) 959 { 960 /* failed to allocate buffer */ 961 return STATUS_INSUFFICIENT_RESOURCES; 962 } 963 964 /* construct id */ 965 wcscpy(Name, BusDeviceExtension->BusIdentifier); 966 wcscat(Name, L"\\"); 967 wcscat(Name, DeviceEntry->BusId); 968 //swprintf(Name, L"%s\\%s", BusDeviceExtension->BusIdentifier, DeviceEntry->BusId); 969 970 /* store result */ 971 Irp->IoStatus.Information = (ULONG_PTR)Name; 972 973 /* done */ 974 return STATUS_SUCCESS; 975 } 976 else 977 { 978 /* other ids are not supported */ 979 //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType); 980 return Irp->IoStatus.Status; 981 } 982 } 983 984 NTSTATUS 985 KspInstallInterface( 986 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 987 IN PSWENUM_INSTALL_INTERFACE InstallInterface) 988 { 989 SIZE_T Length, Index; 990 UNICODE_STRING DeviceString, InterfaceString, ReferenceString; 991 HANDLE hKey, hDeviceKey, hInterfaceKey, hReferenceKey; 992 NTSTATUS Status; 993 OBJECT_ATTRIBUTES ObjectAttributes; 994 995 /* sanity check */ 996 ASSERT(InstallInterface); 997 998 /* calculate length */ 999 Length = wcslen(InstallInterface->ReferenceString); 1000 1001 /* check for invalid characters */ 1002 for(Index = 0; Index < Length; Index++) 1003 { 1004 if (InstallInterface->ReferenceString[Index] <= L' ' || 1005 InstallInterface->ReferenceString[Index] > L'~' || 1006 InstallInterface->ReferenceString[Index] == L',' || 1007 InstallInterface->ReferenceString[Index] == L'\\' || 1008 InstallInterface->ReferenceString[Index] == L'/') 1009 { 1010 /* invalid character */ 1011 return STATUS_INVALID_PARAMETER; 1012 } 1013 } 1014 1015 /* open bus key */ 1016 Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); 1017 if (NT_SUCCESS(Status)) 1018 { 1019 /* convert device guid to string */ 1020 Status = RtlStringFromGUID(&InstallInterface->DeviceId, &DeviceString); 1021 if (NT_SUCCESS(Status)) 1022 { 1023 /* initialize object attributes */ 1024 InitializeObjectAttributes(&ObjectAttributes, &DeviceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); 1025 1026 /* construct device key */ 1027 Status = ZwCreateKey(&hDeviceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 1028 if (NT_SUCCESS(Status)) 1029 { 1030 /* convert interface guid to string */ 1031 Status = RtlStringFromGUID(&InstallInterface->InterfaceId, &InterfaceString); 1032 if (NT_SUCCESS(Status)) 1033 { 1034 /* initialize object attributes */ 1035 InitializeObjectAttributes(&ObjectAttributes, &InterfaceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceKey, NULL); 1036 1037 /* construct device key */ 1038 Status = ZwCreateKey(&hInterfaceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 1039 if (NT_SUCCESS(Status)) 1040 { 1041 /* initialize reference string */ 1042 RtlInitUnicodeString(&ReferenceString, InstallInterface->ReferenceString); 1043 1044 /* initialize object attributes */ 1045 InitializeObjectAttributes(&ObjectAttributes, &ReferenceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hInterfaceKey, NULL); 1046 1047 /* construct device key */ 1048 Status = ZwCreateKey(&hReferenceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 1049 if (NT_SUCCESS(Status)) 1050 { 1051 /* close key */ 1052 ZwClose(hReferenceKey); 1053 } 1054 } 1055 /* free interface string */ 1056 RtlFreeUnicodeString(&InterfaceString); 1057 1058 /* close reference key */ 1059 ZwClose(hInterfaceKey); 1060 } 1061 /* close device key */ 1062 ZwClose(hDeviceKey); 1063 } 1064 /* free device string */ 1065 RtlFreeUnicodeString(&DeviceString); 1066 } 1067 /* close bus key */ 1068 ZwClose(hKey); 1069 } 1070 1071 /* done */ 1072 return Status; 1073 } 1074 1075 VOID 1076 NTAPI 1077 KspInstallBusEnumInterface( 1078 IN PVOID Ctx) 1079 { 1080 PIO_STACK_LOCATION IoStack; 1081 NTSTATUS Status; 1082 PLIST_ENTRY Entry; 1083 PBUS_DEVICE_ENTRY DeviceEntry; 1084 PSWENUM_INSTALL_INTERFACE InstallInterface; 1085 KIRQL OldLevel; 1086 PBUS_INSTALL_ENUM_CONTEXT Context = (PBUS_INSTALL_ENUM_CONTEXT)Ctx; 1087 1088 /* get current irp stack location */ 1089 IoStack = IoGetCurrentIrpStackLocation(Context->Irp); 1090 1091 /* get install request */ 1092 InstallInterface = (PSWENUM_INSTALL_INTERFACE)Context->Irp->AssociatedIrp.SystemBuffer; 1093 1094 /* sanity check */ 1095 ASSERT(InstallInterface); 1096 ASSERT(Context->BusDeviceExtension); 1097 1098 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SWENUM_INSTALL_INTERFACE)) 1099 { 1100 /* buffer too small */ 1101 Context->Status = STATUS_INVALID_PARAMETER; 1102 1103 /* signal completion */ 1104 KeSetEvent(&Context->Event, 0, FALSE); 1105 1106 /* done */ 1107 return; 1108 } 1109 1110 /* FIXME locks */ 1111 1112 /* now install the interface */ 1113 Status = KspInstallInterface(Context->BusDeviceExtension, InstallInterface); 1114 if (!NT_SUCCESS(Status)) 1115 { 1116 /* failed to install interface */ 1117 Context->Status = Status; 1118 1119 /* signal completion */ 1120 KeSetEvent(&Context->Event, 0, FALSE); 1121 1122 /* done */ 1123 return; 1124 } 1125 1126 /* now scan the bus */ 1127 Status = KspScanBus(Context->BusDeviceExtension); 1128 // FIXME: We may need to check for success here, and properly fail... 1129 ASSERT(NT_SUCCESS(Status)); 1130 1131 /* acquire device entry lock */ 1132 KeAcquireSpinLock(&Context->BusDeviceExtension->Lock, &OldLevel); 1133 1134 /* now iterate all device entries */ 1135 ASSERT(!IsListEmpty(&Context->BusDeviceExtension->Common.Entry)); 1136 Entry = Context->BusDeviceExtension->Common.Entry.Flink; 1137 while(Entry != &Context->BusDeviceExtension->Common.Entry) 1138 { 1139 /* get device entry */ 1140 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1141 if (IsEqualGUIDAligned(&DeviceEntry->DeviceGuid, &InstallInterface->DeviceId)) 1142 { 1143 if (!DeviceEntry->PDO) 1144 { 1145 /* release device entry lock */ 1146 KeReleaseSpinLock(&Context->BusDeviceExtension->Lock, OldLevel); 1147 1148 /* create pdo */ 1149 Status = KspCreatePDO(Context->BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 1150 1151 /* acquire device entry lock */ 1152 KeAcquireSpinLock(&Context->BusDeviceExtension->Lock, &OldLevel); 1153 1154 /* done */ 1155 break; 1156 } 1157 } 1158 1159 /* move to next entry */ 1160 Entry = Entry->Flink; 1161 } 1162 1163 /* release device entry lock */ 1164 KeReleaseSpinLock(&Context->BusDeviceExtension->Lock, OldLevel); 1165 1166 /* signal that bus driver relations has changed */ 1167 IoInvalidateDeviceRelations(Context->BusDeviceExtension->PhysicalDeviceObject, BusRelations); 1168 1169 /* update status */ 1170 Context->Status = Status; 1171 1172 /* signal completion */ 1173 KeSetEvent(&Context->Event, 0, FALSE); 1174 } 1175 1176 1177 VOID 1178 NTAPI 1179 KspBusWorkerRoutine( 1180 IN PVOID Parameter) 1181 { 1182 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1183 PBUS_DEVICE_ENTRY DeviceEntry; 1184 PLIST_ENTRY Entry; 1185 LARGE_INTEGER Time, Diff; 1186 BOOLEAN DoInvalidate = FALSE; 1187 KIRQL OldLevel; 1188 1189 /* get device extension */ 1190 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Parameter; 1191 1192 /* acquire lock */ 1193 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1194 1195 /* get current time */ 1196 KeQuerySystemTime(&Time); 1197 1198 /* enumerate all device entries */ 1199 Entry = BusDeviceExtension->Common.Entry.Flink; 1200 while(Entry != &BusDeviceExtension->Common.Entry) 1201 { 1202 /* get offset to device entry */ 1203 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1204 1205 /* sanity check */ 1206 ASSERT(DeviceEntry); 1207 1208 //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState); 1209 1210 if (DeviceEntry->PDO) 1211 { 1212 if (DeviceEntry->DeviceState == NotStarted) 1213 { 1214 Diff.QuadPart = Time.QuadPart - DeviceEntry->TimeCreated.QuadPart; 1215 1216 if (Diff.QuadPart > Int32x32To64(15000, 10000)) 1217 { 1218 /* release spin lock */ 1219 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1220 1221 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry->DeviceName, DeviceEntry->Instance, DeviceEntry->TimeCreated.QuadPart, Time.QuadPart, Diff.QuadPart); 1222 1223 /* deactivate interfaces */ 1224 //KspEnableBusDeviceInterface(DeviceEntry, FALSE); 1225 1226 /* re-acquire lock */ 1227 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1228 1229 /* pending remove device object */ 1230 DeviceEntry->DeviceState = StopPending; 1231 1232 /* perform invalidation */ 1233 DoInvalidate = TRUE; 1234 } 1235 } 1236 else if (DeviceEntry->DeviceState == Started) 1237 { 1238 /* release spin lock */ 1239 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1240 1241 /* found pending irps */ 1242 KspCompletePendingIrps(DeviceEntry, STATUS_REPARSE); 1243 1244 /* re-acquire lock */ 1245 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1246 } 1247 } 1248 1249 1250 /* move to next */ 1251 Entry = Entry->Flink; 1252 } 1253 1254 /* release lock */ 1255 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1256 1257 if (DoInvalidate) 1258 { 1259 /* invalidate device relations */ 1260 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 1261 } 1262 1263 Time.QuadPart = Int32x32To64(5000, -10000); 1264 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 1265 } 1266 1267 VOID 1268 NTAPI 1269 KspBusDpcRoutine( 1270 IN PKDPC Dpc, 1271 IN PVOID DeferredContext OPTIONAL, 1272 IN PVOID SystemArgument1 OPTIONAL, 1273 IN PVOID SystemArgument2 OPTIONAL) 1274 { 1275 /* get device extension */ 1276 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeferredContext; 1277 1278 /* queue the item */ 1279 ExQueueWorkItem(&BusDeviceExtension->WorkItem, DelayedWorkQueue); 1280 } 1281 1282 VOID 1283 NTAPI 1284 KspRemoveBusInterface( 1285 PVOID Ctx) 1286 { 1287 PBUS_INSTALL_ENUM_CONTEXT Context =(PBUS_INSTALL_ENUM_CONTEXT)Ctx; 1288 1289 /* TODO 1290 * get SWENUM_INSTALL_INTERFACE struct 1291 * open device key and delete the keys 1292 */ 1293 1294 UNIMPLEMENTED; 1295 1296 /* set status */ 1297 Context->Status = STATUS_NOT_IMPLEMENTED; 1298 1299 1300 /* signal completion */ 1301 KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE); 1302 } 1303 1304 NTSTATUS 1305 KspQueryBusRelations( 1306 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 1307 IN PIRP Irp) 1308 { 1309 PDEVICE_RELATIONS DeviceRelations; 1310 PLIST_ENTRY Entry; 1311 PBUS_DEVICE_ENTRY DeviceEntry; 1312 ULONG Count = 0, Length; 1313 KIRQL OldLevel; 1314 1315 /* acquire lock */ 1316 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1317 1318 /* first scan all device entries */ 1319 Entry = BusDeviceExtension->Common.Entry.Flink; 1320 1321 while(Entry != &BusDeviceExtension->Common.Entry) 1322 { 1323 /* get offset to device entry */ 1324 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1325 1326 /* is there a pdo yet */ 1327 if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) 1328 { 1329 /* increment count */ 1330 Count++; 1331 } 1332 1333 /* move to next entry */ 1334 Entry = Entry->Flink; 1335 } 1336 1337 /* calculate length */ 1338 Length = sizeof(DEVICE_RELATIONS) + (Count > 1 ? sizeof(PDEVICE_OBJECT) * (Count-1) : 0); 1339 1340 /* allocate device relations */ 1341 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(NonPagedPool, Length); 1342 1343 if (!DeviceRelations) 1344 { 1345 /* not enough memory */ 1346 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1347 return STATUS_INSUFFICIENT_RESOURCES; 1348 } 1349 1350 /* rescan device entries */ 1351 Entry = BusDeviceExtension->Common.Entry.Flink; 1352 1353 while(Entry != &BusDeviceExtension->Common.Entry) 1354 { 1355 /* get offset to device entry */ 1356 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1357 1358 /* is there a pdo yet */ 1359 if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) 1360 { 1361 /* store pdo */ 1362 DeviceRelations->Objects[DeviceRelations->Count] = DeviceEntry->PDO; 1363 1364 /* reference device object */ 1365 ObReferenceObject(DeviceEntry->PDO); 1366 1367 /* increment pdo count */ 1368 DeviceRelations->Count++; 1369 } 1370 1371 /* move to next entry */ 1372 Entry = Entry->Flink; 1373 } 1374 1375 /* release lock */ 1376 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1377 1378 /* FIXME handle existing device relations */ 1379 ASSERT(Irp->IoStatus.Information == 0); 1380 1381 /* store device relations */ 1382 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 1383 1384 /* done */ 1385 return STATUS_SUCCESS; 1386 } 1387 1388 //------------------------------------------------------------------------------------ 1389 1390 /* 1391 @implemented 1392 */ 1393 1394 KSDDKAPI 1395 NTSTATUS 1396 NTAPI 1397 KsGetBusEnumIdentifier( 1398 IN PIRP Irp) 1399 { 1400 PDEV_EXTENSION DeviceExtension; 1401 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1402 PIO_STACK_LOCATION IoStack; 1403 SIZE_T Length; 1404 NTSTATUS Status; 1405 LPWSTR Buffer; 1406 1407 DPRINT("KsGetBusEnumIdentifier\n"); 1408 1409 /* get stack location */ 1410 IoStack = IoGetCurrentIrpStackLocation(Irp); 1411 1412 /* sanity checks */ 1413 ASSERT(IoStack->DeviceObject); 1414 ASSERT(IoStack->DeviceObject->DeviceExtension); 1415 1416 /* get device extension */ 1417 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 1418 1419 /* get bus device extension */ 1420 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1421 1422 /* sanity checks */ 1423 ASSERT(BusDeviceExtension); 1424 ASSERT(BusDeviceExtension->Common.IsBus); 1425 1426 if (!BusDeviceExtension) 1427 { 1428 /* invalid parameter */ 1429 return STATUS_INVALID_PARAMETER; 1430 } 1431 1432 /* get length */ 1433 Length = (wcslen(BusDeviceExtension->BusIdentifier)+1) * sizeof(WCHAR); 1434 1435 /* is there an output buffer provided */ 1436 if (IoStack->Parameters.DeviceIoControl.InputBufferLength) 1437 { 1438 if (Length > IoStack->Parameters.DeviceIoControl.InputBufferLength) 1439 { 1440 /* buffer is too small */ 1441 return STATUS_BUFFER_TOO_SMALL; 1442 } 1443 1444 /* now allocate buffer */ 1445 Buffer = AllocateItem(NonPagedPool, Length); 1446 if (!Buffer) 1447 { 1448 /* no memory */ 1449 Status = STATUS_INSUFFICIENT_RESOURCES; 1450 } 1451 else 1452 { 1453 /* copy bus identifier */ 1454 wcscpy(Buffer, BusDeviceExtension->BusIdentifier); 1455 1456 /* store buffer */ 1457 Irp->AssociatedIrp.SystemBuffer = Buffer; 1458 1459 /* set flag that buffer gets copied back */ 1460 Irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION; 1461 1462 /* done */ 1463 Status = STATUS_SUCCESS; 1464 } 1465 } 1466 else 1467 { 1468 /* no buffer provided */ 1469 Status = STATUS_BUFFER_OVERFLOW; 1470 } 1471 1472 /* done */ 1473 Irp->IoStatus.Status = Status; 1474 return Status; 1475 } 1476 1477 /* 1478 @implemented 1479 */ 1480 KSDDKAPI 1481 NTSTATUS 1482 NTAPI 1483 KsGetBusEnumParentFDOFromChildPDO( 1484 IN PDEVICE_OBJECT DeviceObject, 1485 OUT PDEVICE_OBJECT *FunctionalDeviceObject) 1486 { 1487 PDEV_EXTENSION DeviceExtension; 1488 1489 DPRINT("KsGetBusEnumParentFDOFromChildPDO\n"); 1490 1491 /* get device extension */ 1492 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1493 1494 /* check if this is child pdo */ 1495 if (DeviceExtension->Ext->IsBus == FALSE) 1496 { 1497 /* return bus device object */ 1498 *FunctionalDeviceObject = DeviceExtension->Ext->BusDeviceExtension->BusDeviceObject; 1499 1500 /* done */ 1501 return STATUS_SUCCESS; 1502 } 1503 1504 /* invalid parameter */ 1505 return STATUS_INVALID_PARAMETER; 1506 } 1507 1508 1509 /* 1510 @implemented 1511 */ 1512 KSDDKAPI 1513 NTSTATUS 1514 NTAPI 1515 KsCreateBusEnumObject( 1516 IN PWCHAR BusIdentifier, 1517 IN PDEVICE_OBJECT BusDeviceObject, 1518 IN PDEVICE_OBJECT PhysicalDeviceObject, 1519 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL, 1520 IN REFGUID InterfaceGuid OPTIONAL, 1521 IN PWCHAR ServiceRelativePath OPTIONAL) 1522 { 1523 SIZE_T Length; 1524 NTSTATUS Status = STATUS_SUCCESS; 1525 UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); 1526 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1527 PDEV_EXTENSION DeviceExtension; 1528 PBUS_DEVICE_ENTRY DeviceEntry; 1529 PLIST_ENTRY Entry; 1530 KIRQL OldLevel; 1531 1532 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath, BusDeviceObject); 1533 1534 /* calculate sizeof bus enum device extension */ 1535 Length = wcslen(BusIdentifier) * sizeof(WCHAR); 1536 Length += sizeof(BUS_ENUM_DEVICE_EXTENSION); 1537 1538 BusDeviceExtension = AllocateItem(NonPagedPool, Length); 1539 if (!BusDeviceExtension) 1540 { 1541 /* not enough memory */ 1542 1543 return STATUS_INSUFFICIENT_RESOURCES; 1544 } 1545 1546 /* get device extension */ 1547 DeviceExtension = (PDEV_EXTENSION)BusDeviceObject->DeviceExtension; 1548 1549 /* store bus device extension */ 1550 DeviceExtension->Ext = (PCOMMON_DEVICE_EXTENSION)BusDeviceExtension; 1551 1552 DPRINT("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); 1553 1554 1555 /* zero device extension */ 1556 RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION)); 1557 1558 /* initialize bus device extension */ 1559 wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier); 1560 1561 /* allocate service path string */ 1562 Length = ServiceKeyPath.MaximumLength; 1563 Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength; 1564 1565 if (ServiceRelativePath) 1566 { 1567 /* relative path for devices */ 1568 Length += (wcslen(ServiceRelativePath) + 2) * sizeof(WCHAR); 1569 } 1570 1571 BusDeviceExtension->ServicePath.Length = 0; 1572 BusDeviceExtension->ServicePath.MaximumLength = (USHORT)Length; 1573 BusDeviceExtension->ServicePath.Buffer = AllocateItem(NonPagedPool, Length); 1574 1575 if (!BusDeviceExtension->ServicePath.Buffer) 1576 { 1577 /* not enough memory */ 1578 FreeItem(BusDeviceExtension); 1579 1580 return STATUS_INSUFFICIENT_RESOURCES; 1581 } 1582 1583 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath); 1584 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName); 1585 1586 if (ServiceRelativePath) 1587 { 1588 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\"); 1589 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath); 1590 } 1591 1592 if (InterfaceGuid) 1593 { 1594 /* register an device interface */ 1595 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->DeviceInterfaceLink); 1596 1597 /* check for success */ 1598 if (!NT_SUCCESS(Status)) 1599 { 1600 DPRINT1("IoRegisterDeviceInterface failed Status %lx\n", Status); 1601 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1602 FreeItem(BusDeviceExtension); 1603 return Status; 1604 } 1605 1606 /* now enable device interface */ 1607 Status = IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, TRUE); 1608 1609 if (!NT_SUCCESS(Status)) 1610 { 1611 DPRINT1("IoSetDeviceInterfaceState failed Status %lx\n", Status); 1612 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1613 FreeItem(BusDeviceExtension); 1614 return Status; 1615 } 1616 } 1617 1618 /* initialize common device extension */ 1619 BusDeviceExtension->Common.BusDeviceExtension = NULL; 1620 BusDeviceExtension->Common.DeviceObjectReferenceCount = 1; 1621 BusDeviceExtension->Common.DeviceReferenceCount = 1; 1622 BusDeviceExtension->Common.IsBus = TRUE; 1623 InitializeListHead(&BusDeviceExtension->Common.Entry); 1624 1625 /* store device objects */ 1626 BusDeviceExtension->BusDeviceObject = BusDeviceObject; 1627 BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; 1628 1629 /* initialize lock */ 1630 KeInitializeSpinLock(&BusDeviceExtension->Lock); 1631 1632 /* initialize timer */ 1633 KeInitializeTimer(&BusDeviceExtension->Timer); 1634 1635 /* initialize dpc */ 1636 KeInitializeDpc(&BusDeviceExtension->Dpc, KspBusDpcRoutine, (PVOID)BusDeviceExtension); 1637 1638 /* initialize event */ 1639 KeInitializeEvent(&BusDeviceExtension->Event, SynchronizationEvent, FALSE); 1640 1641 /* initialize work item */ 1642 ExInitializeWorkItem(&BusDeviceExtension->WorkItem, KspBusWorkerRoutine, (PVOID)BusDeviceExtension); 1643 1644 if (!PnpDeviceObject) 1645 { 1646 /* attach device */ 1647 BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject); 1648 1649 if (!BusDeviceExtension->PnpDeviceObject) 1650 { 1651 /* failed to attach device */ 1652 DPRINT1("IoAttachDeviceToDeviceStack failed with %x\n", Status); 1653 if (BusDeviceExtension->DeviceInterfaceLink.Buffer) 1654 { 1655 IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); 1656 RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); 1657 } 1658 1659 /* free device extension */ 1660 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1661 FreeItem(BusDeviceExtension); 1662 1663 return STATUS_DEVICE_REMOVED; 1664 } 1665 1666 /* mark device as attached */ 1667 BusDeviceExtension->DeviceAttached = TRUE; 1668 } 1669 else 1670 { 1671 /* directly attach */ 1672 BusDeviceExtension->PnpDeviceObject = PnpDeviceObject; 1673 } 1674 1675 /* now scan the bus */ 1676 Status = KspScanBus(BusDeviceExtension); 1677 1678 /* check for success */ 1679 if (!NT_SUCCESS(Status)) 1680 { 1681 /* failed to scan bus */ 1682 if (BusDeviceExtension->DeviceInterfaceLink.Buffer) 1683 { 1684 IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); 1685 RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); 1686 } 1687 1688 if (BusDeviceExtension->DeviceAttached) 1689 { 1690 /* detach device */ 1691 IoDetachDevice(BusDeviceExtension->PnpDeviceObject); 1692 } 1693 1694 /* free device extension */ 1695 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1696 FreeItem(BusDeviceExtension); 1697 1698 return Status; 1699 } 1700 1701 /* acquire device entry lock */ 1702 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1703 1704 /* now iterate all device entries */ 1705 Entry = BusDeviceExtension->Common.Entry.Flink; 1706 while(Entry != &BusDeviceExtension->Common.Entry) 1707 { 1708 /* get device entry */ 1709 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1710 if (!DeviceEntry->PDO) 1711 { 1712 /* release device entry lock */ 1713 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1714 1715 /* create pdo */ 1716 Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 1717 1718 /* acquire device entry lock */ 1719 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1720 1721 /* done */ 1722 break; 1723 } 1724 /* move to next entry */ 1725 Entry = Entry->Flink; 1726 } 1727 1728 /* release device entry lock */ 1729 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1730 1731 1732 /* invalidate device relations */ 1733 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 1734 DPRINT("KsCreateBusEnumObject Status %x\n", Status); 1735 /* done */ 1736 return Status; 1737 } 1738 1739 /* 1740 @implemented 1741 */ 1742 KSDDKAPI 1743 NTSTATUS 1744 NTAPI 1745 KsGetBusEnumPnpDeviceObject( 1746 IN PDEVICE_OBJECT DeviceObject, 1747 IN PDEVICE_OBJECT *PnpDeviceObject) 1748 { 1749 PDEV_EXTENSION DeviceExtension; 1750 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension; 1751 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1752 1753 DPRINT("KsGetBusEnumPnpDeviceObject\n"); 1754 1755 if (!DeviceObject->DeviceExtension) 1756 { 1757 /* invalid parameter */ 1758 return STATUS_INVALID_PARAMETER; 1759 } 1760 1761 /* get device extension */ 1762 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1763 1764 /* get common device extension */ 1765 CommonDeviceExtension = DeviceExtension->Ext; 1766 1767 if (!CommonDeviceExtension) 1768 { 1769 /* invalid parameter */ 1770 return STATUS_INVALID_PARAMETER; 1771 } 1772 1773 if (!CommonDeviceExtension->IsBus) 1774 { 1775 /* getting pnp device object is only supported for software bus device object */ 1776 return STATUS_INVALID_PARAMETER; 1777 } 1778 1779 /* sanity checks */ 1780 ASSERT(CommonDeviceExtension); 1781 ASSERT(CommonDeviceExtension->IsBus); 1782 1783 /* cast to bus device extension */ 1784 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)CommonDeviceExtension; 1785 1786 /* store result */ 1787 *PnpDeviceObject = BusDeviceExtension->PnpDeviceObject; 1788 1789 /* done */ 1790 return STATUS_SUCCESS; 1791 } 1792 1793 /* 1794 @implemented 1795 */ 1796 KSDDKAPI 1797 NTSTATUS 1798 NTAPI 1799 KsInstallBusEnumInterface( 1800 PIRP Irp) 1801 { 1802 BUS_INSTALL_ENUM_CONTEXT Context; 1803 KPROCESSOR_MODE Mode; 1804 LUID luid; 1805 PIO_STACK_LOCATION IoStack; 1806 PDEV_EXTENSION DeviceExtension; 1807 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1808 1809 DPRINT("KsInstallBusEnumInterface\n"); 1810 1811 /* get current irp stack location */ 1812 IoStack = IoGetCurrentIrpStackLocation(Irp); 1813 1814 /* get previous mode */ 1815 Mode = ExGetPreviousMode(); 1816 1817 /* convert to luid */ 1818 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); 1819 1820 /* perform access check */ 1821 if (!SeSinglePrivilegeCheck(luid, Mode)) 1822 { 1823 /* FIXME insufficient privileges */ 1824 //return STATUS_PRIVILEGE_NOT_HELD; 1825 } 1826 1827 /* get device extension */ 1828 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 1829 1830 /* get bus device extension */ 1831 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1832 1833 1834 /* initialize context */ 1835 Context.Irp = Irp; 1836 KeInitializeEvent(&Context.Event, NotificationEvent, FALSE); 1837 Context.BusDeviceExtension = BusDeviceExtension; 1838 ExInitializeWorkItem(&Context.WorkItem, KspInstallBusEnumInterface, (PVOID)&Context); 1839 1840 /* queue the work item */ 1841 ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); 1842 /* wait for completion */ 1843 KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL); 1844 1845 /* store result */ 1846 Irp->IoStatus.Status = Context.Status; 1847 1848 /* done */ 1849 return Context.Status; 1850 } 1851 1852 /* 1853 @implemented 1854 */ 1855 KSDDKAPI 1856 NTSTATUS 1857 NTAPI 1858 KsIsBusEnumChildDevice( 1859 IN PDEVICE_OBJECT DeviceObject, 1860 OUT PBOOLEAN ChildDevice) 1861 { 1862 PDEV_EXTENSION DeviceExtension; 1863 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1864 1865 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject); 1866 1867 /* get device extension */ 1868 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1869 1870 /* get bus device extension */ 1871 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1872 1873 if (!BusDeviceExtension) 1874 { 1875 /* not a bus device */ 1876 return STATUS_INVALID_PARAMETER; 1877 } 1878 1879 /* store result */ 1880 *ChildDevice = (BusDeviceExtension->Common.IsBus == FALSE); 1881 1882 return STATUS_SUCCESS; 1883 } 1884 1885 /* 1886 @implemented 1887 */ 1888 KSDDKAPI 1889 NTSTATUS 1890 NTAPI 1891 KsServiceBusEnumCreateRequest( 1892 IN PDEVICE_OBJECT DeviceObject, 1893 IN OUT PIRP Irp) 1894 { 1895 PLIST_ENTRY Entry; 1896 PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* fix gcc */ 1897 PIO_STACK_LOCATION IoStack; 1898 BOOLEAN ItemExists = FALSE; 1899 PDEV_EXTENSION DeviceExtension; 1900 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1901 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; 1902 NTSTATUS Status; 1903 LARGE_INTEGER Time; 1904 1905 /* FIXME: locks */ 1906 1907 /* get device extension */ 1908 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1909 1910 /* get bus device extension */ 1911 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1912 1913 /* get current irp stack location */ 1914 IoStack = IoGetCurrentIrpStackLocation(Irp); 1915 1916 /* sanity checks */ 1917 ASSERT(IoStack->FileObject); 1918 if (IoStack->FileObject->FileName.Buffer == NULL) 1919 { 1920 DPRINT("KsServiceBusEnumCreateRequest PNP Hack\n"); 1921 Irp->IoStatus.Status = STATUS_SUCCESS; 1922 return STATUS_SUCCESS; 1923 } 1924 1925 ASSERT(IoStack->FileObject->FileName.Buffer); 1926 1927 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp, &IoStack->FileObject->FileName); 1928 1929 /* scan list and check if it is already present */ 1930 Entry = BusDeviceExtension->Common.Entry.Flink; 1931 1932 while(Entry != &BusDeviceExtension->Common.Entry) 1933 { 1934 /* get real offset */ 1935 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1936 1937 /* check if name matches */ 1938 if (!wcsicmp(DeviceEntry->DeviceName, IoStack->FileObject->FileName.Buffer + 1)) 1939 { 1940 /* item already exists */ 1941 ItemExists = TRUE; 1942 break; 1943 } 1944 1945 /* move to next entry */ 1946 Entry = Entry->Flink; 1947 } 1948 1949 if (!ItemExists) 1950 { 1951 /* interface not registered */ 1952 DPRINT1("Interface %wZ not registered\n", &IoStack->FileObject->FileName); 1953 return STATUS_OBJECT_NAME_NOT_FOUND; 1954 } 1955 1956 /* is there a pdo yet */ 1957 if (DeviceEntry->PDO) 1958 { 1959 if (DeviceEntry->DeviceState == Started) 1960 { 1961 /* issue reparse */ 1962 Status = KspDoReparseForIrp(Irp, DeviceEntry); 1963 DPRINT("REPARSE Irp %p '%wZ'\n", Irp, &IoStack->FileObject->FileName); 1964 1965 Irp->IoStatus.Status = Status; 1966 Irp->IoStatus.Information = IO_REPARSE; 1967 return Status; 1968 } 1969 1970 /* delay processing until pnp is finished with enumeration */ 1971 IoMarkIrpPending(Irp); 1972 1973 /* insert into irp pending list */ 1974 InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); 1975 1976 Time.QuadPart = Int32x32To64(1500, -10000); 1977 DbgPrint("PENDING Irp %p %wZ DeviceState %d\n", Irp, &IoStack->FileObject->FileName, DeviceEntry->DeviceState); 1978 1979 1980 /* set timer */ 1981 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 1982 1983 /* done for now */ 1984 return STATUS_PENDING; 1985 1986 } 1987 else 1988 { 1989 /* time to create PDO */ 1990 Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 1991 1992 if (!NT_SUCCESS(Status)) 1993 { 1994 /* failed to create PDO */ 1995 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status); 1996 return Status; 1997 } 1998 DPRINT("PENDING CREATE Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); 1999 2000 /* delay processing until pnp is finished with enumeration */ 2001 IoMarkIrpPending(Irp); 2002 2003 /* insert into irp pending list */ 2004 InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); 2005 2006 /* invalidate device relations */ 2007 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 2008 2009 /* done for now */ 2010 return STATUS_PENDING; 2011 } 2012 } 2013 2014 /* 2015 @implemented 2016 */ 2017 KSDDKAPI 2018 NTSTATUS 2019 NTAPI 2020 KsServiceBusEnumPnpRequest( 2021 IN PDEVICE_OBJECT DeviceObject, 2022 IN OUT PIRP Irp) 2023 { 2024 PDEV_EXTENSION DeviceExtension; 2025 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 2026 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; 2027 PIO_STACK_LOCATION IoStack; 2028 NTSTATUS Status; 2029 LARGE_INTEGER Time; 2030 PDEVICE_RELATIONS DeviceRelation; 2031 PBUS_DEVICE_ENTRY DeviceEntry; 2032 2033 /* get device extension */ 2034 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 2035 2036 /* get bus device extension */ 2037 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 2038 2039 /* get current irp stack location */ 2040 IoStack = IoGetCurrentIrpStackLocation(Irp); 2041 2042 if (BusDeviceExtension->Common.IsBus) 2043 { 2044 if (IoStack->MinorFunction == IRP_MN_START_DEVICE) 2045 { 2046 /* no op for bus driver */ 2047 Status = STATUS_SUCCESS; 2048 } 2049 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS) 2050 { 2051 /* handle bus device relations */ 2052 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == BusRelations); 2053 2054 Status = KspQueryBusRelations(BusDeviceExtension, Irp); 2055 } 2056 else 2057 { 2058 /* get default status */ 2059 Status = Irp->IoStatus.Status; 2060 } 2061 } 2062 else 2063 { 2064 /* get child device extension */ 2065 ChildDeviceExtension = DeviceExtension->Ext; 2066 2067 /* get bus device extension */ 2068 BusDeviceExtension = ChildDeviceExtension->BusDeviceExtension; 2069 2070 if (IoStack->MinorFunction == IRP_MN_QUERY_ID) 2071 { 2072 /* query id */ 2073 Status = KspQueryId(ChildDeviceExtension, Irp); 2074 } 2075 else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE) 2076 { 2077 ASSERT(ChildDeviceExtension->DeviceEntry->DeviceState != Started || ChildDeviceExtension->DeviceEntry->DeviceState == NotStarted); 2078 ASSERT(ChildDeviceExtension->DeviceEntry->PDO == DeviceObject); 2079 2080 /* backup device entry */ 2081 DeviceEntry = ChildDeviceExtension->DeviceEntry; 2082 2083 /* free device extension */ 2084 FreeItem(ChildDeviceExtension); 2085 2086 /* clear PDO reference */ 2087 DeviceEntry->PDO = NULL; 2088 2089 /* delete the device */ 2090 IoDeleteDevice(DeviceObject); 2091 2092 if (DeviceEntry->PDODeviceName) 2093 { 2094 /* delete pdo device name */ 2095 FreeItem(DeviceEntry->PDODeviceName); 2096 2097 /* set to null */ 2098 DeviceEntry->PDODeviceName = NULL; 2099 } 2100 2101 /* set state no notstarted */ 2102 DeviceEntry->DeviceState = NotStarted; 2103 2104 /* complete pending irps */ 2105 KspCompletePendingIrps(DeviceEntry, STATUS_DEVICE_REMOVED); 2106 2107 /* done */ 2108 Status = STATUS_SUCCESS; 2109 } 2110 else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION) 2111 { 2112 /* query bus information */ 2113 Status = KspQueryBusInformation(ChildDeviceExtension, Irp); 2114 } 2115 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES) 2116 { 2117 /* no op */ 2118 Status = STATUS_SUCCESS; 2119 } 2120 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS) 2121 { 2122 /* no op */ 2123 Status = STATUS_SUCCESS; 2124 } 2125 else if (IoStack->MinorFunction == IRP_MN_START_DEVICE) 2126 { 2127 /* start bus */ 2128 Status = KspStartBusDevice(DeviceObject, ChildDeviceExtension, Irp); 2129 if (NT_SUCCESS(Status)) 2130 { 2131 /* complete pending irps*/ 2132 KspCompletePendingIrps(ChildDeviceExtension->DeviceEntry, STATUS_REPARSE); 2133 } 2134 2135 /* set time out */ 2136 Time.QuadPart = Int32x32To64(1500, -10000); 2137 2138 /* sanity check */ 2139 ASSERT(BusDeviceExtension); 2140 2141 /* set timer */ 2142 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 2143 } 2144 else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES) 2145 { 2146 /* query capabilities */ 2147 Status = KspQueryBusDeviceCapabilities(ChildDeviceExtension, Irp); 2148 } 2149 else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE) 2150 { 2151 /* query pnp state */ 2152 Status = KspQueryBusDevicePnpState(ChildDeviceExtension, Irp); 2153 } 2154 else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE) 2155 { 2156 /* query interface */ 2157 Status = KspQueryBusDeviceInterface(ChildDeviceExtension, Irp); 2158 } 2159 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS && IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) 2160 { 2161 /* handle target device relations */ 2162 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation); 2163 ASSERT(Irp->IoStatus.Information == 0); 2164 2165 /* allocate device relation */ 2166 DeviceRelation = AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); 2167 if (DeviceRelation) 2168 { 2169 DeviceRelation->Count = 1; 2170 DeviceRelation->Objects[0] = DeviceObject; 2171 2172 /* reference self */ 2173 ObReferenceObject(DeviceObject); 2174 2175 /* store result */ 2176 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; 2177 2178 /* done */ 2179 Status = STATUS_SUCCESS; 2180 } 2181 else 2182 { 2183 /* no memory */ 2184 Status = STATUS_INSUFFICIENT_RESOURCES; 2185 } 2186 } 2187 else 2188 { 2189 /* get default status */ 2190 Status = Irp->IoStatus.Status; 2191 } 2192 } 2193 2194 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject, BusDeviceExtension->Common.IsBus, IoStack->MinorFunction, Status); 2195 Irp->IoStatus.Status = Status; 2196 return Status; 2197 } 2198 2199 /* 2200 @implemented 2201 */ 2202 KSDDKAPI 2203 NTSTATUS 2204 NTAPI 2205 KsRemoveBusEnumInterface( 2206 IN PIRP Irp) 2207 { 2208 KPROCESSOR_MODE Mode; 2209 LUID luid; 2210 BUS_INSTALL_ENUM_CONTEXT Ctx; 2211 PDEV_EXTENSION DeviceExtension; 2212 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 2213 PIO_STACK_LOCATION IoStack; 2214 2215 DPRINT("KsRemoveBusEnumInterface\n"); 2216 2217 /* get io stack location */ 2218 IoStack = IoGetCurrentIrpStackLocation(Irp); 2219 2220 /* get device extension */ 2221 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 2222 2223 /* get bus device extension */ 2224 BusDeviceExtension = DeviceExtension->Ext->BusDeviceExtension; 2225 2226 /* get previous mode */ 2227 Mode = ExGetPreviousMode(); 2228 2229 /* convert to luid */ 2230 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); 2231 2232 /* perform access check */ 2233 if (!SeSinglePrivilegeCheck(luid, Mode)) 2234 { 2235 /* insufficient privileges */ 2236 return STATUS_PRIVILEGE_NOT_HELD; 2237 } 2238 2239 /* initialize context */ 2240 KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE); 2241 Ctx.Irp = Irp; 2242 Ctx.BusDeviceExtension = BusDeviceExtension; 2243 ExInitializeWorkItem(&Ctx.WorkItem, KspRemoveBusInterface, (PVOID)&Ctx); 2244 2245 /* now queue the work item */ 2246 ExQueueWorkItem(&Ctx.WorkItem, DelayedWorkQueue); 2247 2248 /* wait for completion */ 2249 KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL); 2250 2251 /* return result */ 2252 return Ctx.Status; 2253 } 2254