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
);
331 if (ValueInformation
->DataLength
> BufferLength
)
333 ExFreePool(ValueInformation
);
334 return STATUS_BUFFER_TOO_SMALL
;
337 /* FIXME: Verify the value (NULL-terminated, correct format). */
339 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
340 ValueInformation
->DataLength
);
341 ExFreePool(ValueInformation
);
343 return STATUS_SUCCESS
;
346 case DevicePropertyBootConfiguration
:
348 if (DeviceNode
->BootResources
->Count
!= 0)
350 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
352 Data
= &DeviceNode
->BootResources
;
355 /* FIXME: use a translated boot configuration instead */
356 case DevicePropertyBootConfigurationTranslated
:
358 if (DeviceNode
->BootResources
->Count
!= 0)
360 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
362 Data
= &DeviceNode
->BootResources
;
365 case DevicePropertyEnumeratorName
:
366 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
369 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
370 Data
= DeviceNode
->InstancePath
.Buffer
;
379 case DevicePropertyPhysicalDeviceObjectName
:
380 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
381 Data
= DeviceNode
->InstancePath
.Buffer
;
385 return STATUS_INVALID_PARAMETER_2
;
388 *ResultLength
= Length
;
389 if (BufferLength
< Length
)
390 return STATUS_BUFFER_TOO_SMALL
;
391 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
393 /* Terminate the string */
394 if (DeviceProperty
== DevicePropertyEnumeratorName
395 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
397 Ptr
= (PWSTR
)PropertyBuffer
;
398 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
401 return STATUS_SUCCESS
;
409 IoInvalidateDeviceState(
410 IN PDEVICE_OBJECT PhysicalDeviceObject
)
415 * @name IoOpenDeviceRegistryKey
417 * Open a registry key unique for a specified driver or device instance.
419 * @param DeviceObject Device to get the registry key for.
420 * @param DevInstKeyType Type of the key to return.
421 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
422 * @param DevInstRegKey Handle to the opened registry key on
431 IoOpenDeviceRegistryKey(
432 IN PDEVICE_OBJECT DeviceObject
,
433 IN ULONG DevInstKeyType
,
434 IN ACCESS_MASK DesiredAccess
,
435 OUT PHANDLE DevInstRegKey
)
437 static WCHAR RootKeyName
[] =
438 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
439 static WCHAR ProfileKeyName
[] =
440 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
441 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
442 static WCHAR EnumKeyName
[] = L
"Enum\\";
443 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters\\";
445 LPWSTR KeyNameBuffer
;
446 UNICODE_STRING KeyName
;
447 ULONG DriverKeyLength
;
448 OBJECT_ATTRIBUTES ObjectAttributes
;
449 PDEVICE_NODE DeviceNode
= NULL
;
452 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
453 return STATUS_INVALID_PARAMETER
;
456 * Calculate the length of the base key name. This is the full
457 * name for driver key or the name excluding "Device Parameters"
458 * subkey for device key.
461 KeyNameLength
= sizeof(RootKeyName
);
462 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
463 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
464 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
466 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
467 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
468 0, NULL
, &DriverKeyLength
);
469 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
471 KeyNameLength
+= DriverKeyLength
;
475 DeviceNode
= IopGetDeviceNode(DeviceObject
);
476 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
477 DeviceNode
->InstancePath
.Length
;
481 * Now allocate the buffer for the key name...
484 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
485 if (KeyNameBuffer
== NULL
)
486 return STATUS_INSUFFICIENT_RESOURCES
;
489 KeyName
.MaximumLength
= KeyNameLength
;
490 KeyName
.Buffer
= KeyNameBuffer
;
493 * ...and build the key name.
496 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
497 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
499 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
500 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
502 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
504 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
505 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
506 DriverKeyLength
, KeyNameBuffer
+
507 (KeyName
.Length
/ sizeof(WCHAR
)),
509 if (!NT_SUCCESS(Status
))
511 ExFreePool(KeyNameBuffer
);
514 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
518 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
519 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
520 if (DeviceNode
->InstancePath
.Length
== 0)
522 ExFreePool(KeyNameBuffer
);
531 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
532 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
533 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
534 ExFreePool(KeyNameBuffer
);
537 * For driver key we're done now. Also if the base key doesn't
538 * exist we can bail out with error...
541 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
545 * Let's go further. For device key we must open "Device Parameters"
546 * subkey and create it if it doesn't exist yet.
549 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
550 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
551 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
552 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
553 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
554 ZwClose(ObjectAttributes
.RootDirectory
);
564 IoRequestDeviceEject(
565 IN PDEVICE_OBJECT PhysicalDeviceObject
573 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
577 if (PopSystemPowerDeviceNode
)
579 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
580 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
581 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
583 return STATUS_SUCCESS
;
586 return STATUS_UNSUCCESSFUL
;
591 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
593 USHORT i
= 0, FoundIndex
= 0xFFFF;
597 /* Acquire the lock */
598 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
600 /* Loop all entries */
601 while (i
< IopBusTypeGuidList
->GuidCount
)
603 /* Try to find a match */
604 if (RtlCompareMemory(BusTypeGuid
,
605 &IopBusTypeGuidList
->Guids
[i
],
615 /* Check if we have to grow the list */
616 if (IopBusTypeGuidList
->GuidCount
)
618 /* Calculate the new size */
619 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
620 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
622 /* Allocate the new copy */
623 NewList
= ExAllocatePool(PagedPool
, NewSize
);
625 /* Now copy them, decrease the size too */
626 NewSize
-= sizeof(GUID
);
627 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
629 /* Free the old list */
630 ExFreePool(IopBusTypeGuidList
);
632 /* Use the new buffer */
633 IopBusTypeGuidList
= NewList
;
636 /* Copy the new GUID */
637 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
641 /* The new entry is the index */
642 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
643 IopBusTypeGuidList
->GuidCount
++;
646 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
652 * Creates a device node
655 * ParentNode = Pointer to parent device node
656 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
657 * to have the root device node create one
658 * (eg. for legacy drivers)
659 * DeviceNode = Pointer to storage for created device node
665 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
666 PDEVICE_OBJECT PhysicalDeviceObject
,
667 PDEVICE_NODE
*DeviceNode
)
673 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
674 ParentNode
, PhysicalDeviceObject
);
676 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
679 return STATUS_INSUFFICIENT_RESOURCES
;
682 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
684 if (!PhysicalDeviceObject
)
686 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
687 if (!NT_SUCCESS(Status
))
693 /* This is for drivers passed on the command line to ntoskrnl.exe */
694 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
695 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
698 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
700 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
704 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
705 Node
->Parent
= ParentNode
;
706 Node
->NextSibling
= ParentNode
->Child
;
707 if (ParentNode
->Child
!= NULL
)
709 ParentNode
->Child
->PrevSibling
= Node
;
711 ParentNode
->Child
= Node
;
712 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
713 Node
->Level
= ParentNode
->Level
+ 1;
718 return STATUS_SUCCESS
;
722 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
726 /* All children must be deleted before a parent is deleted */
727 ASSERT(!DeviceNode
->Child
);
729 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
731 ASSERT(DeviceNode
->PhysicalDeviceObject
);
733 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
735 /* Unlink from parent if it exists */
737 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
739 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
742 /* Unlink from sibling list */
744 if (DeviceNode
->PrevSibling
)
746 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
749 if (DeviceNode
->NextSibling
)
751 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
754 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
756 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
758 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
760 if (DeviceNode
->ResourceList
)
762 ExFreePool(DeviceNode
->ResourceList
);
765 if (DeviceNode
->ResourceListTranslated
)
767 ExFreePool(DeviceNode
->ResourceListTranslated
);
770 if (DeviceNode
->ResourceRequirements
)
772 ExFreePool(DeviceNode
->ResourceRequirements
);
775 if (DeviceNode
->BootResources
)
777 ExFreePool(DeviceNode
->BootResources
);
780 ExFreePool(DeviceNode
);
782 return STATUS_SUCCESS
;
787 PDEVICE_OBJECT DeviceObject
,
788 PIO_STATUS_BLOCK IoStatusBlock
,
790 PIO_STACK_LOCATION Stack OPTIONAL
)
792 PDEVICE_OBJECT TopDeviceObject
;
793 PIO_STACK_LOCATION IrpSp
;
798 /* Always call the top of the device stack */
799 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
806 Irp
= IoBuildSynchronousFsdRequest(
815 /* PNP IRPs are always initialized with a status code of
816 STATUS_NOT_IMPLEMENTED */
817 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
818 Irp
->IoStatus
.Information
= 0;
820 IrpSp
= IoGetNextIrpStackLocation(Irp
);
821 IrpSp
->MinorFunction
= MinorFunction
;
828 sizeof(Stack
->Parameters
));
831 Status
= IoCallDriver(TopDeviceObject
, Irp
);
832 if (Status
== STATUS_PENDING
)
834 KeWaitForSingleObject(
840 Status
= IoStatusBlock
->Status
;
843 ObDereferenceObject(TopDeviceObject
);
850 IopTraverseDeviceTreeNode(
851 PDEVICETREE_TRAVERSE_CONTEXT Context
)
853 PDEVICE_NODE ParentDeviceNode
;
854 PDEVICE_NODE ChildDeviceNode
;
857 /* Copy context data so we don't overwrite it in subsequent calls to this function */
858 ParentDeviceNode
= Context
->DeviceNode
;
860 /* Call the action routine */
861 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
862 if (!NT_SUCCESS(Status
))
867 /* Traversal of all children nodes */
868 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
869 ChildDeviceNode
!= NULL
;
870 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
872 /* Pass the current device node to the action routine */
873 Context
->DeviceNode
= ChildDeviceNode
;
875 Status
= IopTraverseDeviceTreeNode(Context
);
876 if (!NT_SUCCESS(Status
))
887 IopTraverseDeviceTree(
888 PDEVICETREE_TRAVERSE_CONTEXT Context
)
892 DPRINT("Context 0x%p\n", Context
);
894 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
895 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
897 /* Start from the specified device node */
898 Context
->DeviceNode
= Context
->FirstDeviceNode
;
900 /* Recursively traverse the device tree */
901 Status
= IopTraverseDeviceTreeNode(Context
);
902 if (Status
== STATUS_UNSUCCESSFUL
)
904 /* The action routine just wanted to terminate the traversal with status
905 code STATUS_SUCCESS */
906 Status
= STATUS_SUCCESS
;
914 IopCreateDeviceKeyPath(PWSTR Path
,
917 OBJECT_ATTRIBUTES ObjectAttributes
;
918 WCHAR KeyBuffer
[MAX_PATH
];
919 UNICODE_STRING KeyName
;
927 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
929 return STATUS_INVALID_PARAMETER
;
932 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
934 /* Skip \\Registry\\ */
936 Current
= wcschr (Current
, L
'\\') + 1;
937 Current
= wcschr (Current
, L
'\\') + 1;
941 Next
= wcschr (Current
, L
'\\');
951 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
952 InitializeObjectAttributes (&ObjectAttributes
,
954 OBJ_CASE_INSENSITIVE
,
958 DPRINT("Create '%S'\n", KeyName
.Buffer
);
960 Status
= ZwCreateKey (&KeyHandle
,
967 if (!NT_SUCCESS (Status
))
969 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
976 return STATUS_SUCCESS
;
987 return STATUS_UNSUCCESSFUL
;
992 IopSetDeviceInstanceData(HANDLE InstanceKey
,
993 PDEVICE_NODE DeviceNode
)
995 OBJECT_ATTRIBUTES ObjectAttributes
;
996 UNICODE_STRING KeyName
;
1002 DPRINT("IopSetDeviceInstanceData() called\n");
1004 /* Create the 'LogConf' key */
1005 RtlInitUnicodeString(&KeyName
,
1007 InitializeObjectAttributes(&ObjectAttributes
,
1009 OBJ_CASE_INSENSITIVE
,
1012 Status
= ZwCreateKey(&LogConfKey
,
1019 if (NT_SUCCESS(Status
))
1021 /* Set 'BootConfig' value */
1022 if (DeviceNode
->BootResources
!= NULL
)
1024 ResCount
= DeviceNode
->BootResources
->Count
;
1027 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1029 RtlInitUnicodeString(&KeyName
,
1031 Status
= ZwSetValueKey(LogConfKey
,
1035 &DeviceNode
->BootResources
,
1040 /* Set 'BasicConfigVector' value */
1041 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1042 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1044 RtlInitUnicodeString(&KeyName
,
1045 L
"BasicConfigVector");
1046 Status
= ZwSetValueKey(LogConfKey
,
1049 REG_RESOURCE_REQUIREMENTS_LIST
,
1050 DeviceNode
->ResourceRequirements
,
1051 DeviceNode
->ResourceRequirements
->ListSize
);
1054 ZwClose(LogConfKey
);
1058 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1060 /* Create the 'Control' key */
1061 RtlInitUnicodeString(&KeyName
,
1063 InitializeObjectAttributes(&ObjectAttributes
,
1065 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1068 Status
= ZwCreateKey(&LogConfKey
,
1073 REG_OPTION_VOLATILE
,
1075 if (NT_SUCCESS(Status
))
1077 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1078 RtlInitUnicodeString(&KeyName
,
1079 L
"DeviceReference");
1080 Status
= ZwSetValueKey(LogConfKey
,
1087 ZwClose(LogConfKey
);
1092 DPRINT("IopSetDeviceInstanceData() done\n");
1094 return STATUS_SUCCESS
;
1099 IopAssignDeviceResources(
1100 PDEVICE_NODE DeviceNode
)
1102 PIO_RESOURCE_LIST ResourceList
;
1103 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1104 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1105 ULONG NumberOfResources
= 0;
1109 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
1110 * by using DeviceNode->ResourceRequirements */
1112 if (!DeviceNode
->ResourceRequirements
1113 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
1115 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
1116 return STATUS_SUCCESS
;
1119 /* FIXME: that's here that PnP arbiter should go */
1120 /* Actually, simply use resource list #0 as assigned resource list */
1121 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1122 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1124 Status
= STATUS_REVISION_MISMATCH
;
1128 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
1129 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1130 if (!DeviceNode
->ResourceList
)
1132 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1136 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
1137 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1138 if (!DeviceNode
->ResourceListTranslated
)
1140 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1144 DeviceNode
->ResourceList
->Count
= 1;
1145 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1146 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1147 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1148 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1150 DeviceNode
->ResourceListTranslated
->Count
= 1;
1151 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1152 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1153 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
1154 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
1156 for (i
= 0; i
< ResourceList
->Count
; i
++)
1158 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1160 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1162 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1163 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1164 NumberOfResources
++;
1166 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1167 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1168 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1169 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1170 switch (ResourceDescriptor
->Type
)
1172 case CmResourceTypePort
:
1174 ULONG AddressSpace
= 0; /* IO space */
1175 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1176 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1177 = ResourceDescriptor
->u
.Port
.Length
;
1178 if (!HalTranslateBusAddress(
1179 DeviceNode
->ResourceRequirements
->InterfaceType
,
1180 DeviceNode
->ResourceRequirements
->BusNumber
,
1181 DescriptorRaw
->u
.Port
.Start
,
1183 &DescriptorTranslated
->u
.Port
.Start
))
1185 Status
= STATUS_UNSUCCESSFUL
;
1190 case CmResourceTypeInterrupt
:
1192 INTERFACE_TYPE BusType
;
1197 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1198 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1199 /* FIXME: HACK: if we have a PCI device, we try
1200 * to keep the IRQ assigned by the BIOS */
1201 if (NT_SUCCESS(IoGetDeviceProperty(
1202 DeviceNode
->PhysicalDeviceObject
,
1203 DevicePropertyLegacyBusType
,
1204 sizeof(INTERFACE_TYPE
),
1206 &ret
)) && BusType
== PCIBus
)
1208 /* We have a PCI bus */
1209 if (NT_SUCCESS(IoGetDeviceProperty(
1210 DeviceNode
->PhysicalDeviceObject
,
1211 DevicePropertyAddress
,
1214 &ret
)) && SlotNumber
> 0)
1216 /* We have a good slot number */
1217 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1218 DeviceNode
->ResourceRequirements
->BusNumber
,
1221 0x3c /* PCI_INTERRUPT_LINE */,
1223 if (ret
!= 0 && ret
!= 2
1224 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1225 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1227 /* The device already has an assigned IRQ */
1228 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1232 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1233 DescriptorRaw
->u
.Interrupt
.Vector
,
1234 &DeviceNode
->InstancePath
);
1235 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1236 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1237 DeviceNode
->ResourceRequirements
->BusNumber
,
1240 0x3c /* PCI_INTERRUPT_LINE */,
1242 if (ret
== 0 || ret
== 2)
1248 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1249 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1250 DeviceNode
->ResourceRequirements
->InterfaceType
,
1251 DeviceNode
->ResourceRequirements
->BusNumber
,
1252 DescriptorRaw
->u
.Interrupt
.Level
,
1253 DescriptorRaw
->u
.Interrupt
.Vector
,
1254 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1255 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1256 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1259 case CmResourceTypeMemory
:
1261 ULONG AddressSpace
= 1; /* Memory space */
1262 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1263 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1264 = ResourceDescriptor
->u
.Memory
.Length
;
1265 if (!HalTranslateBusAddress(
1266 DeviceNode
->ResourceRequirements
->InterfaceType
,
1267 DeviceNode
->ResourceRequirements
->BusNumber
,
1268 DescriptorRaw
->u
.Memory
.Start
,
1270 &DescriptorTranslated
->u
.Memory
.Start
))
1272 Status
= STATUS_UNSUCCESSFUL
;
1277 case CmResourceTypeDma
:
1279 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1280 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1281 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1283 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1287 case CmResourceTypeBusNumber
:
1289 DescriptorRaw
->u
.BusNumber
.Start
= DescriptorTranslated
->u
.BusNumber
.Start
1290 = ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1291 DescriptorRaw
->u
.BusNumber
.Length
= DescriptorTranslated
->u
.BusNumber
.Length
1292 = ResourceDescriptor
->u
.BusNumber
.Length
;
1293 DescriptorRaw
->u
.BusNumber
.Reserved
= DescriptorTranslated
->u
.BusNumber
.Reserved
1294 = ResourceDescriptor
->u
.BusNumber
.Reserved
;
1297 /*CmResourceTypeDevicePrivate:
1298 case CmResourceTypePcCardConfig:
1299 case CmResourceTypeMfCardConfig:
1302 &DescriptorRaw->u.DevicePrivate,
1303 &ResourceDescriptor->u.DevicePrivate,
1304 sizeof(ResourceDescriptor->u.DevicePrivate));
1306 &DescriptorTranslated->u.DevicePrivate,
1307 &ResourceDescriptor->u.DevicePrivate,
1308 sizeof(ResourceDescriptor->u.DevicePrivate));
1312 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1313 NumberOfResources
--;
1319 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1320 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1322 return STATUS_SUCCESS
;
1325 if (DeviceNode
->ResourceList
)
1327 ExFreePool(DeviceNode
->ResourceList
);
1328 DeviceNode
->ResourceList
= NULL
;
1330 if (DeviceNode
->ResourceListTranslated
)
1332 ExFreePool(DeviceNode
->ResourceListTranslated
);
1333 DeviceNode
->ResourceListTranslated
= NULL
;
1341 * IopGetParentIdPrefix
1343 * Retrieve (or create) a string which identifies a device.
1347 * Pointer to device node.
1349 * Pointer to the string where is returned the parent node identifier
1352 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1353 * valid and its Buffer field is NULL-terminated. The caller needs to
1354 * to free the string with RtlFreeUnicodeString when it is no longer
1359 IopGetParentIdPrefix(
1360 PDEVICE_NODE DeviceNode
,
1361 PUNICODE_STRING ParentIdPrefix
)
1363 ULONG KeyNameBufferLength
;
1364 PWSTR KeyNameBuffer
= NULL
;
1365 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1366 UNICODE_STRING KeyName
;
1367 UNICODE_STRING KeyValue
;
1368 UNICODE_STRING ValueName
;
1369 OBJECT_ATTRIBUTES ObjectAttributes
;
1370 HANDLE hKey
= INVALID_HANDLE_VALUE
;
1376 /* HACK: As long as some devices have a NULL device
1377 * instance path, the following test is required :(
1379 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1380 return STATUS_UNSUCCESSFUL
;
1382 /* 1. Try to retrieve ParentIdPrefix from registry */
1383 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1384 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1385 if (!ParentIdPrefixInformation
)
1387 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1390 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1393 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1396 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1397 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1398 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1399 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1400 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1401 if (!NT_SUCCESS(Status
))
1403 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1404 Status
= ZwQueryValueKey(
1406 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1407 KeyNameBufferLength
, &KeyNameBufferLength
);
1408 if (NT_SUCCESS(Status
))
1410 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1411 Status
= STATUS_UNSUCCESSFUL
;
1414 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1417 /* 2. Create the ParentIdPrefix value */
1418 currentByte
= (PBYTE
)DeviceNode
->Parent
->InstancePath
.Buffer
;
1419 for (i
= 0; i
< DeviceNode
->Parent
->InstancePath
.Length
; i
++, currentByte
++)
1420 crc32
= (crc32
>> 8) ^ crc32Table
[*currentByte
^ (crc32
& 0xff)];
1422 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1423 swprintf(KeyValue
.Buffer
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1425 /* 3. Try to write the ParentIdPrefix to registry */
1426 RtlInitUnicodeString(&KeyValue
, KeyValue
.Buffer
);
1427 Status
= ZwSetValueKey(
1430 (PVOID
)KeyValue
.Buffer
,
1431 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1434 if (NT_SUCCESS(Status
))
1436 /* Duplicate the string to return it */
1437 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1438 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1439 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1441 ExFreePool(ParentIdPrefixInformation
);
1442 ExFreePool(KeyNameBuffer
);
1443 if (hKey
!= INVALID_HANDLE_VALUE
)
1450 * IopActionInterrogateDeviceStack
1452 * Retrieve information for all (direct) child nodes of a parent node.
1456 * Pointer to device node.
1458 * Pointer to parent node to retrieve child node information for.
1461 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1462 * when we reach a device node which is not a direct child of the device
1463 * node for which we retrieve information of child nodes for. Any errors
1464 * that occur is logged instead so that all child services have a chance
1465 * of being interrogated.
1469 IopActionInterrogateDeviceStack(
1470 PDEVICE_NODE DeviceNode
,
1473 IO_STATUS_BLOCK IoStatusBlock
;
1474 PDEVICE_NODE ParentDeviceNode
;
1475 WCHAR InstancePath
[MAX_PATH
];
1476 IO_STACK_LOCATION Stack
;
1482 ULONG RequiredLength
;
1484 HANDLE InstanceKey
= NULL
;
1485 UNICODE_STRING ValueName
;
1486 UNICODE_STRING ParentIdPrefix
= { 0 };
1487 DEVICE_CAPABILITIES DeviceCapabilities
;
1489 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1490 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1492 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1495 * We are called for the parent too, but we don't need to do special
1496 * handling for this node
1499 if (DeviceNode
== ParentDeviceNode
)
1501 DPRINT("Success\n");
1502 return STATUS_SUCCESS
;
1506 * Make sure this device node is a direct child of the parent device node
1507 * that is given as an argument
1510 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1512 /* Stop the traversal immediately and indicate successful operation */
1514 return STATUS_UNSUCCESSFUL
;
1518 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1519 if (!NT_SUCCESS(Status
))
1521 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1526 * FIXME: For critical errors, cleanup and disable device, but always
1527 * return STATUS_SUCCESS.
1530 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1532 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1533 Status
= IopInitiatePnpIrp(
1534 DeviceNode
->PhysicalDeviceObject
,
1538 if (NT_SUCCESS(Status
))
1540 /* Copy the device id string */
1541 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1544 * FIXME: Check for valid characters, if there is invalid characters
1550 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1553 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1555 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1556 if (!NT_SUCCESS(Status
))
1558 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1561 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1563 if (!DeviceCapabilities
.UniqueID
)
1565 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1566 DPRINT("Instance ID is not unique\n");
1567 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1568 if (!NT_SUCCESS(Status
))
1570 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1574 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1576 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1577 Status
= IopInitiatePnpIrp(
1578 DeviceNode
->PhysicalDeviceObject
,
1582 if (NT_SUCCESS(Status
))
1584 /* Append the instance id string */
1585 wcscat(InstancePath
, L
"\\");
1586 if (ParentIdPrefix
.Length
> 0)
1588 /* Add information from parent bus device to InstancePath */
1589 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1590 if (*(PWSTR
)IoStatusBlock
.Information
)
1591 wcscat(InstancePath
, L
"&");
1593 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1596 * FIXME: Check for valid characters, if there is invalid characters
1602 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1604 RtlFreeUnicodeString(&ParentIdPrefix
);
1606 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1608 DPRINT("No resources\n");
1609 /* FIXME: Cleanup and disable device */
1612 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1615 * Create registry key for the instance id, if it doesn't exist yet
1617 KeyBuffer
= ExAllocatePool(
1619 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1620 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1621 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1622 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1624 ExFreePool(KeyBuffer
);
1625 if (!NT_SUCCESS(Status
))
1627 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1632 /* Set 'Capabilities' value */
1633 RtlInitUnicodeString(&ValueName
,
1635 Status
= ZwSetValueKey(InstanceKey
,
1639 (PVOID
)&DeviceNode
->CapabilityFlags
,
1642 /* Set 'UINumber' value */
1643 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1645 RtlInitUnicodeString(&ValueName
,
1647 Status
= ZwSetValueKey(InstanceKey
,
1651 &DeviceCapabilities
.UINumber
,
1656 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1658 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1659 Status
= IopInitiatePnpIrp(
1660 DeviceNode
->PhysicalDeviceObject
,
1664 if (NT_SUCCESS(Status
))
1667 * FIXME: Check for valid characters, if there is invalid characters
1671 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1672 DPRINT("Hardware IDs:\n");
1675 DPRINT(" %S\n", Ptr
);
1676 Length
= wcslen(Ptr
) + 1;
1679 TotalLength
+= Length
;
1681 DPRINT("TotalLength: %hu\n", TotalLength
);
1684 RtlInitUnicodeString(&ValueName
,
1686 Status
= ZwSetValueKey(InstanceKey
,
1690 (PVOID
)IoStatusBlock
.Information
,
1691 (TotalLength
+ 1) * sizeof(WCHAR
));
1692 if (!NT_SUCCESS(Status
))
1694 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1699 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1702 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1704 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1705 Status
= IopInitiatePnpIrp(
1706 DeviceNode
->PhysicalDeviceObject
,
1710 if (NT_SUCCESS(Status
))
1713 * FIXME: Check for valid characters, if there is invalid characters
1717 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1718 DPRINT("Compatible IDs:\n");
1721 DPRINT(" %S\n", Ptr
);
1722 Length
= wcslen(Ptr
) + 1;
1725 TotalLength
+= Length
;
1727 DPRINT("TotalLength: %hu\n", TotalLength
);
1730 RtlInitUnicodeString(&ValueName
,
1732 Status
= ZwSetValueKey(InstanceKey
,
1736 (PVOID
)IoStatusBlock
.Information
,
1737 (TotalLength
+ 1) * sizeof(WCHAR
));
1738 if (!NT_SUCCESS(Status
))
1740 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1745 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1749 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1751 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1752 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1753 Status
= IopInitiatePnpIrp(
1754 DeviceNode
->PhysicalDeviceObject
,
1756 IRP_MN_QUERY_DEVICE_TEXT
,
1758 if (NT_SUCCESS(Status
))
1760 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1761 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1763 /* This key is overriden when a driver is installed. Don't write the
1764 * new description if another one already exists */
1765 Status
= ZwSetValueKey(InstanceKey
,
1769 (PVOID
)IoStatusBlock
.Information
,
1770 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1772 if (!NT_SUCCESS(Status
))
1774 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1779 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1782 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1784 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1785 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1786 Status
= IopInitiatePnpIrp(
1787 DeviceNode
->PhysicalDeviceObject
,
1789 IRP_MN_QUERY_DEVICE_TEXT
,
1791 if (NT_SUCCESS(Status
))
1793 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1794 RtlInitUnicodeString(&ValueName
,
1795 L
"LocationInformation");
1796 Status
= ZwSetValueKey(InstanceKey
,
1800 (PVOID
)IoStatusBlock
.Information
,
1801 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1802 if (!NT_SUCCESS(Status
))
1804 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1809 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1812 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1814 Status
= IopInitiatePnpIrp(
1815 DeviceNode
->PhysicalDeviceObject
,
1817 IRP_MN_QUERY_BUS_INFORMATION
,
1819 if (NT_SUCCESS(Status
))
1821 PPNP_BUS_INFORMATION BusInformation
=
1822 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1824 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1825 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1826 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1827 ExFreePool(BusInformation
);
1831 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1833 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1834 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1835 DeviceNode
->ChildBusTypeIndex
= -1;
1838 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1840 Status
= IopInitiatePnpIrp(
1841 DeviceNode
->PhysicalDeviceObject
,
1843 IRP_MN_QUERY_RESOURCES
,
1845 if (NT_SUCCESS(Status
))
1847 DeviceNode
->BootResources
=
1848 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1849 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1853 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1854 DeviceNode
->BootResources
= NULL
;
1857 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1859 Status
= IopInitiatePnpIrp(
1860 DeviceNode
->PhysicalDeviceObject
,
1862 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1864 if (NT_SUCCESS(Status
))
1866 DeviceNode
->ResourceRequirements
=
1867 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1871 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1872 DeviceNode
->ResourceRequirements
= NULL
;
1876 if (InstanceKey
!= NULL
)
1878 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1881 ZwClose(InstanceKey
);
1883 Status
= IopAssignDeviceResources(DeviceNode
);
1884 if (!NT_SUCCESS(Status
))
1886 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1889 DeviceNode
->Flags
|= DNF_PROCESSED
;
1891 /* Report the device to the user-mode pnp manager */
1892 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1893 &DeviceNode
->InstancePath
);
1895 return STATUS_SUCCESS
;
1899 * IopActionConfigureChildServices
1901 * Retrieve configuration for all (direct) child nodes of a parent node.
1905 * Pointer to device node.
1907 * Pointer to parent node to retrieve child node configuration for.
1910 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1911 * when we reach a device node which is not a direct child of the device
1912 * node for which we configure child services for. Any errors that occur is
1913 * logged instead so that all child services have a chance of beeing
1918 IopActionConfigureChildServices(
1919 PDEVICE_NODE DeviceNode
,
1922 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1923 PDEVICE_NODE ParentDeviceNode
;
1924 PUNICODE_STRING Service
;
1927 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1929 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1932 * We are called for the parent too, but we don't need to do special
1933 * handling for this node
1935 if (DeviceNode
== ParentDeviceNode
)
1937 DPRINT("Success\n");
1938 return STATUS_SUCCESS
;
1942 * Make sure this device node is a direct child of the parent device node
1943 * that is given as an argument
1945 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1947 /* Stop the traversal immediately and indicate successful operation */
1949 return STATUS_UNSUCCESSFUL
;
1952 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1954 WCHAR RegKeyBuffer
[MAX_PATH
];
1955 UNICODE_STRING RegKey
;
1958 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1959 RegKey
.Buffer
= RegKeyBuffer
;
1962 * Retrieve configuration from Enum key
1965 Service
= &DeviceNode
->ServiceName
;
1967 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1968 RtlInitUnicodeString(Service
, NULL
);
1970 QueryTable
[0].Name
= L
"Service";
1971 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1972 QueryTable
[0].EntryContext
= Service
;
1974 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1975 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1977 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1978 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1980 if (!NT_SUCCESS(Status
))
1982 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1983 /* FIXME: Log the error */
1984 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1985 DeviceNode
->InstancePath
.Buffer
, Status
);
1986 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1987 return STATUS_SUCCESS
;
1990 if (Service
->Buffer
== NULL
)
1992 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1993 return STATUS_SUCCESS
;
1996 DPRINT("Got Service %S\n", Service
->Buffer
);
1999 return STATUS_SUCCESS
;
2003 * IopActionInitChildServices
2005 * Initialize the service for all (direct) child nodes of a parent node
2009 * Pointer to device node.
2011 * Pointer to parent node to initialize child node services for.
2013 * Load only driver marked as boot start.
2016 * If the driver image for a service is not loaded and initialized
2017 * it is done here too. We only return a status code indicating an
2018 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2019 * not a direct child of the device node for which we initialize
2020 * child services for. Any errors that occur is logged instead so
2021 * that all child services have a chance of being initialized.
2025 IopActionInitChildServices(
2026 PDEVICE_NODE DeviceNode
,
2028 BOOLEAN BootDrivers
)
2030 PDEVICE_NODE ParentDeviceNode
;
2033 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2036 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2039 * We are called for the parent too, but we don't need to do special
2040 * handling for this node
2042 if (DeviceNode
== ParentDeviceNode
)
2044 DPRINT("Success\n");
2045 return STATUS_SUCCESS
;
2049 * Make sure this device node is a direct child of the parent device node
2050 * that is given as an argument
2053 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2056 * Stop the traversal immediately and indicate unsuccessful operation
2059 return STATUS_UNSUCCESSFUL
;
2063 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2064 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2065 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2067 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2068 PDRIVER_OBJECT DriverObject
;
2070 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2071 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2073 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2074 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2075 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2078 /* get existing DriverObject pointer */
2079 Status
= IopGetDriverObject(
2081 &DeviceNode
->ServiceName
,
2084 if (NT_SUCCESS(Status
))
2086 /* Attach lower level filter drivers. */
2087 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2088 /* Initialize the function driver for the device node */
2089 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2090 if (NT_SUCCESS(Status
))
2092 /* Attach upper level filter drivers. */
2093 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2094 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2096 Status
= IopStartDevice(DeviceNode
);
2103 * Don't disable when trying to load only boot drivers
2107 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2108 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2110 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2111 CPRINT("Initialization of service %S failed (Status %x)\n",
2112 DeviceNode
->ServiceName
.Buffer
, Status
);
2116 DPRINT("Service %S is disabled or already initialized\n",
2117 DeviceNode
->ServiceName
.Buffer
);
2120 return STATUS_SUCCESS
;
2124 * IopActionInitAllServices
2126 * Initialize the service for all (direct) child nodes of a parent node. This
2127 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2131 IopActionInitAllServices(
2132 PDEVICE_NODE DeviceNode
,
2135 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2139 * IopActionInitBootServices
2141 * Initialize the boot start services for all (direct) child nodes of a
2142 * parent node. This function just calls IopActionInitChildServices with
2143 * BootDrivers = TRUE.
2146 IopActionInitBootServices(
2147 PDEVICE_NODE DeviceNode
,
2150 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2154 * IopInitializePnpServices
2156 * Initialize services for discovered children
2160 * Top device node to start initializing services.
2163 * When set to TRUE, only drivers marked as boot start will
2164 * be loaded. Otherwise, all drivers will be loaded.
2170 IopInitializePnpServices(
2171 IN PDEVICE_NODE DeviceNode
,
2172 IN BOOLEAN BootDrivers
)
2174 DEVICETREE_TRAVERSE_CONTEXT Context
;
2176 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2180 IopInitDeviceTreeTraverseContext(
2183 IopActionInitBootServices
,
2188 IopInitDeviceTreeTraverseContext(
2191 IopActionInitAllServices
,
2195 return IopTraverseDeviceTree(&Context
);
2200 IopInvalidateDeviceRelations(
2201 IN PDEVICE_NODE DeviceNode
,
2202 IN DEVICE_RELATION_TYPE Type
)
2204 DEVICETREE_TRAVERSE_CONTEXT Context
;
2205 PDEVICE_RELATIONS DeviceRelations
;
2206 IO_STATUS_BLOCK IoStatusBlock
;
2207 PDEVICE_NODE ChildDeviceNode
;
2208 IO_STACK_LOCATION Stack
;
2210 OBJECT_ATTRIBUTES ObjectAttributes
;
2211 UNICODE_STRING LinkName
;
2216 DPRINT("DeviceNode 0x%p\n", DeviceNode
);
2218 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2220 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
2222 Status
= IopInitiatePnpIrp(
2223 DeviceNode
->PhysicalDeviceObject
,
2225 IRP_MN_QUERY_DEVICE_RELATIONS
,
2227 if (!NT_SUCCESS(Status
))
2229 DPRINT("IopInitiatePnpIrp() failed\n");
2233 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2235 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
2237 DPRINT("No PDOs\n");
2238 if (DeviceRelations
)
2240 ExFreePool(DeviceRelations
);
2242 return STATUS_SUCCESS
;
2245 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2248 * Create device nodes for all discovered devices
2251 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2253 Status
= IopCreateDeviceNode(
2255 DeviceRelations
->Objects
[i
],
2257 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2258 if (!NT_SUCCESS(Status
))
2260 DPRINT("No resources\n");
2261 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2262 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2263 ExFreePool(DeviceRelations
);
2264 return STATUS_INSUFFICIENT_RESOURCES
;
2267 ExFreePool(DeviceRelations
);
2270 * Retrieve information about all discovered children from the bus driver
2273 IopInitDeviceTreeTraverseContext(
2276 IopActionInterrogateDeviceStack
,
2279 Status
= IopTraverseDeviceTree(&Context
);
2280 if (!NT_SUCCESS(Status
))
2282 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2287 * Retrieve configuration from the registry for discovered children
2290 IopInitDeviceTreeTraverseContext(
2293 IopActionConfigureChildServices
,
2296 Status
= IopTraverseDeviceTree(&Context
);
2297 if (!NT_SUCCESS(Status
))
2299 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2304 * Get the state of the system boot. If the \\SystemRoot link isn't
2305 * created yet, we will assume that it's possible to load only boot
2309 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
2311 InitializeObjectAttributes(
2318 Status
= ZwOpenFile(
2325 if(NT_SUCCESS(Status
))
2327 BootDrivers
= FALSE
;
2334 * Initialize services for discovered children. Only boot drivers will
2335 * be loaded from boot driver!
2338 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2339 if (!NT_SUCCESS(Status
))
2341 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2345 return STATUS_SUCCESS
;
2349 static NTSTATUS INIT_FUNCTION
2350 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
2354 HANDLE InstanceKey
= NULL
;
2357 /* Create registry key for the instance id, if it doesn't exist yet */
2358 KeyBuffer
= ExAllocatePool(PagedPool
,
2359 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
2360 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2361 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2362 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2364 ExFreePool(KeyBuffer
);
2365 if (!NT_SUCCESS(Status
))
2367 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2371 /* FIXME: Set 'ConfigFlags' value */
2373 ZwClose(InstanceKey
);
2377 return STATUS_SUCCESS
;
2387 DPRINT("PnpInit()\n");
2389 KeInitializeSpinLock(&IopDeviceTreeLock
);
2391 /* Initialize the Bus Type GUID List */
2392 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2393 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2394 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2396 /* Initialize PnP-Event notification support */
2397 Status
= IopInitPlugPlayEvents();
2398 if (!NT_SUCCESS(Status
))
2400 CPRINT("IopInitPlugPlayEvents() failed\n");
2401 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2405 * Create root device node
2408 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2409 if (!NT_SUCCESS(Status
))
2411 CPRINT("IoCreateDriverObject() failed\n");
2412 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2415 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2417 if (!NT_SUCCESS(Status
))
2419 CPRINT("IoCreateDevice() failed\n");
2420 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2423 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2424 if (!NT_SUCCESS(Status
))
2426 CPRINT("Insufficient resources\n");
2427 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2430 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2433 CPRINT("Failed to create the instance path!\n");
2434 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2437 /* Report the device to the user-mode pnp manager */
2438 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2439 &IopRootDeviceNode
->InstancePath
);
2441 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2442 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2443 IopRootDriverObject
->DriverExtension
->AddDevice(
2444 IopRootDriverObject
,
2445 IopRootDeviceNode
->PhysicalDeviceObject
);
2454 /* Set root device instance data */
2455 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
2456 if (!NT_SUCCESS(Status
))
2458 CPRINT("Failed to set instance data\n");
2459 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);