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