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 KeQueryTickCount(&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 KeQueryTickCount(&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 KeQueryTickCount(&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) * KeQueryTimeIncrement(); 1215 1216 /* wait for 15 sec */ 1217 if (Diff.QuadPart > Int32x32To64(15000, 10000)) 1218 { 1219 /* release spin lock */ 1220 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1221 1222 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", 1223 DeviceEntry->DeviceName, 1224 DeviceEntry->Instance, 1225 DeviceEntry->TimeCreated.QuadPart * KeQueryTimeIncrement(), 1226 Time.QuadPart * KeQueryTimeIncrement(), 1227 Diff.QuadPart); 1228 1229 /* deactivate interfaces */ 1230 //KspEnableBusDeviceInterface(DeviceEntry, FALSE); 1231 1232 /* re-acquire lock */ 1233 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1234 1235 /* pending remove device object */ 1236 DeviceEntry->DeviceState = StopPending; 1237 1238 /* perform invalidation */ 1239 DoInvalidate = TRUE; 1240 } 1241 } 1242 else if (DeviceEntry->DeviceState == Started) 1243 { 1244 /* release spin lock */ 1245 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1246 1247 /* found pending irps */ 1248 KspCompletePendingIrps(DeviceEntry, STATUS_REPARSE); 1249 1250 /* re-acquire lock */ 1251 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1252 } 1253 } 1254 1255 1256 /* move to next */ 1257 Entry = Entry->Flink; 1258 } 1259 1260 /* release lock */ 1261 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1262 1263 if (DoInvalidate) 1264 { 1265 /* invalidate device relations */ 1266 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 1267 } 1268 1269 Time.QuadPart = Int32x32To64(5000, -10000); 1270 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 1271 } 1272 1273 VOID 1274 NTAPI 1275 KspBusDpcRoutine( 1276 IN PKDPC Dpc, 1277 IN PVOID DeferredContext OPTIONAL, 1278 IN PVOID SystemArgument1 OPTIONAL, 1279 IN PVOID SystemArgument2 OPTIONAL) 1280 { 1281 /* get device extension */ 1282 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeferredContext; 1283 1284 /* queue the item */ 1285 ExQueueWorkItem(&BusDeviceExtension->WorkItem, DelayedWorkQueue); 1286 } 1287 1288 VOID 1289 NTAPI 1290 KspRemoveBusInterface( 1291 PVOID Ctx) 1292 { 1293 PBUS_INSTALL_ENUM_CONTEXT Context =(PBUS_INSTALL_ENUM_CONTEXT)Ctx; 1294 1295 /* TODO 1296 * get SWENUM_INSTALL_INTERFACE struct 1297 * open device key and delete the keys 1298 */ 1299 1300 UNIMPLEMENTED; 1301 1302 /* set status */ 1303 Context->Status = STATUS_NOT_IMPLEMENTED; 1304 1305 1306 /* signal completion */ 1307 KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE); 1308 } 1309 1310 NTSTATUS 1311 KspQueryBusRelations( 1312 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 1313 IN PIRP Irp) 1314 { 1315 PDEVICE_RELATIONS DeviceRelations; 1316 PLIST_ENTRY Entry; 1317 PBUS_DEVICE_ENTRY DeviceEntry; 1318 ULONG Count = 0, Length; 1319 KIRQL OldLevel; 1320 1321 /* acquire lock */ 1322 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1323 1324 /* first scan all device entries */ 1325 Entry = BusDeviceExtension->Common.Entry.Flink; 1326 1327 while(Entry != &BusDeviceExtension->Common.Entry) 1328 { 1329 /* get offset to device entry */ 1330 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1331 1332 /* is there a pdo yet */ 1333 if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) 1334 { 1335 /* increment count */ 1336 Count++; 1337 } 1338 1339 /* move to next entry */ 1340 Entry = Entry->Flink; 1341 } 1342 1343 /* calculate length */ 1344 Length = sizeof(DEVICE_RELATIONS) + (Count > 1 ? sizeof(PDEVICE_OBJECT) * (Count-1) : 0); 1345 1346 /* allocate device relations */ 1347 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(NonPagedPool, Length); 1348 1349 if (!DeviceRelations) 1350 { 1351 /* not enough memory */ 1352 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1353 return STATUS_INSUFFICIENT_RESOURCES; 1354 } 1355 1356 /* rescan device entries */ 1357 Entry = BusDeviceExtension->Common.Entry.Flink; 1358 1359 while(Entry != &BusDeviceExtension->Common.Entry) 1360 { 1361 /* get offset to device entry */ 1362 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1363 1364 /* is there a pdo yet */ 1365 if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) 1366 { 1367 /* store pdo */ 1368 DeviceRelations->Objects[DeviceRelations->Count] = DeviceEntry->PDO; 1369 1370 /* reference device object */ 1371 ObReferenceObject(DeviceEntry->PDO); 1372 1373 /* increment pdo count */ 1374 DeviceRelations->Count++; 1375 } 1376 1377 /* move to next entry */ 1378 Entry = Entry->Flink; 1379 } 1380 1381 /* release lock */ 1382 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1383 1384 /* FIXME handle existing device relations */ 1385 ASSERT(Irp->IoStatus.Information == 0); 1386 1387 /* store device relations */ 1388 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 1389 1390 /* done */ 1391 return STATUS_SUCCESS; 1392 } 1393 1394 //------------------------------------------------------------------------------------ 1395 1396 /* 1397 @implemented 1398 */ 1399 1400 KSDDKAPI 1401 NTSTATUS 1402 NTAPI 1403 KsGetBusEnumIdentifier( 1404 IN PIRP Irp) 1405 { 1406 PDEV_EXTENSION DeviceExtension; 1407 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1408 PIO_STACK_LOCATION IoStack; 1409 SIZE_T Length; 1410 NTSTATUS Status; 1411 LPWSTR Buffer; 1412 1413 DPRINT("KsGetBusEnumIdentifier\n"); 1414 1415 /* get stack location */ 1416 IoStack = IoGetCurrentIrpStackLocation(Irp); 1417 1418 /* sanity checks */ 1419 ASSERT(IoStack->DeviceObject); 1420 ASSERT(IoStack->DeviceObject->DeviceExtension); 1421 1422 /* get device extension */ 1423 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 1424 1425 /* get bus device extension */ 1426 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1427 1428 /* sanity checks */ 1429 ASSERT(BusDeviceExtension); 1430 ASSERT(BusDeviceExtension->Common.IsBus); 1431 1432 if (!BusDeviceExtension) 1433 { 1434 /* invalid parameter */ 1435 return STATUS_INVALID_PARAMETER; 1436 } 1437 1438 /* get length */ 1439 Length = (wcslen(BusDeviceExtension->BusIdentifier)+1) * sizeof(WCHAR); 1440 1441 /* is there an output buffer provided */ 1442 if (IoStack->Parameters.DeviceIoControl.InputBufferLength) 1443 { 1444 if (Length > IoStack->Parameters.DeviceIoControl.InputBufferLength) 1445 { 1446 /* buffer is too small */ 1447 return STATUS_BUFFER_TOO_SMALL; 1448 } 1449 1450 /* now allocate buffer */ 1451 Buffer = AllocateItem(NonPagedPool, Length); 1452 if (!Buffer) 1453 { 1454 /* no memory */ 1455 Status = STATUS_INSUFFICIENT_RESOURCES; 1456 } 1457 else 1458 { 1459 /* copy bus identifier */ 1460 wcscpy(Buffer, BusDeviceExtension->BusIdentifier); 1461 1462 /* store buffer */ 1463 Irp->AssociatedIrp.SystemBuffer = Buffer; 1464 1465 /* set flag that buffer gets copied back */ 1466 Irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION; 1467 1468 /* done */ 1469 Status = STATUS_SUCCESS; 1470 } 1471 } 1472 else 1473 { 1474 /* no buffer provided */ 1475 Status = STATUS_BUFFER_OVERFLOW; 1476 } 1477 1478 /* done */ 1479 Irp->IoStatus.Status = Status; 1480 return Status; 1481 } 1482 1483 /* 1484 @implemented 1485 */ 1486 KSDDKAPI 1487 NTSTATUS 1488 NTAPI 1489 KsGetBusEnumParentFDOFromChildPDO( 1490 IN PDEVICE_OBJECT DeviceObject, 1491 OUT PDEVICE_OBJECT *FunctionalDeviceObject) 1492 { 1493 PDEV_EXTENSION DeviceExtension; 1494 1495 DPRINT("KsGetBusEnumParentFDOFromChildPDO\n"); 1496 1497 /* get device extension */ 1498 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1499 1500 /* check if this is child pdo */ 1501 if (DeviceExtension->Ext->IsBus == FALSE) 1502 { 1503 /* return bus device object */ 1504 *FunctionalDeviceObject = DeviceExtension->Ext->BusDeviceExtension->BusDeviceObject; 1505 1506 /* done */ 1507 return STATUS_SUCCESS; 1508 } 1509 1510 /* invalid parameter */ 1511 return STATUS_INVALID_PARAMETER; 1512 } 1513 1514 1515 /* 1516 @implemented 1517 */ 1518 KSDDKAPI 1519 NTSTATUS 1520 NTAPI 1521 KsCreateBusEnumObject( 1522 IN PWCHAR BusIdentifier, 1523 IN PDEVICE_OBJECT BusDeviceObject, 1524 IN PDEVICE_OBJECT PhysicalDeviceObject, 1525 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL, 1526 IN REFGUID InterfaceGuid OPTIONAL, 1527 IN PWCHAR ServiceRelativePath OPTIONAL) 1528 { 1529 SIZE_T Length; 1530 NTSTATUS Status = STATUS_SUCCESS; 1531 UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); 1532 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1533 PDEV_EXTENSION DeviceExtension; 1534 PBUS_DEVICE_ENTRY DeviceEntry; 1535 PLIST_ENTRY Entry; 1536 KIRQL OldLevel; 1537 1538 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath, BusDeviceObject); 1539 1540 /* calculate sizeof bus enum device extension */ 1541 Length = wcslen(BusIdentifier) * sizeof(WCHAR); 1542 Length += sizeof(BUS_ENUM_DEVICE_EXTENSION); 1543 1544 BusDeviceExtension = AllocateItem(NonPagedPool, Length); 1545 if (!BusDeviceExtension) 1546 { 1547 /* not enough memory */ 1548 1549 return STATUS_INSUFFICIENT_RESOURCES; 1550 } 1551 1552 /* get device extension */ 1553 DeviceExtension = (PDEV_EXTENSION)BusDeviceObject->DeviceExtension; 1554 1555 /* store bus device extension */ 1556 DeviceExtension->Ext = (PCOMMON_DEVICE_EXTENSION)BusDeviceExtension; 1557 1558 DPRINT("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); 1559 1560 1561 /* zero device extension */ 1562 RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION)); 1563 1564 /* initialize bus device extension */ 1565 wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier); 1566 1567 /* allocate service path string */ 1568 Length = ServiceKeyPath.MaximumLength; 1569 Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength; 1570 1571 if (ServiceRelativePath) 1572 { 1573 /* relative path for devices */ 1574 Length += (wcslen(ServiceRelativePath) + 2) * sizeof(WCHAR); 1575 } 1576 1577 BusDeviceExtension->ServicePath.Length = 0; 1578 BusDeviceExtension->ServicePath.MaximumLength = (USHORT)Length; 1579 BusDeviceExtension->ServicePath.Buffer = AllocateItem(NonPagedPool, Length); 1580 1581 if (!BusDeviceExtension->ServicePath.Buffer) 1582 { 1583 /* not enough memory */ 1584 FreeItem(BusDeviceExtension); 1585 1586 return STATUS_INSUFFICIENT_RESOURCES; 1587 } 1588 1589 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath); 1590 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName); 1591 1592 if (ServiceRelativePath) 1593 { 1594 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\"); 1595 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath); 1596 } 1597 1598 if (InterfaceGuid) 1599 { 1600 /* register an device interface */ 1601 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->DeviceInterfaceLink); 1602 1603 /* check for success */ 1604 if (!NT_SUCCESS(Status)) 1605 { 1606 DPRINT1("IoRegisterDeviceInterface failed Status %lx\n", Status); 1607 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1608 FreeItem(BusDeviceExtension); 1609 return Status; 1610 } 1611 1612 /* now enable device interface */ 1613 Status = IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, TRUE); 1614 1615 if (!NT_SUCCESS(Status)) 1616 { 1617 DPRINT1("IoSetDeviceInterfaceState failed Status %lx\n", Status); 1618 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1619 FreeItem(BusDeviceExtension); 1620 return Status; 1621 } 1622 } 1623 1624 /* initialize common device extension */ 1625 BusDeviceExtension->Common.BusDeviceExtension = NULL; 1626 BusDeviceExtension->Common.DeviceObjectReferenceCount = 1; 1627 BusDeviceExtension->Common.DeviceReferenceCount = 1; 1628 BusDeviceExtension->Common.IsBus = TRUE; 1629 InitializeListHead(&BusDeviceExtension->Common.Entry); 1630 1631 /* store device objects */ 1632 BusDeviceExtension->BusDeviceObject = BusDeviceObject; 1633 BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; 1634 1635 /* initialize lock */ 1636 KeInitializeSpinLock(&BusDeviceExtension->Lock); 1637 1638 /* initialize timer */ 1639 KeInitializeTimer(&BusDeviceExtension->Timer); 1640 1641 /* initialize dpc */ 1642 KeInitializeDpc(&BusDeviceExtension->Dpc, KspBusDpcRoutine, (PVOID)BusDeviceExtension); 1643 1644 /* initialize event */ 1645 KeInitializeEvent(&BusDeviceExtension->Event, SynchronizationEvent, FALSE); 1646 1647 /* initialize work item */ 1648 ExInitializeWorkItem(&BusDeviceExtension->WorkItem, KspBusWorkerRoutine, (PVOID)BusDeviceExtension); 1649 1650 if (!PnpDeviceObject) 1651 { 1652 /* attach device */ 1653 BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject); 1654 1655 if (!BusDeviceExtension->PnpDeviceObject) 1656 { 1657 /* failed to attach device */ 1658 DPRINT1("IoAttachDeviceToDeviceStack failed with %x\n", Status); 1659 if (BusDeviceExtension->DeviceInterfaceLink.Buffer) 1660 { 1661 IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); 1662 RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); 1663 } 1664 1665 /* free device extension */ 1666 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1667 FreeItem(BusDeviceExtension); 1668 1669 return STATUS_DEVICE_REMOVED; 1670 } 1671 1672 /* mark device as attached */ 1673 BusDeviceExtension->DeviceAttached = TRUE; 1674 } 1675 else 1676 { 1677 /* directly attach */ 1678 BusDeviceExtension->PnpDeviceObject = PnpDeviceObject; 1679 } 1680 1681 /* now scan the bus */ 1682 Status = KspScanBus(BusDeviceExtension); 1683 1684 /* check for success */ 1685 if (!NT_SUCCESS(Status)) 1686 { 1687 /* failed to scan bus */ 1688 if (BusDeviceExtension->DeviceInterfaceLink.Buffer) 1689 { 1690 IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); 1691 RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); 1692 } 1693 1694 if (BusDeviceExtension->DeviceAttached) 1695 { 1696 /* detach device */ 1697 IoDetachDevice(BusDeviceExtension->PnpDeviceObject); 1698 } 1699 1700 /* free device extension */ 1701 FreeItem(BusDeviceExtension->ServicePath.Buffer); 1702 FreeItem(BusDeviceExtension); 1703 1704 return Status; 1705 } 1706 1707 /* acquire device entry lock */ 1708 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1709 1710 /* now iterate all device entries */ 1711 Entry = BusDeviceExtension->Common.Entry.Flink; 1712 while(Entry != &BusDeviceExtension->Common.Entry) 1713 { 1714 /* get device entry */ 1715 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1716 if (!DeviceEntry->PDO) 1717 { 1718 /* release device entry lock */ 1719 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1720 1721 /* create pdo */ 1722 Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 1723 1724 /* acquire device entry lock */ 1725 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 1726 1727 /* done */ 1728 break; 1729 } 1730 /* move to next entry */ 1731 Entry = Entry->Flink; 1732 } 1733 1734 /* release device entry lock */ 1735 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 1736 1737 1738 /* invalidate device relations */ 1739 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 1740 DPRINT("KsCreateBusEnumObject Status %x\n", Status); 1741 /* done */ 1742 return Status; 1743 } 1744 1745 /* 1746 @implemented 1747 */ 1748 KSDDKAPI 1749 NTSTATUS 1750 NTAPI 1751 KsGetBusEnumPnpDeviceObject( 1752 IN PDEVICE_OBJECT DeviceObject, 1753 IN PDEVICE_OBJECT *PnpDeviceObject) 1754 { 1755 PDEV_EXTENSION DeviceExtension; 1756 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension; 1757 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1758 1759 DPRINT("KsGetBusEnumPnpDeviceObject\n"); 1760 1761 if (!DeviceObject->DeviceExtension) 1762 { 1763 /* invalid parameter */ 1764 return STATUS_INVALID_PARAMETER; 1765 } 1766 1767 /* get device extension */ 1768 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1769 1770 /* get common device extension */ 1771 CommonDeviceExtension = DeviceExtension->Ext; 1772 1773 if (!CommonDeviceExtension) 1774 { 1775 /* invalid parameter */ 1776 return STATUS_INVALID_PARAMETER; 1777 } 1778 1779 if (!CommonDeviceExtension->IsBus) 1780 { 1781 /* getting pnp device object is only supported for software bus device object */ 1782 return STATUS_INVALID_PARAMETER; 1783 } 1784 1785 /* sanity checks */ 1786 ASSERT(CommonDeviceExtension); 1787 ASSERT(CommonDeviceExtension->IsBus); 1788 1789 /* cast to bus device extension */ 1790 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)CommonDeviceExtension; 1791 1792 /* store result */ 1793 *PnpDeviceObject = BusDeviceExtension->PnpDeviceObject; 1794 1795 /* done */ 1796 return STATUS_SUCCESS; 1797 } 1798 1799 /* 1800 @implemented 1801 */ 1802 KSDDKAPI 1803 NTSTATUS 1804 NTAPI 1805 KsInstallBusEnumInterface( 1806 PIRP Irp) 1807 { 1808 BUS_INSTALL_ENUM_CONTEXT Context; 1809 KPROCESSOR_MODE Mode; 1810 LUID luid; 1811 PIO_STACK_LOCATION IoStack; 1812 PDEV_EXTENSION DeviceExtension; 1813 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1814 1815 DPRINT("KsInstallBusEnumInterface\n"); 1816 1817 /* get current irp stack location */ 1818 IoStack = IoGetCurrentIrpStackLocation(Irp); 1819 1820 /* get previous mode */ 1821 Mode = ExGetPreviousMode(); 1822 1823 /* convert to luid */ 1824 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); 1825 1826 /* perform access check */ 1827 if (!SeSinglePrivilegeCheck(luid, Mode)) 1828 { 1829 /* FIXME insufficient privileges */ 1830 //return STATUS_PRIVILEGE_NOT_HELD; 1831 } 1832 1833 /* get device extension */ 1834 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 1835 1836 /* get bus device extension */ 1837 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1838 1839 1840 /* initialize context */ 1841 Context.Irp = Irp; 1842 KeInitializeEvent(&Context.Event, NotificationEvent, FALSE); 1843 Context.BusDeviceExtension = BusDeviceExtension; 1844 ExInitializeWorkItem(&Context.WorkItem, KspInstallBusEnumInterface, (PVOID)&Context); 1845 1846 /* queue the work item */ 1847 ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); 1848 /* wait for completion */ 1849 KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL); 1850 1851 /* store result */ 1852 Irp->IoStatus.Status = Context.Status; 1853 1854 /* done */ 1855 return Context.Status; 1856 } 1857 1858 /* 1859 @implemented 1860 */ 1861 KSDDKAPI 1862 NTSTATUS 1863 NTAPI 1864 KsIsBusEnumChildDevice( 1865 IN PDEVICE_OBJECT DeviceObject, 1866 OUT PBOOLEAN ChildDevice) 1867 { 1868 PDEV_EXTENSION DeviceExtension; 1869 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1870 1871 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject); 1872 1873 /* get device extension */ 1874 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1875 1876 /* get bus device extension */ 1877 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1878 1879 if (!BusDeviceExtension) 1880 { 1881 /* not a bus device */ 1882 return STATUS_INVALID_PARAMETER; 1883 } 1884 1885 /* store result */ 1886 *ChildDevice = (BusDeviceExtension->Common.IsBus == FALSE); 1887 1888 return STATUS_SUCCESS; 1889 } 1890 1891 /* 1892 @implemented 1893 */ 1894 KSDDKAPI 1895 NTSTATUS 1896 NTAPI 1897 KsServiceBusEnumCreateRequest( 1898 IN PDEVICE_OBJECT DeviceObject, 1899 IN OUT PIRP Irp) 1900 { 1901 PLIST_ENTRY Entry; 1902 PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* fix gcc */ 1903 PIO_STACK_LOCATION IoStack; 1904 BOOLEAN ItemExists = FALSE; 1905 PDEV_EXTENSION DeviceExtension; 1906 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 1907 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; 1908 NTSTATUS Status; 1909 LARGE_INTEGER Time; 1910 1911 /* FIXME: locks */ 1912 1913 /* get device extension */ 1914 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 1915 1916 /* get bus device extension */ 1917 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 1918 1919 /* get current irp stack location */ 1920 IoStack = IoGetCurrentIrpStackLocation(Irp); 1921 1922 /* sanity checks */ 1923 ASSERT(IoStack->FileObject); 1924 if (IoStack->FileObject->FileName.Buffer == NULL) 1925 { 1926 DPRINT("KsServiceBusEnumCreateRequest PNP Hack\n"); 1927 Irp->IoStatus.Status = STATUS_SUCCESS; 1928 return STATUS_SUCCESS; 1929 } 1930 1931 ASSERT(IoStack->FileObject->FileName.Buffer); 1932 1933 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp, &IoStack->FileObject->FileName); 1934 1935 /* scan list and check if it is already present */ 1936 Entry = BusDeviceExtension->Common.Entry.Flink; 1937 1938 while(Entry != &BusDeviceExtension->Common.Entry) 1939 { 1940 /* get real offset */ 1941 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 1942 1943 /* check if name matches */ 1944 if (!_wcsicmp(DeviceEntry->DeviceName, IoStack->FileObject->FileName.Buffer + 1)) 1945 { 1946 /* item already exists */ 1947 ItemExists = TRUE; 1948 break; 1949 } 1950 1951 /* move to next entry */ 1952 Entry = Entry->Flink; 1953 } 1954 1955 if (!ItemExists) 1956 { 1957 /* interface not registered */ 1958 DPRINT1("Interface %wZ not registered\n", &IoStack->FileObject->FileName); 1959 return STATUS_OBJECT_NAME_NOT_FOUND; 1960 } 1961 1962 /* is there a pdo yet */ 1963 if (DeviceEntry->PDO) 1964 { 1965 if (DeviceEntry->DeviceState == Started) 1966 { 1967 /* issue reparse */ 1968 Status = KspDoReparseForIrp(Irp, DeviceEntry); 1969 DPRINT("REPARSE Irp %p '%wZ'\n", Irp, &IoStack->FileObject->FileName); 1970 1971 Irp->IoStatus.Status = Status; 1972 Irp->IoStatus.Information = IO_REPARSE; 1973 return Status; 1974 } 1975 1976 /* delay processing until pnp is finished with enumeration */ 1977 IoMarkIrpPending(Irp); 1978 1979 /* insert into irp pending list */ 1980 InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); 1981 1982 Time.QuadPart = Int32x32To64(1500, -10000); 1983 DbgPrint("PENDING Irp %p %wZ DeviceState %d\n", Irp, &IoStack->FileObject->FileName, DeviceEntry->DeviceState); 1984 1985 1986 /* set timer */ 1987 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 1988 1989 /* done for now */ 1990 return STATUS_PENDING; 1991 1992 } 1993 else 1994 { 1995 /* time to create PDO */ 1996 Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 1997 1998 if (!NT_SUCCESS(Status)) 1999 { 2000 /* failed to create PDO */ 2001 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status); 2002 return Status; 2003 } 2004 DPRINT("PENDING CREATE Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); 2005 2006 /* delay processing until pnp is finished with enumeration */ 2007 IoMarkIrpPending(Irp); 2008 2009 /* insert into irp pending list */ 2010 InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); 2011 2012 /* invalidate device relations */ 2013 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 2014 2015 /* done for now */ 2016 return STATUS_PENDING; 2017 } 2018 } 2019 2020 /* 2021 @implemented 2022 */ 2023 KSDDKAPI 2024 NTSTATUS 2025 NTAPI 2026 KsServiceBusEnumPnpRequest( 2027 IN PDEVICE_OBJECT DeviceObject, 2028 IN OUT PIRP Irp) 2029 { 2030 PDEV_EXTENSION DeviceExtension; 2031 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 2032 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; 2033 PIO_STACK_LOCATION IoStack; 2034 NTSTATUS Status; 2035 LARGE_INTEGER Time; 2036 PDEVICE_RELATIONS DeviceRelation; 2037 PBUS_DEVICE_ENTRY DeviceEntry; 2038 2039 /* get device extension */ 2040 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 2041 2042 /* get bus device extension */ 2043 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 2044 2045 /* get current irp stack location */ 2046 IoStack = IoGetCurrentIrpStackLocation(Irp); 2047 2048 if (BusDeviceExtension->Common.IsBus) 2049 { 2050 if (IoStack->MinorFunction == IRP_MN_START_DEVICE) 2051 { 2052 /* no op for bus driver */ 2053 Status = STATUS_SUCCESS; 2054 } 2055 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS) 2056 { 2057 /* handle bus device relations */ 2058 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == BusRelations); 2059 2060 Status = KspQueryBusRelations(BusDeviceExtension, Irp); 2061 } 2062 else 2063 { 2064 /* get default status */ 2065 Status = Irp->IoStatus.Status; 2066 } 2067 } 2068 else 2069 { 2070 /* get child device extension */ 2071 ChildDeviceExtension = DeviceExtension->Ext; 2072 2073 /* get bus device extension */ 2074 BusDeviceExtension = ChildDeviceExtension->BusDeviceExtension; 2075 2076 if (IoStack->MinorFunction == IRP_MN_QUERY_ID) 2077 { 2078 /* query id */ 2079 Status = KspQueryId(ChildDeviceExtension, Irp); 2080 } 2081 else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE) 2082 { 2083 ASSERT(ChildDeviceExtension->DeviceEntry->DeviceState != Started || ChildDeviceExtension->DeviceEntry->DeviceState == NotStarted); 2084 ASSERT(ChildDeviceExtension->DeviceEntry->PDO == DeviceObject); 2085 2086 /* backup device entry */ 2087 DeviceEntry = ChildDeviceExtension->DeviceEntry; 2088 2089 /* free device extension */ 2090 FreeItem(ChildDeviceExtension); 2091 2092 /* clear PDO reference */ 2093 DeviceEntry->PDO = NULL; 2094 2095 /* delete the device */ 2096 IoDeleteDevice(DeviceObject); 2097 2098 if (DeviceEntry->PDODeviceName) 2099 { 2100 /* delete pdo device name */ 2101 FreeItem(DeviceEntry->PDODeviceName); 2102 2103 /* set to null */ 2104 DeviceEntry->PDODeviceName = NULL; 2105 } 2106 2107 /* set state no notstarted */ 2108 DeviceEntry->DeviceState = NotStarted; 2109 2110 /* complete pending irps */ 2111 KspCompletePendingIrps(DeviceEntry, STATUS_DEVICE_REMOVED); 2112 2113 /* done */ 2114 Status = STATUS_SUCCESS; 2115 } 2116 else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION) 2117 { 2118 /* query bus information */ 2119 Status = KspQueryBusInformation(ChildDeviceExtension, Irp); 2120 } 2121 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES) 2122 { 2123 /* no op */ 2124 Status = STATUS_SUCCESS; 2125 } 2126 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS) 2127 { 2128 /* no op */ 2129 Status = STATUS_SUCCESS; 2130 } 2131 else if (IoStack->MinorFunction == IRP_MN_START_DEVICE) 2132 { 2133 /* start bus */ 2134 Status = KspStartBusDevice(DeviceObject, ChildDeviceExtension, Irp); 2135 if (NT_SUCCESS(Status)) 2136 { 2137 /* complete pending irps*/ 2138 KspCompletePendingIrps(ChildDeviceExtension->DeviceEntry, STATUS_REPARSE); 2139 } 2140 2141 /* set time out */ 2142 Time.QuadPart = Int32x32To64(1500, -10000); 2143 2144 /* sanity check */ 2145 ASSERT(BusDeviceExtension); 2146 2147 /* set timer */ 2148 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 2149 } 2150 else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES) 2151 { 2152 /* query capabilities */ 2153 Status = KspQueryBusDeviceCapabilities(ChildDeviceExtension, Irp); 2154 } 2155 else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE) 2156 { 2157 /* query pnp state */ 2158 Status = KspQueryBusDevicePnpState(ChildDeviceExtension, Irp); 2159 } 2160 else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE) 2161 { 2162 /* query interface */ 2163 Status = KspQueryBusDeviceInterface(ChildDeviceExtension, Irp); 2164 } 2165 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS && IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) 2166 { 2167 /* handle target device relations */ 2168 ASSERT(Irp->IoStatus.Information == 0); 2169 2170 /* allocate device relation */ 2171 DeviceRelation = AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); 2172 if (DeviceRelation) 2173 { 2174 DeviceRelation->Count = 1; 2175 DeviceRelation->Objects[0] = DeviceObject; 2176 2177 /* reference self */ 2178 ObReferenceObject(DeviceObject); 2179 2180 /* store result */ 2181 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; 2182 2183 /* done */ 2184 Status = STATUS_SUCCESS; 2185 } 2186 else 2187 { 2188 /* no memory */ 2189 Status = STATUS_INSUFFICIENT_RESOURCES; 2190 } 2191 } 2192 else 2193 { 2194 /* get default status */ 2195 Status = Irp->IoStatus.Status; 2196 } 2197 } 2198 2199 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject, BusDeviceExtension->Common.IsBus, IoStack->MinorFunction, Status); 2200 Irp->IoStatus.Status = Status; 2201 return Status; 2202 } 2203 2204 /* 2205 @implemented 2206 */ 2207 KSDDKAPI 2208 NTSTATUS 2209 NTAPI 2210 KsRemoveBusEnumInterface( 2211 IN PIRP Irp) 2212 { 2213 KPROCESSOR_MODE Mode; 2214 LUID luid; 2215 BUS_INSTALL_ENUM_CONTEXT Ctx; 2216 PDEV_EXTENSION DeviceExtension; 2217 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 2218 PIO_STACK_LOCATION IoStack; 2219 2220 DPRINT("KsRemoveBusEnumInterface\n"); 2221 2222 /* get io stack location */ 2223 IoStack = IoGetCurrentIrpStackLocation(Irp); 2224 2225 /* get device extension */ 2226 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 2227 2228 /* get bus device extension */ 2229 BusDeviceExtension = DeviceExtension->Ext->BusDeviceExtension; 2230 2231 /* get previous mode */ 2232 Mode = ExGetPreviousMode(); 2233 2234 /* convert to luid */ 2235 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); 2236 2237 /* perform access check */ 2238 if (!SeSinglePrivilegeCheck(luid, Mode)) 2239 { 2240 /* insufficient privileges */ 2241 return STATUS_PRIVILEGE_NOT_HELD; 2242 } 2243 2244 /* initialize context */ 2245 KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE); 2246 Ctx.Irp = Irp; 2247 Ctx.BusDeviceExtension = BusDeviceExtension; 2248 ExInitializeWorkItem(&Ctx.WorkItem, KspRemoveBusInterface, (PVOID)&Ctx); 2249 2250 /* now queue the work item */ 2251 ExQueueWorkItem(&Ctx.WorkItem, DelayedWorkQueue); 2252 2253 /* wait for completion */ 2254 KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL); 2255 2256 /* return result */ 2257 return Ctx.Status; 2258 } 2259