Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenswenum.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/ksfilter/ks/swenum.c 00005 * PURPOSE: KS Software BUS functions 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 00010 #include "priv.h" 00011 00012 LONG KsDeviceCount = 0; 00013 00014 typedef NTSTATUS (NTAPI *PKSP_BUS_ENUM_CALLBACK)( 00015 IN PHANDLE hKey, 00016 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00017 IN PBUS_DEVICE_ENTRY DummyEntry, 00018 IN LPWSTR RootName, 00019 IN LPWSTR DirectoryName); 00020 00021 NTSTATUS 00022 KspCreatePDO( 00023 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00024 IN PBUS_DEVICE_ENTRY DeviceEntry, 00025 OUT PDEVICE_OBJECT * OutDeviceObject) 00026 { 00027 PDEVICE_OBJECT DeviceObject; 00028 WCHAR Buffer[50]; 00029 ULONG CurDeviceId; 00030 UNICODE_STRING DeviceName; 00031 NTSTATUS Status; 00032 PCOMMON_DEVICE_EXTENSION DeviceExtension; 00033 00034 /* increment device count */ 00035 CurDeviceId = InterlockedIncrement(&KsDeviceCount); 00036 00037 /* generate new device id */ 00038 swprintf(Buffer, L"\\Device\\KSENUM%08x", CurDeviceId); 00039 00040 /* initialize new device name */ 00041 RtlInitUnicodeString(&DeviceName, Buffer); 00042 00043 /* create new device object */ 00044 Status = IoCreateDevice(BusDeviceExtension->BusDeviceObject->DriverObject, sizeof(PVOID), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); 00045 00046 /* check for success */ 00047 if (!NT_SUCCESS(Status)) 00048 { 00049 /* failed to create pdo */ 00050 return Status; 00051 } 00052 00053 /* now allocate device extension */ 00054 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)AllocateItem(NonPagedPool, sizeof(COMMON_DEVICE_EXTENSION)); 00055 if (!DeviceExtension) 00056 { 00057 /* no memory */ 00058 IoDeleteDevice(DeviceObject); 00059 return STATUS_INSUFFICIENT_RESOURCES; 00060 } 00061 00062 /* store device extension */ 00063 *((PVOID*)DeviceObject->DeviceExtension) = DeviceExtension; 00064 00065 /* initialize device extension */ 00066 DeviceExtension->IsBus = FALSE; 00067 DeviceExtension->DeviceObject = DeviceObject; 00068 DeviceExtension->DeviceEntry = DeviceEntry; 00069 DeviceExtension->BusDeviceExtension = BusDeviceExtension; 00070 00071 /* TODO: update last creation time in bus device extension */ 00072 00073 /* setup flags */ 00074 DeviceObject->Flags |= DO_POWER_PAGABLE; 00075 DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; 00076 /* TODO: fire time when expired */ 00077 00078 *OutDeviceObject = DeviceObject; 00079 00080 return STATUS_SUCCESS; 00081 } 00082 00083 NTSTATUS 00084 KspRegisterDeviceAssociation( 00085 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00086 IN PBUS_DEVICE_ENTRY DeviceEntry, 00087 IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry) 00088 { 00089 NTSTATUS Status; 00090 UNICODE_STRING ReferenceString; 00091 00092 /* initialize reference string */ 00093 RtlInitUnicodeString(&ReferenceString, DeviceEntry->DeviceName); 00094 00095 /* register device interface */ 00096 Status = IoRegisterDeviceInterface(BusDeviceExtension->PhysicalDeviceObject, &BusInstanceEntry->InterfaceGuid, &ReferenceString, &BusInstanceEntry->SymbolicLink); 00097 00098 /* check for success */ 00099 if (!NT_SUCCESS(Status)) 00100 { 00101 /* failed */ 00102 return Status; 00103 } 00104 00105 /* now enable the interface */ 00106 Status = IoSetDeviceInterfaceState(&BusInstanceEntry->SymbolicLink, TRUE); 00107 00108 /* check for success */ 00109 if (!NT_SUCCESS(Status)) 00110 { 00111 /* failed, free memory */ 00112 FreeItem(BusInstanceEntry->SymbolicLink.Buffer); 00113 return Status; 00114 } 00115 00116 DPRINT1("Registered DeviceInterface %wZ\n", &BusInstanceEntry->SymbolicLink); 00117 00118 00119 /* done */ 00120 return Status; 00121 } 00122 00123 VOID 00124 KspRemoveDeviceAssociations( 00125 IN PBUS_DEVICE_ENTRY DeviceEntry) 00126 { 00127 PLIST_ENTRY Entry; 00128 PBUS_INSTANCE_ENTRY CurEntry; 00129 00130 /* remove all entries */ 00131 Entry = DeviceEntry->DeviceInterfaceList.Flink; 00132 00133 while(Entry != &DeviceEntry->DeviceInterfaceList) 00134 { 00135 /* get offset */ 00136 CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); 00137 00138 /* sanity check */ 00139 ASSERT(CurEntry->SymbolicLink.Buffer); 00140 00141 /* de-register interface */ 00142 IoSetDeviceInterfaceState(&CurEntry->SymbolicLink, FALSE); 00143 00144 /* free symbolic link buffer */ 00145 FreeItem(CurEntry->SymbolicLink.Buffer); 00146 00147 /* remove entry from list */ 00148 RemoveEntryList(Entry); 00149 00150 /* move to next entry */ 00151 Entry = Entry->Flink; 00152 00153 /* free entry */ 00154 FreeItem(CurEntry); 00155 } 00156 } 00157 00158 NTSTATUS 00159 KspEnumerateBusRegistryKeys( 00160 IN HANDLE hKey, 00161 IN LPWSTR ReferenceString, 00162 IN PKSP_BUS_ENUM_CALLBACK Callback, 00163 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00164 IN PBUS_DEVICE_ENTRY DeviceEntry) 00165 { 00166 UNICODE_STRING String; 00167 OBJECT_ATTRIBUTES ObjectAttributes; 00168 HANDLE hNewKey; 00169 NTSTATUS Status; 00170 ULONG ResultLength, Index, KeyInfoLength; 00171 KEY_FULL_INFORMATION KeyInformation; 00172 PKEY_BASIC_INFORMATION KeyInfo; 00173 00174 /* initialize key name */ 00175 RtlInitUnicodeString(&String, ReferenceString); 00176 00177 /* initialize object attributes */ 00178 InitializeObjectAttributes(&ObjectAttributes, &String, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); 00179 00180 /* open new key */ 00181 Status = ZwOpenKey(&hNewKey, GENERIC_READ, &ObjectAttributes); 00182 00183 /* check for success */ 00184 if (!NT_SUCCESS(Status)) 00185 { 00186 /* failed to open key */ 00187 00188 return Status; 00189 } 00190 00191 /* query key stats */ 00192 Status = ZwQueryKey(hNewKey, KeyFullInformation, &KeyInformation, sizeof(KeyInformation), &ResultLength); 00193 00194 if (!NT_SUCCESS(Status)) 00195 { 00196 /* close key */ 00197 ZwClose(hNewKey); 00198 00199 /* done */ 00200 return Status; 00201 } 00202 00203 /* calculate key info length */ 00204 KeyInfoLength = KeyInformation.MaxNameLen + sizeof(KEY_BASIC_INFORMATION) + 1 * sizeof(WCHAR); 00205 00206 /* allocate buffer */ 00207 KeyInfo = (PKEY_BASIC_INFORMATION)AllocateItem(NonPagedPool, KeyInfoLength); 00208 if (!KeyInfo) 00209 { 00210 00211 /* no memory */ 00212 ZwClose(hNewKey); 00213 00214 /* done */ 00215 return STATUS_INSUFFICIENT_RESOURCES; 00216 } 00217 00218 /* enumerate all keys */ 00219 for(Index = 0; Index < KeyInformation.SubKeys; Index++) 00220 { 00221 00222 /* query sub key */ 00223 Status = ZwEnumerateKey(hNewKey, Index, KeyBasicInformation, (PVOID)KeyInfo, KeyInfoLength, &ResultLength); 00224 00225 /* check for success */ 00226 if (NT_SUCCESS(Status)) 00227 { 00228 /* perform callback */ 00229 Status = Callback(hNewKey, BusDeviceExtension, DeviceEntry, ReferenceString, KeyInfo->Name); 00230 00231 /* should enumeration stop */ 00232 if (!NT_SUCCESS(Status)) 00233 break; 00234 } 00235 } 00236 00237 /* free info buffer */ 00238 FreeItem(KeyInfo); 00239 00240 /* close key */ 00241 ZwClose(hNewKey); 00242 00243 /* done */ 00244 return Status; 00245 } 00246 00247 NTSTATUS 00248 NTAPI 00249 KspCreateDeviceAssociation( 00250 IN PHANDLE hKey, 00251 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00252 IN PBUS_DEVICE_ENTRY DeviceEntry, 00253 IN LPWSTR ReferenceString, 00254 IN LPWSTR InterfaceString) 00255 { 00256 GUID DeviceGuid; 00257 NTSTATUS Status; 00258 PLIST_ENTRY Entry; 00259 PBUS_INSTANCE_ENTRY CurEntry; 00260 UNICODE_STRING DeviceName; 00261 00262 /* initialize interface string */ 00263 RtlInitUnicodeString(&DeviceName, InterfaceString); 00264 00265 /* first convert device name to guid */ 00266 RtlGUIDFromString(&DeviceName, &DeviceGuid); 00267 00268 /* check if the device is already present */ 00269 Entry = DeviceEntry->DeviceInterfaceList.Flink; 00270 00271 while(Entry != &DeviceEntry->DeviceInterfaceList) 00272 { 00273 /* get offset */ 00274 CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); 00275 00276 if (IsEqualGUIDAligned(&CurEntry->InterfaceGuid, &DeviceGuid)) 00277 { 00278 /* entry already exists */ 00279 return STATUS_SUCCESS; 00280 } 00281 00282 /* move to next entry */ 00283 Entry = Entry->Flink; 00284 } 00285 00286 /* time to allocate new entry */ 00287 CurEntry = (PBUS_INSTANCE_ENTRY)AllocateItem(NonPagedPool, sizeof(BUS_INSTANCE_ENTRY)); 00288 00289 if (!CurEntry) 00290 { 00291 /* no memory */ 00292 return STATUS_INSUFFICIENT_RESOURCES; 00293 } 00294 00295 /* store guid */ 00296 RtlMoveMemory(&CurEntry->InterfaceGuid, &DeviceGuid, sizeof(GUID)); 00297 00298 /* now register the association */ 00299 Status = KspRegisterDeviceAssociation(BusDeviceExtension, DeviceEntry, CurEntry); 00300 00301 /* check for success */ 00302 if (NT_SUCCESS(Status)) 00303 { 00304 /* store entry */ 00305 InsertTailList(&DeviceEntry->DeviceInterfaceList, &CurEntry->Entry); 00306 } 00307 else 00308 { 00309 /* failed to associated device */ 00310 FreeItem(CurEntry); 00311 } 00312 00313 /* done */ 00314 return Status; 00315 } 00316 00317 NTSTATUS 00318 NTAPI 00319 KspCreateDeviceReference( 00320 IN PHANDLE hKey, 00321 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00322 IN PBUS_DEVICE_ENTRY DummyEntry, 00323 IN LPWSTR DeviceCategory, 00324 IN LPWSTR ReferenceString) 00325 { 00326 LPWSTR DeviceName; 00327 ULONG Length; 00328 PLIST_ENTRY Entry; 00329 PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */ 00330 BOOLEAN ItemExists = FALSE; 00331 UNICODE_STRING String; 00332 NTSTATUS Status; 00333 KIRQL OldLevel; 00334 00335 /* first construct device name & reference guid */ 00336 Length = wcslen(DeviceCategory) + wcslen(ReferenceString); 00337 00338 /* append '&' and null byte */ 00339 Length += 2; 00340 00341 /* allocate device name */ 00342 DeviceName = AllocateItem(NonPagedPool, Length * sizeof(WCHAR)); 00343 00344 if (!DeviceName) 00345 { 00346 /* not enough memory */ 00347 return STATUS_INSUFFICIENT_RESOURCES; 00348 } 00349 00350 /* construct device name */ 00351 swprintf(DeviceName, L"%s&%s", DeviceCategory, ReferenceString); 00352 00353 /* scan list and check if it is already present */ 00354 Entry = BusDeviceExtension->Common.Entry.Flink; 00355 00356 while(Entry != &BusDeviceExtension->Common.Entry) 00357 { 00358 /* get real offset */ 00359 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 00360 00361 /* check if name matches */ 00362 if (!wcsicmp(DeviceEntry->DeviceName, DeviceName)) 00363 { 00364 /* item already exists */ 00365 ItemExists = TRUE; 00366 break; 00367 } 00368 00369 /* move to next entry */ 00370 Entry = Entry->Flink; 00371 } 00372 00373 if (!ItemExists) 00374 { 00375 /* allocate new device entry */ 00376 DeviceEntry = AllocateItem(NonPagedPool, sizeof(BUS_DEVICE_ENTRY)); 00377 if (!DeviceEntry) 00378 { 00379 /* no memory */ 00380 FreeItem(DeviceName); 00381 return STATUS_INSUFFICIENT_RESOURCES; 00382 } 00383 00384 /* initialize device entry */ 00385 InitializeListHead(&DeviceEntry->DeviceInterfaceList); 00386 InitializeListHead(&DeviceEntry->IrpPendingList); 00387 00388 /* copy device guid */ 00389 RtlInitUnicodeString(&String, ReferenceString); 00390 RtlGUIDFromString(&String, &DeviceEntry->DeviceGuid); 00391 00392 /* copy device names */ 00393 DeviceEntry->DeviceName = DeviceName; 00394 DeviceEntry->Instance = (DeviceName + wcslen(DeviceCategory) + 1); 00395 00396 /* copy name */ 00397 DeviceEntry->BusId = AllocateItem(NonPagedPool, (wcslen(DeviceCategory) + 1) * sizeof(WCHAR)); 00398 if (!DeviceEntry->BusId) 00399 { 00400 /* no memory */ 00401 FreeItem(DeviceName); 00402 FreeItem(DeviceEntry); 00403 return STATUS_INSUFFICIENT_RESOURCES; 00404 } 00405 wcscpy(DeviceEntry->BusId, DeviceCategory); 00406 } 00407 00408 /* now enumerate the devices */ 00409 Status = KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceAssociation, BusDeviceExtension, DeviceEntry); 00410 00411 /* check if list is empty */ 00412 if (IsListEmpty(&DeviceEntry->DeviceInterfaceList)) 00413 { 00414 /* invalid device settings */ 00415 FreeItem(DeviceEntry->BusId); 00416 FreeItem(DeviceEntry->DeviceName); 00417 FreeItem(DeviceEntry); 00418 00419 ASSERT(ItemExists == FALSE); 00420 00421 return STATUS_INVALID_DEVICE_STATE; 00422 } 00423 00424 /* check if enumeration failed */ 00425 if (!NT_SUCCESS(Status)) 00426 { 00427 /* failed */ 00428 KspRemoveDeviceAssociations(DeviceEntry); 00429 FreeItem(DeviceEntry->BusId); 00430 FreeItem(DeviceEntry->DeviceName); 00431 FreeItem(DeviceEntry); 00432 00433 ASSERT(ItemExists == FALSE); 00434 00435 /* done */ 00436 return Status; 00437 } 00438 00439 if (!ItemExists) 00440 { 00441 /* acquire lock */ 00442 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 00443 00444 /* successfully initialized entry */ 00445 InsertTailList(&BusDeviceExtension->Common.Entry, &DeviceEntry->Entry); 00446 00447 /* release lock */ 00448 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 00449 } 00450 00451 /* done */ 00452 return Status; 00453 } 00454 00455 NTSTATUS 00456 NTAPI 00457 KspCreateDeviceReferenceTrampoline( 00458 IN PHANDLE hKey, 00459 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00460 IN PBUS_DEVICE_ENTRY DummyEntry, 00461 IN LPWSTR DeviceCategory, 00462 IN LPWSTR ReferenceString) 00463 { 00464 return KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceReference, BusDeviceExtension, DummyEntry); 00465 } 00466 00467 00468 NTSTATUS 00469 KspOpenBusRegistryKey( 00470 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00471 OUT PHANDLE hKey) 00472 { 00473 OBJECT_ATTRIBUTES ObjectAttributes; 00474 00475 /* initialize object attributes */ 00476 InitializeObjectAttributes(&ObjectAttributes, &BusDeviceExtension->ServicePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 00477 00478 return ZwCreateKey(hKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 00479 } 00480 00481 NTSTATUS 00482 KspScanBus( 00483 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension) 00484 { 00485 HANDLE hKey; 00486 NTSTATUS Status; 00487 00488 /* first open key */ 00489 Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); 00490 00491 /* check for success */ 00492 if (!NT_SUCCESS(Status)) 00493 { 00494 /* no success */ 00495 00496 return Status; 00497 } 00498 00499 /* TODO clear reference marks */ 00500 00501 /* construct device entries */ 00502 Status = KspEnumerateBusRegistryKeys(hKey, NULL, KspCreateDeviceReferenceTrampoline, BusDeviceExtension, NULL); 00503 00504 /* TODO: delete unreferenced devices */ 00505 00506 /* close handle */ 00507 ZwClose(hKey); 00508 00509 /* done */ 00510 return Status; 00511 } 00512 00513 00514 NTSTATUS 00515 NTAPI 00516 KspBusQueryReferenceString( 00517 IN PVOID Context, 00518 IN OUT PWCHAR *String) 00519 { 00520 LPWSTR Name; 00521 ULONG Length; 00522 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context; 00523 00524 /* sanity checks */ 00525 ASSERT(BusDeviceExtension); 00526 ASSERT(BusDeviceExtension->BusIdentifier); 00527 00528 /* calculate length */ 00529 Length = wcslen(BusDeviceExtension->BusIdentifier) + 1; 00530 00531 /* allocate buffer */ 00532 Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); 00533 00534 if (!Name) 00535 { 00536 /* failed to allocate buffer */ 00537 return STATUS_INSUFFICIENT_RESOURCES; 00538 } 00539 00540 /* copy buffer */ 00541 wcscpy(Name, BusDeviceExtension->BusIdentifier); 00542 00543 /* store result */ 00544 *String = Name; 00545 00546 /* done */ 00547 return STATUS_SUCCESS; 00548 } 00549 00550 VOID 00551 NTAPI 00552 KspBusDeviceReference( 00553 IN PVOID Context) 00554 { 00555 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 00556 00557 /* reference count */ 00558 InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); 00559 } 00560 00561 VOID 00562 NTAPI 00563 KspBusDeviceDereference( 00564 IN PVOID Context) 00565 { 00566 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 00567 00568 /* reference count */ 00569 InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); 00570 } 00571 00572 VOID 00573 NTAPI 00574 KspBusReferenceDeviceObject( 00575 IN PVOID Context) 00576 { 00577 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 00578 00579 /* reference count */ 00580 InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); 00581 } 00582 00583 VOID 00584 NTAPI 00585 KspBusDereferenceDeviceObject( 00586 IN PVOID Context) 00587 { 00588 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; 00589 00590 /* reference count */ 00591 InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); 00592 } 00593 00594 NTSTATUS 00595 KspQueryBusDeviceInterface( 00596 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 00597 IN PIRP Irp) 00598 { 00599 PBUS_INTERFACE_SWENUM Interface; 00600 PIO_STACK_LOCATION IoStack; 00601 00602 /* get current irp stack location */ 00603 IoStack = IoGetCurrentIrpStackLocation(Irp); 00604 00605 /* sanity checks */ 00606 ASSERT(IoStack->Parameters.QueryInterface.Size == sizeof(BUS_INTERFACE_SWENUM)); 00607 ASSERT(IoStack->Parameters.QueryInterface.Interface); 00608 00609 /* fill in interface */ 00610 Interface = (PBUS_INTERFACE_SWENUM)IoStack->Parameters.QueryInterface.Interface; 00611 Interface->Interface.Size = sizeof(BUS_INTERFACE_SWENUM); 00612 Interface->Interface.Version = BUS_INTERFACE_SWENUM_VERSION; 00613 Interface->Interface.Context = ChildDeviceExtension; 00614 Interface->Interface.InterfaceReference = KspBusDeviceReference; 00615 Interface->Interface.InterfaceDereference = KspBusDeviceDereference; 00616 Interface->ReferenceDeviceObject = KspBusReferenceDeviceObject; 00617 Interface->DereferenceDeviceObject = KspBusDereferenceDeviceObject; 00618 Interface->QueryReferenceString = KspBusQueryReferenceString; 00619 00620 return STATUS_SUCCESS; 00621 } 00622 00623 NTSTATUS 00624 KspEnableBusDeviceInterface( 00625 PBUS_DEVICE_ENTRY DeviceEntry, 00626 BOOLEAN bEnable) 00627 { 00628 PLIST_ENTRY Entry; 00629 PBUS_INSTANCE_ENTRY InstanceEntry; 00630 NTSTATUS Status = STATUS_SUCCESS; 00631 00632 /* enable now all interfaces */ 00633 Entry = DeviceEntry->DeviceInterfaceList.Flink; 00634 00635 while(Entry != &DeviceEntry->DeviceInterfaceList) 00636 { 00637 /* get bus instance entry */ 00638 InstanceEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); 00639 DPRINT1("Enabling %u %wZ Irql %u\n", bEnable, &InstanceEntry->SymbolicLink, KeGetCurrentIrql()); 00640 00641 /* set interface state */ 00642 Status = IoSetDeviceInterfaceState(&InstanceEntry->SymbolicLink, bEnable); 00643 00644 if (!NT_SUCCESS(Status)) 00645 { 00646 /* failed to set interface */ 00647 break; 00648 } 00649 00650 /* move to next entry */ 00651 Entry = Entry->Flink; 00652 } 00653 00654 /* done */ 00655 return Status; 00656 } 00657 00658 NTSTATUS 00659 KspDoReparseForIrp( 00660 PIRP Irp, 00661 PBUS_DEVICE_ENTRY DeviceEntry) 00662 { 00663 ULONG Length; 00664 LPWSTR Buffer; 00665 PIO_STACK_LOCATION IoStack; 00666 00667 /* get stack location */ 00668 IoStack = IoGetCurrentIrpStackLocation(Irp); 00669 00670 /* sanity checks */ 00671 ASSERT(DeviceEntry->PDODeviceName); 00672 ASSERT(DeviceEntry->Instance); 00673 ASSERT(IoStack->FileObject); 00674 ASSERT(IoStack->FileObject->FileName.Buffer); 00675 00676 /* calculate length */ 00677 Length = wcslen(DeviceEntry->PDODeviceName); 00678 Length += wcslen(DeviceEntry->Instance); 00679 00680 /* zero byte and '\\' */ 00681 Length += 2; 00682 00683 /* allocate buffer */ 00684 Buffer = AllocateItem(NonPagedPool, Length * sizeof(WCHAR)); 00685 if (!Buffer) 00686 { 00687 /* no resources */ 00688 return STATUS_INSUFFICIENT_RESOURCES; 00689 } 00690 00691 /* construct buffer */ 00692 swprintf(Buffer, L"%s\\%s", DeviceEntry->PDODeviceName, DeviceEntry->Instance); 00693 00694 ExFreePool(IoStack->FileObject->FileName.Buffer); 00695 00696 /* store new file name */ 00697 RtlInitUnicodeString(&IoStack->FileObject->FileName, Buffer); 00698 00699 /* done */ 00700 return STATUS_REPARSE; 00701 } 00702 00703 VOID 00704 KspCompletePendingIrps( 00705 IN PBUS_DEVICE_ENTRY DeviceEntry, 00706 IN OUT NTSTATUS ResultCode) 00707 { 00708 PLIST_ENTRY Entry; 00709 PIRP Irp; 00710 NTSTATUS Status; 00711 00712 /* go through list */ 00713 while(!IsListEmpty(&DeviceEntry->IrpPendingList)) 00714 { 00715 /* get first entry */ 00716 Entry = RemoveHeadList(&DeviceEntry->IrpPendingList); 00717 00718 /* get irp */ 00719 Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); 00720 00721 if (ResultCode == STATUS_REPARSE) 00722 { 00723 /* construct reparse information */ 00724 Status = KspDoReparseForIrp(Irp, DeviceEntry); 00725 } 00726 else 00727 { 00728 /* use default code */ 00729 Status = ResultCode; 00730 } 00731 00732 /* store result code */ 00733 Irp->IoStatus.Status = Status; 00734 00735 DPRINT1("Completing IRP %p Status %x\n", Irp, Status); 00736 00737 /* complete the request */ 00738 CompleteRequest(Irp, IO_NO_INCREMENT); 00739 } 00740 00741 } 00742 00743 00744 00745 NTSTATUS 00746 KspStartBusDevice( 00747 IN PDEVICE_OBJECT DeviceObject, 00748 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 00749 IN PIRP Irp) 00750 { 00751 WCHAR PDOName[256]; 00752 NTSTATUS Status; 00753 ULONG ResultLength; 00754 LPWSTR Name; 00755 PBUS_DEVICE_ENTRY DeviceEntry; 00756 00757 /* FIXME handle pending remove */ 00758 00759 /* get full device name */ 00760 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyPhysicalDeviceObjectName, sizeof(PDOName), (PVOID)PDOName, &ResultLength); 00761 00762 if (!NT_SUCCESS(Status)) 00763 { 00764 /* failed to get device name */ 00765 return Status; 00766 } 00767 00768 /* allocate device name buffer */ 00769 Name = AllocateItem(NonPagedPool, (ResultLength + 1) * sizeof(WCHAR)); 00770 if (!Name) 00771 { 00772 /* no memory */ 00773 return STATUS_INSUFFICIENT_RESOURCES; 00774 } 00775 00776 /* copy name */ 00777 wcscpy(Name, PDOName); 00778 00779 /* TODO: time stamp creation time */ 00780 00781 /* get device entry */ 00782 DeviceEntry = (PBUS_DEVICE_ENTRY)ChildDeviceExtension->DeviceEntry; 00783 00784 /* sanity check */ 00785 ASSERT(DeviceEntry); 00786 00787 /* store device name */ 00788 DeviceEntry->PDODeviceName = Name; 00789 00790 /* mark device as started */ 00791 DeviceEntry->DeviceState = Started; 00792 00793 /* reference start time */ 00794 KeQuerySystemTime(&DeviceEntry->TimeCreated); 00795 00796 DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name, DeviceEntry->DeviceName, DeviceEntry->Instance); 00797 00798 /* enable device classes */ 00799 //KspEnableBusDeviceInterface(DeviceEntry, TRUE); 00800 00801 /* done */ 00802 return STATUS_SUCCESS; 00803 } 00804 00805 NTSTATUS 00806 KspQueryBusDeviceCapabilities( 00807 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 00808 IN PIRP Irp) 00809 { 00810 PDEVICE_CAPABILITIES Capabilities; 00811 PIO_STACK_LOCATION IoStack; 00812 00813 /* get stack location */ 00814 IoStack = IoGetCurrentIrpStackLocation(Irp); 00815 00816 /* get capabilities */ 00817 Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; 00818 00819 RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES)); 00820 00821 /* setup capabilities */ 00822 Capabilities->UniqueID = TRUE; 00823 Capabilities->SilentInstall = TRUE; 00824 Capabilities->SurpriseRemovalOK = TRUE; 00825 Capabilities->Address = 0; 00826 Capabilities->UINumber = 0; 00827 Capabilities->SystemWake = PowerSystemWorking; /* FIXME common device extension */ 00828 Capabilities->DeviceWake = PowerDeviceD0; 00829 00830 /* done */ 00831 return STATUS_SUCCESS; 00832 } 00833 00834 NTSTATUS 00835 KspQueryBusInformation( 00836 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 00837 IN PIRP Irp) 00838 { 00839 PPNP_BUS_INFORMATION BusInformation; 00840 00841 /* allocate bus information */ 00842 BusInformation = (PPNP_BUS_INFORMATION)AllocateItem(PagedPool, sizeof(PNP_BUS_INFORMATION)); 00843 00844 if (!BusInformation) 00845 { 00846 /* no memory */ 00847 return STATUS_INSUFFICIENT_RESOURCES; 00848 } 00849 00850 /* return info */ 00851 BusInformation->BusNumber = 0; 00852 BusInformation->LegacyBusType = InterfaceTypeUndefined; 00853 RtlMoveMemory(&BusInformation->BusTypeGuid, &KSMEDIUMSETID_Standard, sizeof(GUID)); 00854 00855 /* store result */ 00856 Irp->IoStatus.Information = (ULONG_PTR)BusInformation; 00857 00858 /* done */ 00859 return STATUS_SUCCESS; 00860 } 00861 00862 NTSTATUS 00863 KspQueryBusDevicePnpState( 00864 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 00865 IN PIRP Irp) 00866 { 00867 /* set device flags */ 00868 Irp->IoStatus.Information = PNP_DEVICE_DONT_DISPLAY_IN_UI | PNP_DEVICE_NOT_DISABLEABLE; 00869 00870 /* done */ 00871 return STATUS_SUCCESS; 00872 } 00873 00874 NTSTATUS 00875 KspQueryId( 00876 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, 00877 IN PIRP Irp) 00878 { 00879 PIO_STACK_LOCATION IoStack; 00880 PBUS_DEVICE_ENTRY DeviceEntry; 00881 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 00882 LPWSTR Name; 00883 ULONG Length; 00884 00885 /* get current irp stack location */ 00886 IoStack = IoGetCurrentIrpStackLocation(Irp); 00887 00888 if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID) 00889 { 00890 /* get device entry */ 00891 DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; 00892 00893 /* sanity check */ 00894 ASSERT(DeviceEntry); 00895 ASSERT(DeviceEntry->Instance); 00896 00897 /* calculate length */ 00898 Length = wcslen(DeviceEntry->Instance) + 1; 00899 00900 /* allocate buffer */ 00901 Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); 00902 00903 if (!Name) 00904 { 00905 /* failed to allocate buffer */ 00906 return STATUS_INSUFFICIENT_RESOURCES; 00907 } 00908 00909 /* copy buffer */ 00910 wcscpy(Name, DeviceEntry->Instance); 00911 00912 /* store result */ 00913 Irp->IoStatus.Information = (ULONG_PTR)Name; 00914 00915 /* done */ 00916 return STATUS_SUCCESS; 00917 } 00918 else if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID || 00919 IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) 00920 { 00921 /* get device entry */ 00922 DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; 00923 00924 /* get bus device extension */ 00925 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION) ChildDeviceExtension->BusDeviceExtension; 00926 00927 /* sanity check */ 00928 ASSERT(DeviceEntry); 00929 ASSERT(DeviceEntry->BusId); 00930 ASSERT(BusDeviceExtension); 00931 ASSERT(BusDeviceExtension->BusIdentifier); 00932 00933 /* calculate length */ 00934 Length = wcslen(BusDeviceExtension->BusIdentifier); 00935 Length += wcslen(DeviceEntry->BusId); 00936 00937 /* extra length for '\\' and zero byte */ 00938 Length += 2; 00939 00940 /* allocate buffer */ 00941 Name = ExAllocatePool(PagedPool, Length * sizeof(WCHAR)); 00942 if (!Name) 00943 { 00944 /* failed to allocate buffer */ 00945 return STATUS_INSUFFICIENT_RESOURCES; 00946 } 00947 00948 /* construct id */ 00949 swprintf(Name, L"%s\\%s", BusDeviceExtension->BusIdentifier, DeviceEntry->BusId); 00950 00951 /* store result */ 00952 Irp->IoStatus.Information = (ULONG_PTR)Name; 00953 00954 /* done */ 00955 return STATUS_SUCCESS; 00956 } 00957 else 00958 { 00959 /* other ids are not supported */ 00960 //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType); 00961 return Irp->IoStatus.Status; 00962 } 00963 } 00964 00965 NTSTATUS 00966 KspInstallInterface( 00967 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 00968 IN PSWENUM_INSTALL_INTERFACE InstallInterface) 00969 { 00970 ULONG Length, Index; 00971 UNICODE_STRING DeviceString, InterfaceString, ReferenceString; 00972 HANDLE hKey, hDeviceKey, hInterfaceKey, hReferenceKey; 00973 NTSTATUS Status; 00974 OBJECT_ATTRIBUTES ObjectAttributes; 00975 00976 /* sanity check */ 00977 ASSERT(InstallInterface); 00978 00979 /* calculate length */ 00980 Length = wcslen(InstallInterface->ReferenceString); 00981 00982 /* check for invalid characters */ 00983 for(Index = 0; Index < Length; Index++) 00984 { 00985 if (InstallInterface->ReferenceString[Index] <= L' ' || 00986 InstallInterface->ReferenceString[Index] > L'~' || 00987 InstallInterface->ReferenceString[Index] == L',' || 00988 InstallInterface->ReferenceString[Index] == L'\\' || 00989 InstallInterface->ReferenceString[Index] == L'/') 00990 { 00991 /* invalid character */ 00992 return STATUS_INVALID_PARAMETER; 00993 } 00994 } 00995 00996 /* open bus key */ 00997 Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); 00998 if (NT_SUCCESS(Status)) 00999 { 01000 /* convert device guid to string */ 01001 Status = RtlStringFromGUID(&InstallInterface->DeviceId, &DeviceString); 01002 if (NT_SUCCESS(Status)) 01003 { 01004 /* initialize object attributes */ 01005 InitializeObjectAttributes(&ObjectAttributes, &DeviceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); 01006 01007 /* construct device key */ 01008 Status = ZwCreateKey(&hDeviceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 01009 if (NT_SUCCESS(Status)) 01010 { 01011 /* initialize reference string */ 01012 RtlInitUnicodeString(&ReferenceString, InstallInterface->ReferenceString); 01013 01014 /* initialize object attributes */ 01015 InitializeObjectAttributes(&ObjectAttributes, &ReferenceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceKey, NULL); 01016 01017 /* construct device key */ 01018 Status = ZwCreateKey(&hReferenceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 01019 if (NT_SUCCESS(Status)) 01020 { 01021 /* convert interface guid to string */ 01022 Status = RtlStringFromGUID(&InstallInterface->InterfaceId, &InterfaceString); 01023 if (NT_SUCCESS(Status)) 01024 { 01025 /* initialize object attributes */ 01026 InitializeObjectAttributes(&ObjectAttributes, &InterfaceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hReferenceKey, NULL); 01027 01028 /* construct device key */ 01029 Status = ZwCreateKey(&hInterfaceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); 01030 if (NT_SUCCESS(Status)) 01031 { 01032 /* close key */ 01033 ZwClose(hInterfaceKey); 01034 } 01035 /* free interface string */ 01036 RtlFreeUnicodeString(&InterfaceString); 01037 } 01038 /* close reference key */ 01039 ZwClose(hReferenceKey); 01040 } 01041 /* close device key */ 01042 ZwClose(hDeviceKey); 01043 } 01044 /* free device string */ 01045 RtlFreeUnicodeString(&DeviceString); 01046 } 01047 /* close bus key */ 01048 ZwClose(hKey); 01049 } 01050 01051 /* done */ 01052 return Status; 01053 } 01054 01055 VOID 01056 NTAPI 01057 KspInstallBusEnumInterface( 01058 IN PVOID Ctx) 01059 { 01060 PIO_STACK_LOCATION IoStack; 01061 NTSTATUS Status; 01062 PLIST_ENTRY Entry; 01063 PBUS_DEVICE_ENTRY DeviceEntry; 01064 PSWENUM_INSTALL_INTERFACE InstallInterface; 01065 KIRQL OldLevel; 01066 PBUS_INSTALL_ENUM_CONTEXT Context = (PBUS_INSTALL_ENUM_CONTEXT)Ctx; 01067 01068 /* get current irp stack location */ 01069 IoStack = IoGetCurrentIrpStackLocation(Context->Irp); 01070 01071 /* get install request */ 01072 InstallInterface = (PSWENUM_INSTALL_INTERFACE)Context->Irp->AssociatedIrp.SystemBuffer; 01073 01074 /* sanity check */ 01075 ASSERT(InstallInterface); 01076 ASSERT(Context->BusDeviceExtension); 01077 01078 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SWENUM_INSTALL_INTERFACE)) 01079 { 01080 /* buffer too small */ 01081 Context->Status = STATUS_INVALID_PARAMETER; 01082 01083 /* signal completion */ 01084 KeSetEvent(&Context->Event, 0, FALSE); 01085 01086 /* done */ 01087 return; 01088 } 01089 01090 /* FIXME locks */ 01091 01092 /* now install the interface */ 01093 Status = KspInstallInterface(Context->BusDeviceExtension, InstallInterface); 01094 if (!NT_SUCCESS(Status)) 01095 { 01096 /* failed to install interface */ 01097 Context->Status = Status; 01098 01099 /* signal completion */ 01100 KeSetEvent(&Context->Event, 0, FALSE); 01101 01102 /* done */ 01103 return; 01104 } 01105 01106 /* acquire device entry lock */ 01107 KeAcquireSpinLock(&Context->BusDeviceExtension->Lock, &OldLevel); 01108 01109 /* now iterate all device entries */ 01110 Entry = Context->BusDeviceExtension->Common.Entry.Flink; 01111 while(Entry != &Context->BusDeviceExtension->Common.Entry) 01112 { 01113 /* get device entry */ 01114 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 01115 01116 if (IsEqualGUIDAligned(&DeviceEntry->DeviceGuid, &InstallInterface->DeviceId) && 01117 !wcsicmp(DeviceEntry->Instance, InstallInterface->ReferenceString)) 01118 { 01119 if (!DeviceEntry->PDO) 01120 { 01121 /* create pdo */ 01122 Status = KspCreatePDO(Context->BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 01123 01124 /* done */ 01125 break; 01126 } 01127 } 01128 01129 /* move to next entry */ 01130 Entry = Entry->Flink; 01131 } 01132 01133 /* release device entry lock */ 01134 KeReleaseSpinLock(&Context->BusDeviceExtension->Lock, OldLevel); 01135 01136 /* signal that bus driver relations has changed */ 01137 IoInvalidateDeviceRelations(Context->BusDeviceExtension->PhysicalDeviceObject, BusRelations); 01138 01139 /* update status */ 01140 Context->Status = Status; 01141 01142 /* signal completion */ 01143 KeSetEvent(&Context->Event, 0, FALSE); 01144 } 01145 01146 01147 VOID 01148 NTAPI 01149 KspBusWorkerRoutine( 01150 IN PVOID Parameter) 01151 { 01152 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01153 PBUS_DEVICE_ENTRY DeviceEntry; 01154 PLIST_ENTRY Entry; 01155 LARGE_INTEGER Time, Diff; 01156 BOOLEAN DoInvalidate = FALSE; 01157 KIRQL OldLevel; 01158 01159 /* get device extension */ 01160 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Parameter; 01161 01162 /* acquire lock */ 01163 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 01164 01165 /* get current time */ 01166 KeQuerySystemTime(&Time); 01167 01168 /* enumerate all device entries */ 01169 Entry = BusDeviceExtension->Common.Entry.Flink; 01170 while(Entry != &BusDeviceExtension->Common.Entry) 01171 { 01172 /* get offset to device entry */ 01173 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 01174 01175 /* sanity check */ 01176 ASSERT(DeviceEntry); 01177 01178 //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState); 01179 01180 if (DeviceEntry->PDO) 01181 { 01182 if (DeviceEntry->DeviceState == NotStarted) 01183 { 01184 Diff.QuadPart = Time.QuadPart - DeviceEntry->TimeCreated.QuadPart; 01185 01186 if (Diff.QuadPart > Int32x32To64(15000, 10000)) 01187 { 01188 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry->DeviceName, DeviceEntry->Instance, DeviceEntry->TimeCreated.QuadPart, Time.QuadPart, Diff.QuadPart); 01189 01190 /* release spin lock */ 01191 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 01192 01193 /* deactivate interfaces */ 01194 //KspEnableBusDeviceInterface(DeviceEntry, FALSE); 01195 01196 /* re-acquire lock */ 01197 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 01198 01199 /* pending remove device object */ 01200 DeviceEntry->DeviceState = StopPending; 01201 01202 /* perform invalidation */ 01203 DoInvalidate = TRUE; 01204 } 01205 } 01206 else if (DeviceEntry->DeviceState == Started) 01207 { 01208 /* found pending irps */ 01209 KspCompletePendingIrps(DeviceEntry, STATUS_REPARSE); 01210 } 01211 } 01212 01213 01214 /* move to next */ 01215 Entry = Entry->Flink; 01216 } 01217 01218 /* release lock */ 01219 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 01220 01221 if (DoInvalidate) 01222 { 01223 /* invalidate device relations */ 01224 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 01225 } 01226 01227 Time.QuadPart = Int32x32To64(5000, -10000); 01228 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 01229 } 01230 01231 VOID 01232 NTAPI 01233 KspBusDpcRoutine( 01234 IN PKDPC Dpc, 01235 IN PVOID DeferredContext OPTIONAL, 01236 IN PVOID SystemArgument1 OPTIONAL, 01237 IN PVOID SystemArgument2 OPTIONAL) 01238 { 01239 /* get device extension */ 01240 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeferredContext; 01241 01242 /* queue the item */ 01243 ExQueueWorkItem(&BusDeviceExtension->WorkItem, DelayedWorkQueue); 01244 } 01245 01246 VOID 01247 NTAPI 01248 KspRemoveBusInterface( 01249 PVOID Ctx) 01250 { 01251 PBUS_INSTALL_ENUM_CONTEXT Context =(PBUS_INSTALL_ENUM_CONTEXT)Ctx; 01252 01253 /* TODO 01254 * get SWENUM_INSTALL_INTERFACE struct 01255 * open device key and delete the keys 01256 */ 01257 01258 UNIMPLEMENTED 01259 01260 /* set status */ 01261 Context->Status = STATUS_NOT_IMPLEMENTED; 01262 01263 01264 /* signal completion */ 01265 KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE); 01266 } 01267 01268 NTSTATUS 01269 KspQueryBusRelations( 01270 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, 01271 IN PIRP Irp) 01272 { 01273 PDEVICE_RELATIONS DeviceRelations; 01274 PLIST_ENTRY Entry; 01275 PBUS_DEVICE_ENTRY DeviceEntry; 01276 ULONG Count = 0, Length; 01277 KIRQL OldLevel; 01278 01279 /* acquire lock */ 01280 KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); 01281 01282 /* first scan all device entries */ 01283 Entry = BusDeviceExtension->Common.Entry.Flink; 01284 01285 while(Entry != &BusDeviceExtension->Common.Entry) 01286 { 01287 /* get offset to device entry */ 01288 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 01289 01290 /* is there a pdo yet */ 01291 if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) 01292 { 01293 /* increment count */ 01294 Count++; 01295 } 01296 01297 /* move to next entry */ 01298 Entry = Entry->Flink; 01299 } 01300 01301 /* calculate length */ 01302 Length = sizeof(DEVICE_RELATIONS) + (Count > 1 ? sizeof(PDEVICE_OBJECT) * (Count-1) : 0); 01303 01304 /* allocate device relations */ 01305 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(NonPagedPool, Length); 01306 01307 if (!DeviceRelations) 01308 { 01309 /* not enough memory */ 01310 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 01311 return STATUS_INSUFFICIENT_RESOURCES; 01312 } 01313 01314 /* rescan device entries */ 01315 Entry = BusDeviceExtension->Common.Entry.Flink; 01316 01317 while(Entry != &BusDeviceExtension->Common.Entry) 01318 { 01319 /* get offset to device entry */ 01320 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 01321 01322 /* is there a pdo yet */ 01323 if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) 01324 { 01325 /* store pdo */ 01326 DeviceRelations->Objects[DeviceRelations->Count] = DeviceEntry->PDO; 01327 01328 /* reference device object */ 01329 ObReferenceObject(DeviceEntry->PDO); 01330 01331 /* increment pdo count */ 01332 DeviceRelations->Count++; 01333 } 01334 01335 /* move to next entry */ 01336 Entry = Entry->Flink; 01337 } 01338 01339 /* release lock */ 01340 KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); 01341 01342 /* FIXME handle existing device relations */ 01343 ASSERT(Irp->IoStatus.Information == 0); 01344 01345 /* store device relations */ 01346 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 01347 01348 /* done */ 01349 return STATUS_SUCCESS; 01350 } 01351 01352 //------------------------------------------------------------------------------------ 01353 01354 /* 01355 @implemented 01356 */ 01357 01358 KSDDKAPI 01359 NTSTATUS 01360 NTAPI 01361 KsGetBusEnumIdentifier( 01362 IN PIRP Irp) 01363 { 01364 PDEV_EXTENSION DeviceExtension; 01365 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01366 PIO_STACK_LOCATION IoStack; 01367 ULONG Length; 01368 NTSTATUS Status; 01369 LPWSTR Buffer; 01370 01371 DPRINT1("KsGetBusEnumIdentifier\n"); 01372 01373 /* get stack location */ 01374 IoStack = IoGetCurrentIrpStackLocation(Irp); 01375 01376 /* sanity checks */ 01377 ASSERT(IoStack->DeviceObject); 01378 ASSERT(IoStack->DeviceObject->DeviceExtension); 01379 01380 /* get device extension */ 01381 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 01382 01383 /* get bus device extension */ 01384 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 01385 01386 /* sanity checks */ 01387 ASSERT(BusDeviceExtension); 01388 ASSERT(BusDeviceExtension->Common.IsBus); 01389 01390 if (!BusDeviceExtension) 01391 { 01392 /* invalid parameter */ 01393 return STATUS_INVALID_PARAMETER; 01394 } 01395 01396 /* get length */ 01397 Length = (wcslen(BusDeviceExtension->BusIdentifier)+1) * sizeof(WCHAR); 01398 01399 /* is there an output buffer provided */ 01400 if (IoStack->Parameters.DeviceIoControl.InputBufferLength) 01401 { 01402 if (Length > IoStack->Parameters.DeviceIoControl.InputBufferLength) 01403 { 01404 /* buffer is too small */ 01405 return STATUS_BUFFER_TOO_SMALL; 01406 } 01407 01408 /* now allocate buffer */ 01409 Buffer = AllocateItem(NonPagedPool, Length); 01410 if (!Buffer) 01411 { 01412 /* no memory */ 01413 Status = STATUS_INSUFFICIENT_RESOURCES; 01414 } 01415 else 01416 { 01417 /* copy bus identifier */ 01418 wcscpy(Buffer, BusDeviceExtension->BusIdentifier); 01419 01420 /* store buffer */ 01421 Irp->AssociatedIrp.SystemBuffer = Buffer; 01422 01423 /* set flag that buffer gets copied back */ 01424 Irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION; 01425 01426 /* done */ 01427 Status = STATUS_SUCCESS; 01428 } 01429 } 01430 else 01431 { 01432 /* no buffer provided */ 01433 Status = STATUS_BUFFER_OVERFLOW; 01434 } 01435 01436 /* done */ 01437 Irp->IoStatus.Status = Status; 01438 return Status; 01439 } 01440 01441 /* 01442 @implemented 01443 */ 01444 KSDDKAPI 01445 NTSTATUS 01446 NTAPI 01447 KsGetBusEnumParentFDOFromChildPDO( 01448 IN PDEVICE_OBJECT DeviceObject, 01449 OUT PDEVICE_OBJECT *FunctionalDeviceObject) 01450 { 01451 PDEV_EXTENSION DeviceExtension; 01452 01453 DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n"); 01454 01455 /* get device extension */ 01456 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 01457 01458 /* check if this is child pdo */ 01459 if (DeviceExtension->Ext->IsBus == FALSE) 01460 { 01461 /* return bus device object */ 01462 *FunctionalDeviceObject = DeviceExtension->Ext->BusDeviceExtension->BusDeviceObject; 01463 01464 /* done */ 01465 return STATUS_SUCCESS; 01466 } 01467 01468 /* invalid parameter */ 01469 return STATUS_INVALID_PARAMETER; 01470 } 01471 01472 01473 /* 01474 @implemented 01475 */ 01476 KSDDKAPI 01477 NTSTATUS 01478 NTAPI 01479 KsCreateBusEnumObject( 01480 IN PWCHAR BusIdentifier, 01481 IN PDEVICE_OBJECT BusDeviceObject, 01482 IN PDEVICE_OBJECT PhysicalDeviceObject, 01483 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL, 01484 IN REFGUID InterfaceGuid OPTIONAL, 01485 IN PWCHAR ServiceRelativePath OPTIONAL) 01486 { 01487 ULONG Length; 01488 NTSTATUS Status = STATUS_SUCCESS; 01489 UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); 01490 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01491 PDEV_EXTENSION DeviceExtension; 01492 01493 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath, BusDeviceObject); 01494 01495 /* calculate sizeof bus enum device extension */ 01496 Length = wcslen(BusIdentifier) * sizeof(WCHAR); 01497 Length += sizeof(BUS_ENUM_DEVICE_EXTENSION); 01498 01499 BusDeviceExtension = AllocateItem(NonPagedPool, Length); 01500 if (!BusDeviceExtension) 01501 { 01502 /* not enough memory */ 01503 01504 return STATUS_INSUFFICIENT_RESOURCES; 01505 } 01506 01507 /* get device extension */ 01508 DeviceExtension = (PDEV_EXTENSION)BusDeviceObject->DeviceExtension; 01509 01510 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); 01511 01512 /* store bus device extension */ 01513 DeviceExtension->Ext = (PCOMMON_DEVICE_EXTENSION)BusDeviceExtension; 01514 01515 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); 01516 01517 01518 /* zero device extension */ 01519 RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION)); 01520 01521 /* initialize bus device extension */ 01522 wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier); 01523 01524 /* allocate service path string */ 01525 Length = ServiceKeyPath.MaximumLength; 01526 Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength; 01527 01528 if (ServiceRelativePath) 01529 { 01530 /* relative path for devices */ 01531 Length += (wcslen(ServiceRelativePath) + 2) * sizeof(WCHAR); 01532 } 01533 01534 BusDeviceExtension->ServicePath.Length = 0; 01535 BusDeviceExtension->ServicePath.MaximumLength = Length; 01536 BusDeviceExtension->ServicePath.Buffer = AllocateItem(NonPagedPool, Length); 01537 01538 if (!BusDeviceExtension->ServicePath.Buffer) 01539 { 01540 /* not enough memory */ 01541 FreeItem(BusDeviceExtension); 01542 01543 return STATUS_INSUFFICIENT_RESOURCES; 01544 } 01545 01546 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath); 01547 RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName); 01548 01549 if (ServiceRelativePath) 01550 { 01551 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\"); 01552 RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath); 01553 } 01554 01555 if (InterfaceGuid) 01556 { 01557 /* register an device interface */ 01558 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->DeviceInterfaceLink); 01559 01560 /* check for success */ 01561 if (!NT_SUCCESS(Status)) 01562 { 01563 01564 FreeItem(BusDeviceExtension->ServicePath.Buffer); 01565 FreeItem(BusDeviceExtension); 01566 return Status; 01567 } 01568 01569 /* now enable device interface */ 01570 Status = IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, TRUE); 01571 01572 if (!NT_SUCCESS(Status)) 01573 { 01574 FreeItem(BusDeviceExtension->ServicePath.Buffer); 01575 FreeItem(BusDeviceExtension); 01576 return Status; 01577 } 01578 } 01579 01580 /* initialize common device extension */ 01581 BusDeviceExtension->Common.BusDeviceExtension = NULL; 01582 BusDeviceExtension->Common.DeviceObjectReferenceCount = 1; 01583 BusDeviceExtension->Common.DeviceReferenceCount = 1; 01584 BusDeviceExtension->Common.IsBus = TRUE; 01585 InitializeListHead(&BusDeviceExtension->Common.Entry); 01586 01587 /* store device objects */ 01588 BusDeviceExtension->BusDeviceObject = BusDeviceObject; 01589 BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; 01590 01591 /* initialize lock */ 01592 KeInitializeSpinLock(&BusDeviceExtension->Lock); 01593 01594 /* initialize timer */ 01595 KeInitializeTimer(&BusDeviceExtension->Timer); 01596 01597 /* initialize dpc */ 01598 KeInitializeDpc(&BusDeviceExtension->Dpc, KspBusDpcRoutine, (PVOID)BusDeviceExtension); 01599 01600 /* initialize event */ 01601 KeInitializeEvent(&BusDeviceExtension->Event, SynchronizationEvent, FALSE); 01602 01603 /* initialize work item */ 01604 ExInitializeWorkItem(&BusDeviceExtension->WorkItem, KspBusWorkerRoutine, (PVOID)BusDeviceExtension); 01605 01606 if (!PnpDeviceObject) 01607 { 01608 /* attach device */ 01609 BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject); 01610 01611 if (!BusDeviceExtension->PnpDeviceObject) 01612 { 01613 /* failed to attach device */ 01614 if (BusDeviceExtension->DeviceInterfaceLink.Buffer) 01615 { 01616 IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); 01617 RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); 01618 } 01619 01620 /* free device extension */ 01621 FreeItem(BusDeviceExtension->ServicePath.Buffer); 01622 FreeItem(BusDeviceExtension); 01623 01624 return STATUS_DEVICE_REMOVED; 01625 } 01626 01627 /* mark device as attached */ 01628 BusDeviceExtension->DeviceAttached = TRUE; 01629 } 01630 else 01631 { 01632 /* directly attach */ 01633 BusDeviceExtension->PnpDeviceObject = PnpDeviceObject; 01634 } 01635 01636 /* now scan the bus */ 01637 Status = KspScanBus(BusDeviceExtension); 01638 01639 /* check for success */ 01640 if (!NT_SUCCESS(Status)) 01641 { 01642 /* failed to scan bus */ 01643 if (BusDeviceExtension->DeviceInterfaceLink.Buffer) 01644 { 01645 IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); 01646 RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); 01647 } 01648 01649 if (BusDeviceExtension->DeviceAttached) 01650 { 01651 /* detach device */ 01652 IoDetachDevice(BusDeviceExtension->PnpDeviceObject); 01653 } 01654 01655 /* free device extension */ 01656 FreeItem(BusDeviceExtension->ServicePath.Buffer); 01657 FreeItem(BusDeviceExtension); 01658 } 01659 01660 DPRINT("KsCreateBusEnumObject Status %x\n", Status); 01661 /* done */ 01662 return Status; 01663 } 01664 01665 /* 01666 @implemented 01667 */ 01668 KSDDKAPI 01669 NTSTATUS 01670 NTAPI 01671 KsGetBusEnumPnpDeviceObject( 01672 IN PDEVICE_OBJECT DeviceObject, 01673 IN PDEVICE_OBJECT *PnpDeviceObject) 01674 { 01675 PDEV_EXTENSION DeviceExtension; 01676 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension; 01677 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01678 01679 DPRINT("KsGetBusEnumPnpDeviceObject\n"); 01680 01681 if (!DeviceObject->DeviceExtension) 01682 { 01683 /* invalid parameter */ 01684 return STATUS_INVALID_PARAMETER; 01685 } 01686 01687 /* get device extension */ 01688 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 01689 01690 /* get common device extension */ 01691 CommonDeviceExtension = DeviceExtension->Ext; 01692 01693 if (!CommonDeviceExtension) 01694 { 01695 /* invalid parameter */ 01696 return STATUS_INVALID_PARAMETER; 01697 } 01698 01699 if (!CommonDeviceExtension->IsBus) 01700 { 01701 /* getting pnp device object is only supported for software bus device object */ 01702 return STATUS_INVALID_PARAMETER; 01703 } 01704 01705 /* sanity checks */ 01706 ASSERT(CommonDeviceExtension); 01707 ASSERT(CommonDeviceExtension->IsBus); 01708 01709 /* cast to bus device extension */ 01710 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)CommonDeviceExtension; 01711 01712 /* store result */ 01713 *PnpDeviceObject = BusDeviceExtension->PnpDeviceObject; 01714 01715 /* done */ 01716 return STATUS_SUCCESS; 01717 } 01718 01719 /* 01720 @implemented 01721 */ 01722 KSDDKAPI 01723 NTSTATUS 01724 NTAPI 01725 KsInstallBusEnumInterface( 01726 PIRP Irp) 01727 { 01728 BUS_INSTALL_ENUM_CONTEXT Context; 01729 KPROCESSOR_MODE Mode; 01730 LUID luid; 01731 PIO_STACK_LOCATION IoStack; 01732 PDEV_EXTENSION DeviceExtension; 01733 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01734 01735 DPRINT1("KsInstallBusEnumInterface\n"); 01736 01737 /* get current irp stack location */ 01738 IoStack = IoGetCurrentIrpStackLocation(Irp); 01739 01740 /* get previous mode */ 01741 Mode = ExGetPreviousMode(); 01742 01743 /* convert to luid */ 01744 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); 01745 01746 /* perform access check */ 01747 if (!SeSinglePrivilegeCheck(luid, Mode)) 01748 { 01749 /* insufficient privileges */ 01750 return STATUS_PRIVILEGE_NOT_HELD; 01751 } 01752 01753 /* get device extension */ 01754 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 01755 01756 /* get bus device extension */ 01757 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 01758 01759 01760 /* initialize context */ 01761 Context.Irp = Irp; 01762 KeInitializeEvent(&Context.Event, NotificationEvent, FALSE); 01763 Context.BusDeviceExtension = BusDeviceExtension; 01764 ExInitializeWorkItem(&Context.WorkItem, KspInstallBusEnumInterface, (PVOID)&Context); 01765 01766 /* queue the work item */ 01767 ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); 01768 /* wait for completion */ 01769 KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL); 01770 01771 /* store result */ 01772 Irp->IoStatus.Status = Context.Status; 01773 01774 /* done */ 01775 return Context.Status; 01776 } 01777 01778 /* 01779 @implemented 01780 */ 01781 KSDDKAPI 01782 NTSTATUS 01783 NTAPI 01784 KsIsBusEnumChildDevice( 01785 IN PDEVICE_OBJECT DeviceObject, 01786 OUT PBOOLEAN ChildDevice) 01787 { 01788 PDEV_EXTENSION DeviceExtension; 01789 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01790 01791 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject); 01792 01793 /* get device extension */ 01794 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 01795 01796 /* get bus device extension */ 01797 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 01798 01799 if (!BusDeviceExtension) 01800 { 01801 /* not a bus device */ 01802 return STATUS_INVALID_PARAMETER; 01803 } 01804 01805 /* store result */ 01806 *ChildDevice = (BusDeviceExtension->Common.IsBus == FALSE); 01807 01808 return STATUS_SUCCESS; 01809 } 01810 01811 /* 01812 @implemented 01813 */ 01814 KSDDKAPI 01815 NTSTATUS 01816 NTAPI 01817 KsServiceBusEnumCreateRequest( 01818 IN PDEVICE_OBJECT DeviceObject, 01819 IN OUT PIRP Irp) 01820 { 01821 PLIST_ENTRY Entry; 01822 PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* fix gcc */ 01823 PIO_STACK_LOCATION IoStack; 01824 BOOLEAN ItemExists = FALSE; 01825 PDEV_EXTENSION DeviceExtension; 01826 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01827 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; 01828 NTSTATUS Status; 01829 LARGE_INTEGER Time; 01830 01831 /* FIXME: locks */ 01832 01833 /* get device extension */ 01834 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 01835 01836 /* get bus device extension */ 01837 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 01838 01839 /* get current irp stack location */ 01840 IoStack = IoGetCurrentIrpStackLocation(Irp); 01841 01842 /* sanity checks */ 01843 ASSERT(IoStack->FileObject); 01844 ASSERT(IoStack->FileObject->FileName.Buffer); 01845 01846 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp, &IoStack->FileObject->FileName); 01847 01848 /* scan list and check if it is already present */ 01849 Entry = BusDeviceExtension->Common.Entry.Flink; 01850 01851 while(Entry != &BusDeviceExtension->Common.Entry) 01852 { 01853 /* get real offset */ 01854 DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); 01855 01856 /* check if name matches */ 01857 if (!wcsicmp(DeviceEntry->DeviceName, IoStack->FileObject->FileName.Buffer + 1)) 01858 { 01859 /* item already exists */ 01860 ItemExists = TRUE; 01861 break; 01862 } 01863 01864 /* move to next entry */ 01865 Entry = Entry->Flink; 01866 } 01867 01868 if (!ItemExists) 01869 { 01870 /* interface not registered */ 01871 DPRINT1("Interface %wZ not registered\n", &IoStack->FileObject->FileName); 01872 return STATUS_OBJECT_NAME_NOT_FOUND; 01873 } 01874 01875 /* is there a pdo yet */ 01876 if (DeviceEntry->PDO) 01877 { 01878 if (DeviceEntry->DeviceState == Started) 01879 { 01880 /* issue reparse */ 01881 Status = KspDoReparseForIrp(Irp, DeviceEntry); 01882 DPRINT("REPARSE Irp %p '%wZ'\n", Irp, &IoStack->FileObject->FileName); 01883 01884 Irp->IoStatus.Status = Status; 01885 return Status; 01886 } 01887 01888 /* delay processing until pnp is finished with enumeration */ 01889 IoMarkIrpPending(Irp); 01890 01891 /* insert into irp pending list */ 01892 InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); 01893 01894 Time.QuadPart = Int32x32To64(1500, -10000); 01895 DbgPrint("PENDING Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); 01896 01897 /* query current time */ 01898 KeQuerySystemTime(&DeviceEntry->TimeCreated); 01899 01900 /* set timer */ 01901 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 01902 01903 /* done for now */ 01904 return STATUS_PENDING; 01905 01906 } 01907 else 01908 { 01909 /* time to create PDO */ 01910 Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 01911 01912 if (!NT_SUCCESS(Status)) 01913 { 01914 /* failed to create PDO */ 01915 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status); 01916 return Status; 01917 } 01918 DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); 01919 01920 /* delay processing until pnp is finished with enumeration */ 01921 IoMarkIrpPending(Irp); 01922 01923 /* insert into irp pending list */ 01924 InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); 01925 01926 /* get current time */ 01927 KeQuerySystemTime(&DeviceEntry->TimeCreated); 01928 01929 /* invalidate device relations */ 01930 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 01931 01932 /* done for now */ 01933 return STATUS_PENDING; 01934 } 01935 } 01936 01937 /* 01938 @implemented 01939 */ 01940 KSDDKAPI 01941 NTSTATUS 01942 NTAPI 01943 KsServiceBusEnumPnpRequest( 01944 IN PDEVICE_OBJECT DeviceObject, 01945 IN OUT PIRP Irp) 01946 { 01947 PDEV_EXTENSION DeviceExtension; 01948 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 01949 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; 01950 PIO_STACK_LOCATION IoStack; 01951 NTSTATUS Status; 01952 LARGE_INTEGER Time; 01953 PDEVICE_RELATIONS DeviceRelation; 01954 PBUS_DEVICE_ENTRY DeviceEntry; 01955 01956 /* get device extension */ 01957 DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; 01958 01959 /* get bus device extension */ 01960 BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; 01961 01962 /* get current irp stack location */ 01963 IoStack = IoGetCurrentIrpStackLocation(Irp); 01964 01965 if (BusDeviceExtension->Common.IsBus) 01966 { 01967 if (IoStack->MinorFunction == IRP_MN_START_DEVICE) 01968 { 01969 /* no op for bus driver */ 01970 Status = STATUS_SUCCESS; 01971 } 01972 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS) 01973 { 01974 /* handle bus device relations */ 01975 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == BusRelations); 01976 01977 Status = KspQueryBusRelations(BusDeviceExtension, Irp); 01978 } 01979 else 01980 { 01981 /* get default status */ 01982 Status = Irp->IoStatus.Status; 01983 } 01984 } 01985 else 01986 { 01987 /* get child device extension */ 01988 ChildDeviceExtension = DeviceExtension->Ext; 01989 01990 /* get bus device extension */ 01991 BusDeviceExtension = ChildDeviceExtension->BusDeviceExtension; 01992 01993 if (IoStack->MinorFunction == IRP_MN_QUERY_ID) 01994 { 01995 /* query id */ 01996 Status = KspQueryId(ChildDeviceExtension, Irp); 01997 } 01998 else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE) 01999 { 02000 ASSERT(ChildDeviceExtension->DeviceEntry->DeviceState != Started || ChildDeviceExtension->DeviceEntry->DeviceState == NotStarted); 02001 ASSERT(ChildDeviceExtension->DeviceEntry->PDO == DeviceObject); 02002 02003 /* backup device entry */ 02004 DeviceEntry = ChildDeviceExtension->DeviceEntry; 02005 02006 /* free device extension */ 02007 FreeItem(ChildDeviceExtension); 02008 02009 /* clear PDO reference */ 02010 DeviceEntry->PDO = NULL; 02011 02012 /* delete the device */ 02013 IoDeleteDevice(DeviceObject); 02014 02015 if (DeviceEntry->PDODeviceName) 02016 { 02017 /* delete pdo device name */ 02018 FreeItem(DeviceEntry->PDODeviceName); 02019 02020 /* set to null */ 02021 DeviceEntry->PDODeviceName = NULL; 02022 } 02023 02024 /* set state no notstarted */ 02025 DeviceEntry->DeviceState = NotStarted; 02026 02027 /* time to create PDO */ 02028 KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); 02029 02030 /* invalidate device relations */ 02031 IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); 02032 02033 /* done */ 02034 Status = STATUS_SUCCESS; 02035 } 02036 else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION) 02037 { 02038 /* query bus information */ 02039 Status = KspQueryBusInformation(ChildDeviceExtension, Irp); 02040 } 02041 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES) 02042 { 02043 /* no op */ 02044 Status = STATUS_SUCCESS; 02045 } 02046 else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS) 02047 { 02048 /* no op */ 02049 Status = STATUS_SUCCESS; 02050 } 02051 else if (IoStack->MinorFunction == IRP_MN_START_DEVICE) 02052 { 02053 /* start bus */ 02054 Status = KspStartBusDevice(DeviceObject, ChildDeviceExtension, Irp); 02055 02056 /* set time out */ 02057 Time.QuadPart = Int32x32To64(1500, -10000); 02058 02059 /* sanity check */ 02060 ASSERT(BusDeviceExtension); 02061 02062 /* set timer */ 02063 KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); 02064 } 02065 else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES) 02066 { 02067 /* query capabilities */ 02068 Status = KspQueryBusDeviceCapabilities(ChildDeviceExtension, Irp); 02069 } 02070 else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE) 02071 { 02072 /* query pnp state */ 02073 Status = KspQueryBusDevicePnpState(ChildDeviceExtension, Irp); 02074 } 02075 else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE) 02076 { 02077 /* query interface */ 02078 Status = KspQueryBusDeviceInterface(ChildDeviceExtension, Irp); 02079 } 02080 else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS && IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) 02081 { 02082 /* handle target device relations */ 02083 ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation); 02084 ASSERT(Irp->IoStatus.Information == 0); 02085 02086 /* allocate device relation */ 02087 DeviceRelation = AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); 02088 if (DeviceRelation) 02089 { 02090 DeviceRelation->Count = 1; 02091 DeviceRelation->Objects[0] = DeviceObject; 02092 02093 /* reference self */ 02094 ObReferenceObject(DeviceObject); 02095 02096 /* store result */ 02097 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; 02098 02099 /* done */ 02100 Status = STATUS_SUCCESS; 02101 } 02102 else 02103 { 02104 /* no memory */ 02105 Status = STATUS_INSUFFICIENT_RESOURCES; 02106 } 02107 } 02108 else 02109 { 02110 /* get default status */ 02111 Status = Irp->IoStatus.Status; 02112 } 02113 } 02114 02115 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject, BusDeviceExtension->Common.IsBus, IoStack->MinorFunction, Status); 02116 Irp->IoStatus.Status = Status; 02117 return Status; 02118 } 02119 02120 /* 02121 @implemented 02122 */ 02123 KSDDKAPI 02124 NTSTATUS 02125 NTAPI 02126 KsRemoveBusEnumInterface( 02127 IN PIRP Irp) 02128 { 02129 KPROCESSOR_MODE Mode; 02130 LUID luid; 02131 BUS_INSTALL_ENUM_CONTEXT Ctx; 02132 PDEV_EXTENSION DeviceExtension; 02133 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; 02134 PIO_STACK_LOCATION IoStack; 02135 02136 DPRINT1("KsRemoveBusEnumInterface\n"); 02137 02138 /* get io stack location */ 02139 IoStack = IoGetCurrentIrpStackLocation(Irp); 02140 02141 /* get device extension */ 02142 DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; 02143 02144 /* get bus device extension */ 02145 BusDeviceExtension = DeviceExtension->Ext->BusDeviceExtension; 02146 02147 /* get previous mode */ 02148 Mode = ExGetPreviousMode(); 02149 02150 /* convert to luid */ 02151 luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE); 02152 02153 /* perform access check */ 02154 if (!SeSinglePrivilegeCheck(luid, Mode)) 02155 { 02156 /* insufficient privileges */ 02157 return STATUS_PRIVILEGE_NOT_HELD; 02158 } 02159 02160 /* initialize context */ 02161 KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE); 02162 Ctx.Irp = Irp; 02163 Ctx.BusDeviceExtension = BusDeviceExtension; 02164 ExInitializeWorkItem(&Ctx.WorkItem, KspRemoveBusInterface, (PVOID)&Ctx); 02165 02166 /* now queue the work item */ 02167 ExQueueWorkItem(&Ctx.WorkItem, DelayedWorkQueue); 02168 02169 /* wait for completion */ 02170 KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL); 02171 02172 /* return result */ 02173 return Ctx.Status; 02174 } Generated on Sun May 27 2012 04:27:58 for ReactOS by
1.7.6.1
|