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