preliminary comment out the self-modifying code for RtlPrefetchMemoryNonTemporal
[reactos.git] / reactos / ntoskrnl / io / pnproot.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnproot.c
5 * PURPOSE: PnP manager root device
6 *
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/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 // Service name
29 UNICODE_STRING ServiceName;
30 // Device ID
31 UNICODE_STRING DeviceID;
32 // Instance ID
33 UNICODE_STRING InstanceID;
34 // Device description
35 UNICODE_STRING DeviceDescription;
36 // Resource requirement list
37 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
38 } PNPROOT_DEVICE, *PPNPROOT_DEVICE;
39
40 typedef enum
41 {
42 dsStopped,
43 dsStarted,
44 dsPaused,
45 dsRemoved,
46 dsSurpriseRemoved
47 } PNPROOT_DEVICE_STATE;
48
49
50 #include <pshpack1.h>
51
52 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
53 {
54 // Pointer to device object, this device extension is associated with
55 PDEVICE_OBJECT DeviceObject;
56 // Wether this device extension is for an FDO or PDO
57 BOOLEAN IsFDO;
58 // Wether the device is removed
59 BOOLEAN Removed;
60 // Current device power state for the device
61 DEVICE_POWER_STATE DevicePowerState;
62 } PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION;
63
64
65 /* Physical Device Object device extension for a child device */
66 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
67 {
68 // Common device data
69 PNPROOT_COMMON_DEVICE_EXTENSION Common;
70 // Device ID
71 UNICODE_STRING DeviceID;
72 // Instance ID
73 UNICODE_STRING InstanceID;
74 // Resource requirement list
75 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
76 } PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;
77
78
79 /* Functional Device Object device extension for the PCI driver device object */
80 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
81 {
82 // Common device data
83 PNPROOT_COMMON_DEVICE_EXTENSION Common;
84 // Physical Device Object
85 PDEVICE_OBJECT Pdo;
86 // Lower device object
87 PDEVICE_OBJECT Ldo;
88 // Current state of the driver
89 PNPROOT_DEVICE_STATE State;
90 // Namespace device list
91 LIST_ENTRY DeviceListHead;
92 // Number of (not removed) devices in device list
93 ULONG DeviceListCount;
94 // Lock for namespace device list
95 // FIXME: Use fast mutex instead?
96 KSPIN_LOCK DeviceListLock;
97 } PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;
98
99 #include <poppack.h>
100
101
102
103 PDEVICE_OBJECT PnpRootDeviceObject;
104
105
106 /* FUNCTIONS *****************************************************************/
107
108 /* Physical Device Object routines */
109
110 NTSTATUS
111 PnpRootCreateDevice(
112 PDEVICE_OBJECT *PhysicalDeviceObject)
113 {
114 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
115 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
116 PPNPROOT_DEVICE Device;
117 NTSTATUS Status;
118
119 /* This function should be obsoleted soon */
120
121 DPRINT("Called\n");
122
123 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
124
125 Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
126 if (!Device)
127 return STATUS_INSUFFICIENT_RESOURCES;
128
129 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
130
131 Status = IoCreateDevice(
132 PnpRootDeviceObject->DriverObject,
133 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
134 NULL,
135 FILE_DEVICE_CONTROLLER,
136 FILE_AUTOGENERATED_DEVICE_NAME,
137 FALSE,
138 &Device->Pdo);
139 if (!NT_SUCCESS(Status)) {
140 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
141 ExFreePool(Device);
142 return Status;
143 }
144
145 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
146
147 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
148
149 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
150
151 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
152
153 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
154
155 PdoDeviceExtension->Common.IsFDO = FALSE;
156
157 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
158
159 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
160
161 if (!RtlCreateUnicodeString(
162 &PdoDeviceExtension->DeviceID,
163 ENUM_NAME_ROOT \
164 L"\\LEGACY_UNKNOWN"))
165 {
166 /* FIXME: */
167 DPRINT("RtlCreateUnicodeString() failed\n");
168 }
169
170 if (!RtlCreateUnicodeString(
171 &PdoDeviceExtension->InstanceID,
172 L"0000"))
173 {
174 /* FIXME: */
175 DPRINT("RtlCreateUnicodeString() failed\n");
176 }
177
178 ExInterlockedInsertTailList(
179 &DeviceExtension->DeviceListHead,
180 &Device->ListEntry,
181 &DeviceExtension->DeviceListLock);
182
183 DeviceExtension->DeviceListCount++;
184
185 *PhysicalDeviceObject = Device->Pdo;
186
187 return STATUS_SUCCESS;
188 }
189
190
191 NTSTATUS
192 PdoQueryId(
193 IN PDEVICE_OBJECT DeviceObject,
194 IN PIRP Irp,
195 PIO_STACK_LOCATION IrpSp)
196 {
197 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
198 UNICODE_STRING String;
199 NTSTATUS Status;
200
201 DPRINT("Called\n");
202
203 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
204
205 // Irp->IoStatus.Information = 0;
206
207 Status = STATUS_SUCCESS;
208
209 RtlInitUnicodeString(&String, NULL);
210
211 switch (IrpSp->Parameters.QueryId.IdType) {
212 case BusQueryDeviceID:
213 Status = RtlDuplicateUnicodeString(TRUE,
214 &DeviceExtension->DeviceID,
215 &String);
216
217 DPRINT("DeviceID: %wZ\n", &String);
218
219 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
220 break;
221
222 case BusQueryHardwareIDs:
223 case BusQueryCompatibleIDs:
224 Status = STATUS_NOT_IMPLEMENTED;
225 break;
226
227 case BusQueryInstanceID:
228 Status = RtlDuplicateUnicodeString(TRUE,
229 &DeviceExtension->InstanceID,
230 &String);
231
232 DPRINT("InstanceID: %S\n", String.Buffer);
233
234 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
235 break;
236
237 case BusQueryDeviceSerialNumber:
238 default:
239 Status = STATUS_NOT_IMPLEMENTED;
240 }
241
242 return Status;
243 }
244
245
246 NTSTATUS
247 PdoQueryResources(
248 IN PDEVICE_OBJECT DeviceObject,
249 IN PIRP Irp,
250 PIO_STACK_LOCATION IrpSp)
251 {
252 PCM_RESOURCE_LIST ResourceList;
253 ULONG ResourceListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);
254
255 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
256 if (ResourceList == NULL)
257 return STATUS_INSUFFICIENT_RESOURCES;
258
259 ResourceList->Count = 0;
260
261 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
262
263 return STATUS_SUCCESS;
264 }
265
266
267 NTSTATUS
268 PdoQueryResourceRequirements(
269 IN PDEVICE_OBJECT DeviceObject,
270 IN PIRP Irp,
271 PIO_STACK_LOCATION IrpSp)
272 {
273 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
274 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
275 ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
276
277 DPRINT("Called\n");
278
279 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
280
281 if (DeviceExtension->ResourceRequirementsList == NULL)
282 {
283 /* Create an empty resource list */
284 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
285 if (ResourceList == NULL)
286 return STATUS_INSUFFICIENT_RESOURCES;
287
288 RtlZeroMemory(ResourceList, ResourceListSize);
289 ResourceList->ListSize = ResourceListSize;
290
291 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
292 }
293 else
294 {
295 /* Copy existing resource requirement list */
296 ResourceList = ExAllocatePool(PagedPool, DeviceExtension->ResourceRequirementsList->ListSize);
297 if (ResourceList == NULL)
298 return STATUS_INSUFFICIENT_RESOURCES;
299
300 RtlCopyMemory(
301 ResourceList,
302 DeviceExtension->ResourceRequirementsList,
303 DeviceExtension->ResourceRequirementsList->ListSize);
304 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
305 }
306
307 return STATUS_SUCCESS;
308 }
309
310
311 static NTSTATUS
312 PnpRootPdoQueryCapabilities(
313 IN PDEVICE_OBJECT DeviceObject,
314 IN PIRP Irp,
315 PIO_STACK_LOCATION IrpSp)
316 {
317 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
318 PDEVICE_CAPABILITIES DeviceCapabilities;
319
320 DPRINT("Called\n");
321
322 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
323 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
324
325 if (DeviceCapabilities->Version != 1)
326 return STATUS_UNSUCCESSFUL;
327
328 DeviceCapabilities->UniqueID = TRUE;
329 /* FIXME: Fill other fields */
330
331 return STATUS_SUCCESS;
332 }
333
334
335 /*
336 * FUNCTION: Handle Plug and Play IRPs for the child device
337 * ARGUMENTS:
338 * DeviceObject = Pointer to physical device object of the child device
339 * Irp = Pointer to IRP that should be handled
340 * RETURNS:
341 * Status
342 */
343 NTSTATUS
344 PnpRootPdoPnpControl(
345 PDEVICE_OBJECT DeviceObject,
346 PIRP Irp)
347 {
348 PIO_STACK_LOCATION IrpSp;
349 NTSTATUS Status;
350
351 DPRINT("Called\n");
352
353 Status = Irp->IoStatus.Status;
354
355 IrpSp = IoGetCurrentIrpStackLocation(Irp);
356
357 switch (IrpSp->MinorFunction) {
358 #if 0
359 case IRP_MN_QUERY_BUS_INFORMATION:
360 break;
361
362 case IRP_MN_QUERY_DEVICE_RELATIONS:
363 /* FIXME: Handle for TargetDeviceRelation */
364 break;
365 #endif
366
367 case IRP_MN_QUERY_ID:
368 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
369 break;
370
371 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
372 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
373 break;
374
375 case IRP_MN_QUERY_RESOURCES:
376 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
377 break;
378
379 case IRP_MN_QUERY_CAPABILITIES:
380 Status = PnpRootPdoQueryCapabilities(DeviceObject, Irp, IrpSp);
381 break;
382
383 case IRP_MN_START_DEVICE:
384 case IRP_MN_QUERY_STOP_DEVICE:
385 case IRP_MN_CANCEL_STOP_DEVICE:
386 case IRP_MN_STOP_DEVICE:
387 case IRP_MN_QUERY_REMOVE_DEVICE:
388 case IRP_MN_CANCEL_REMOVE_DEVICE:
389 case IRP_MN_REMOVE_DEVICE:
390 case IRP_MN_SURPRISE_REMOVAL:
391 Status = STATUS_SUCCESS;
392 break;
393
394 default:
395 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
396 break;
397 }
398
399 Irp->IoStatus.Status = Status;
400 IoCompleteRequest(Irp, IO_NO_INCREMENT);
401
402 DPRINT("Leaving. Status 0x%X\n", Status);
403
404 return Status;
405 }
406
407
408 /*
409 * FUNCTION: Handle power management IRPs for the child device
410 * ARGUMENTS:
411 * DeviceObject = Pointer to physical device object of the child device
412 * Irp = Pointer to IRP that should be handled
413 * RETURNS:
414 * Status
415 */
416 NTSTATUS
417 PnpRootPdoPowerControl(
418 PDEVICE_OBJECT DeviceObject,
419 PIRP Irp)
420 {
421 PIO_STACK_LOCATION IrpSp;
422 NTSTATUS Status;
423
424 DPRINT("Called\n");
425
426 Status = Irp->IoStatus.Status;
427
428 IrpSp = IoGetCurrentIrpStackLocation(Irp);
429
430 switch (IrpSp->MinorFunction) {
431 default:
432 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
433 Status = STATUS_NOT_IMPLEMENTED;
434 break;
435 }
436
437 Irp->IoStatus.Status = Status;
438 IoCompleteRequest(Irp, IO_NO_INCREMENT);
439
440 DPRINT("Leaving. Status 0x%X\n", Status);
441
442 return Status;
443 }
444
445
446 /* Functional Device Object routines */
447
448 static NTSTATUS
449 PnpRootReadRegistryBinary(
450 IN PWSTR KeyName,
451 IN PWSTR ValueKeyName,
452 OUT PVOID* Buffer)
453 {
454 OBJECT_ATTRIBUTES ObjectAttributes;
455 UNICODE_STRING KeyNameU;
456 UNICODE_STRING ValueKeyNameU;
457 KEY_VALUE_PARTIAL_INFORMATION Size;
458 PKEY_VALUE_PARTIAL_INFORMATION Data = NULL;
459 ULONG DataSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
460 HANDLE KeyHandle;
461 NTSTATUS Status;
462
463 DPRINT("Called\n");
464
465 RtlInitUnicodeString(&KeyNameU, KeyName);
466 RtlInitUnicodeString(&ValueKeyNameU, ValueKeyName);
467
468 InitializeObjectAttributes(
469 &ObjectAttributes,
470 &KeyNameU,
471 OBJ_CASE_INSENSITIVE,
472 NULL, /* Root dir */
473 NULL); /* Security descriptor */
474 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
475 if (!NT_SUCCESS(Status))
476 {
477 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
478 return Status;
479 }
480
481 Status = ZwQueryValueKey(
482 KeyHandle,
483 &ValueKeyNameU,
484 KeyValuePartialInformation,
485 &Size, DataSize,
486 &DataSize);
487 if (Status != STATUS_BUFFER_OVERFLOW)
488 {
489 DPRINT("ZwQueryValueKey() failed (Status 0x%08lx)\n", Status);
490 ZwClose(KeyHandle);
491 return Status;
492 }
493
494 while (Status == STATUS_BUFFER_OVERFLOW)
495 {
496 if (Data)
497 ExFreePoolWithTag(Data, TAG_PNP_ROOT);
498 Data = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, DataSize, TAG_PNP_ROOT);
499 if (!Data)
500 {
501 DPRINT("ExAllocatePoolWithTag() failed\n", Status);
502 ZwClose(KeyHandle);
503 return Status;
504 }
505
506 Status = ZwQueryValueKey(
507 KeyHandle,
508 &ValueKeyNameU,
509 KeyValuePartialInformation,
510 Data, DataSize,
511 &DataSize);
512 if (NT_SUCCESS(Status))
513 {
514 *Buffer = ExAllocatePoolWithTag(PagedPool, Data->DataLength, TAG_PNP_ROOT);
515 if (!*Buffer)
516 {
517 DPRINT("ExAllocatePoolWithTag() failed\n", Status);
518 ExFreePoolWithTag(Data, TAG_PNP_ROOT);
519 ZwClose(KeyHandle);
520 return Status;
521 }
522
523 RtlCopyMemory(
524 *Buffer,
525 Data->Data,
526 Data->DataLength);
527 break;
528 }
529 }
530
531 if (Data)
532 ExFreePoolWithTag(Data, TAG_PNP_ROOT);
533 ZwClose(KeyHandle);
534
535 return Status;
536 }
537
538 NTSTATUS
539 PnpRootFdoReadDeviceInfo(
540 PPNPROOT_DEVICE Device)
541 {
542 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
543 PUNICODE_STRING DeviceDesc;
544 WCHAR KeyName[MAX_PATH];
545 NTSTATUS Status;
546
547 DPRINT("Called\n");
548
549 /* Retrieve configuration from Enum key */
550
551 DeviceDesc = &Device->DeviceDescription;
552
553 wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
554 wcscat(KeyName, ENUM_NAME_ROOT);
555 wcscat(KeyName, L"\\");
556 wcscat(KeyName, Device->ServiceName.Buffer);
557 wcscat(KeyName, L"\\");
558 wcscat(KeyName, Device->InstanceID.Buffer);
559
560 DPRINT("KeyName %S\n", KeyName);
561
562 /* 1. Read informations in instance key */
563 RtlZeroMemory(QueryTable, sizeof(QueryTable));
564
565 RtlInitUnicodeString(DeviceDesc, NULL);
566
567 QueryTable[0].Name = L"DeviceDesc";
568 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
569 QueryTable[0].EntryContext = DeviceDesc;
570
571 Status = RtlQueryRegistryValues(
572 RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
573 KeyName,
574 QueryTable,
575 NULL,
576 NULL);
577
578 DPRINT("RtlQueryRegistryValues() returned status 0x%08lx\n", Status);
579
580 if (!NT_SUCCESS(Status))
581 {
582 /* FIXME: */
583 }
584
585 DPRINT("Got device description: %S\n", DeviceDesc->Buffer);
586
587 /* 2. Read informations in instance key, LogConf subkey */
588 RtlZeroMemory(QueryTable, sizeof(QueryTable));
589 wcscat(KeyName, L"\\LogConf");
590
591 Status = PnpRootReadRegistryBinary(
592 KeyName,
593 L"BasicConfigVector",
594 (PVOID*)&Device->ResourceRequirementsList);
595
596 DPRINT("PnpRootReadRegistryBinary() returned status 0x%08lx\n", Status);
597
598 if (!NT_SUCCESS(Status))
599 {
600 /* FIXME: */
601 }
602
603 return STATUS_SUCCESS;
604 }
605
606
607 NTSTATUS
608 PnpRootFdoEnumerateDevices(
609 PDEVICE_OBJECT DeviceObject)
610 {
611 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
612 OBJECT_ATTRIBUTES ObjectAttributes, SubKeyAttributes;
613 PKEY_BASIC_INFORMATION KeyInfo, SubKeyInfo;
614 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" ENUM_NAME_ROOT);
615 UNICODE_STRING SubKeyName;
616 PPNPROOT_DEVICE Device;
617 WCHAR Buffer[MAX_PATH];
618 HANDLE KeyHandle, SubKeyHandle;
619 ULONG BufferSize;
620 ULONG ResultSize;
621 NTSTATUS Status;
622 ULONG Index1, Index2;
623
624 DPRINT("Called\n");
625
626 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
627
628 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
629 KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
630 if (!KeyInfo)
631 {
632 return STATUS_INSUFFICIENT_RESOURCES;
633 }
634 SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
635 if (!SubKeyInfo)
636 {
637 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
638 return STATUS_INSUFFICIENT_RESOURCES;
639 }
640
641 InitializeObjectAttributes(
642 &ObjectAttributes,
643 &KeyName,
644 OBJ_CASE_INSENSITIVE,
645 NULL,
646 NULL);
647
648 Status = ZwOpenKey(&KeyHandle, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
649 if (!NT_SUCCESS(Status))
650 {
651 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
652 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
653 ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
654 return Status;
655 }
656
657 /* FIXME: Disabled due to still using the old method of auto loading drivers e.g.
658 there are more entries in the list than found in the registry as some
659 drivers are passed on the command line */
660 // DeviceExtension->DeviceListCount = 0;
661
662 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
663 * KeyHandle. We'll first do a first enumeration to have first level keys,
664 * and an inner one to have the real devices list.
665 */
666 Index1 = 0;
667
668 while (TRUE)
669 {
670 Status = ZwEnumerateKey(
671 KeyHandle,
672 Index1,
673 KeyBasicInformation,
674 KeyInfo,
675 BufferSize,
676 &ResultSize);
677 if (!NT_SUCCESS(Status))
678 {
679 DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status);
680 break;
681 }
682
683 /* Terminate the string */
684 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
685
686 /* Open the key */
687 RtlInitUnicodeString(&SubKeyName, KeyInfo->Name);
688 InitializeObjectAttributes(
689 &SubKeyAttributes,
690 &SubKeyName,
691 0, /* Attributes */
692 KeyHandle,
693 NULL); /* Security descriptor */
694 Status = ZwOpenKey(&SubKeyHandle, KEY_ENUMERATE_SUB_KEYS, &SubKeyAttributes);
695 if (!NT_SUCCESS(Status))
696 {
697 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
698 break;
699 }
700
701 /* Enumerate the sub-keys */
702 Index2 = 0;
703 while (TRUE)
704 {
705 Status = ZwEnumerateKey(
706 SubKeyHandle,
707 Index2,
708 KeyBasicInformation,
709 SubKeyInfo,
710 BufferSize,
711 &ResultSize);
712 if (!NT_SUCCESS(Status))
713 {
714 DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status);
715 break;
716 }
717
718 /* Terminate the string */
719 SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
720
721 Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
722 if (!Device)
723 {
724 /* FIXME: */
725 DPRINT("ExAllocatePoolWithTag() failed\n");
726 break;
727 }
728
729 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
730
731 if (!RtlCreateUnicodeString(&Device->ServiceName, KeyInfo->Name))
732 {
733 /* FIXME: */
734 DPRINT("RtlCreateUnicodeString() failed\n");
735 }
736
737 wcscpy(Buffer, ENUM_NAME_ROOT);
738 wcscat(Buffer, L"\\");
739 wcscat(Buffer, KeyInfo->Name);
740
741 if (!RtlCreateUnicodeString(&Device->DeviceID, Buffer))
742 {
743 /* FIXME: */
744 DPRINT("RtlCreateUnicodeString() failed\n");
745 }
746
747 DPRINT("Got entry: %S\n", Device->DeviceID.Buffer);
748
749 if (!RtlCreateUnicodeString(
750 &Device->InstanceID,
751 SubKeyInfo->Name))
752 {
753 /* FIXME: */
754 DPRINT("RtlCreateUnicodeString() failed\n");
755 }
756
757 Status = PnpRootFdoReadDeviceInfo(Device);
758 if (!NT_SUCCESS(Status))
759 {
760 /* FIXME */
761 DPRINT("PnpRootFdoReadDeviceInfo() failed with status 0x%08lx\n", Status);
762 }
763
764 ExInterlockedInsertTailList(
765 &DeviceExtension->DeviceListHead,
766 &Device->ListEntry,
767 &DeviceExtension->DeviceListLock);
768
769 DeviceExtension->DeviceListCount++;
770
771 Index2++;
772 }
773
774 ZwClose(SubKeyHandle);
775 Index1++;
776 }
777
778 ZwClose(KeyHandle);
779
780 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
781 ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
782
783 return STATUS_SUCCESS;
784 }
785
786
787 NTSTATUS
788 PnpRootQueryBusRelations(
789 IN PDEVICE_OBJECT DeviceObject,
790 IN PIRP Irp,
791 IN PIO_STACK_LOCATION IrpSp)
792 {
793 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
794 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
795 PDEVICE_RELATIONS Relations;
796 PPNPROOT_DEVICE Device;
797 NTSTATUS Status;
798 ULONG Size;
799 ULONG i;
800
801 DPRINT("Called\n");
802
803 Status = PnpRootFdoEnumerateDevices(DeviceObject);
804 if (!NT_SUCCESS(Status))
805 return Status;
806
807 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
808
809 if (Irp->IoStatus.Information)
810 {
811 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
812 structure so we must merge this structure with our own */
813 }
814
815 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
816 (DeviceExtension->DeviceListCount - 1);
817
818 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
819 if (!Relations)
820 return STATUS_INSUFFICIENT_RESOURCES;
821
822 Relations->Count = DeviceExtension->DeviceListCount;
823
824 i = 0;
825 LIST_FOR_EACH(Device,&DeviceExtension->DeviceListHead,PNPROOT_DEVICE, ListEntry)
826 {
827 if (!Device->Pdo)
828 {
829 /* Create a physical device object for the
830 device as it does not already have one */
831 Status = IoCreateDevice(
832 DeviceObject->DriverObject,
833 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
834 NULL,
835 FILE_DEVICE_CONTROLLER,
836 FILE_AUTOGENERATED_DEVICE_NAME,
837 FALSE,
838 &Device->Pdo);
839 if (!NT_SUCCESS(Status))
840 {
841 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
842 ExFreePool(Relations);
843 return Status;
844 }
845
846 DPRINT("Created PDO 0x%p\n", Device->Pdo);
847
848 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
849
850 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
851
852 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
853
854 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
855
856 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
857
858 PdoDeviceExtension->Common.IsFDO = FALSE;
859
860 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
861
862 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
863
864 if (!RtlCreateUnicodeString(
865 &PdoDeviceExtension->DeviceID,
866 Device->DeviceID.Buffer))
867 {
868 DPRINT("Insufficient resources\n");
869 /* FIXME: */
870 }
871
872 DPRINT("DeviceID: %wZ PDO %p\n",
873 &PdoDeviceExtension->DeviceID,
874 Device->Pdo);
875
876 if (!RtlCreateUnicodeString(
877 &PdoDeviceExtension->InstanceID,
878 Device->InstanceID.Buffer))
879 {
880 DPRINT("Insufficient resources\n");
881 /* FIXME: */
882 }
883
884 DPRINT("InstanceID: %wZ PDO %p\n",
885 &PdoDeviceExtension->InstanceID,
886 Device->Pdo);
887
888 if (Device->ResourceRequirementsList != NULL)
889 {
890 PdoDeviceExtension->ResourceRequirementsList = ExAllocatePoolWithTag(
891 PagedPool,
892 Device->ResourceRequirementsList->ListSize,
893 TAG_PNP_ROOT);
894 if (PdoDeviceExtension->ResourceRequirementsList)
895 {
896 RtlCopyMemory(
897 PdoDeviceExtension->ResourceRequirementsList,
898 Device->ResourceRequirementsList,
899 Device->ResourceRequirementsList->ListSize);
900 }
901 else
902 {
903 /* FIXME */
904 DPRINT("ExAllocatePoolWithTag() failed\n");
905 }
906 }
907
908 DPRINT("ResourceRequirementsList: %p PDO %p\n",
909 PdoDeviceExtension->ResourceRequirementsList,
910 Device->Pdo);
911 }
912
913 /* Reference the physical device object. The PnP manager
914 will dereference it again when it is no longer needed */
915 ObReferenceObject(Device->Pdo);
916
917 Relations->Objects[i] = Device->Pdo;
918
919 i++;
920 }
921
922 if (NT_SUCCESS(Status))
923 {
924 Irp->IoStatus.Information = (ULONG_PTR)Relations;
925 }
926 else
927 {
928 Irp->IoStatus.Information = 0;
929 }
930
931 return Status;
932 }
933
934
935 NTSTATUS
936 PnpRootQueryDeviceRelations(
937 IN PDEVICE_OBJECT DeviceObject,
938 IN PIRP Irp,
939 IN PIO_STACK_LOCATION IrpSp)
940 {
941 NTSTATUS Status;
942
943 DPRINT("Called\n");
944
945 switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
946 case BusRelations:
947 Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp);
948 break;
949
950 default:
951 Status = STATUS_NOT_IMPLEMENTED;
952 }
953
954 return Status;
955 }
956
957
958 /*
959 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
960 * ARGUMENTS:
961 * DeviceObject = Pointer to functional device object of the root bus driver
962 * Irp = Pointer to IRP that should be handled
963 * RETURNS:
964 * Status
965 */
966 NTSTATUS
967 STDCALL
968 PnpRootFdoPnpControl(
969 IN PDEVICE_OBJECT DeviceObject,
970 IN PIRP Irp)
971 {
972 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
973 PIO_STACK_LOCATION IrpSp;
974 NTSTATUS Status;
975
976 DPRINT("Called\n");
977
978 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
979
980 Status = Irp->IoStatus.Status;
981
982 IrpSp = IoGetCurrentIrpStackLocation(Irp);
983
984 switch (IrpSp->MinorFunction) {
985 case IRP_MN_QUERY_DEVICE_RELATIONS:
986 Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp);
987 break;
988
989 case IRP_MN_START_DEVICE:
990 DeviceExtension->State = dsStarted;
991 Status = STATUS_SUCCESS;
992 break;
993
994 case IRP_MN_STOP_DEVICE:
995 /* Root device cannot be stopped */
996 Status = STATUS_UNSUCCESSFUL;
997 break;
998
999 default:
1000 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1001 Status = STATUS_NOT_IMPLEMENTED;
1002 break;
1003 }
1004
1005 if (Status != STATUS_PENDING) {
1006 Irp->IoStatus.Status = Status;
1007 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1008 }
1009
1010 DPRINT("Leaving. Status 0x%X\n", Status);
1011
1012 return Status;
1013 }
1014
1015
1016 /*
1017 * FUNCTION: Handle power management IRPs for the root bus device object
1018 * ARGUMENTS:
1019 * DeviceObject = Pointer to functional device object of the root bus driver
1020 * Irp = Pointer to IRP that should be handled
1021 * RETURNS:
1022 * Status
1023 */
1024 NTSTATUS
1025 STDCALL
1026 PnpRootFdoPowerControl(
1027 IN PDEVICE_OBJECT DeviceObject,
1028 IN PIRP Irp)
1029 {
1030 PIO_STACK_LOCATION IrpSp;
1031 NTSTATUS Status;
1032
1033 DPRINT("Called\n");
1034
1035 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1036
1037 switch (IrpSp->MinorFunction) {
1038 default:
1039 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1040 Status = STATUS_NOT_IMPLEMENTED;
1041 break;
1042 }
1043
1044 if (Status != STATUS_PENDING) {
1045 Irp->IoStatus.Status = Status;
1046 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1047 }
1048
1049 DPRINT("Leaving. Status 0x%X\n", Status);
1050
1051 return Status;
1052 }
1053
1054
1055 /*
1056 * FUNCTION: Handle Plug and Play IRPs
1057 * ARGUMENTS:
1058 * DeviceObject = Pointer to PDO or FDO
1059 * Irp = Pointer to IRP that should be handled
1060 * RETURNS:
1061 * Status
1062 */
1063 NTSTATUS
1064 STDCALL
1065 PnpRootPnpControl(
1066 IN PDEVICE_OBJECT DeviceObject,
1067 IN PIRP Irp)
1068 {
1069 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
1070 NTSTATUS Status;
1071
1072 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1073
1074 DPRINT("DeviceObject 0x%p DeviceExtension 0x%p IsFDO %d\n",
1075 DeviceObject,
1076 DeviceExtension,
1077 DeviceExtension->IsFDO);
1078
1079 if (DeviceExtension->IsFDO) {
1080 Status = PnpRootFdoPnpControl(DeviceObject, Irp);
1081 } else {
1082 Status = PnpRootPdoPnpControl(DeviceObject, Irp);
1083 }
1084
1085 return Status;
1086 }
1087
1088
1089 /*
1090 * FUNCTION: Handle power management IRPs
1091 * ARGUMENTS:
1092 * DeviceObject = Pointer to PDO or FDO
1093 * Irp = Pointer to IRP that should be handled
1094 * RETURNS:
1095 * Status
1096 */
1097 NTSTATUS
1098 STDCALL
1099 PnpRootPowerControl(
1100 IN PDEVICE_OBJECT DeviceObject,
1101 IN PIRP Irp)
1102 {
1103 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
1104 NTSTATUS Status;
1105
1106 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1107
1108 if (DeviceExtension->IsFDO) {
1109 Status = PnpRootFdoPowerControl(DeviceObject, Irp);
1110 } else {
1111 Status = PnpRootPdoPowerControl(DeviceObject, Irp);
1112 }
1113
1114 return Status;
1115 }
1116
1117
1118 NTSTATUS
1119 STDCALL
1120 PnpRootAddDevice(
1121 IN PDRIVER_OBJECT DriverObject,
1122 IN PDEVICE_OBJECT PhysicalDeviceObject)
1123 {
1124 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
1125 NTSTATUS Status;
1126
1127 DPRINT("Called\n");
1128
1129 Status = IoCreateDevice(
1130 DriverObject,
1131 sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
1132 NULL,
1133 FILE_DEVICE_BUS_EXTENDER,
1134 FILE_DEVICE_SECURE_OPEN,
1135 TRUE,
1136 &PnpRootDeviceObject);
1137 if (!NT_SUCCESS(Status)) {
1138 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1139 }
1140
1141 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
1142
1143 RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
1144
1145 DeviceExtension->Common.IsFDO = TRUE;
1146
1147 DeviceExtension->State = dsStopped;
1148
1149 DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(
1150 PnpRootDeviceObject,
1151 PhysicalDeviceObject);
1152
1153 if (!PnpRootDeviceObject) {
1154 CPRINT("PnpRootDeviceObject 0x%p\n", PnpRootDeviceObject);
1155 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1156 }
1157
1158 if (!PhysicalDeviceObject) {
1159 CPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject);
1160 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1161 }
1162
1163 InitializeListHead(&DeviceExtension->DeviceListHead);
1164
1165 DeviceExtension->DeviceListCount = 0;
1166
1167 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
1168
1169 PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1170
1171 //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE;
1172
1173 DPRINT("Done AddDevice()\n");
1174
1175 return STATUS_SUCCESS;
1176 }
1177
1178
1179 NTSTATUS
1180 STDCALL
1181 PnpRootDriverEntry(
1182 IN PDRIVER_OBJECT DriverObject,
1183 IN PUNICODE_STRING RegistryPath)
1184 {
1185 DPRINT("Called\n");
1186
1187 DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PnpRootPnpControl;
1188 DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PnpRootPowerControl;
1189 DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
1190
1191 return STATUS_SUCCESS;
1192 }
1193
1194 /* EOF */