- Merge the remaining portion of the wlan-bringup branch
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnproot.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnproot.c
5 * PURPOSE: PnP manager root device
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Copyright 2007 Herv? Poussineau (hpoussin@reactos.org)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS *******************************************************************/
17
18 #define ENUM_NAME_ROOT L"Root"
19
20 /* DATA **********************************************************************/
21
22 typedef struct _PNPROOT_DEVICE
23 {
24 // Entry on device list
25 LIST_ENTRY ListEntry;
26 // Physical Device Object of device
27 PDEVICE_OBJECT Pdo;
28 // Device ID
29 UNICODE_STRING DeviceID;
30 // Instance ID
31 UNICODE_STRING InstanceID;
32 // Device description
33 UNICODE_STRING DeviceDescription;
34 // Resource requirement list
35 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
36 // Associated resource list
37 PCM_RESOURCE_LIST ResourceList;
38 ULONG ResourceListSize;
39 } PNPROOT_DEVICE, *PPNPROOT_DEVICE;
40
41 typedef enum
42 {
43 dsStopped,
44 dsStarted,
45 dsPaused,
46 dsRemoved,
47 dsSurpriseRemoved
48 } PNPROOT_DEVICE_STATE;
49
50 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
51 {
52 // Wether this device extension is for an FDO or PDO
53 BOOLEAN IsFDO;
54 } PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION;
55
56 /* Physical Device Object device extension for a child device */
57 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
58 {
59 // Common device data
60 PNPROOT_COMMON_DEVICE_EXTENSION Common;
61 // Informations about the device
62 PPNPROOT_DEVICE DeviceInfo;
63 } PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;
64
65 /* Physical Device Object device extension for the Root bus device object */
66 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
67 {
68 // Common device data
69 PNPROOT_COMMON_DEVICE_EXTENSION Common;
70 // Lower device object
71 PDEVICE_OBJECT Ldo;
72 // Current state of the driver
73 PNPROOT_DEVICE_STATE State;
74 // Namespace device list
75 LIST_ENTRY DeviceListHead;
76 // Number of (not removed) devices in device list
77 ULONG DeviceListCount;
78 // Lock for namespace device list
79 KGUARDED_MUTEX DeviceListLock;
80 } PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;
81
82 typedef struct _BUFFER
83 {
84 PVOID *Data;
85 PULONG Length;
86 } BUFFER, *PBUFFER;
87
88 static PDEVICE_OBJECT PnpRootDeviceObject = NULL;
89
90 /* FUNCTIONS *****************************************************************/
91
92 static NTSTATUS
93 LocateChildDevice(
94 IN PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension,
95 IN PCWSTR DeviceId,
96 IN PCWSTR InstanceId,
97 OUT PPNPROOT_DEVICE* ChildDevice)
98 {
99 PPNPROOT_DEVICE Device;
100 UNICODE_STRING DeviceIdU, InstanceIdU;
101 PLIST_ENTRY NextEntry;
102
103 /* Initialize the strings to compare */
104 RtlInitUnicodeString(&DeviceIdU, DeviceId);
105 RtlInitUnicodeString(&InstanceIdU, InstanceId);
106
107 /* Start looping */
108 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
109 NextEntry != &DeviceExtension->DeviceListHead;
110 NextEntry = NextEntry->Flink)
111 {
112 /* Get the entry */
113 Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry);
114
115 /* See if the strings match */
116 if (RtlEqualUnicodeString(&DeviceIdU, &Device->DeviceID, TRUE) &&
117 RtlEqualUnicodeString(&InstanceIdU, &Device->InstanceID, TRUE))
118 {
119 /* They do, so set the pointer and return success */
120 *ChildDevice = Device;
121 return STATUS_SUCCESS;
122 }
123 }
124
125 /* No device found */
126 return STATUS_NO_SUCH_DEVICE;
127 }
128
129 /* Creates a new PnP device for a legacy driver */
130 NTSTATUS
131 PnpRootCreateDevice(
132 IN PUNICODE_STRING ServiceName,
133 IN OPTIONAL PDRIVER_OBJECT DriverObject,
134 OUT PDEVICE_OBJECT *PhysicalDeviceObject,
135 OUT OPTIONAL PUNICODE_STRING FullInstancePath)
136 {
137 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
138 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
139 WCHAR DevicePath[MAX_PATH + 1];
140 WCHAR InstancePath[5];
141 PPNPROOT_DEVICE Device = NULL;
142 NTSTATUS Status;
143 UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
144 ULONG NextInstance;
145 UNICODE_STRING EnumKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM);
146 HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE, InstanceKeyHandle;
147 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
148 OBJECT_ATTRIBUTES ObjectAttributes;
149
150 DeviceExtension = PnpRootDeviceObject->DeviceExtension;
151 KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
152
153 DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName);
154
155 _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\%wZ", REGSTR_KEY_ROOTENUM, ServiceName);
156
157 /* Initialize a PNPROOT_DEVICE structure */
158 Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
159 if (!Device)
160 {
161 DPRINT("ExAllocatePoolWithTag() failed\n");
162 Status = STATUS_NO_MEMORY;
163 goto cleanup;
164 }
165 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
166 if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
167 {
168 Status = STATUS_NO_MEMORY;
169 goto cleanup;
170 }
171
172 Status = IopOpenRegistryKeyEx(&EnumHandle, NULL, &EnumKeyName, KEY_READ);
173 if (NT_SUCCESS(Status))
174 {
175 InitializeObjectAttributes(&ObjectAttributes, &Device->DeviceID, OBJ_CASE_INSENSITIVE, EnumHandle, NULL);
176 Status = ZwCreateKey(&DeviceKeyHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
177 ZwClose(EnumHandle);
178 }
179
180 if (!NT_SUCCESS(Status))
181 {
182 DPRINT1("Failed to open registry key\n");
183 goto cleanup;
184 }
185
186 tryagain:
187 RtlZeroMemory(QueryTable, sizeof(QueryTable));
188 QueryTable[0].Name = L"NextInstance";
189 QueryTable[0].EntryContext = &NextInstance;
190 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
191
192 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
193 (PWSTR)DeviceKeyHandle,
194 QueryTable,
195 NULL,
196 NULL);
197 if (!NT_SUCCESS(Status))
198 {
199 for (NextInstance = 0; NextInstance <= 9999; NextInstance++)
200 {
201 _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance);
202 Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device);
203 if (Status == STATUS_NO_SUCH_DEVICE)
204 break;
205 }
206
207 if (NextInstance > 9999)
208 {
209 DPRINT1("Too many legacy devices reported for service '%wZ'\n", ServiceName);
210 Status = STATUS_INSUFFICIENT_RESOURCES;
211 goto cleanup;
212 }
213 }
214
215 _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance);
216 Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device);
217 if (Status != STATUS_NO_SUCH_DEVICE || NextInstance > 9999)
218 {
219 DPRINT1("NextInstance value is corrupt! (%d)\n", NextInstance);
220 RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE,
221 (PWSTR)DeviceKeyHandle,
222 L"NextInstance");
223 goto tryagain;
224 }
225
226 NextInstance++;
227 Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE,
228 (PWSTR)DeviceKeyHandle,
229 L"NextInstance",
230 REG_DWORD,
231 &NextInstance,
232 sizeof(NextInstance));
233 if (!NT_SUCCESS(Status))
234 {
235 DPRINT1("Failed to write new NextInstance value! (0x%x)\n", Status);
236 goto cleanup;
237 }
238
239 if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath))
240 {
241 Status = STATUS_NO_MEMORY;
242 goto cleanup;
243 }
244
245 /* Finish creating the instance path in the registry */
246 InitializeObjectAttributes(&ObjectAttributes, &Device->InstanceID, OBJ_CASE_INSENSITIVE, DeviceKeyHandle, NULL);
247 Status = ZwCreateKey(&InstanceKeyHandle, KEY_QUERY_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
248 if (NT_SUCCESS(Status))
249 {
250 DPRINT1("Failed to create instance path (0x%x)\n", Status);
251 goto cleanup;
252 }
253
254 /* Just close the handle */
255 ZwClose(InstanceKeyHandle);
256
257 if (FullInstancePath)
258 {
259 FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length;
260 FullInstancePath->Length = 0;
261 FullInstancePath->Buffer = ExAllocatePool(PagedPool, FullInstancePath->MaximumLength);
262 if (!FullInstancePath->Buffer)
263 {
264 Status = STATUS_NO_MEMORY;
265 goto cleanup;
266 }
267
268 RtlAppendUnicodeStringToString(FullInstancePath, &Device->DeviceID);
269 RtlAppendUnicodeStringToString(FullInstancePath, &PathSep);
270 RtlAppendUnicodeStringToString(FullInstancePath, &Device->InstanceID);
271 }
272
273 /* Initialize a device object */
274 Status = IoCreateDevice(
275 DriverObject ? DriverObject : PnpRootDeviceObject->DriverObject,
276 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
277 NULL,
278 FILE_DEVICE_CONTROLLER,
279 FILE_AUTOGENERATED_DEVICE_NAME,
280 FALSE,
281 &Device->Pdo);
282 if (!NT_SUCCESS(Status))
283 {
284 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
285 Status = STATUS_NO_MEMORY;
286 goto cleanup;
287 }
288
289 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
290 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
291 PdoDeviceExtension->Common.IsFDO = FALSE;
292 PdoDeviceExtension->DeviceInfo = Device;
293
294 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
295 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
296
297 InsertTailList(
298 &DeviceExtension->DeviceListHead,
299 &Device->ListEntry);
300 DeviceExtension->DeviceListCount++;
301
302 *PhysicalDeviceObject = Device->Pdo;
303 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject, &Device->DeviceID, &Device->InstanceID);
304 Device = NULL;
305 Status = STATUS_SUCCESS;
306
307 cleanup:
308 KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
309 if (Device)
310 {
311 if (Device->Pdo)
312 IoDeleteDevice(Device->Pdo);
313 RtlFreeUnicodeString(&Device->DeviceID);
314 RtlFreeUnicodeString(&Device->InstanceID);
315 ExFreePoolWithTag(Device, TAG_PNP_ROOT);
316 }
317 if (DeviceKeyHandle != INVALID_HANDLE_VALUE)
318 ZwClose(DeviceKeyHandle);
319 return Status;
320 }
321
322 static NTSTATUS NTAPI
323 QueryStringCallback(
324 IN PWSTR ValueName,
325 IN ULONG ValueType,
326 IN PVOID ValueData,
327 IN ULONG ValueLength,
328 IN PVOID Context,
329 IN PVOID EntryContext)
330 {
331 PUNICODE_STRING Destination = (PUNICODE_STRING)EntryContext;
332 UNICODE_STRING Source;
333
334 if (ValueType != REG_SZ || ValueLength == 0 || ValueLength % sizeof(WCHAR) != 0)
335 {
336 Destination->Length = 0;
337 Destination->MaximumLength = 0;
338 Destination->Buffer = NULL;
339 return STATUS_SUCCESS;
340 }
341
342 Source.MaximumLength = Source.Length = (USHORT)ValueLength;
343 Source.Buffer = ValueData;
344
345 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &Source, Destination);
346 }
347
348 static NTSTATUS NTAPI
349 QueryBinaryValueCallback(
350 IN PWSTR ValueName,
351 IN ULONG ValueType,
352 IN PVOID ValueData,
353 IN ULONG ValueLength,
354 IN PVOID Context,
355 IN PVOID EntryContext)
356 {
357 PBUFFER Buffer = (PBUFFER)EntryContext;
358 PVOID BinaryValue;
359
360 if (ValueLength == 0)
361 {
362 *Buffer->Data = NULL;
363 return STATUS_SUCCESS;
364 }
365
366 BinaryValue = ExAllocatePoolWithTag(PagedPool, ValueLength, TAG_PNP_ROOT);
367 if (BinaryValue == NULL)
368 return STATUS_NO_MEMORY;
369 RtlCopyMemory(BinaryValue, ValueData, ValueLength);
370 *Buffer->Data = BinaryValue;
371 if (Buffer->Length) *Buffer->Length = ValueLength;
372 return STATUS_SUCCESS;
373 }
374
375 static NTSTATUS
376 EnumerateDevices(
377 IN PDEVICE_OBJECT DeviceObject)
378 {
379 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
380 PKEY_BASIC_INFORMATION KeyInfo = NULL, SubKeyInfo = NULL;
381 UNICODE_STRING LegacyU = RTL_CONSTANT_STRING(L"LEGACY_");
382 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L"\\" REGSTR_KEY_ROOTENUM);
383 UNICODE_STRING SubKeyName;
384 WCHAR DevicePath[MAX_PATH + 1];
385 RTL_QUERY_REGISTRY_TABLE QueryTable[4];
386 PPNPROOT_DEVICE Device = NULL;
387 HANDLE KeyHandle = INVALID_HANDLE_VALUE;
388 HANDLE SubKeyHandle = INVALID_HANDLE_VALUE;
389 HANDLE DeviceKeyHandle = INVALID_HANDLE_VALUE;
390 ULONG BufferSize;
391 ULONG ResultSize;
392 ULONG Index1, Index2;
393 BUFFER Buffer1, Buffer2;
394 NTSTATUS Status = STATUS_UNSUCCESSFUL;
395
396 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject);
397
398 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
399 KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
400
401 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH + 1) * sizeof(WCHAR);
402 KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
403 if (!KeyInfo)
404 {
405 DPRINT("ExAllocatePoolWithTag() failed\n");
406 Status = STATUS_NO_MEMORY;
407 goto cleanup;
408 }
409 SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
410 if (!SubKeyInfo)
411 {
412 DPRINT("ExAllocatePoolWithTag() failed\n");
413 Status = STATUS_NO_MEMORY;
414 goto cleanup;
415 }
416
417 Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &KeyName, KEY_ENUMERATE_SUB_KEYS);
418 if (!NT_SUCCESS(Status))
419 {
420 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName, Status);
421 goto cleanup;
422 }
423
424 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
425 * KeyHandle. We'll first do a first enumeration to have first level keys,
426 * and an inner one to have the real devices list.
427 */
428 Index1 = 0;
429 while (TRUE)
430 {
431 Status = ZwEnumerateKey(
432 KeyHandle,
433 Index1,
434 KeyBasicInformation,
435 KeyInfo,
436 BufferSize,
437 &ResultSize);
438 if (Status == STATUS_NO_MORE_ENTRIES)
439 {
440 Status = STATUS_SUCCESS;
441 break;
442 }
443 else if (!NT_SUCCESS(Status))
444 {
445 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
446 goto cleanup;
447 }
448
449 /* Terminate the string */
450 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
451
452 /* Check if it is a legacy driver */
453 RtlInitUnicodeString(&SubKeyName, KeyInfo->Name);
454 if (RtlPrefixUnicodeString(&LegacyU, &SubKeyName, FALSE))
455 {
456 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName);
457 Index1++;
458 continue;
459 }
460
461 /* Open the key */
462 Status = IopOpenRegistryKeyEx(&SubKeyHandle, KeyHandle, &SubKeyName, KEY_ENUMERATE_SUB_KEYS);
463 if (!NT_SUCCESS(Status))
464 {
465 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
466 break;
467 }
468
469 /* Enumerate the sub-keys */
470 Index2 = 0;
471 while (TRUE)
472 {
473 Status = ZwEnumerateKey(
474 SubKeyHandle,
475 Index2,
476 KeyBasicInformation,
477 SubKeyInfo,
478 BufferSize,
479 &ResultSize);
480 if (Status == STATUS_NO_MORE_ENTRIES)
481 break;
482 else if (!NT_SUCCESS(Status))
483 {
484 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
485 break;
486 }
487
488 /* Terminate the string */
489 SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
490
491 _snwprintf(
492 DevicePath,
493 sizeof(DevicePath) / sizeof(WCHAR),
494 L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name);
495 DPRINT("Found device %S\\%s!\n", DevicePath, SubKeyInfo->Name);
496 if (LocateChildDevice(DeviceExtension, DevicePath, SubKeyInfo->Name, &Device) == STATUS_NO_SUCH_DEVICE)
497 {
498 /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
499 Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
500 if (!Device)
501 {
502 DPRINT("ExAllocatePoolWithTag() failed\n");
503 Status = STATUS_NO_MEMORY;
504 goto cleanup;
505 }
506 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
507
508 /* Fill device ID and instance ID */
509 if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
510 {
511 DPRINT1("RtlCreateUnicodeString() failed\n");
512 Status = STATUS_NO_MEMORY;
513 goto cleanup;
514 }
515
516 if (!RtlCreateUnicodeString(&Device->InstanceID, SubKeyInfo->Name))
517 {
518 DPRINT1("RtlCreateUnicodeString() failed\n");
519 Status = STATUS_NO_MEMORY;
520 goto cleanup;
521 }
522
523 /* Open registry key to fill other informations */
524 Status = IopOpenRegistryKeyEx(&DeviceKeyHandle, SubKeyHandle, &Device->InstanceID, KEY_READ);
525 if (!NT_SUCCESS(Status))
526 {
527 DPRINT1("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
528 break;
529 }
530
531 /* Fill information from the device instance key */
532 RtlZeroMemory(QueryTable, sizeof(QueryTable));
533 QueryTable[0].QueryRoutine = QueryStringCallback;
534 QueryTable[0].Name = L"DeviceDesc";
535 QueryTable[0].EntryContext = &Device->DeviceDescription;
536
537 RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
538 (PCWSTR)DeviceKeyHandle,
539 QueryTable,
540 NULL,
541 NULL);
542
543 /* Fill information from the LogConf subkey */
544 Buffer1.Data = (PVOID *)&Device->ResourceRequirementsList;
545 Buffer1.Length = NULL;
546 Buffer2.Data = (PVOID *)&Device->ResourceList;
547 Buffer2.Length = &Device->ResourceListSize;
548 RtlZeroMemory(QueryTable, sizeof(QueryTable));
549 QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
550 QueryTable[0].Name = L"LogConf";
551 QueryTable[1].QueryRoutine = QueryBinaryValueCallback;
552 QueryTable[1].Name = L"BasicConfigVector";
553 QueryTable[1].EntryContext = &Buffer1;
554 QueryTable[2].QueryRoutine = QueryBinaryValueCallback;
555 QueryTable[2].Name = L"BootConfig";
556 QueryTable[2].EntryContext = &Buffer2;
557
558 if (!NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
559 (PCWSTR)DeviceKeyHandle,
560 QueryTable,
561 NULL,
562 NULL)))
563 {
564 /* Non-fatal error */
565 DPRINT1("Failed to read the LogConf key for %S\\%S\n", DevicePath, SubKeyInfo->Name);
566 }
567
568 ZwClose(DeviceKeyHandle);
569 DeviceKeyHandle = INVALID_HANDLE_VALUE;
570
571 /* Insert the newly created device into the list */
572 InsertTailList(
573 &DeviceExtension->DeviceListHead,
574 &Device->ListEntry);
575 DeviceExtension->DeviceListCount++;
576 }
577 Device = NULL;
578
579 Index2++;
580 }
581
582 ZwClose(SubKeyHandle);
583 SubKeyHandle = INVALID_HANDLE_VALUE;
584 Index1++;
585 }
586
587 cleanup:
588 if (Device)
589 {
590 /* We have a device that has not been added to device list. We need to clean it up */
591 /* FIXME */
592 ExFreePoolWithTag(Device, TAG_PNP_ROOT);
593 }
594 if (DeviceKeyHandle != INVALID_HANDLE_VALUE)
595 ZwClose(DeviceKeyHandle);
596 if (SubKeyHandle != INVALID_HANDLE_VALUE)
597 ZwClose(SubKeyHandle);
598 if (KeyHandle != INVALID_HANDLE_VALUE)
599 ZwClose(KeyHandle);
600 if (KeyInfo)
601 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
602 if (SubKeyInfo)
603 ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
604 KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
605 return Status;
606 }
607
608 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
609 * ARGUMENTS:
610 * DeviceObject = Pointer to functional device object of the root bus driver
611 * Irp = Pointer to IRP that should be handled
612 * RETURNS:
613 * Status
614 */
615 static NTSTATUS
616 PnpRootQueryDeviceRelations(
617 IN PDEVICE_OBJECT DeviceObject,
618 IN PIRP Irp)
619 {
620 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
621 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
622 PDEVICE_RELATIONS Relations = NULL, OtherRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
623 PPNPROOT_DEVICE Device = NULL;
624 ULONG Size;
625 NTSTATUS Status;
626 PLIST_ENTRY NextEntry;
627
628 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject, Irp);
629
630 Status = EnumerateDevices(DeviceObject);
631 if (!NT_SUCCESS(Status))
632 {
633 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status);
634 return Status;
635 }
636
637 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
638
639 Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + sizeof(PDEVICE_OBJECT) * DeviceExtension->DeviceListCount;
640 if (OtherRelations)
641 {
642 /* Another bus driver has already created a DEVICE_RELATIONS
643 * structure so we must merge this structure with our own */
644
645 Size += sizeof(PDEVICE_OBJECT) * OtherRelations->Count;
646 }
647 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
648 if (!Relations)
649 {
650 DPRINT("ExAllocatePoolWithTag() failed\n");
651 Status = STATUS_NO_MEMORY;
652 goto cleanup;
653 }
654 RtlZeroMemory(Relations, Size);
655 if (OtherRelations)
656 {
657 Relations->Count = OtherRelations->Count;
658 RtlCopyMemory(Relations->Objects, OtherRelations->Objects, sizeof(PDEVICE_OBJECT) * OtherRelations->Count);
659 }
660
661 KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
662
663 /* Start looping */
664 for (NextEntry = DeviceExtension->DeviceListHead.Flink;
665 NextEntry != &DeviceExtension->DeviceListHead;
666 NextEntry = NextEntry->Flink)
667 {
668 /* Get the entry */
669 Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry);
670
671 if (!Device->Pdo)
672 {
673 /* Create a physical device object for the
674 * device as it does not already have one */
675 Status = IoCreateDevice(
676 DeviceObject->DriverObject,
677 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
678 NULL,
679 FILE_DEVICE_CONTROLLER,
680 FILE_AUTOGENERATED_DEVICE_NAME,
681 FALSE,
682 &Device->Pdo);
683 if (!NT_SUCCESS(Status))
684 {
685 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
686 break;
687 }
688
689 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
690 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
691 PdoDeviceExtension->Common.IsFDO = FALSE;
692 PdoDeviceExtension->DeviceInfo = Device;
693
694 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
695 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
696 }
697
698 /* Reference the physical device object. The PnP manager
699 will dereference it again when it is no longer needed */
700 ObReferenceObject(Device->Pdo);
701
702 Relations->Objects[Relations->Count++] = Device->Pdo;
703 }
704 KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
705
706 Irp->IoStatus.Information = (ULONG_PTR)Relations;
707
708 cleanup:
709 if (!NT_SUCCESS(Status))
710 {
711 if (OtherRelations)
712 ExFreePool(OtherRelations);
713 if (Relations)
714 ExFreePool(Relations);
715 if (Device && Device->Pdo)
716 {
717 IoDeleteDevice(Device->Pdo);
718 Device->Pdo = NULL;
719 }
720 }
721
722 return Status;
723 }
724
725 /*
726 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
727 * ARGUMENTS:
728 * DeviceObject = Pointer to functional device object of the root bus driver
729 * Irp = Pointer to IRP that should be handled
730 * RETURNS:
731 * Status
732 */
733 static NTSTATUS
734 PnpRootFdoPnpControl(
735 IN PDEVICE_OBJECT DeviceObject,
736 IN PIRP Irp)
737 {
738 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
739 PIO_STACK_LOCATION IrpSp;
740 NTSTATUS Status;
741
742 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
743 Status = Irp->IoStatus.Status;
744 IrpSp = IoGetCurrentIrpStackLocation(Irp);
745
746 switch (IrpSp->MinorFunction)
747 {
748 case IRP_MN_QUERY_DEVICE_RELATIONS:
749 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
750 Status = PnpRootQueryDeviceRelations(DeviceObject, Irp);
751 break;
752
753 case IRP_MN_START_DEVICE:
754 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
755 if (!IoForwardIrpSynchronously(DeviceExtension->Ldo, Irp))
756 Status = STATUS_UNSUCCESSFUL;
757 else
758 {
759 Status = Irp->IoStatus.Status;
760 if (NT_SUCCESS(Status))
761 DeviceExtension->State = dsStarted;
762 }
763
764 Irp->IoStatus.Status = Status;
765 IoCompleteRequest(Irp, IO_NO_INCREMENT);
766 return Status;
767
768 case IRP_MN_STOP_DEVICE:
769 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
770 /* Root device cannot be stopped */
771 Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
772 IoCompleteRequest(Irp, IO_NO_INCREMENT);
773 return Status;
774
775 default:
776 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
777 break;
778 }
779
780 if (Status != STATUS_PENDING)
781 {
782 Irp->IoStatus.Status = Status;
783 IoCompleteRequest(Irp, IO_NO_INCREMENT);
784 }
785
786 return Status;
787 }
788
789 static NTSTATUS
790 PdoQueryDeviceRelations(
791 IN PDEVICE_OBJECT DeviceObject,
792 IN PIRP Irp,
793 IN PIO_STACK_LOCATION IrpSp)
794 {
795 PDEVICE_RELATIONS Relations;
796 NTSTATUS Status = Irp->IoStatus.Status;
797
798 if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
799 return Status;
800
801 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
802 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
803 if (!Relations)
804 {
805 DPRINT("ExAllocatePoolWithTag() failed\n");
806 Status = STATUS_NO_MEMORY;
807 }
808 else
809 {
810 ObReferenceObject(DeviceObject);
811 Relations->Count = 1;
812 Relations->Objects[0] = DeviceObject;
813 Status = STATUS_SUCCESS;
814 Irp->IoStatus.Information = (ULONG_PTR)Relations;
815 }
816
817 return Status;
818 }
819
820 static NTSTATUS
821 PdoQueryCapabilities(
822 IN PDEVICE_OBJECT DeviceObject,
823 IN PIRP Irp,
824 IN PIO_STACK_LOCATION IrpSp)
825 {
826 PDEVICE_CAPABILITIES DeviceCapabilities;
827
828 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
829
830 if (DeviceCapabilities->Version != 1)
831 return STATUS_REVISION_MISMATCH;
832
833 DeviceCapabilities->UniqueID = TRUE;
834 /* FIXME: Fill other fields */
835
836 return STATUS_SUCCESS;
837 }
838
839 static NTSTATUS
840 PdoQueryResources(
841 IN PDEVICE_OBJECT DeviceObject,
842 IN PIRP Irp,
843 IN PIO_STACK_LOCATION IrpSp)
844 {
845 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
846 PCM_RESOURCE_LIST ResourceList;
847
848 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
849
850 if (DeviceExtension->DeviceInfo->ResourceList)
851 {
852 /* Copy existing resource requirement list */
853 ResourceList = ExAllocatePool(
854 PagedPool,
855 DeviceExtension->DeviceInfo->ResourceListSize);
856 if (!ResourceList)
857 return STATUS_NO_MEMORY;
858
859 RtlCopyMemory(
860 ResourceList,
861 DeviceExtension->DeviceInfo->ResourceList,
862 DeviceExtension->DeviceInfo->ResourceListSize);
863
864 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
865
866 return STATUS_SUCCESS;
867 }
868 else
869 {
870 /* No resources so just return without changing the status */
871 return Irp->IoStatus.Status;
872 }
873 }
874
875 static NTSTATUS
876 PdoQueryResourceRequirements(
877 IN PDEVICE_OBJECT DeviceObject,
878 IN PIRP Irp,
879 IN PIO_STACK_LOCATION IrpSp)
880 {
881 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
882 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
883
884 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
885
886 if (DeviceExtension->DeviceInfo->ResourceRequirementsList)
887 {
888 /* Copy existing resource requirement list */
889 ResourceList = ExAllocatePool(PagedPool, DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
890 if (!ResourceList)
891 return STATUS_NO_MEMORY;
892
893 RtlCopyMemory(
894 ResourceList,
895 DeviceExtension->DeviceInfo->ResourceRequirementsList,
896 DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
897
898 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
899
900 return STATUS_SUCCESS;
901 }
902 else
903 {
904 /* No resource requirements so just return without changing the status */
905 return Irp->IoStatus.Status;
906 }
907 }
908
909 static NTSTATUS
910 PdoQueryDeviceText(
911 IN PDEVICE_OBJECT DeviceObject,
912 IN PIRP Irp,
913 IN PIO_STACK_LOCATION IrpSp)
914 {
915 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
916 DEVICE_TEXT_TYPE DeviceTextType;
917 NTSTATUS Status = Irp->IoStatus.Status;
918
919 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
920 DeviceTextType = IrpSp->Parameters.QueryDeviceText.DeviceTextType;
921
922 switch (DeviceTextType)
923 {
924 case DeviceTextDescription:
925 {
926 UNICODE_STRING String;
927 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
928
929 if (DeviceExtension->DeviceInfo->DeviceDescription.Buffer != NULL)
930 {
931 Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
932 &DeviceExtension->DeviceInfo->DeviceDescription,
933 &String);
934 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
935 }
936 break;
937 }
938
939 case DeviceTextLocationInformation:
940 {
941 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
942 break;
943 }
944
945 default:
946 {
947 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType);
948 }
949 }
950
951 return Status;
952 }
953
954 static NTSTATUS
955 PdoQueryId(
956 IN PDEVICE_OBJECT DeviceObject,
957 IN PIRP Irp,
958 IN PIO_STACK_LOCATION IrpSp)
959 {
960 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
961 BUS_QUERY_ID_TYPE IdType;
962 NTSTATUS Status = Irp->IoStatus.Status;
963
964 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
965 IdType = IrpSp->Parameters.QueryId.IdType;
966
967 switch (IdType)
968 {
969 case BusQueryDeviceID:
970 {
971 UNICODE_STRING String;
972 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
973
974 Status = RtlDuplicateUnicodeString(
975 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
976 &DeviceExtension->DeviceInfo->DeviceID,
977 &String);
978 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
979 break;
980 }
981
982 case BusQueryHardwareIDs:
983 case BusQueryCompatibleIDs:
984 {
985 /* Optional, do nothing */
986 break;
987 }
988
989 case BusQueryInstanceID:
990 {
991 UNICODE_STRING String;
992 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
993
994 Status = RtlDuplicateUnicodeString(
995 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
996 &DeviceExtension->DeviceInfo->InstanceID,
997 &String);
998 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
999 break;
1000 }
1001
1002 default:
1003 {
1004 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
1005 }
1006 }
1007
1008 return Status;
1009 }
1010
1011 static NTSTATUS
1012 PdoQueryBusInformation(
1013 IN PDEVICE_OBJECT DeviceObject,
1014 IN PIRP Irp,
1015 IN PIO_STACK_LOCATION IrpSp)
1016 {
1017 PPNP_BUS_INFORMATION BusInfo;
1018 NTSTATUS Status;
1019
1020 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), TAG_PNP_ROOT);
1021 if (!BusInfo)
1022 Status = STATUS_NO_MEMORY;
1023 else
1024 {
1025 RtlCopyMemory(
1026 &BusInfo->BusTypeGuid,
1027 &GUID_BUS_TYPE_INTERNAL,
1028 sizeof(BusInfo->BusTypeGuid));
1029 BusInfo->LegacyBusType = PNPBus;
1030 /* We're the only root bus enumerator on the computer */
1031 BusInfo->BusNumber = 0;
1032 Irp->IoStatus.Information = (ULONG_PTR)BusInfo;
1033 Status = STATUS_SUCCESS;
1034 }
1035
1036 return Status;
1037 }
1038
1039 /*
1040 * FUNCTION: Handle Plug and Play IRPs for the child device
1041 * ARGUMENTS:
1042 * DeviceObject = Pointer to physical device object of the child device
1043 * Irp = Pointer to IRP that should be handled
1044 * RETURNS:
1045 * Status
1046 */
1047 static NTSTATUS
1048 PnpRootPdoPnpControl(
1049 IN PDEVICE_OBJECT DeviceObject,
1050 IN PIRP Irp)
1051 {
1052 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
1053 PPNPROOT_FDO_DEVICE_EXTENSION FdoDeviceExtension;
1054 PIO_STACK_LOCATION IrpSp;
1055 NTSTATUS Status;
1056
1057 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1058 FdoDeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
1059 Status = Irp->IoStatus.Status;
1060 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1061
1062 switch (IrpSp->MinorFunction)
1063 {
1064 case IRP_MN_START_DEVICE: /* 0x00 */
1065 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1066 Status = STATUS_SUCCESS;
1067 break;
1068
1069 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
1070 Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
1071 break;
1072
1073 case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
1074 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
1075 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
1076 break;
1077
1078 case IRP_MN_QUERY_RESOURCES: /* 0x0a */
1079 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
1080 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
1081 break;
1082
1083 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
1084 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1085 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
1086 break;
1087
1088 case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
1089 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1090 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
1091 break;
1092
1093 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
1094 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1095 break;
1096
1097 case IRP_MN_REMOVE_DEVICE:
1098 /* Remove the device from the device list and decrement the device count*/
1099 KeAcquireGuardedMutex(&FdoDeviceExtension->DeviceListLock);
1100 RemoveEntryList(&DeviceExtension->DeviceInfo->ListEntry);
1101 FdoDeviceExtension->DeviceListCount--;
1102 KeReleaseGuardedMutex(&FdoDeviceExtension->DeviceListLock);
1103
1104 /* Free some strings we created */
1105 RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceDescription);
1106 RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceID);
1107 RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->InstanceID);
1108
1109 /* Free the resource requirements list */
1110 if (DeviceExtension->DeviceInfo->ResourceRequirementsList != NULL)
1111 ExFreePool(DeviceExtension->DeviceInfo->ResourceRequirementsList);
1112
1113 /* Free the boot resources list */
1114 if (DeviceExtension->DeviceInfo->ResourceList != NULL)
1115 ExFreePool(DeviceExtension->DeviceInfo->ResourceList);
1116
1117 /* Free the device info */
1118 ExFreePool(DeviceExtension->DeviceInfo);
1119
1120 /* Finally, delete the device object */
1121 IoDeleteDevice(DeviceObject);
1122
1123 /* Return success */
1124 Status = STATUS_SUCCESS;
1125 break;
1126
1127 case IRP_MN_QUERY_ID: /* 0x13 */
1128 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
1129 break;
1130
1131 case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
1132 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
1133 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
1134 break;
1135
1136 default:
1137 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
1138 break;
1139 }
1140
1141 if (Status != STATUS_PENDING)
1142 {
1143 Irp->IoStatus.Status = Status;
1144 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1145 }
1146
1147 return Status;
1148 }
1149
1150 /*
1151 * FUNCTION: Handle Plug and Play IRPs
1152 * ARGUMENTS:
1153 * DeviceObject = Pointer to PDO or FDO
1154 * Irp = Pointer to IRP that should be handled
1155 * RETURNS:
1156 * Status
1157 */
1158 static NTSTATUS NTAPI
1159 PnpRootPnpControl(
1160 IN PDEVICE_OBJECT DeviceObject,
1161 IN PIRP Irp)
1162 {
1163 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
1164 NTSTATUS Status;
1165
1166 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1167
1168 if (DeviceExtension->IsFDO)
1169 Status = PnpRootFdoPnpControl(DeviceObject, Irp);
1170 else
1171 Status = PnpRootPdoPnpControl(DeviceObject, Irp);
1172
1173 return Status;
1174 }
1175
1176 NTSTATUS
1177 NTAPI
1178 PnpRootAddDevice(
1179 IN PDRIVER_OBJECT DriverObject,
1180 IN PDEVICE_OBJECT PhysicalDeviceObject)
1181 {
1182 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
1183 NTSTATUS Status;
1184
1185 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject, PhysicalDeviceObject);
1186
1187 if (!PhysicalDeviceObject)
1188 {
1189 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject);
1190 Status = STATUS_INSUFFICIENT_RESOURCES;
1191 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1192 }
1193
1194 Status = IoCreateDevice(
1195 DriverObject,
1196 sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
1197 NULL,
1198 FILE_DEVICE_BUS_EXTENDER,
1199 FILE_DEVICE_SECURE_OPEN,
1200 TRUE,
1201 &PnpRootDeviceObject);
1202 if (!NT_SUCCESS(Status))
1203 {
1204 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
1205 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1206 }
1207 DPRINT("Created FDO %p\n", PnpRootDeviceObject);
1208
1209 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
1210 RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
1211
1212 DeviceExtension->Common.IsFDO = TRUE;
1213 DeviceExtension->State = dsStopped;
1214 InitializeListHead(&DeviceExtension->DeviceListHead);
1215 DeviceExtension->DeviceListCount = 0;
1216 KeInitializeGuardedMutex(&DeviceExtension->DeviceListLock);
1217
1218 Status = IoAttachDeviceToDeviceStackSafe(
1219 PnpRootDeviceObject,
1220 PhysicalDeviceObject,
1221 &DeviceExtension->Ldo);
1222 if (!NT_SUCCESS(Status))
1223 {
1224 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
1225 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1226 }
1227
1228 PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1229
1230 DPRINT("Done AddDevice()\n");
1231
1232 return STATUS_SUCCESS;
1233 }
1234
1235 NTSTATUS NTAPI
1236 PnpRootDriverEntry(
1237 IN PDRIVER_OBJECT DriverObject,
1238 IN PUNICODE_STRING RegistryPath)
1239 {
1240 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject, RegistryPath);
1241
1242 IopRootDriverObject = DriverObject;
1243
1244 DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
1245
1246 DriverObject->MajorFunction[IRP_MJ_PNP] = PnpRootPnpControl;
1247 //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
1248
1249 return STATUS_SUCCESS;
1250 }