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 (!NT_SUCCESS(Status
))
327 ExFreePool(ValueInformation
);
328 if (Status
== STATUS_BUFFER_OVERFLOW
)
329 return STATUS_BUFFER_TOO_SMALL
;
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
],
612 /* Check if we have to grow the list */
613 if (IopBusTypeGuidList
->GuidCount
)
615 /* Calculate the new size */
616 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
617 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
619 /* Allocate the new copy */
620 NewList
= ExAllocatePool(PagedPool
, NewSize
);
622 /* Now copy them, decrease the size too */
623 NewSize
-= sizeof(GUID
);
624 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
626 /* Free the old list */
627 ExFreePool(IopBusTypeGuidList
);
629 /* Use the new buffer */
630 IopBusTypeGuidList
= NewList
;
633 /* Copy the new GUID */
634 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
638 /* The new entry is the index */
639 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
640 IopBusTypeGuidList
->GuidCount
++;
643 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
649 * Creates a device node
652 * ParentNode = Pointer to parent device node
653 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
654 * to have the root device node create one
655 * (eg. for legacy drivers)
656 * DeviceNode = Pointer to storage for created device node
662 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
663 PDEVICE_OBJECT PhysicalDeviceObject
,
664 PDEVICE_NODE
*DeviceNode
)
670 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
671 ParentNode
, PhysicalDeviceObject
);
673 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
676 return STATUS_INSUFFICIENT_RESOURCES
;
679 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
681 if (!PhysicalDeviceObject
)
683 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
684 if (!NT_SUCCESS(Status
))
690 /* This is for drivers passed on the command line to ntoskrnl.exe */
691 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
692 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
695 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
697 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
701 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
702 Node
->Parent
= ParentNode
;
703 Node
->NextSibling
= ParentNode
->Child
;
704 if (ParentNode
->Child
!= NULL
)
706 ParentNode
->Child
->PrevSibling
= Node
;
708 ParentNode
->Child
= Node
;
709 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
710 Node
->Level
= ParentNode
->Level
+ 1;
715 return STATUS_SUCCESS
;
719 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
723 /* All children must be deleted before a parent is deleted */
724 ASSERT(!DeviceNode
->Child
);
726 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
728 ASSERT(DeviceNode
->PhysicalDeviceObject
);
730 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
732 /* Unlink from parent if it exists */
734 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
736 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
739 /* Unlink from sibling list */
741 if (DeviceNode
->PrevSibling
)
743 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
746 if (DeviceNode
->NextSibling
)
748 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
751 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
753 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
755 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
757 if (DeviceNode
->ResourceList
)
759 ExFreePool(DeviceNode
->ResourceList
);
762 if (DeviceNode
->ResourceListTranslated
)
764 ExFreePool(DeviceNode
->ResourceListTranslated
);
767 if (DeviceNode
->ResourceRequirements
)
769 ExFreePool(DeviceNode
->ResourceRequirements
);
772 if (DeviceNode
->BootResources
)
774 ExFreePool(DeviceNode
->BootResources
);
777 ExFreePool(DeviceNode
);
779 return STATUS_SUCCESS
;
784 PDEVICE_OBJECT DeviceObject
,
785 PIO_STATUS_BLOCK IoStatusBlock
,
787 PIO_STACK_LOCATION Stack OPTIONAL
)
789 PDEVICE_OBJECT TopDeviceObject
;
790 PIO_STACK_LOCATION IrpSp
;
795 /* Always call the top of the device stack */
796 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
803 Irp
= IoBuildSynchronousFsdRequest(
812 /* PNP IRPs are always initialized with a status code of
813 STATUS_NOT_IMPLEMENTED */
814 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
815 Irp
->IoStatus
.Information
= 0;
817 IrpSp
= IoGetNextIrpStackLocation(Irp
);
818 IrpSp
->MinorFunction
= MinorFunction
;
825 sizeof(Stack
->Parameters
));
828 Status
= IoCallDriver(TopDeviceObject
, Irp
);
829 if (Status
== STATUS_PENDING
)
831 KeWaitForSingleObject(
837 Status
= IoStatusBlock
->Status
;
840 ObDereferenceObject(TopDeviceObject
);
847 IopTraverseDeviceTreeNode(
848 PDEVICETREE_TRAVERSE_CONTEXT Context
)
850 PDEVICE_NODE ParentDeviceNode
;
851 PDEVICE_NODE ChildDeviceNode
;
854 /* Copy context data so we don't overwrite it in subsequent calls to this function */
855 ParentDeviceNode
= Context
->DeviceNode
;
857 /* Call the action routine */
858 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
859 if (!NT_SUCCESS(Status
))
864 /* Traversal of all children nodes */
865 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
866 ChildDeviceNode
!= NULL
;
867 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
869 /* Pass the current device node to the action routine */
870 Context
->DeviceNode
= ChildDeviceNode
;
872 Status
= IopTraverseDeviceTreeNode(Context
);
873 if (!NT_SUCCESS(Status
))
884 IopTraverseDeviceTree(
885 PDEVICETREE_TRAVERSE_CONTEXT Context
)
889 DPRINT("Context 0x%p\n", Context
);
891 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
892 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
894 /* Start from the specified device node */
895 Context
->DeviceNode
= Context
->FirstDeviceNode
;
897 /* Recursively traverse the device tree */
898 Status
= IopTraverseDeviceTreeNode(Context
);
899 if (Status
== STATUS_UNSUCCESSFUL
)
901 /* The action routine just wanted to terminate the traversal with status
902 code STATUS_SUCCESS */
903 Status
= STATUS_SUCCESS
;
911 IopCreateDeviceKeyPath(PWSTR Path
,
914 OBJECT_ATTRIBUTES ObjectAttributes
;
915 WCHAR KeyBuffer
[MAX_PATH
];
916 UNICODE_STRING KeyName
;
924 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
926 return STATUS_INVALID_PARAMETER
;
929 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
931 /* Skip \\Registry\\ */
933 Current
= wcschr (Current
, L
'\\') + 1;
934 Current
= wcschr (Current
, L
'\\') + 1;
938 Next
= wcschr (Current
, L
'\\');
948 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
949 InitializeObjectAttributes (&ObjectAttributes
,
951 OBJ_CASE_INSENSITIVE
,
955 DPRINT("Create '%S'\n", KeyName
.Buffer
);
957 Status
= ZwCreateKey (&KeyHandle
,
964 if (!NT_SUCCESS (Status
))
966 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
973 return STATUS_SUCCESS
;
984 return STATUS_UNSUCCESSFUL
;
989 IopSetDeviceInstanceData(HANDLE InstanceKey
,
990 PDEVICE_NODE DeviceNode
)
992 OBJECT_ATTRIBUTES ObjectAttributes
;
993 UNICODE_STRING KeyName
;
999 DPRINT("IopSetDeviceInstanceData() called\n");
1001 /* Create the 'LogConf' key */
1002 RtlInitUnicodeString(&KeyName
,
1004 InitializeObjectAttributes(&ObjectAttributes
,
1006 OBJ_CASE_INSENSITIVE
,
1009 Status
= ZwCreateKey(&LogConfKey
,
1016 if (NT_SUCCESS(Status
))
1018 /* Set 'BootConfig' value */
1019 if (DeviceNode
->BootResources
!= NULL
)
1021 ResCount
= DeviceNode
->BootResources
->Count
;
1024 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1026 RtlInitUnicodeString(&KeyName
,
1028 Status
= ZwSetValueKey(LogConfKey
,
1032 &DeviceNode
->BootResources
,
1037 /* Set 'BasicConfigVector' value */
1038 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1039 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1041 RtlInitUnicodeString(&KeyName
,
1042 L
"BasicConfigVector");
1043 Status
= ZwSetValueKey(LogConfKey
,
1046 REG_RESOURCE_REQUIREMENTS_LIST
,
1047 DeviceNode
->ResourceRequirements
,
1048 DeviceNode
->ResourceRequirements
->ListSize
);
1051 ZwClose(LogConfKey
);
1055 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1057 /* Create the 'Control' key */
1058 RtlInitUnicodeString(&KeyName
,
1060 InitializeObjectAttributes(&ObjectAttributes
,
1062 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1065 Status
= ZwCreateKey(&LogConfKey
,
1070 REG_OPTION_VOLATILE
,
1072 if (NT_SUCCESS(Status
))
1074 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1075 RtlInitUnicodeString(&KeyName
,
1076 L
"DeviceReference");
1077 Status
= ZwSetValueKey(LogConfKey
,
1084 ZwClose(LogConfKey
);
1089 DPRINT("IopSetDeviceInstanceData() done\n");
1091 return STATUS_SUCCESS
;
1096 IopAssignDeviceResources(
1097 PDEVICE_NODE DeviceNode
)
1099 PIO_RESOURCE_LIST ResourceList
;
1100 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1101 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1102 ULONG NumberOfResources
= 0;
1106 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
1107 * by using DeviceNode->ResourceRequirements */
1109 if (!DeviceNode
->ResourceRequirements
1110 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
1112 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
1113 return STATUS_SUCCESS
;
1116 /* FIXME: that's here that PnP arbiter should go */
1117 /* Actually, simply use resource list #0 as assigned resource list */
1118 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1119 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1121 Status
= STATUS_REVISION_MISMATCH
;
1125 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
1126 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1127 if (!DeviceNode
->ResourceList
)
1129 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1133 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
1134 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1135 if (!DeviceNode
->ResourceListTranslated
)
1137 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1141 DeviceNode
->ResourceList
->Count
= 1;
1142 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1143 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1144 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1145 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1147 DeviceNode
->ResourceListTranslated
->Count
= 1;
1148 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1149 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1150 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
1151 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
1153 for (i
= 0; i
< ResourceList
->Count
; i
++)
1155 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1157 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1159 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1160 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1161 NumberOfResources
++;
1163 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1164 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1165 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1166 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1167 switch (ResourceDescriptor
->Type
)
1169 case CmResourceTypePort
:
1171 ULONG AddressSpace
= 0; /* IO space */
1172 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1173 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1174 = ResourceDescriptor
->u
.Port
.Length
;
1175 if (!HalTranslateBusAddress(
1176 DeviceNode
->ResourceRequirements
->InterfaceType
,
1177 DeviceNode
->ResourceRequirements
->BusNumber
,
1178 DescriptorRaw
->u
.Port
.Start
,
1180 &DescriptorTranslated
->u
.Port
.Start
))
1182 Status
= STATUS_UNSUCCESSFUL
;
1187 case CmResourceTypeInterrupt
:
1189 INTERFACE_TYPE BusType
;
1194 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1195 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1196 /* FIXME: HACK: if we have a PCI device, we try
1197 * to keep the IRQ assigned by the BIOS */
1198 if (NT_SUCCESS(IoGetDeviceProperty(
1199 DeviceNode
->PhysicalDeviceObject
,
1200 DevicePropertyLegacyBusType
,
1201 sizeof(INTERFACE_TYPE
),
1203 &ret
)) && BusType
== PCIBus
)
1205 /* We have a PCI bus */
1206 if (NT_SUCCESS(IoGetDeviceProperty(
1207 DeviceNode
->PhysicalDeviceObject
,
1208 DevicePropertyAddress
,
1211 &ret
)) && SlotNumber
> 0)
1213 /* We have a good slot number */
1214 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1215 DeviceNode
->ResourceRequirements
->BusNumber
,
1218 0x3c /* PCI_INTERRUPT_LINE */,
1220 if (ret
!= 0 && ret
!= 2
1221 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1222 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1224 /* The device already has an assigned IRQ */
1225 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1229 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1230 DescriptorRaw
->u
.Interrupt
.Vector
,
1231 &DeviceNode
->InstancePath
);
1232 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1233 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1234 DeviceNode
->ResourceRequirements
->BusNumber
,
1237 0x3c /* PCI_INTERRUPT_LINE */,
1239 if (ret
== 0 || ret
== 2)
1245 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1246 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1247 DeviceNode
->ResourceRequirements
->InterfaceType
,
1248 DeviceNode
->ResourceRequirements
->BusNumber
,
1249 DescriptorRaw
->u
.Interrupt
.Level
,
1250 DescriptorRaw
->u
.Interrupt
.Vector
,
1251 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1252 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1253 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1256 case CmResourceTypeMemory
:
1258 ULONG AddressSpace
= 1; /* Memory space */
1259 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1260 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1261 = ResourceDescriptor
->u
.Memory
.Length
;
1262 if (!HalTranslateBusAddress(
1263 DeviceNode
->ResourceRequirements
->InterfaceType
,
1264 DeviceNode
->ResourceRequirements
->BusNumber
,
1265 DescriptorRaw
->u
.Memory
.Start
,
1267 &DescriptorTranslated
->u
.Memory
.Start
))
1269 Status
= STATUS_UNSUCCESSFUL
;
1274 case CmResourceTypeDma
:
1276 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1277 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1278 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1280 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1284 case CmResourceTypeBusNumber
:
1286 DescriptorRaw
->u
.BusNumber
.Start
= DescriptorTranslated
->u
.BusNumber
.Start
1287 = ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1288 DescriptorRaw
->u
.BusNumber
.Length
= DescriptorTranslated
->u
.BusNumber
.Length
1289 = ResourceDescriptor
->u
.BusNumber
.Length
;
1290 DescriptorRaw
->u
.BusNumber
.Reserved
= DescriptorTranslated
->u
.BusNumber
.Reserved
1291 = ResourceDescriptor
->u
.BusNumber
.Reserved
;
1294 /*CmResourceTypeDevicePrivate:
1295 case CmResourceTypePcCardConfig:
1296 case CmResourceTypeMfCardConfig:
1299 &DescriptorRaw->u.DevicePrivate,
1300 &ResourceDescriptor->u.DevicePrivate,
1301 sizeof(ResourceDescriptor->u.DevicePrivate));
1303 &DescriptorTranslated->u.DevicePrivate,
1304 &ResourceDescriptor->u.DevicePrivate,
1305 sizeof(ResourceDescriptor->u.DevicePrivate));
1309 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1310 NumberOfResources
--;
1316 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1317 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1319 return STATUS_SUCCESS
;
1322 if (DeviceNode
->ResourceList
)
1324 ExFreePool(DeviceNode
->ResourceList
);
1325 DeviceNode
->ResourceList
= NULL
;
1327 if (DeviceNode
->ResourceListTranslated
)
1329 ExFreePool(DeviceNode
->ResourceListTranslated
);
1330 DeviceNode
->ResourceListTranslated
= NULL
;
1338 * IopGetParentIdPrefix
1340 * Retrieve (or create) a string which identifies a device.
1344 * Pointer to device node.
1346 * Pointer to the string where is returned the parent node identifier
1349 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1350 * valid and its Buffer field is NULL-terminated. The caller needs to
1351 * to free the string with RtlFreeUnicodeString when it is no longer
1356 IopGetParentIdPrefix(
1357 PDEVICE_NODE DeviceNode
,
1358 PUNICODE_STRING ParentIdPrefix
)
1360 ULONG KeyNameBufferLength
;
1361 PWSTR KeyNameBuffer
= NULL
;
1362 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1363 UNICODE_STRING KeyName
;
1364 UNICODE_STRING KeyValue
;
1365 UNICODE_STRING ValueName
;
1366 OBJECT_ATTRIBUTES ObjectAttributes
;
1367 HANDLE hKey
= INVALID_HANDLE_VALUE
;
1373 /* HACK: As long as some devices have a NULL device
1374 * instance path, the following test is required :(
1376 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1377 return STATUS_UNSUCCESSFUL
;
1379 /* 1. Try to retrieve ParentIdPrefix from registry */
1380 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1381 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1382 if (!ParentIdPrefixInformation
)
1384 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1387 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1390 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1393 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1394 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1395 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1396 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1397 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1398 if (!NT_SUCCESS(Status
))
1400 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1401 Status
= ZwQueryValueKey(
1403 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1404 KeyNameBufferLength
, &KeyNameBufferLength
);
1405 if (NT_SUCCESS(Status
))
1407 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1408 Status
= STATUS_UNSUCCESSFUL
;
1411 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1412 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1416 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1418 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1419 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1423 /* 2. Create the ParentIdPrefix value */
1424 currentByte
= (PBYTE
)DeviceNode
->Parent
->InstancePath
.Buffer
;
1425 for (i
= 0; i
< DeviceNode
->Parent
->InstancePath
.Length
; i
++, currentByte
++)
1426 crc32
= (crc32
>> 8) ^ crc32Table
[*currentByte
^ (crc32
& 0xff)];
1428 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1429 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1431 /* 3. Try to write the ParentIdPrefix to registry */
1432 Status
= ZwSetValueKey(
1435 (PVOID
)KeyValue
.Buffer
,
1436 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1439 if (NT_SUCCESS(Status
))
1441 /* Duplicate the string to return it */
1442 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1444 ExFreePool(ParentIdPrefixInformation
);
1445 ExFreePool(KeyNameBuffer
);
1446 if (hKey
!= INVALID_HANDLE_VALUE
)
1453 * IopActionInterrogateDeviceStack
1455 * Retrieve information for all (direct) child nodes of a parent node.
1459 * Pointer to device node.
1461 * Pointer to parent node to retrieve child node information for.
1464 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1465 * when we reach a device node which is not a direct child of the device
1466 * node for which we retrieve information of child nodes for. Any errors
1467 * that occur is logged instead so that all child services have a chance
1468 * of being interrogated.
1472 IopActionInterrogateDeviceStack(
1473 PDEVICE_NODE DeviceNode
,
1476 IO_STATUS_BLOCK IoStatusBlock
;
1477 PDEVICE_NODE ParentDeviceNode
;
1478 WCHAR InstancePath
[MAX_PATH
];
1479 IO_STACK_LOCATION Stack
;
1485 ULONG RequiredLength
;
1487 HANDLE InstanceKey
= NULL
;
1488 UNICODE_STRING ValueName
;
1489 UNICODE_STRING ParentIdPrefix
= { 0 };
1490 DEVICE_CAPABILITIES DeviceCapabilities
;
1492 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1493 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1495 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1498 * We are called for the parent too, but we don't need to do special
1499 * handling for this node
1502 if (DeviceNode
== ParentDeviceNode
)
1504 DPRINT("Success\n");
1505 return STATUS_SUCCESS
;
1509 * Make sure this device node is a direct child of the parent device node
1510 * that is given as an argument
1513 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1515 /* Stop the traversal immediately and indicate successful operation */
1517 return STATUS_UNSUCCESSFUL
;
1521 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1522 if (!NT_SUCCESS(Status
))
1524 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1529 * FIXME: For critical errors, cleanup and disable device, but always
1530 * return STATUS_SUCCESS.
1533 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1535 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1536 Status
= IopInitiatePnpIrp(
1537 DeviceNode
->PhysicalDeviceObject
,
1541 if (NT_SUCCESS(Status
))
1543 /* Copy the device id string */
1544 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1547 * FIXME: Check for valid characters, if there is invalid characters
1553 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1556 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1558 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1559 if (!NT_SUCCESS(Status
))
1561 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1564 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1566 if (!DeviceCapabilities
.UniqueID
)
1568 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1569 DPRINT("Instance ID is not unique\n");
1570 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1571 if (!NT_SUCCESS(Status
))
1573 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1577 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1579 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1580 Status
= IopInitiatePnpIrp(
1581 DeviceNode
->PhysicalDeviceObject
,
1585 if (NT_SUCCESS(Status
))
1587 /* Append the instance id string */
1588 wcscat(InstancePath
, L
"\\");
1589 if (ParentIdPrefix
.Length
> 0)
1591 /* Add information from parent bus device to InstancePath */
1592 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1593 if (*(PWSTR
)IoStatusBlock
.Information
)
1594 wcscat(InstancePath
, L
"&");
1596 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1599 * FIXME: Check for valid characters, if there is invalid characters
1605 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1607 RtlFreeUnicodeString(&ParentIdPrefix
);
1609 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1611 DPRINT("No resources\n");
1612 /* FIXME: Cleanup and disable device */
1615 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1618 * Create registry key for the instance id, if it doesn't exist yet
1620 KeyBuffer
= ExAllocatePool(
1622 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1623 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1624 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1625 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1627 ExFreePool(KeyBuffer
);
1628 if (!NT_SUCCESS(Status
))
1630 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1635 /* Set 'Capabilities' value */
1636 RtlInitUnicodeString(&ValueName
,
1638 Status
= ZwSetValueKey(InstanceKey
,
1642 (PVOID
)&DeviceNode
->CapabilityFlags
,
1645 /* Set 'UINumber' value */
1646 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1648 RtlInitUnicodeString(&ValueName
,
1650 Status
= ZwSetValueKey(InstanceKey
,
1654 &DeviceCapabilities
.UINumber
,
1659 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1661 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1662 Status
= IopInitiatePnpIrp(
1663 DeviceNode
->PhysicalDeviceObject
,
1667 if (NT_SUCCESS(Status
))
1670 * FIXME: Check for valid characters, if there is invalid characters
1674 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1675 DPRINT("Hardware IDs:\n");
1678 DPRINT(" %S\n", Ptr
);
1679 Length
= wcslen(Ptr
) + 1;
1682 TotalLength
+= Length
;
1684 DPRINT("TotalLength: %hu\n", TotalLength
);
1687 RtlInitUnicodeString(&ValueName
,
1689 Status
= ZwSetValueKey(InstanceKey
,
1693 (PVOID
)IoStatusBlock
.Information
,
1694 (TotalLength
+ 1) * sizeof(WCHAR
));
1695 if (!NT_SUCCESS(Status
))
1697 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1702 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1705 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1707 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1708 Status
= IopInitiatePnpIrp(
1709 DeviceNode
->PhysicalDeviceObject
,
1713 if (NT_SUCCESS(Status
))
1716 * FIXME: Check for valid characters, if there is invalid characters
1720 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1721 DPRINT("Compatible IDs:\n");
1724 DPRINT(" %S\n", Ptr
);
1725 Length
= wcslen(Ptr
) + 1;
1728 TotalLength
+= Length
;
1730 DPRINT("TotalLength: %hu\n", TotalLength
);
1733 RtlInitUnicodeString(&ValueName
,
1735 Status
= ZwSetValueKey(InstanceKey
,
1739 (PVOID
)IoStatusBlock
.Information
,
1740 (TotalLength
+ 1) * sizeof(WCHAR
));
1741 if (!NT_SUCCESS(Status
))
1743 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1748 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1752 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1754 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1755 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1756 Status
= IopInitiatePnpIrp(
1757 DeviceNode
->PhysicalDeviceObject
,
1759 IRP_MN_QUERY_DEVICE_TEXT
,
1761 if (NT_SUCCESS(Status
))
1763 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1764 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1766 /* This key is overriden when a driver is installed. Don't write the
1767 * new description if another one already exists */
1768 Status
= ZwSetValueKey(InstanceKey
,
1772 (PVOID
)IoStatusBlock
.Information
,
1773 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1775 if (!NT_SUCCESS(Status
))
1777 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1782 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1785 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1787 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1788 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1789 Status
= IopInitiatePnpIrp(
1790 DeviceNode
->PhysicalDeviceObject
,
1792 IRP_MN_QUERY_DEVICE_TEXT
,
1794 if (NT_SUCCESS(Status
))
1796 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1797 RtlInitUnicodeString(&ValueName
,
1798 L
"LocationInformation");
1799 Status
= ZwSetValueKey(InstanceKey
,
1803 (PVOID
)IoStatusBlock
.Information
,
1804 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1805 if (!NT_SUCCESS(Status
))
1807 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1812 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1815 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1817 Status
= IopInitiatePnpIrp(
1818 DeviceNode
->PhysicalDeviceObject
,
1820 IRP_MN_QUERY_BUS_INFORMATION
,
1822 if (NT_SUCCESS(Status
))
1824 PPNP_BUS_INFORMATION BusInformation
=
1825 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1827 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1828 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1829 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1830 ExFreePool(BusInformation
);
1834 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1836 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1837 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1838 DeviceNode
->ChildBusTypeIndex
= -1;
1841 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1843 Status
= IopInitiatePnpIrp(
1844 DeviceNode
->PhysicalDeviceObject
,
1846 IRP_MN_QUERY_RESOURCES
,
1848 if (NT_SUCCESS(Status
))
1850 DeviceNode
->BootResources
=
1851 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1852 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1856 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1857 DeviceNode
->BootResources
= NULL
;
1860 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1862 Status
= IopInitiatePnpIrp(
1863 DeviceNode
->PhysicalDeviceObject
,
1865 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1867 if (NT_SUCCESS(Status
))
1869 DeviceNode
->ResourceRequirements
=
1870 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1874 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1875 DeviceNode
->ResourceRequirements
= NULL
;
1879 if (InstanceKey
!= NULL
)
1881 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1884 ZwClose(InstanceKey
);
1886 Status
= IopAssignDeviceResources(DeviceNode
);
1887 if (!NT_SUCCESS(Status
))
1889 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1892 DeviceNode
->Flags
|= DNF_PROCESSED
;
1894 /* Report the device to the user-mode pnp manager */
1895 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1896 &DeviceNode
->InstancePath
);
1898 return STATUS_SUCCESS
;
1902 * IopActionConfigureChildServices
1904 * Retrieve configuration for all (direct) child nodes of a parent node.
1908 * Pointer to device node.
1910 * Pointer to parent node to retrieve child node configuration for.
1913 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1914 * when we reach a device node which is not a direct child of the device
1915 * node for which we configure child services for. Any errors that occur is
1916 * logged instead so that all child services have a chance of beeing
1921 IopActionConfigureChildServices(
1922 PDEVICE_NODE DeviceNode
,
1925 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1926 PDEVICE_NODE ParentDeviceNode
;
1927 PUNICODE_STRING Service
;
1928 UNICODE_STRING ClassGUID
;
1929 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
1932 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1934 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1937 * We are called for the parent too, but we don't need to do special
1938 * handling for this node
1940 if (DeviceNode
== ParentDeviceNode
)
1942 DPRINT("Success\n");
1943 return STATUS_SUCCESS
;
1947 * Make sure this device node is a direct child of the parent device node
1948 * that is given as an argument
1950 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1952 /* Stop the traversal immediately and indicate successful operation */
1954 return STATUS_UNSUCCESSFUL
;
1957 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1959 WCHAR RegKeyBuffer
[MAX_PATH
];
1960 UNICODE_STRING RegKey
;
1963 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1964 RegKey
.Buffer
= RegKeyBuffer
;
1967 * Retrieve configuration from Enum key
1970 Service
= &DeviceNode
->ServiceName
;
1972 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1973 RtlInitUnicodeString(Service
, NULL
);
1974 RtlInitUnicodeString(&ClassGUID
, NULL
);
1976 QueryTable
[0].Name
= L
"Service";
1977 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1978 QueryTable
[0].EntryContext
= Service
;
1980 QueryTable
[1].Name
= L
"ClassGUID";
1981 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1982 QueryTable
[1].EntryContext
= &ClassGUID
;
1983 QueryTable
[1].DefaultType
= REG_SZ
;
1984 QueryTable
[1].DefaultData
= &NullString
;
1985 QueryTable
[1].DefaultLength
= 0;
1987 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1988 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1990 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1991 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1993 if (!NT_SUCCESS(Status
))
1995 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1996 /* FIXME: Log the error */
1997 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1998 DeviceNode
->InstancePath
.Buffer
, Status
);
1999 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2000 return STATUS_SUCCESS
;
2003 if (Service
->Buffer
== NULL
)
2005 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2007 if (ClassGUID
.Length
!= 0)
2009 /* Device has a ClassGUID value, but no Service value.
2010 * Suppose it is using the NULL driver, so state the
2011 * device is started */
2012 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2013 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2015 return STATUS_SUCCESS
;
2018 DPRINT("Got Service %S\n", Service
->Buffer
);
2021 return STATUS_SUCCESS
;
2025 * IopActionInitChildServices
2027 * Initialize the service for all (direct) child nodes of a parent node
2031 * Pointer to device node.
2033 * Pointer to parent node to initialize child node services for.
2035 * Load only driver marked as boot start.
2038 * If the driver image for a service is not loaded and initialized
2039 * it is done here too. We only return a status code indicating an
2040 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2041 * not a direct child of the device node for which we initialize
2042 * child services for. Any errors that occur is logged instead so
2043 * that all child services have a chance of being initialized.
2047 IopActionInitChildServices(
2048 PDEVICE_NODE DeviceNode
,
2050 BOOLEAN BootDrivers
)
2052 PDEVICE_NODE ParentDeviceNode
;
2055 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2058 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2061 * We are called for the parent too, but we don't need to do special
2062 * handling for this node
2064 if (DeviceNode
== ParentDeviceNode
)
2066 DPRINT("Success\n");
2067 return STATUS_SUCCESS
;
2071 * Make sure this device node is a direct child of the parent device node
2072 * that is given as an argument
2075 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2078 * Stop the traversal immediately and indicate unsuccessful operation
2081 return STATUS_UNSUCCESSFUL
;
2085 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2086 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2087 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2089 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2090 PDRIVER_OBJECT DriverObject
;
2092 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2093 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2095 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2096 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2097 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2100 /* get existing DriverObject pointer */
2101 Status
= IopGetDriverObject(
2103 &DeviceNode
->ServiceName
,
2106 if (NT_SUCCESS(Status
))
2108 /* Attach lower level filter drivers. */
2109 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2110 /* Initialize the function driver for the device node */
2111 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2112 if (NT_SUCCESS(Status
))
2114 /* Attach upper level filter drivers. */
2115 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2116 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2118 Status
= IopStartDevice(DeviceNode
);
2125 * Don't disable when trying to load only boot drivers
2129 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2130 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2132 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2133 CPRINT("Initialization of service %S failed (Status %x)\n",
2134 DeviceNode
->ServiceName
.Buffer
, Status
);
2138 DPRINT("Service %S is disabled or already initialized\n",
2139 DeviceNode
->ServiceName
.Buffer
);
2142 return STATUS_SUCCESS
;
2146 * IopActionInitAllServices
2148 * Initialize the service for all (direct) child nodes of a parent node. This
2149 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2153 IopActionInitAllServices(
2154 PDEVICE_NODE DeviceNode
,
2157 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2161 * IopActionInitBootServices
2163 * Initialize the boot start services for all (direct) child nodes of a
2164 * parent node. This function just calls IopActionInitChildServices with
2165 * BootDrivers = TRUE.
2168 IopActionInitBootServices(
2169 PDEVICE_NODE DeviceNode
,
2172 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2176 * IopInitializePnpServices
2178 * Initialize services for discovered children
2182 * Top device node to start initializing services.
2185 * When set to TRUE, only drivers marked as boot start will
2186 * be loaded. Otherwise, all drivers will be loaded.
2192 IopInitializePnpServices(
2193 IN PDEVICE_NODE DeviceNode
,
2194 IN BOOLEAN BootDrivers
)
2196 DEVICETREE_TRAVERSE_CONTEXT Context
;
2198 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2202 IopInitDeviceTreeTraverseContext(
2205 IopActionInitBootServices
,
2210 IopInitDeviceTreeTraverseContext(
2213 IopActionInitAllServices
,
2217 return IopTraverseDeviceTree(&Context
);
2222 IopInvalidateDeviceRelations(
2223 IN PDEVICE_NODE DeviceNode
,
2224 IN DEVICE_RELATION_TYPE Type
)
2226 DEVICETREE_TRAVERSE_CONTEXT Context
;
2227 PDEVICE_RELATIONS DeviceRelations
;
2228 IO_STATUS_BLOCK IoStatusBlock
;
2229 PDEVICE_NODE ChildDeviceNode
;
2230 IO_STACK_LOCATION Stack
;
2232 OBJECT_ATTRIBUTES ObjectAttributes
;
2233 UNICODE_STRING LinkName
;
2238 DPRINT("DeviceNode 0x%p\n", DeviceNode
);
2240 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2242 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
2244 Status
= IopInitiatePnpIrp(
2245 DeviceNode
->PhysicalDeviceObject
,
2247 IRP_MN_QUERY_DEVICE_RELATIONS
,
2249 if (!NT_SUCCESS(Status
))
2251 DPRINT("IopInitiatePnpIrp() failed\n");
2255 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2257 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
2259 DPRINT("No PDOs\n");
2260 if (DeviceRelations
)
2262 ExFreePool(DeviceRelations
);
2264 return STATUS_SUCCESS
;
2267 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2270 * Create device nodes for all discovered devices
2273 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2275 Status
= IopCreateDeviceNode(
2277 DeviceRelations
->Objects
[i
],
2279 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2280 if (!NT_SUCCESS(Status
))
2282 DPRINT("No resources\n");
2283 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2284 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2285 ExFreePool(DeviceRelations
);
2286 return STATUS_INSUFFICIENT_RESOURCES
;
2289 ExFreePool(DeviceRelations
);
2292 * Retrieve information about all discovered children from the bus driver
2295 IopInitDeviceTreeTraverseContext(
2298 IopActionInterrogateDeviceStack
,
2301 Status
= IopTraverseDeviceTree(&Context
);
2302 if (!NT_SUCCESS(Status
))
2304 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2309 * Retrieve configuration from the registry for discovered children
2312 IopInitDeviceTreeTraverseContext(
2315 IopActionConfigureChildServices
,
2318 Status
= IopTraverseDeviceTree(&Context
);
2319 if (!NT_SUCCESS(Status
))
2321 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2326 * Get the state of the system boot. If the \\SystemRoot link isn't
2327 * created yet, we will assume that it's possible to load only boot
2331 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
2333 InitializeObjectAttributes(
2340 Status
= ZwOpenFile(
2347 if(NT_SUCCESS(Status
))
2349 BootDrivers
= FALSE
;
2356 * Initialize services for discovered children. Only boot drivers will
2357 * be loaded from boot driver!
2360 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2361 if (!NT_SUCCESS(Status
))
2363 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2367 return STATUS_SUCCESS
;
2371 static NTSTATUS INIT_FUNCTION
2372 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
2376 HANDLE InstanceKey
= NULL
;
2379 /* Create registry key for the instance id, if it doesn't exist yet */
2380 KeyBuffer
= ExAllocatePool(PagedPool
,
2381 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
2382 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2383 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2384 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2386 ExFreePool(KeyBuffer
);
2387 if (!NT_SUCCESS(Status
))
2389 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2393 /* FIXME: Set 'ConfigFlags' value */
2395 ZwClose(InstanceKey
);
2399 return STATUS_SUCCESS
;
2409 DPRINT("PnpInit()\n");
2411 KeInitializeSpinLock(&IopDeviceTreeLock
);
2413 /* Initialize the Bus Type GUID List */
2414 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2415 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2416 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2418 /* Initialize PnP-Event notification support */
2419 Status
= IopInitPlugPlayEvents();
2420 if (!NT_SUCCESS(Status
))
2422 CPRINT("IopInitPlugPlayEvents() failed\n");
2423 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2427 * Create root device node
2430 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2431 if (!NT_SUCCESS(Status
))
2433 CPRINT("IoCreateDriverObject() failed\n");
2434 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2437 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2439 if (!NT_SUCCESS(Status
))
2441 CPRINT("IoCreateDevice() failed\n");
2442 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2445 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2446 if (!NT_SUCCESS(Status
))
2448 CPRINT("Insufficient resources\n");
2449 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2452 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2455 CPRINT("Failed to create the instance path!\n");
2456 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2459 /* Report the device to the user-mode pnp manager */
2460 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2461 &IopRootDeviceNode
->InstancePath
);
2463 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2464 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2465 IopRootDriverObject
->DriverExtension
->AddDevice(
2466 IopRootDriverObject
,
2467 IopRootDeviceNode
->PhysicalDeviceObject
);
2476 /* Set root device instance data */
2477 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
2478 if (!NT_SUCCESS(Status
))
2480 CPRINT("Failed to set instance data\n");
2481 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);