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