2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES ******************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *******************************************************************/
20 PDEVICE_NODE IopRootDeviceNode
;
21 KSPIN_LOCK IopDeviceTreeLock
;
23 /* DATA **********************************************************************/
25 PDRIVER_OBJECT IopRootDriverObject
;
26 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
29 ULONG crc32Table
[256] =
31 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
32 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
33 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
34 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
35 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
36 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
37 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
38 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
39 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
40 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
41 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
42 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
43 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
44 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
45 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
46 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
48 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
49 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
50 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
51 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
52 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
53 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
54 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
55 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
56 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
57 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
58 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
59 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
60 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
61 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
62 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
63 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
65 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
66 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
67 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
68 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
69 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
70 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
71 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
72 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
73 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
74 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
75 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
76 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
77 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
78 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
79 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
80 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
82 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
83 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
84 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
85 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
86 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
87 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
88 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
89 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
90 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
91 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
92 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
93 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
94 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
95 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
96 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
97 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
101 /* FUNCTIONS *****************************************************************/
103 PDEVICE_NODE FASTCALL
105 PDEVICE_OBJECT DeviceObject
)
107 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
112 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
113 PDEVICE_CAPABILITIES DeviceCaps
)
115 IO_STATUS_BLOCK StatusBlock
;
116 IO_STACK_LOCATION Stack
;
118 /* Set up the Header */
119 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
120 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
121 DeviceCaps
->Version
= 1;
122 DeviceCaps
->Address
= -1;
123 DeviceCaps
->UINumber
= -1;
125 /* Set up the Stack */
126 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
127 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
130 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
132 IRP_MN_QUERY_CAPABILITIES
,
141 IoInvalidateDeviceRelations(
142 IN PDEVICE_OBJECT DeviceObject
,
143 IN DEVICE_RELATION_TYPE Type
)
145 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Type
);
154 IN PDEVICE_OBJECT DeviceObject
,
155 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
156 IN ULONG BufferLength
,
157 OUT PVOID PropertyBuffer
,
158 OUT PULONG ResultLength
)
160 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
161 DEVICE_CAPABILITIES DeviceCaps
;
167 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
169 if (DeviceNode
== NULL
)
170 return STATUS_INVALID_DEVICE_REQUEST
;
172 switch (DeviceProperty
)
174 case DevicePropertyBusNumber
:
175 Length
= sizeof(ULONG
);
176 Data
= &DeviceNode
->ChildBusNumber
;
179 /* Complete, untested */
180 case DevicePropertyBusTypeGuid
:
182 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
183 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
185 /* Return the GUID */
186 *ResultLength
= sizeof(GUID
);
188 /* Check if the buffer given was large enough */
189 if (BufferLength
< *ResultLength
)
191 return STATUS_BUFFER_TOO_SMALL
;
195 RtlCopyMemory(PropertyBuffer
,
196 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
198 return STATUS_SUCCESS
;
202 return STATUS_OBJECT_NAME_NOT_FOUND
;
206 case DevicePropertyLegacyBusType
:
207 Length
= sizeof(INTERFACE_TYPE
);
208 Data
= &DeviceNode
->ChildInterfaceType
;
211 case DevicePropertyAddress
:
213 /* Query the device caps */
214 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
215 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= -1))
218 *ResultLength
= sizeof(ULONG
);
220 /* Check if the buffer given was large enough */
221 if (BufferLength
< *ResultLength
)
223 return STATUS_BUFFER_TOO_SMALL
;
227 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
228 return STATUS_SUCCESS
;
232 return STATUS_OBJECT_NAME_NOT_FOUND
;
236 // case DevicePropertyUINumber:
237 // if (DeviceNode->CapabilityFlags == NULL)
238 // return STATUS_INVALID_DEVICE_REQUEST;
239 // Length = sizeof(ULONG);
240 // Data = &DeviceNode->CapabilityFlags->UINumber;
243 case DevicePropertyClassName
:
244 case DevicePropertyClassGuid
:
245 case DevicePropertyDriverKeyName
:
246 case DevicePropertyManufacturer
:
247 case DevicePropertyFriendlyName
:
248 case DevicePropertyHardwareID
:
249 case DevicePropertyCompatibleIDs
:
250 case DevicePropertyDeviceDescription
:
251 case DevicePropertyLocationInformation
:
252 case DevicePropertyUINumber
:
254 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
255 UNICODE_STRING KeyName
, ValueName
;
256 OBJECT_ATTRIBUTES ObjectAttributes
;
257 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
258 ULONG ValueInformationLength
;
262 switch (DeviceProperty
)
264 case DevicePropertyClassName
:
265 RegistryPropertyName
= L
"Class"; break;
266 case DevicePropertyClassGuid
:
267 RegistryPropertyName
= L
"ClassGuid"; break;
268 case DevicePropertyDriverKeyName
:
269 RegistryPropertyName
= L
"Driver"; break;
270 case DevicePropertyManufacturer
:
271 RegistryPropertyName
= L
"Mfg"; break;
272 case DevicePropertyFriendlyName
:
273 RegistryPropertyName
= L
"FriendlyName"; break;
274 case DevicePropertyHardwareID
:
275 RegistryPropertyName
= L
"HardwareID"; break;
276 case DevicePropertyCompatibleIDs
:
277 RegistryPropertyName
= L
"CompatibleIDs"; break;
278 case DevicePropertyDeviceDescription
:
279 RegistryPropertyName
= L
"DeviceDesc"; break;
280 case DevicePropertyLocationInformation
:
281 RegistryPropertyName
= L
"LocationInformation"; break;
282 case DevicePropertyUINumber
:
283 RegistryPropertyName
= L
"UINumber"; break;
285 RegistryPropertyName
= NULL
; break;
288 KeyNameBuffer
= ExAllocatePool(PagedPool
,
289 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
291 DPRINT("KeyNameBuffer: 0x%p, value %S\n",
292 KeyNameBuffer
, RegistryPropertyName
);
294 if (KeyNameBuffer
== NULL
)
295 return STATUS_INSUFFICIENT_RESOURCES
;
297 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
298 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
299 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
300 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
301 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
303 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
304 ExFreePool(KeyNameBuffer
);
305 if (!NT_SUCCESS(Status
))
308 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
309 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
310 Data
[0]) + BufferLength
;
311 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
312 if (ValueInformation
== NULL
)
315 return STATUS_INSUFFICIENT_RESOURCES
;
318 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
319 KeyValuePartialInformation
, ValueInformation
,
320 ValueInformationLength
,
321 &ValueInformationLength
);
322 *ResultLength
= ValueInformation
->DataLength
;
325 if (ValueInformation
->DataLength
> BufferLength
)
326 Status
= STATUS_BUFFER_TOO_SMALL
;
328 if (!NT_SUCCESS(Status
))
330 ExFreePool(ValueInformation
);
334 /* FIXME: Verify the value (NULL-terminated, correct format). */
336 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
337 ValueInformation
->DataLength
);
338 ExFreePool(ValueInformation
);
340 return STATUS_SUCCESS
;
343 case DevicePropertyBootConfiguration
:
345 if (DeviceNode
->BootResources
->Count
!= 0)
347 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
349 Data
= &DeviceNode
->BootResources
;
352 /* FIXME: use a translated boot configuration instead */
353 case DevicePropertyBootConfigurationTranslated
:
355 if (DeviceNode
->BootResources
->Count
!= 0)
357 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
359 Data
= &DeviceNode
->BootResources
;
362 case DevicePropertyEnumeratorName
:
363 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
366 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
367 Data
= DeviceNode
->InstancePath
.Buffer
;
376 case DevicePropertyPhysicalDeviceObjectName
:
377 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
378 Data
= DeviceNode
->InstancePath
.Buffer
;
382 return STATUS_INVALID_PARAMETER_2
;
385 *ResultLength
= Length
;
386 if (BufferLength
< Length
)
387 return STATUS_BUFFER_TOO_SMALL
;
388 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
390 /* Terminate the string */
391 if (DeviceProperty
== DevicePropertyEnumeratorName
392 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
394 Ptr
= (PWSTR
)PropertyBuffer
;
395 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
398 return STATUS_SUCCESS
;
406 IoInvalidateDeviceState(
407 IN PDEVICE_OBJECT PhysicalDeviceObject
)
412 * @name IoOpenDeviceRegistryKey
414 * Open a registry key unique for a specified driver or device instance.
416 * @param DeviceObject Device to get the registry key for.
417 * @param DevInstKeyType Type of the key to return.
418 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
419 * @param DevInstRegKey Handle to the opened registry key on
428 IoOpenDeviceRegistryKey(
429 IN PDEVICE_OBJECT DeviceObject
,
430 IN ULONG DevInstKeyType
,
431 IN ACCESS_MASK DesiredAccess
,
432 OUT PHANDLE DevInstRegKey
)
434 static WCHAR RootKeyName
[] =
435 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
436 static WCHAR ProfileKeyName
[] =
437 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
438 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
439 static WCHAR EnumKeyName
[] = L
"Enum\\";
440 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters\\";
442 LPWSTR KeyNameBuffer
;
443 UNICODE_STRING KeyName
;
444 ULONG DriverKeyLength
;
445 OBJECT_ATTRIBUTES ObjectAttributes
;
446 PDEVICE_NODE DeviceNode
= NULL
;
449 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
450 return STATUS_INVALID_PARAMETER
;
453 * Calculate the length of the base key name. This is the full
454 * name for driver key or the name excluding "Device Parameters"
455 * subkey for device key.
458 KeyNameLength
= sizeof(RootKeyName
);
459 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
460 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
461 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
463 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
464 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
465 0, NULL
, &DriverKeyLength
);
466 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
468 KeyNameLength
+= DriverKeyLength
;
472 DeviceNode
= IopGetDeviceNode(DeviceObject
);
473 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
474 DeviceNode
->InstancePath
.Length
;
478 * Now allocate the buffer for the key name...
481 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
482 if (KeyNameBuffer
== NULL
)
483 return STATUS_INSUFFICIENT_RESOURCES
;
486 KeyName
.MaximumLength
= KeyNameLength
;
487 KeyName
.Buffer
= KeyNameBuffer
;
490 * ...and build the key name.
493 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
494 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
496 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
497 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
499 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
501 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
502 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
503 DriverKeyLength
, KeyNameBuffer
+
504 (KeyName
.Length
/ sizeof(WCHAR
)),
506 if (!NT_SUCCESS(Status
))
508 ExFreePool(KeyNameBuffer
);
511 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
515 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
516 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
517 if (DeviceNode
->InstancePath
.Length
== 0)
519 ExFreePool(KeyNameBuffer
);
528 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
529 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
530 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
531 ExFreePool(KeyNameBuffer
);
534 * For driver key we're done now. Also if the base key doesn't
535 * exist we can bail out with error...
538 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
542 * Let's go further. For device key we must open "Device Parameters"
543 * subkey and create it if it doesn't exist yet.
546 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
547 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
548 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
549 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
550 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
551 ZwClose(ObjectAttributes
.RootDirectory
);
561 IoRequestDeviceEject(
562 IN PDEVICE_OBJECT PhysicalDeviceObject
570 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
574 if (PopSystemPowerDeviceNode
)
576 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
577 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
578 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
580 return STATUS_SUCCESS
;
583 return STATUS_UNSUCCESSFUL
;
588 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
590 USHORT i
= 0, FoundIndex
= 0xFFFF;
594 /* Acquire the lock */
595 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
597 /* Loop all entries */
598 while (i
< IopBusTypeGuidList
->GuidCount
)
600 /* Try to find a match */
601 if (RtlCompareMemory(BusTypeGuid
,
602 &IopBusTypeGuidList
->Guids
[i
],
611 /* Check if we have to grow the list */
612 if (IopBusTypeGuidList
->GuidCount
)
614 /* Calculate the new size */
615 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
616 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
618 /* Allocate the new copy */
619 NewList
= ExAllocatePool(PagedPool
, NewSize
);
621 /* Now copy them, decrease the size too */
622 NewSize
-= sizeof(GUID
);
623 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
625 /* Free the old list */
626 ExFreePool(IopBusTypeGuidList
);
628 /* Use the new buffer */
629 IopBusTypeGuidList
= NewList
;
632 /* Copy the new GUID */
633 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
637 /* The new entry is the index */
638 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
639 IopBusTypeGuidList
->GuidCount
++;
642 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
648 * Creates a device node
651 * ParentNode = Pointer to parent device node
652 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
653 * to have the root device node create one
654 * (eg. for legacy drivers)
655 * DeviceNode = Pointer to storage for created device node
661 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
662 PDEVICE_OBJECT PhysicalDeviceObject
,
663 PDEVICE_NODE
*DeviceNode
)
669 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
670 ParentNode
, PhysicalDeviceObject
);
672 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
675 return STATUS_INSUFFICIENT_RESOURCES
;
678 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
680 if (!PhysicalDeviceObject
)
682 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
683 if (!NT_SUCCESS(Status
))
689 /* This is for drivers passed on the command line to ntoskrnl.exe */
690 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
691 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
694 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
696 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
700 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
701 Node
->Parent
= ParentNode
;
702 Node
->NextSibling
= ParentNode
->Child
;
703 if (ParentNode
->Child
!= NULL
)
705 ParentNode
->Child
->PrevSibling
= Node
;
707 ParentNode
->Child
= Node
;
708 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
709 Node
->Level
= ParentNode
->Level
+ 1;
714 return STATUS_SUCCESS
;
718 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
722 /* All children must be deleted before a parent is deleted */
723 ASSERT(!DeviceNode
->Child
);
725 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
727 ASSERT(DeviceNode
->PhysicalDeviceObject
);
729 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
731 /* Unlink from parent if it exists */
733 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
735 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
738 /* Unlink from sibling list */
740 if (DeviceNode
->PrevSibling
)
742 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
745 if (DeviceNode
->NextSibling
)
747 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
750 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
752 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
754 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
756 if (DeviceNode
->ResourceList
)
758 ExFreePool(DeviceNode
->ResourceList
);
761 if (DeviceNode
->ResourceListTranslated
)
763 ExFreePool(DeviceNode
->ResourceListTranslated
);
766 if (DeviceNode
->ResourceRequirements
)
768 ExFreePool(DeviceNode
->ResourceRequirements
);
771 if (DeviceNode
->BootResources
)
773 ExFreePool(DeviceNode
->BootResources
);
776 ExFreePool(DeviceNode
);
778 return STATUS_SUCCESS
;
783 PDEVICE_OBJECT DeviceObject
,
784 PIO_STATUS_BLOCK IoStatusBlock
,
786 PIO_STACK_LOCATION Stack OPTIONAL
)
788 PDEVICE_OBJECT TopDeviceObject
;
789 PIO_STACK_LOCATION IrpSp
;
794 /* Always call the top of the device stack */
795 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
802 Irp
= IoBuildSynchronousFsdRequest(
811 /* PNP IRPs are always initialized with a status code of
812 STATUS_NOT_IMPLEMENTED */
813 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
814 Irp
->IoStatus
.Information
= 0;
816 IrpSp
= IoGetNextIrpStackLocation(Irp
);
817 IrpSp
->MinorFunction
= MinorFunction
;
824 sizeof(Stack
->Parameters
));
827 Status
= IoCallDriver(TopDeviceObject
, Irp
);
828 if (Status
== STATUS_PENDING
)
830 KeWaitForSingleObject(
836 Status
= IoStatusBlock
->Status
;
839 ObDereferenceObject(TopDeviceObject
);
846 IopTraverseDeviceTreeNode(
847 PDEVICETREE_TRAVERSE_CONTEXT Context
)
849 PDEVICE_NODE ParentDeviceNode
;
850 PDEVICE_NODE ChildDeviceNode
;
853 /* Copy context data so we don't overwrite it in subsequent calls to this function */
854 ParentDeviceNode
= Context
->DeviceNode
;
856 /* Call the action routine */
857 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
858 if (!NT_SUCCESS(Status
))
863 /* Traversal of all children nodes */
864 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
865 ChildDeviceNode
!= NULL
;
866 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
868 /* Pass the current device node to the action routine */
869 Context
->DeviceNode
= ChildDeviceNode
;
871 Status
= IopTraverseDeviceTreeNode(Context
);
872 if (!NT_SUCCESS(Status
))
883 IopTraverseDeviceTree(
884 PDEVICETREE_TRAVERSE_CONTEXT Context
)
888 DPRINT("Context 0x%p\n", Context
);
890 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
891 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
893 /* Start from the specified device node */
894 Context
->DeviceNode
= Context
->FirstDeviceNode
;
896 /* Recursively traverse the device tree */
897 Status
= IopTraverseDeviceTreeNode(Context
);
898 if (Status
== STATUS_UNSUCCESSFUL
)
900 /* The action routine just wanted to terminate the traversal with status
901 code STATUS_SUCCESS */
902 Status
= STATUS_SUCCESS
;
910 IopCreateDeviceKeyPath(PWSTR Path
,
913 OBJECT_ATTRIBUTES ObjectAttributes
;
914 WCHAR KeyBuffer
[MAX_PATH
];
915 UNICODE_STRING KeyName
;
923 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
925 return STATUS_INVALID_PARAMETER
;
928 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
930 /* Skip \\Registry\\ */
932 Current
= wcschr (Current
, L
'\\') + 1;
933 Current
= wcschr (Current
, L
'\\') + 1;
937 Next
= wcschr (Current
, L
'\\');
947 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
948 InitializeObjectAttributes (&ObjectAttributes
,
950 OBJ_CASE_INSENSITIVE
,
954 DPRINT("Create '%S'\n", KeyName
.Buffer
);
956 Status
= ZwCreateKey (&KeyHandle
,
963 if (!NT_SUCCESS (Status
))
965 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
972 return STATUS_SUCCESS
;
983 return STATUS_UNSUCCESSFUL
;
988 IopSetDeviceInstanceData(HANDLE InstanceKey
,
989 PDEVICE_NODE DeviceNode
)
991 OBJECT_ATTRIBUTES ObjectAttributes
;
992 UNICODE_STRING KeyName
;
998 DPRINT("IopSetDeviceInstanceData() called\n");
1000 /* Create the 'LogConf' key */
1001 RtlInitUnicodeString(&KeyName
,
1003 InitializeObjectAttributes(&ObjectAttributes
,
1005 OBJ_CASE_INSENSITIVE
,
1008 Status
= ZwCreateKey(&LogConfKey
,
1015 if (NT_SUCCESS(Status
))
1017 /* Set 'BootConfig' value */
1018 if (DeviceNode
->BootResources
!= NULL
)
1020 ResCount
= DeviceNode
->BootResources
->Count
;
1023 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1025 RtlInitUnicodeString(&KeyName
,
1027 Status
= ZwSetValueKey(LogConfKey
,
1031 &DeviceNode
->BootResources
,
1036 /* Set 'BasicConfigVector' value */
1037 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1038 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1040 RtlInitUnicodeString(&KeyName
,
1041 L
"BasicConfigVector");
1042 Status
= ZwSetValueKey(LogConfKey
,
1045 REG_RESOURCE_REQUIREMENTS_LIST
,
1046 DeviceNode
->ResourceRequirements
,
1047 DeviceNode
->ResourceRequirements
->ListSize
);
1050 ZwClose(LogConfKey
);
1054 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1056 /* Create the 'Control' key */
1057 RtlInitUnicodeString(&KeyName
,
1059 InitializeObjectAttributes(&ObjectAttributes
,
1061 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1064 Status
= ZwCreateKey(&LogConfKey
,
1069 REG_OPTION_VOLATILE
,
1071 if (NT_SUCCESS(Status
))
1073 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1074 RtlInitUnicodeString(&KeyName
,
1075 L
"DeviceReference");
1076 Status
= ZwSetValueKey(LogConfKey
,
1083 ZwClose(LogConfKey
);
1088 DPRINT("IopSetDeviceInstanceData() done\n");
1090 return STATUS_SUCCESS
;
1095 IopAssignDeviceResources(
1096 PDEVICE_NODE DeviceNode
)
1098 PIO_RESOURCE_LIST ResourceList
;
1099 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1100 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1101 ULONG NumberOfResources
= 0;
1105 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
1106 * by using DeviceNode->ResourceRequirements */
1108 if (!DeviceNode
->ResourceRequirements
1109 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
1111 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
1112 return STATUS_SUCCESS
;
1115 /* FIXME: that's here that PnP arbiter should go */
1116 /* Actually, simply use resource list #0 as assigned resource list */
1117 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1118 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1120 Status
= STATUS_REVISION_MISMATCH
;
1124 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
1125 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1126 if (!DeviceNode
->ResourceList
)
1128 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1132 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
1133 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1134 if (!DeviceNode
->ResourceListTranslated
)
1136 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1140 DeviceNode
->ResourceList
->Count
= 1;
1141 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1142 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1143 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1144 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1146 DeviceNode
->ResourceListTranslated
->Count
= 1;
1147 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1148 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1149 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
1150 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
1152 for (i
= 0; i
< ResourceList
->Count
; i
++)
1154 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1156 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1158 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1159 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1160 NumberOfResources
++;
1162 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1163 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1164 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1165 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1166 switch (ResourceDescriptor
->Type
)
1168 case CmResourceTypePort
:
1170 ULONG AddressSpace
= 0; /* IO space */
1171 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1172 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1173 = ResourceDescriptor
->u
.Port
.Length
;
1174 if (!HalTranslateBusAddress(
1175 DeviceNode
->ResourceRequirements
->InterfaceType
,
1176 DeviceNode
->ResourceRequirements
->BusNumber
,
1177 DescriptorRaw
->u
.Port
.Start
,
1179 &DescriptorTranslated
->u
.Port
.Start
))
1181 Status
= STATUS_UNSUCCESSFUL
;
1186 case CmResourceTypeInterrupt
:
1188 INTERFACE_TYPE BusType
;
1193 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1194 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1195 /* FIXME: HACK: if we have a PCI device, we try
1196 * to keep the IRQ assigned by the BIOS */
1197 if (NT_SUCCESS(IoGetDeviceProperty(
1198 DeviceNode
->PhysicalDeviceObject
,
1199 DevicePropertyLegacyBusType
,
1200 sizeof(INTERFACE_TYPE
),
1202 &ret
)) && BusType
== PCIBus
)
1204 /* We have a PCI bus */
1205 if (NT_SUCCESS(IoGetDeviceProperty(
1206 DeviceNode
->PhysicalDeviceObject
,
1207 DevicePropertyAddress
,
1210 &ret
)) && SlotNumber
> 0)
1212 /* We have a good slot number */
1213 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1214 DeviceNode
->ResourceRequirements
->BusNumber
,
1217 0x3c /* PCI_INTERRUPT_LINE */,
1219 if (ret
!= 0 && ret
!= 2
1220 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1221 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1223 /* The device already has an assigned IRQ */
1224 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1228 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1229 DescriptorRaw
->u
.Interrupt
.Vector
,
1230 &DeviceNode
->InstancePath
);
1231 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1232 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1233 DeviceNode
->ResourceRequirements
->BusNumber
,
1236 0x3c /* PCI_INTERRUPT_LINE */,
1238 if (ret
== 0 || ret
== 2)
1244 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1245 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1246 DeviceNode
->ResourceRequirements
->InterfaceType
,
1247 DeviceNode
->ResourceRequirements
->BusNumber
,
1248 DescriptorRaw
->u
.Interrupt
.Level
,
1249 DescriptorRaw
->u
.Interrupt
.Vector
,
1250 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1251 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1252 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1255 case CmResourceTypeMemory
:
1257 ULONG AddressSpace
= 1; /* Memory space */
1258 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1259 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1260 = ResourceDescriptor
->u
.Memory
.Length
;
1261 if (!HalTranslateBusAddress(
1262 DeviceNode
->ResourceRequirements
->InterfaceType
,
1263 DeviceNode
->ResourceRequirements
->BusNumber
,
1264 DescriptorRaw
->u
.Memory
.Start
,
1266 &DescriptorTranslated
->u
.Memory
.Start
))
1268 Status
= STATUS_UNSUCCESSFUL
;
1273 case CmResourceTypeDma
:
1275 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1276 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1277 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1279 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1283 /*case CmResourceTypeBusNumber:
1285 DescriptorRaw->u.BusNumber.Start = DescriptorTranslated->u.BusNumber.Start
1286 = ResourceDescriptor->u.BusNumber.MinBusNumber;
1287 DescriptorRaw->u.BusNumber.Length = DescriptorTranslated->u.BusNumber.Length
1288 = ResourceDescriptor->u.BusNumber.Length;
1289 DescriptorRaw->u.BusNumber.Reserved = DescriptorTranslated->u.BusNumber.Reserved
1290 = ResourceDescriptor->u.BusNumber.Reserved;
1293 /*CmResourceTypeDevicePrivate:
1294 case CmResourceTypePcCardConfig:
1295 case CmResourceTypeMfCardConfig:
1298 &DescriptorRaw->u.DevicePrivate,
1299 &ResourceDescriptor->u.DevicePrivate,
1300 sizeof(ResourceDescriptor->u.DevicePrivate));
1302 &DescriptorTranslated->u.DevicePrivate,
1303 &ResourceDescriptor->u.DevicePrivate,
1304 sizeof(ResourceDescriptor->u.DevicePrivate));
1308 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1309 NumberOfResources
--;
1315 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1316 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1318 return STATUS_SUCCESS
;
1321 if (DeviceNode
->ResourceList
)
1323 ExFreePool(DeviceNode
->ResourceList
);
1324 DeviceNode
->ResourceList
= NULL
;
1326 if (DeviceNode
->ResourceListTranslated
)
1328 ExFreePool(DeviceNode
->ResourceListTranslated
);
1329 DeviceNode
->ResourceListTranslated
= NULL
;
1337 * IopGetParentIdPrefix
1339 * Retrieve (or create) a string which identifies a device.
1343 * Pointer to device node.
1345 * Pointer to the string where is returned the parent node identifier
1348 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1349 * valid and its Buffer field is NULL-terminated. The caller needs to
1350 * to free the string with RtlFreeUnicodeString when it is no longer
1355 IopGetParentIdPrefix(
1356 PDEVICE_NODE DeviceNode
,
1357 PUNICODE_STRING ParentIdPrefix
)
1359 ULONG KeyNameBufferLength
;
1360 PWSTR KeyNameBuffer
= NULL
;
1361 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1362 UNICODE_STRING KeyName
;
1363 UNICODE_STRING KeyValue
;
1364 UNICODE_STRING ValueName
;
1365 OBJECT_ATTRIBUTES ObjectAttributes
;
1366 HANDLE hKey
= INVALID_HANDLE_VALUE
;
1372 /* HACK: As long as some devices have a NULL device
1373 * instance path, the following test is required :(
1375 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1376 return STATUS_UNSUCCESSFUL
;
1378 /* 1. Try to retrieve ParentIdPrefix from registry */
1379 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1380 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1381 if (!ParentIdPrefixInformation
)
1383 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1386 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1389 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1392 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1393 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1394 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1395 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1396 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1397 if (!NT_SUCCESS(Status
))
1399 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1400 Status
= ZwQueryValueKey(
1402 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1403 KeyNameBufferLength
, &KeyNameBufferLength
);
1404 if (NT_SUCCESS(Status
))
1406 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1407 Status
= STATUS_UNSUCCESSFUL
;
1410 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1413 /* 2. Create the ParentIdPrefix value */
1414 currentByte
= (PBYTE
)DeviceNode
->Parent
;
1415 for (i
= 0; i
< sizeof(DEVICE_NODE
); i
++, currentByte
++)
1416 crc32
= (crc32
>> 8) ^ crc32Table
[*currentByte
^ (crc32
& 0xff)];
1418 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1419 swprintf(KeyValue
.Buffer
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1421 /* 3. Try to write the ParentIdPrefix to registry */
1422 RtlInitUnicodeString(&KeyValue
, KeyValue
.Buffer
);
1423 Status
= ZwSetValueKey(
1426 (PVOID
)KeyValue
.Buffer
,
1427 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1430 if (NT_SUCCESS(Status
))
1432 /* Duplicate the string to return it */
1433 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1434 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1435 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1437 ExFreePool(ParentIdPrefixInformation
);
1438 ExFreePool(KeyNameBuffer
);
1439 if (hKey
!= INVALID_HANDLE_VALUE
)
1446 * IopActionInterrogateDeviceStack
1448 * Retrieve information for all (direct) child nodes of a parent node.
1452 * Pointer to device node.
1454 * Pointer to parent node to retrieve child node information for.
1457 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1458 * when we reach a device node which is not a direct child of the device
1459 * node for which we retrieve information of child nodes for. Any errors
1460 * that occur is logged instead so that all child services have a chance
1461 * of being interrogated.
1465 IopActionInterrogateDeviceStack(
1466 PDEVICE_NODE DeviceNode
,
1469 IO_STATUS_BLOCK IoStatusBlock
;
1470 PDEVICE_NODE ParentDeviceNode
;
1471 WCHAR InstancePath
[MAX_PATH
];
1472 IO_STACK_LOCATION Stack
;
1478 HANDLE InstanceKey
= NULL
;
1479 UNICODE_STRING ValueName
;
1480 UNICODE_STRING ParentIdPrefix
= { 0 };
1481 DEVICE_CAPABILITIES DeviceCapabilities
;
1483 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1484 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1486 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1489 * We are called for the parent too, but we don't need to do special
1490 * handling for this node
1493 if (DeviceNode
== ParentDeviceNode
)
1495 DPRINT("Success\n");
1496 return STATUS_SUCCESS
;
1500 * Make sure this device node is a direct child of the parent device node
1501 * that is given as an argument
1504 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1506 /* Stop the traversal immediately and indicate successful operation */
1508 return STATUS_UNSUCCESSFUL
;
1512 * FIXME: For critical errors, cleanup and disable device, but always
1513 * return STATUS_SUCCESS.
1516 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1518 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1519 Status
= IopInitiatePnpIrp(
1520 DeviceNode
->PhysicalDeviceObject
,
1524 if (NT_SUCCESS(Status
))
1526 /* Copy the device id string */
1527 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1530 * FIXME: Check for valid characters, if there is invalid characters
1536 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1539 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1541 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1542 if (!NT_SUCCESS(Status
))
1544 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1547 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1549 if (!DeviceCapabilities
.UniqueID
)
1551 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1552 DPRINT("Instance ID is not unique\n");
1553 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1554 if (!NT_SUCCESS(Status
))
1556 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1560 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1562 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1563 Status
= IopInitiatePnpIrp(
1564 DeviceNode
->PhysicalDeviceObject
,
1568 if (NT_SUCCESS(Status
))
1570 /* Append the instance id string */
1571 wcscat(InstancePath
, L
"\\");
1572 if (ParentIdPrefix
.Length
> 0)
1574 /* Add information from parent bus device to InstancePath */
1575 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1576 if (*(PWSTR
)IoStatusBlock
.Information
)
1577 wcscat(InstancePath
, L
"&");
1579 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1582 * FIXME: Check for valid characters, if there is invalid characters
1588 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1590 RtlFreeUnicodeString(&ParentIdPrefix
);
1592 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1594 DPRINT("No resources\n");
1595 /* FIXME: Cleanup and disable device */
1598 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1601 * Create registry key for the instance id, if it doesn't exist yet
1603 KeyBuffer
= ExAllocatePool(
1605 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1606 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1607 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1608 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1610 ExFreePool(KeyBuffer
);
1611 if (!NT_SUCCESS(Status
))
1613 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1618 /* Set 'Capabilities' value */
1619 RtlInitUnicodeString(&ValueName
,
1621 Status
= ZwSetValueKey(InstanceKey
,
1625 (PVOID
)&DeviceNode
->CapabilityFlags
,
1628 /* Set 'UINumber' value */
1629 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1631 RtlInitUnicodeString(&ValueName
,
1633 Status
= ZwSetValueKey(InstanceKey
,
1637 &DeviceCapabilities
.UINumber
,
1642 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1644 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1645 Status
= IopInitiatePnpIrp(
1646 DeviceNode
->PhysicalDeviceObject
,
1650 if (NT_SUCCESS(Status
))
1653 * FIXME: Check for valid characters, if there is invalid characters
1657 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1658 DPRINT("Hardware IDs:\n");
1661 DPRINT(" %S\n", Ptr
);
1662 Length
= wcslen(Ptr
) + 1;
1665 TotalLength
+= Length
;
1667 DPRINT("TotalLength: %hu\n", TotalLength
);
1670 RtlInitUnicodeString(&ValueName
,
1672 Status
= ZwSetValueKey(InstanceKey
,
1676 (PVOID
)IoStatusBlock
.Information
,
1677 (TotalLength
+ 1) * sizeof(WCHAR
));
1678 if (!NT_SUCCESS(Status
))
1680 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1685 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1688 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1690 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1691 Status
= IopInitiatePnpIrp(
1692 DeviceNode
->PhysicalDeviceObject
,
1696 if (NT_SUCCESS(Status
))
1699 * FIXME: Check for valid characters, if there is invalid characters
1703 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1704 DPRINT("Compatible IDs:\n");
1707 DPRINT(" %S\n", Ptr
);
1708 Length
= wcslen(Ptr
) + 1;
1711 TotalLength
+= Length
;
1713 DPRINT("TotalLength: %hu\n", TotalLength
);
1716 RtlInitUnicodeString(&ValueName
,
1718 Status
= ZwSetValueKey(InstanceKey
,
1722 (PVOID
)IoStatusBlock
.Information
,
1723 (TotalLength
+ 1) * sizeof(WCHAR
));
1724 if (!NT_SUCCESS(Status
))
1726 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1731 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1735 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1737 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1738 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1739 Status
= IopInitiatePnpIrp(
1740 DeviceNode
->PhysicalDeviceObject
,
1742 IRP_MN_QUERY_DEVICE_TEXT
,
1744 if (NT_SUCCESS(Status
))
1746 RtlInitUnicodeString(&ValueName
,
1748 Status
= ZwSetValueKey(InstanceKey
,
1752 (PVOID
)IoStatusBlock
.Information
,
1753 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1754 if (!NT_SUCCESS(Status
))
1756 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1761 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1764 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1766 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1767 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1768 Status
= IopInitiatePnpIrp(
1769 DeviceNode
->PhysicalDeviceObject
,
1771 IRP_MN_QUERY_DEVICE_TEXT
,
1773 if (NT_SUCCESS(Status
))
1775 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1776 RtlInitUnicodeString(&ValueName
,
1777 L
"LocationInformation");
1778 Status
= ZwSetValueKey(InstanceKey
,
1782 (PVOID
)IoStatusBlock
.Information
,
1783 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1784 if (!NT_SUCCESS(Status
))
1786 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1791 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1794 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1796 Status
= IopInitiatePnpIrp(
1797 DeviceNode
->PhysicalDeviceObject
,
1799 IRP_MN_QUERY_BUS_INFORMATION
,
1801 if (NT_SUCCESS(Status
))
1803 PPNP_BUS_INFORMATION BusInformation
=
1804 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1806 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1807 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1808 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1809 ExFreePool(BusInformation
);
1813 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1815 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1816 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1817 DeviceNode
->ChildBusTypeIndex
= -1;
1820 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1822 Status
= IopInitiatePnpIrp(
1823 DeviceNode
->PhysicalDeviceObject
,
1825 IRP_MN_QUERY_RESOURCES
,
1827 if (NT_SUCCESS(Status
))
1829 DeviceNode
->BootResources
=
1830 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1831 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1835 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1836 DeviceNode
->BootResources
= NULL
;
1839 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1841 Status
= IopInitiatePnpIrp(
1842 DeviceNode
->PhysicalDeviceObject
,
1844 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1846 if (NT_SUCCESS(Status
))
1848 DeviceNode
->ResourceRequirements
=
1849 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1853 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1854 DeviceNode
->ResourceRequirements
= NULL
;
1858 if (InstanceKey
!= NULL
)
1860 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1863 ZwClose(InstanceKey
);
1865 Status
= IopAssignDeviceResources(DeviceNode
);
1866 if (!NT_SUCCESS(Status
))
1868 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1871 DeviceNode
->Flags
|= DNF_PROCESSED
;
1873 /* Report the device to the user-mode pnp manager */
1874 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1875 &DeviceNode
->InstancePath
);
1877 return STATUS_SUCCESS
;
1881 * IopActionConfigureChildServices
1883 * Retrieve configuration for all (direct) child nodes of a parent node.
1887 * Pointer to device node.
1889 * Pointer to parent node to retrieve child node configuration for.
1892 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1893 * when we reach a device node which is not a direct child of the device
1894 * node for which we configure child services for. Any errors that occur is
1895 * logged instead so that all child services have a chance of beeing
1900 IopActionConfigureChildServices(
1901 PDEVICE_NODE DeviceNode
,
1904 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1905 PDEVICE_NODE ParentDeviceNode
;
1906 PUNICODE_STRING Service
;
1909 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1911 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1914 * We are called for the parent too, but we don't need to do special
1915 * handling for this node
1917 if (DeviceNode
== ParentDeviceNode
)
1919 DPRINT("Success\n");
1920 return STATUS_SUCCESS
;
1924 * Make sure this device node is a direct child of the parent device node
1925 * that is given as an argument
1927 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1929 /* Stop the traversal immediately and indicate successful operation */
1931 return STATUS_UNSUCCESSFUL
;
1934 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1936 WCHAR RegKeyBuffer
[MAX_PATH
];
1937 UNICODE_STRING RegKey
;
1940 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1941 RegKey
.Buffer
= RegKeyBuffer
;
1944 * Retrieve configuration from Enum key
1947 Service
= &DeviceNode
->ServiceName
;
1949 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1950 RtlInitUnicodeString(Service
, NULL
);
1952 QueryTable
[0].Name
= L
"Service";
1953 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1954 QueryTable
[0].EntryContext
= Service
;
1956 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1957 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1959 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1960 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1962 if (!NT_SUCCESS(Status
))
1964 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1965 /* FIXME: Log the error */
1966 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1967 DeviceNode
->InstancePath
.Buffer
, Status
);
1968 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1969 return STATUS_SUCCESS
;
1972 if (Service
->Buffer
== NULL
)
1974 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1975 return STATUS_SUCCESS
;
1978 DPRINT("Got Service %S\n", Service
->Buffer
);
1981 return STATUS_SUCCESS
;
1985 * IopActionInitChildServices
1987 * Initialize the service for all (direct) child nodes of a parent node
1991 * Pointer to device node.
1993 * Pointer to parent node to initialize child node services for.
1995 * Load only driver marked as boot start.
1998 * If the driver image for a service is not loaded and initialized
1999 * it is done here too. We only return a status code indicating an
2000 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2001 * not a direct child of the device node for which we initialize
2002 * child services for. Any errors that occur is logged instead so
2003 * that all child services have a chance of being initialized.
2007 IopActionInitChildServices(
2008 PDEVICE_NODE DeviceNode
,
2010 BOOLEAN BootDrivers
)
2012 PDEVICE_NODE ParentDeviceNode
;
2015 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2018 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2021 * We are called for the parent too, but we don't need to do special
2022 * handling for this node
2024 if (DeviceNode
== ParentDeviceNode
)
2026 DPRINT("Success\n");
2027 return STATUS_SUCCESS
;
2031 * Make sure this device node is a direct child of the parent device node
2032 * that is given as an argument
2035 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2038 * Stop the traversal immediately and indicate unsuccessful operation
2041 return STATUS_UNSUCCESSFUL
;
2045 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2046 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2047 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2049 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2050 PDRIVER_OBJECT DriverObject
;
2052 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2053 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2055 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2056 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2057 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2060 /* get existing DriverObject pointer */
2061 Status
= IopGetDriverObject(
2063 &DeviceNode
->ServiceName
,
2066 if (NT_SUCCESS(Status
))
2068 /* Attach lower level filter drivers. */
2069 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2070 /* Initialize the function driver for the device node */
2071 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2072 if (NT_SUCCESS(Status
))
2074 /* Attach upper level filter drivers. */
2075 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2076 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2078 Status
= IopStartDevice(DeviceNode
);
2085 * Don't disable when trying to load only boot drivers
2089 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2090 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2092 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2093 CPRINT("Initialization of service %S failed (Status %x)\n",
2094 DeviceNode
->ServiceName
.Buffer
, Status
);
2098 DPRINT("Service %S is disabled or already initialized\n",
2099 DeviceNode
->ServiceName
.Buffer
);
2102 return STATUS_SUCCESS
;
2106 * IopActionInitAllServices
2108 * Initialize the service for all (direct) child nodes of a parent node. This
2109 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2113 IopActionInitAllServices(
2114 PDEVICE_NODE DeviceNode
,
2117 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2121 * IopActionInitBootServices
2123 * Initialize the boot start services for all (direct) child nodes of a
2124 * parent node. This function just calls IopActionInitChildServices with
2125 * BootDrivers = TRUE.
2128 IopActionInitBootServices(
2129 PDEVICE_NODE DeviceNode
,
2132 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2136 * IopInitializePnpServices
2138 * Initialize services for discovered children
2142 * Top device node to start initializing services.
2145 * When set to TRUE, only drivers marked as boot start will
2146 * be loaded. Otherwise, all drivers will be loaded.
2152 IopInitializePnpServices(
2153 IN PDEVICE_NODE DeviceNode
,
2154 IN BOOLEAN BootDrivers
)
2156 DEVICETREE_TRAVERSE_CONTEXT Context
;
2158 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2162 IopInitDeviceTreeTraverseContext(
2165 IopActionInitBootServices
,
2170 IopInitDeviceTreeTraverseContext(
2173 IopActionInitAllServices
,
2177 return IopTraverseDeviceTree(&Context
);
2182 IopInvalidateDeviceRelations(
2183 IN PDEVICE_NODE DeviceNode
,
2184 IN DEVICE_RELATION_TYPE Type
)
2186 DEVICETREE_TRAVERSE_CONTEXT Context
;
2187 PDEVICE_RELATIONS DeviceRelations
;
2188 IO_STATUS_BLOCK IoStatusBlock
;
2189 PDEVICE_NODE ChildDeviceNode
;
2190 IO_STACK_LOCATION Stack
;
2192 OBJECT_ATTRIBUTES ObjectAttributes
;
2193 UNICODE_STRING LinkName
;
2198 DPRINT("DeviceNode 0x%p\n", DeviceNode
);
2200 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2202 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
2204 Status
= IopInitiatePnpIrp(
2205 DeviceNode
->PhysicalDeviceObject
,
2207 IRP_MN_QUERY_DEVICE_RELATIONS
,
2209 if (!NT_SUCCESS(Status
))
2211 DPRINT("IopInitiatePnpIrp() failed\n");
2215 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2217 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
2219 DPRINT("No PDOs\n");
2220 if (DeviceRelations
)
2222 ExFreePool(DeviceRelations
);
2224 return STATUS_SUCCESS
;
2227 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2230 * Create device nodes for all discovered devices
2233 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2235 Status
= IopCreateDeviceNode(
2237 DeviceRelations
->Objects
[i
],
2239 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2240 if (!NT_SUCCESS(Status
))
2242 DPRINT("No resources\n");
2243 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2244 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2245 ExFreePool(DeviceRelations
);
2246 return STATUS_INSUFFICIENT_RESOURCES
;
2249 ExFreePool(DeviceRelations
);
2252 * Retrieve information about all discovered children from the bus driver
2255 IopInitDeviceTreeTraverseContext(
2258 IopActionInterrogateDeviceStack
,
2261 Status
= IopTraverseDeviceTree(&Context
);
2262 if (!NT_SUCCESS(Status
))
2264 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2269 * Retrieve configuration from the registry for discovered children
2272 IopInitDeviceTreeTraverseContext(
2275 IopActionConfigureChildServices
,
2278 Status
= IopTraverseDeviceTree(&Context
);
2279 if (!NT_SUCCESS(Status
))
2281 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2286 * Get the state of the system boot. If the \\SystemRoot link isn't
2287 * created yet, we will assume that it's possible to load only boot
2291 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
2293 InitializeObjectAttributes(
2300 Status
= ZwOpenFile(
2307 if(NT_SUCCESS(Status
))
2309 BootDrivers
= FALSE
;
2316 * Initialize services for discovered children. Only boot drivers will
2317 * be loaded from boot driver!
2320 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2321 if (!NT_SUCCESS(Status
))
2323 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2327 return STATUS_SUCCESS
;
2331 static NTSTATUS INIT_FUNCTION
2332 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
2336 HANDLE InstanceKey
= NULL
;
2339 /* Create registry key for the instance id, if it doesn't exist yet */
2340 KeyBuffer
= ExAllocatePool(PagedPool
,
2341 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
2342 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2343 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2344 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2346 ExFreePool(KeyBuffer
);
2347 if (!NT_SUCCESS(Status
))
2349 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2353 /* FIXME: Set 'ConfigFlags' value */
2355 ZwClose(InstanceKey
);
2359 return STATUS_SUCCESS
;
2369 DPRINT("PnpInit()\n");
2371 KeInitializeSpinLock(&IopDeviceTreeLock
);
2373 /* Initialize the Bus Type GUID List */
2374 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2375 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2376 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2378 /* Initialize PnP-Event notification support */
2379 Status
= IopInitPlugPlayEvents();
2380 if (!NT_SUCCESS(Status
))
2382 CPRINT("IopInitPlugPlayEvents() failed\n");
2383 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2387 * Create root device node
2390 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2391 if (!NT_SUCCESS(Status
))
2393 CPRINT("IoCreateDriverObject() failed\n");
2394 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2397 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2399 if (!NT_SUCCESS(Status
))
2401 CPRINT("IoCreateDevice() failed\n");
2402 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2405 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2406 if (!NT_SUCCESS(Status
))
2408 CPRINT("Insufficient resources\n");
2409 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2412 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2415 CPRINT("Failed to create the instance path!\n");
2416 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2419 /* Report the device to the user-mode pnp manager */
2420 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2421 &IopRootDeviceNode
->InstancePath
);
2423 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2424 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2425 IopRootDriverObject
->DriverExtension
->AddDevice(
2426 IopRootDriverObject
,
2427 IopRootDeviceNode
->PhysicalDeviceObject
);
2436 /* Set root device instance data */
2437 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
2438 if (!NT_SUCCESS(Status
))
2440 CPRINT("Failed to set instance data\n");
2441 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);