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,
100 static NTSTATUS INIT_FUNCTION
101 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
);
103 #if defined (ALLOC_PRAGMA)
104 #pragma alloc_text(INIT, IopSetRootDeviceInstanceData)
105 #pragma alloc_text(INIT, PnpInit)
106 #pragma alloc_text(INIT, PnpInit2)
110 /* FUNCTIONS *****************************************************************/
114 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
116 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
121 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
122 PDEVICE_CAPABILITIES DeviceCaps
)
124 IO_STATUS_BLOCK StatusBlock
;
125 IO_STACK_LOCATION Stack
;
127 /* Set up the Header */
128 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
129 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
130 DeviceCaps
->Version
= 1;
131 DeviceCaps
->Address
= -1;
132 DeviceCaps
->UINumber
= -1;
134 /* Set up the Stack */
135 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
136 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
139 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
141 IRP_MN_QUERY_CAPABILITIES
,
150 IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
151 IN DEVICE_RELATION_TYPE Type
)
153 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Type
);
161 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
162 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
163 IN ULONG BufferLength
,
164 OUT PVOID PropertyBuffer
,
165 OUT PULONG ResultLength
)
167 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
168 DEVICE_CAPABILITIES DeviceCaps
;
174 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
176 if (DeviceNode
== NULL
)
177 return STATUS_INVALID_DEVICE_REQUEST
;
179 switch (DeviceProperty
)
181 case DevicePropertyBusNumber
:
182 Length
= sizeof(ULONG
);
183 Data
= &DeviceNode
->ChildBusNumber
;
186 /* Complete, untested */
187 case DevicePropertyBusTypeGuid
:
189 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
190 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
192 /* Return the GUID */
193 *ResultLength
= sizeof(GUID
);
195 /* Check if the buffer given was large enough */
196 if (BufferLength
< *ResultLength
)
198 return STATUS_BUFFER_TOO_SMALL
;
202 RtlCopyMemory(PropertyBuffer
,
203 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
205 return STATUS_SUCCESS
;
209 return STATUS_OBJECT_NAME_NOT_FOUND
;
213 case DevicePropertyLegacyBusType
:
214 Length
= sizeof(INTERFACE_TYPE
);
215 Data
= &DeviceNode
->ChildInterfaceType
;
218 case DevicePropertyAddress
:
219 /* Query the device caps */
220 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
221 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
224 *ResultLength
= sizeof(ULONG
);
226 /* Check if the buffer given was large enough */
227 if (BufferLength
< *ResultLength
)
229 return STATUS_BUFFER_TOO_SMALL
;
233 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
234 return STATUS_SUCCESS
;
238 return STATUS_OBJECT_NAME_NOT_FOUND
;
242 // case DevicePropertyUINumber:
243 // if (DeviceNode->CapabilityFlags == NULL)
244 // return STATUS_INVALID_DEVICE_REQUEST;
245 // Length = sizeof(ULONG);
246 // Data = &DeviceNode->CapabilityFlags->UINumber;
249 case DevicePropertyClassName
:
250 case DevicePropertyClassGuid
:
251 case DevicePropertyDriverKeyName
:
252 case DevicePropertyManufacturer
:
253 case DevicePropertyFriendlyName
:
254 case DevicePropertyHardwareID
:
255 case DevicePropertyCompatibleIDs
:
256 case DevicePropertyDeviceDescription
:
257 case DevicePropertyLocationInformation
:
258 case DevicePropertyUINumber
:
260 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
261 UNICODE_STRING KeyName
, ValueName
;
262 OBJECT_ATTRIBUTES ObjectAttributes
;
263 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
264 ULONG ValueInformationLength
;
268 switch (DeviceProperty
)
270 case DevicePropertyClassName
:
271 RegistryPropertyName
= L
"Class"; break;
272 case DevicePropertyClassGuid
:
273 RegistryPropertyName
= L
"ClassGuid"; break;
274 case DevicePropertyDriverKeyName
:
275 RegistryPropertyName
= L
"Driver"; break;
276 case DevicePropertyManufacturer
:
277 RegistryPropertyName
= L
"Mfg"; break;
278 case DevicePropertyFriendlyName
:
279 RegistryPropertyName
= L
"FriendlyName"; break;
280 case DevicePropertyHardwareID
:
281 RegistryPropertyName
= L
"HardwareID"; break;
282 case DevicePropertyCompatibleIDs
:
283 RegistryPropertyName
= L
"CompatibleIDs"; break;
284 case DevicePropertyDeviceDescription
:
285 RegistryPropertyName
= L
"DeviceDesc"; break;
286 case DevicePropertyLocationInformation
:
287 RegistryPropertyName
= L
"LocationInformation"; break;
288 case DevicePropertyUINumber
:
289 RegistryPropertyName
= L
"UINumber"; break;
291 RegistryPropertyName
= NULL
; break;
294 KeyNameBuffer
= ExAllocatePool(PagedPool
,
295 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
297 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
299 if (KeyNameBuffer
== NULL
)
300 return STATUS_INSUFFICIENT_RESOURCES
;
302 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
303 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
304 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
305 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
306 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
308 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
309 ExFreePool(KeyNameBuffer
);
310 if (!NT_SUCCESS(Status
))
313 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
314 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
315 Data
[0]) + BufferLength
;
316 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
317 if (ValueInformation
== NULL
)
320 return STATUS_INSUFFICIENT_RESOURCES
;
323 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
324 KeyValuePartialInformation
, ValueInformation
,
325 ValueInformationLength
,
326 &ValueInformationLength
);
327 *ResultLength
= ValueInformation
->DataLength
;
330 if (!NT_SUCCESS(Status
))
332 ExFreePool(ValueInformation
);
333 if (Status
== STATUS_BUFFER_OVERFLOW
)
334 return STATUS_BUFFER_TOO_SMALL
;
339 /* FIXME: Verify the value (NULL-terminated, correct format). */
341 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
342 ValueInformation
->DataLength
);
343 ExFreePool(ValueInformation
);
345 return STATUS_SUCCESS
;
348 case DevicePropertyBootConfiguration
:
350 if (DeviceNode
->BootResources
->Count
!= 0)
352 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
354 Data
= &DeviceNode
->BootResources
;
357 /* FIXME: use a translated boot configuration instead */
358 case DevicePropertyBootConfigurationTranslated
:
360 if (DeviceNode
->BootResources
->Count
!= 0)
362 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
364 Data
= &DeviceNode
->BootResources
;
367 case DevicePropertyEnumeratorName
:
368 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
371 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
372 Data
= DeviceNode
->InstancePath
.Buffer
;
381 case DevicePropertyPhysicalDeviceObjectName
:
382 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
383 Data
= DeviceNode
->InstancePath
.Buffer
;
387 return STATUS_INVALID_PARAMETER_2
;
390 *ResultLength
= Length
;
391 if (BufferLength
< Length
)
392 return STATUS_BUFFER_TOO_SMALL
;
393 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
395 /* Terminate the string */
396 if (DeviceProperty
== DevicePropertyEnumeratorName
397 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
399 Ptr
= (PWSTR
)PropertyBuffer
;
400 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
403 return STATUS_SUCCESS
;
411 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
416 * @name IoOpenDeviceRegistryKey
418 * Open a registry key unique for a specified driver or device instance.
420 * @param DeviceObject Device to get the registry key for.
421 * @param DevInstKeyType Type of the key to return.
422 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
423 * @param DevInstRegKey Handle to the opened registry key on
432 IoOpenDeviceRegistryKey(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 DPRINT("IoOpenDeviceRegistryKey() called\n");
454 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
455 return STATUS_INVALID_PARAMETER
;
458 * Calculate the length of the base key name. This is the full
459 * name for driver key or the name excluding "Device Parameters"
460 * subkey for device key.
463 KeyNameLength
= sizeof(RootKeyName
);
464 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
465 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
466 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
468 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
469 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
470 0, NULL
, &DriverKeyLength
);
471 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
473 KeyNameLength
+= DriverKeyLength
;
477 DeviceNode
= IopGetDeviceNode(DeviceObject
);
478 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
479 DeviceNode
->InstancePath
.Length
;
483 * Now allocate the buffer for the key name...
486 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
487 if (KeyNameBuffer
== NULL
)
488 return STATUS_INSUFFICIENT_RESOURCES
;
491 KeyName
.MaximumLength
= KeyNameLength
;
492 KeyName
.Buffer
= KeyNameBuffer
;
495 * ...and build the key name.
498 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
499 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
501 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
502 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
504 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
506 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
507 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
508 DriverKeyLength
, KeyNameBuffer
+
509 (KeyName
.Length
/ sizeof(WCHAR
)),
511 if (!NT_SUCCESS(Status
))
513 ExFreePool(KeyNameBuffer
);
516 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
520 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
521 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
522 if (DeviceNode
->InstancePath
.Length
== 0)
524 ExFreePool(KeyNameBuffer
);
533 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
534 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
535 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
536 ExFreePool(KeyNameBuffer
);
539 * For driver key we're done now. Also if the base key doesn't
540 * exist we can bail out with error...
543 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
545 DPRINT1("IoOpenDeviceRegistryKey(): Base key doesn't exist, exiting...\n");
550 * Let's go further. For device key we must open "Device Parameters"
551 * subkey and create it if it doesn't exist yet.
554 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
555 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
556 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
557 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
558 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
559 ZwClose(ObjectAttributes
.RootDirectory
);
569 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
576 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
580 if (PopSystemPowerDeviceNode
)
582 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
583 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
584 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
586 return STATUS_SUCCESS
;
589 return STATUS_UNSUCCESSFUL
;
594 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
596 USHORT i
= 0, FoundIndex
= 0xFFFF;
600 /* Acquire the lock */
601 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
603 /* Loop all entries */
604 while (i
< IopBusTypeGuidList
->GuidCount
)
606 /* Try to find a match */
607 if (RtlCompareMemory(BusTypeGuid
,
608 &IopBusTypeGuidList
->Guids
[i
],
618 /* Check if we have to grow the list */
619 if (IopBusTypeGuidList
->GuidCount
)
621 /* Calculate the new size */
622 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
623 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
625 /* Allocate the new copy */
626 NewList
= ExAllocatePool(PagedPool
, NewSize
);
628 /* Now copy them, decrease the size too */
629 NewSize
-= sizeof(GUID
);
630 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
632 /* Free the old list */
633 ExFreePool(IopBusTypeGuidList
);
635 /* Use the new buffer */
636 IopBusTypeGuidList
= NewList
;
639 /* Copy the new GUID */
640 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
644 /* The new entry is the index */
645 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
646 IopBusTypeGuidList
->GuidCount
++;
649 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
655 * Creates a device node
658 * ParentNode = Pointer to parent device node
659 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
660 * to have the root device node create one
661 * (eg. for legacy drivers)
662 * DeviceNode = Pointer to storage for created device node
668 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
669 PDEVICE_OBJECT PhysicalDeviceObject
,
670 PDEVICE_NODE
*DeviceNode
)
676 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
677 ParentNode
, PhysicalDeviceObject
);
679 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
682 return STATUS_INSUFFICIENT_RESOURCES
;
685 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
687 if (!PhysicalDeviceObject
)
689 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
690 if (!NT_SUCCESS(Status
))
696 /* This is for drivers passed on the command line to ntoskrnl.exe */
697 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
698 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
701 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
703 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
707 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
708 Node
->Parent
= ParentNode
;
709 Node
->NextSibling
= ParentNode
->Child
;
710 if (ParentNode
->Child
!= NULL
)
712 ParentNode
->Child
->PrevSibling
= Node
;
714 ParentNode
->Child
= Node
;
715 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
716 Node
->Level
= ParentNode
->Level
+ 1;
721 return STATUS_SUCCESS
;
725 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
729 /* All children must be deleted before a parent is deleted */
730 ASSERT(!DeviceNode
->Child
);
732 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
734 ASSERT(DeviceNode
->PhysicalDeviceObject
);
736 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
738 /* Unlink from parent if it exists */
740 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
742 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
745 /* Unlink from sibling list */
747 if (DeviceNode
->PrevSibling
)
749 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
752 if (DeviceNode
->NextSibling
)
754 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
757 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
759 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
761 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
763 if (DeviceNode
->ResourceList
)
765 ExFreePool(DeviceNode
->ResourceList
);
768 if (DeviceNode
->ResourceListTranslated
)
770 ExFreePool(DeviceNode
->ResourceListTranslated
);
773 if (DeviceNode
->ResourceRequirements
)
775 ExFreePool(DeviceNode
->ResourceRequirements
);
778 if (DeviceNode
->BootResources
)
780 ExFreePool(DeviceNode
->BootResources
);
783 ExFreePool(DeviceNode
);
785 return STATUS_SUCCESS
;
789 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
790 PIO_STATUS_BLOCK IoStatusBlock
,
792 PIO_STACK_LOCATION Stack OPTIONAL
)
794 PDEVICE_OBJECT TopDeviceObject
;
795 PIO_STACK_LOCATION IrpSp
;
800 /* Always call the top of the device stack */
801 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
808 Irp
= IoBuildSynchronousFsdRequest(
817 /* PNP IRPs are always initialized with a status code of
818 STATUS_NOT_IMPLEMENTED */
819 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
820 Irp
->IoStatus
.Information
= 0;
822 IrpSp
= IoGetNextIrpStackLocation(Irp
);
823 IrpSp
->MinorFunction
= MinorFunction
;
827 RtlMoveMemory(&IrpSp
->Parameters
,
829 sizeof(Stack
->Parameters
));
832 Status
= IoCallDriver(TopDeviceObject
, Irp
);
833 if (Status
== STATUS_PENDING
)
835 KeWaitForSingleObject(&Event
,
840 Status
= IoStatusBlock
->Status
;
843 ObDereferenceObject(TopDeviceObject
);
850 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
852 PDEVICE_NODE ParentDeviceNode
;
853 PDEVICE_NODE ChildDeviceNode
;
856 /* Copy context data so we don't overwrite it in subsequent calls to this function */
857 ParentDeviceNode
= Context
->DeviceNode
;
859 /* Call the action routine */
860 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
861 if (!NT_SUCCESS(Status
))
866 /* Traversal of all children nodes */
867 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
868 ChildDeviceNode
!= NULL
;
869 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
871 /* Pass the current device node to the action routine */
872 Context
->DeviceNode
= ChildDeviceNode
;
874 Status
= IopTraverseDeviceTreeNode(Context
);
875 if (!NT_SUCCESS(Status
))
886 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
890 DPRINT("Context 0x%p\n", Context
);
892 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
893 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
895 /* Start from the specified device node */
896 Context
->DeviceNode
= Context
->FirstDeviceNode
;
898 /* Recursively traverse the device tree */
899 Status
= IopTraverseDeviceTreeNode(Context
);
900 if (Status
== STATUS_UNSUCCESSFUL
)
902 /* The action routine just wanted to terminate the traversal with status
903 code STATUS_SUCCESS */
904 Status
= STATUS_SUCCESS
;
913 IopCreateDeviceKeyPath(PWSTR Path
,
916 OBJECT_ATTRIBUTES ObjectAttributes
;
917 WCHAR KeyBuffer
[MAX_PATH
];
918 UNICODE_STRING KeyName
;
926 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
928 return STATUS_INVALID_PARAMETER
;
931 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
933 /* Skip \\Registry\\ */
935 Current
= wcschr (Current
, L
'\\') + 1;
936 Current
= wcschr (Current
, L
'\\') + 1;
940 Next
= wcschr (Current
, L
'\\');
950 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
951 InitializeObjectAttributes (&ObjectAttributes
,
953 OBJ_CASE_INSENSITIVE
,
957 DPRINT("Create '%S'\n", KeyName
.Buffer
);
959 Status
= ZwCreateKey (&KeyHandle
,
966 if (!NT_SUCCESS (Status
))
968 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
975 return STATUS_SUCCESS
;
986 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
, L
"LogConf");
1006 InitializeObjectAttributes(&ObjectAttributes
,
1008 OBJ_CASE_INSENSITIVE
,
1011 Status
= ZwCreateKey(&LogConfKey
,
1018 if (NT_SUCCESS(Status
))
1020 /* Set 'BootConfig' value */
1021 if (DeviceNode
->BootResources
!= NULL
)
1023 ResCount
= DeviceNode
->BootResources
->Count
;
1026 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1028 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1029 Status
= ZwSetValueKey(LogConfKey
,
1033 &DeviceNode
->BootResources
,
1038 /* Set 'BasicConfigVector' value */
1039 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1040 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1042 RtlInitUnicodeString(&KeyName
, 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(PDEVICE_NODE DeviceNode
)
1098 PIO_RESOURCE_LIST ResourceList
;
1099 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1100 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1101 ULONG NumberOfResources
= 0;
1105 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
1106 * by using DeviceNode->ResourceRequirements */
1108 if (!DeviceNode
->ResourceRequirements
1109 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
1111 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
1112 return STATUS_SUCCESS
;
1115 /* FIXME: that's here that PnP arbiter should go */
1116 /* Actually, simply use resource list #0 as assigned resource list */
1117 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1118 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1120 Status
= STATUS_REVISION_MISMATCH
;
1124 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
1125 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1126 if (!DeviceNode
->ResourceList
)
1128 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1132 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
1133 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1134 if (!DeviceNode
->ResourceListTranslated
)
1136 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1140 DeviceNode
->ResourceList
->Count
= 1;
1141 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1142 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1143 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1144 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1146 DeviceNode
->ResourceListTranslated
->Count
= 1;
1147 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1148 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1149 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
1150 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
1152 for (i
= 0; i
< ResourceList
->Count
; i
++)
1154 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1156 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1158 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1159 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1160 NumberOfResources
++;
1162 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1163 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1164 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1165 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1166 switch (ResourceDescriptor
->Type
)
1168 case CmResourceTypePort
:
1170 ULONG AddressSpace
= 0; /* IO space */
1171 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1172 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1173 = ResourceDescriptor
->u
.Port
.Length
;
1174 if (!HalTranslateBusAddress(
1175 DeviceNode
->ResourceRequirements
->InterfaceType
,
1176 DeviceNode
->ResourceRequirements
->BusNumber
,
1177 DescriptorRaw
->u
.Port
.Start
,
1179 &DescriptorTranslated
->u
.Port
.Start
))
1181 Status
= STATUS_UNSUCCESSFUL
;
1186 case CmResourceTypeInterrupt
:
1188 INTERFACE_TYPE BusType
;
1193 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1194 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1195 /* FIXME: HACK: if we have a PCI device, we try
1196 * to keep the IRQ assigned by the BIOS */
1197 if (NT_SUCCESS(IoGetDeviceProperty(
1198 DeviceNode
->PhysicalDeviceObject
,
1199 DevicePropertyLegacyBusType
,
1200 sizeof(INTERFACE_TYPE
),
1202 &ret
)) && BusType
== PCIBus
)
1204 /* We have a PCI bus */
1205 if (NT_SUCCESS(IoGetDeviceProperty(
1206 DeviceNode
->PhysicalDeviceObject
,
1207 DevicePropertyAddress
,
1210 &ret
)) && SlotNumber
> 0)
1212 /* We have a good slot number */
1213 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1214 DeviceNode
->ResourceRequirements
->BusNumber
,
1217 0x3c /* PCI_INTERRUPT_LINE */,
1219 if (ret
!= 0 && ret
!= 2
1220 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1221 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1223 /* The device already has an assigned IRQ */
1224 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1228 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1229 DescriptorRaw
->u
.Interrupt
.Vector
,
1230 &DeviceNode
->InstancePath
);
1231 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1232 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1233 DeviceNode
->ResourceRequirements
->BusNumber
,
1236 0x3c /* PCI_INTERRUPT_LINE */,
1238 if (ret
== 0 || ret
== 2)
1244 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1245 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1246 DeviceNode
->ResourceRequirements
->InterfaceType
,
1247 DeviceNode
->ResourceRequirements
->BusNumber
,
1248 DescriptorRaw
->u
.Interrupt
.Level
,
1249 DescriptorRaw
->u
.Interrupt
.Vector
,
1250 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1251 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1252 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1255 case CmResourceTypeMemory
:
1257 ULONG AddressSpace
= 1; /* Memory space */
1258 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1259 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1260 = ResourceDescriptor
->u
.Memory
.Length
;
1261 if (!HalTranslateBusAddress(
1262 DeviceNode
->ResourceRequirements
->InterfaceType
,
1263 DeviceNode
->ResourceRequirements
->BusNumber
,
1264 DescriptorRaw
->u
.Memory
.Start
,
1266 &DescriptorTranslated
->u
.Memory
.Start
))
1268 Status
= STATUS_UNSUCCESSFUL
;
1273 case CmResourceTypeDma
:
1275 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1276 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1277 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1279 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1283 case CmResourceTypeBusNumber
:
1285 DescriptorRaw
->u
.BusNumber
.Start
= DescriptorTranslated
->u
.BusNumber
.Start
1286 = ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1287 DescriptorRaw
->u
.BusNumber
.Length
= DescriptorTranslated
->u
.BusNumber
.Length
1288 = ResourceDescriptor
->u
.BusNumber
.Length
;
1289 DescriptorRaw
->u
.BusNumber
.Reserved
= DescriptorTranslated
->u
.BusNumber
.Reserved
1290 = ResourceDescriptor
->u
.BusNumber
.Reserved
;
1293 /*CmResourceTypeDevicePrivate:
1294 case CmResourceTypePcCardConfig:
1295 case CmResourceTypeMfCardConfig:
1298 &DescriptorRaw->u.DevicePrivate,
1299 &ResourceDescriptor->u.DevicePrivate,
1300 sizeof(ResourceDescriptor->u.DevicePrivate));
1302 &DescriptorTranslated->u.DevicePrivate,
1303 &ResourceDescriptor->u.DevicePrivate,
1304 sizeof(ResourceDescriptor->u.DevicePrivate));
1308 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1309 NumberOfResources
--;
1315 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1316 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1318 return STATUS_SUCCESS
;
1321 if (DeviceNode
->ResourceList
)
1323 ExFreePool(DeviceNode
->ResourceList
);
1324 DeviceNode
->ResourceList
= NULL
;
1326 if (DeviceNode
->ResourceListTranslated
)
1328 ExFreePool(DeviceNode
->ResourceListTranslated
);
1329 DeviceNode
->ResourceListTranslated
= NULL
;
1337 * IopGetParentIdPrefix
1339 * Retrieve (or create) a string which identifies a device.
1343 * Pointer to device node.
1345 * Pointer to the string where is returned the parent node identifier
1348 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1349 * valid and its Buffer field is NULL-terminated. The caller needs to
1350 * to free the string with RtlFreeUnicodeString when it is no longer
1355 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1356 PUNICODE_STRING ParentIdPrefix
)
1358 ULONG KeyNameBufferLength
;
1359 PWSTR KeyNameBuffer
= NULL
;
1360 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1361 UNICODE_STRING KeyName
;
1362 UNICODE_STRING KeyValue
;
1363 UNICODE_STRING ValueName
;
1364 OBJECT_ATTRIBUTES ObjectAttributes
;
1365 HANDLE hKey
= INVALID_HANDLE_VALUE
;
1371 /* HACK: As long as some devices have a NULL device
1372 * instance path, the following test is required :(
1374 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1375 return STATUS_UNSUCCESSFUL
;
1377 /* 1. Try to retrieve ParentIdPrefix from registry */
1378 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1379 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1380 if (!ParentIdPrefixInformation
)
1382 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1385 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1388 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1391 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1392 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1393 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1394 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1395 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1396 if (!NT_SUCCESS(Status
))
1398 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1399 Status
= ZwQueryValueKey(
1401 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1402 KeyNameBufferLength
, &KeyNameBufferLength
);
1403 if (NT_SUCCESS(Status
))
1405 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1406 Status
= STATUS_UNSUCCESSFUL
;
1409 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1410 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1414 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1416 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1417 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1421 /* 2. Create the ParentIdPrefix value */
1422 currentByte
= (PBYTE
)DeviceNode
->Parent
->InstancePath
.Buffer
;
1423 for (i
= 0; i
< DeviceNode
->Parent
->InstancePath
.Length
; i
++, currentByte
++)
1424 crc32
= (crc32
>> 8) ^ crc32Table
[*currentByte
^ (crc32
& 0xff)];
1426 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1427 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1429 /* 3. Try to write the ParentIdPrefix to registry */
1430 Status
= ZwSetValueKey(hKey
,
1434 (PVOID
)KeyValue
.Buffer
,
1435 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1438 if (NT_SUCCESS(Status
))
1440 /* Duplicate the string to return it */
1441 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1443 ExFreePool(ParentIdPrefixInformation
);
1444 ExFreePool(KeyNameBuffer
);
1445 if (hKey
!= INVALID_HANDLE_VALUE
)
1452 * IopActionInterrogateDeviceStack
1454 * Retrieve information for all (direct) child nodes of a parent node.
1458 * Pointer to device node.
1460 * Pointer to parent node to retrieve child node information for.
1463 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1464 * when we reach a device node which is not a direct child of the device
1465 * node for which we retrieve information of child nodes for. Any errors
1466 * that occur is logged instead so that all child services have a chance
1467 * of being interrogated.
1471 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1474 IO_STATUS_BLOCK IoStatusBlock
;
1475 PDEVICE_NODE ParentDeviceNode
;
1476 WCHAR InstancePath
[MAX_PATH
];
1477 IO_STACK_LOCATION Stack
;
1483 ULONG RequiredLength
;
1485 HANDLE InstanceKey
= NULL
;
1486 UNICODE_STRING ValueName
;
1487 UNICODE_STRING ParentIdPrefix
= { 0 };
1488 DEVICE_CAPABILITIES DeviceCapabilities
;
1490 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1491 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1493 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1496 * We are called for the parent too, but we don't need to do special
1497 * handling for this node
1500 if (DeviceNode
== ParentDeviceNode
)
1502 DPRINT("Success\n");
1503 return STATUS_SUCCESS
;
1507 * Make sure this device node is a direct child of the parent device node
1508 * that is given as an argument
1511 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1513 /* Stop the traversal immediately and indicate successful operation */
1515 return STATUS_UNSUCCESSFUL
;
1519 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1520 if (!NT_SUCCESS(Status
))
1522 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1527 * FIXME: For critical errors, cleanup and disable device, but always
1528 * return STATUS_SUCCESS.
1531 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1533 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1534 Status
= IopInitiatePnpIrp(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(DeviceNode
->PhysicalDeviceObject
,
1581 if (NT_SUCCESS(Status
))
1583 /* Append the instance id string */
1584 wcscat(InstancePath
, L
"\\");
1585 if (ParentIdPrefix
.Length
> 0)
1587 /* Add information from parent bus device to InstancePath */
1588 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1589 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1590 wcscat(InstancePath
, L
"&");
1592 if (IoStatusBlock
.Information
)
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
, &InstanceKey
);
1623 ExFreePool(KeyBuffer
);
1624 if (!NT_SUCCESS(Status
))
1626 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1631 /* Set 'Capabilities' value */
1632 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1633 Status
= ZwSetValueKey(InstanceKey
,
1637 (PVOID
)&DeviceNode
->CapabilityFlags
,
1640 /* Set 'UINumber' value */
1641 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1643 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1644 Status
= ZwSetValueKey(InstanceKey
,
1648 &DeviceCapabilities
.UINumber
,
1653 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1655 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1656 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1660 if (NT_SUCCESS(Status
))
1663 * FIXME: Check for valid characters, if there is invalid characters
1667 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1668 DPRINT("Hardware IDs:\n");
1671 DPRINT(" %S\n", Ptr
);
1672 Length
= wcslen(Ptr
) + 1;
1675 TotalLength
+= Length
;
1677 DPRINT("TotalLength: %hu\n", TotalLength
);
1680 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1681 Status
= ZwSetValueKey(InstanceKey
,
1685 (PVOID
)IoStatusBlock
.Information
,
1686 (TotalLength
+ 1) * sizeof(WCHAR
));
1687 if (!NT_SUCCESS(Status
))
1689 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1694 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1697 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1699 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1700 Status
= IopInitiatePnpIrp(
1701 DeviceNode
->PhysicalDeviceObject
,
1705 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1708 * FIXME: Check for valid characters, if there is invalid characters
1712 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1713 DPRINT("Compatible IDs:\n");
1716 DPRINT(" %S\n", Ptr
);
1717 Length
= wcslen(Ptr
) + 1;
1720 TotalLength
+= Length
;
1722 DPRINT("TotalLength: %hu\n", TotalLength
);
1725 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1726 Status
= ZwSetValueKey(InstanceKey
,
1730 (PVOID
)IoStatusBlock
.Information
,
1731 (TotalLength
+ 1) * sizeof(WCHAR
));
1732 if (!NT_SUCCESS(Status
))
1734 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1739 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1743 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1745 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1746 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1747 Status
= IopInitiatePnpIrp(
1748 DeviceNode
->PhysicalDeviceObject
,
1750 IRP_MN_QUERY_DEVICE_TEXT
,
1752 /* This key is mandatory, so even if the Irp fails, we still write it */
1753 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1754 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1756 if (NT_SUCCESS(IoStatusBlock
.Status
) &&
1757 IoStatusBlock
.Information
&&
1758 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1760 /* This key is overriden when a driver is installed. Don't write the
1761 * new description if another one already exists */
1762 Status
= ZwSetValueKey(InstanceKey
,
1766 (PVOID
)IoStatusBlock
.Information
,
1767 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1771 UNICODE_STRING DeviceDesc
;
1772 RtlInitUnicodeString(&DeviceDesc
, L
"Unknown Device");
1773 DPRINT("Driver didn't return DeviceDesc (Status %x), so place unknown device there\n", Status
);
1775 Status
= ZwSetValueKey(InstanceKey
,
1780 (wcslen((PWSTR
)&DeviceDesc
) + 1) * sizeof(WCHAR
));
1782 if (!NT_SUCCESS(Status
))
1784 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1790 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1792 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1793 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1794 Status
= IopInitiatePnpIrp(
1795 DeviceNode
->PhysicalDeviceObject
,
1797 IRP_MN_QUERY_DEVICE_TEXT
,
1799 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1801 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1802 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1803 Status
= ZwSetValueKey(InstanceKey
,
1807 (PVOID
)IoStatusBlock
.Information
,
1808 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1809 if (!NT_SUCCESS(Status
))
1811 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1816 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1819 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1821 Status
= IopInitiatePnpIrp(
1822 DeviceNode
->PhysicalDeviceObject
,
1824 IRP_MN_QUERY_BUS_INFORMATION
,
1826 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1828 PPNP_BUS_INFORMATION BusInformation
=
1829 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1831 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1832 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1833 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1834 ExFreePool(BusInformation
);
1838 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1840 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1841 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1842 DeviceNode
->ChildBusTypeIndex
= -1;
1845 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1847 Status
= IopInitiatePnpIrp(
1848 DeviceNode
->PhysicalDeviceObject
,
1850 IRP_MN_QUERY_RESOURCES
,
1852 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1854 DeviceNode
->BootResources
=
1855 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1856 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1860 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1861 DeviceNode
->BootResources
= NULL
;
1864 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1866 Status
= IopInitiatePnpIrp(
1867 DeviceNode
->PhysicalDeviceObject
,
1869 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1871 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1873 DeviceNode
->ResourceRequirements
=
1874 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1878 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1879 DeviceNode
->ResourceRequirements
= NULL
;
1883 if (InstanceKey
!= NULL
)
1885 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1888 ZwClose(InstanceKey
);
1890 Status
= IopAssignDeviceResources(DeviceNode
);
1891 if (!NT_SUCCESS(Status
))
1893 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1896 DeviceNode
->Flags
|= DNF_PROCESSED
;
1898 /* Report the device to the user-mode pnp manager */
1899 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1900 &DeviceNode
->InstancePath
);
1902 return STATUS_SUCCESS
;
1906 * IopActionConfigureChildServices
1908 * Retrieve configuration for all (direct) child nodes of a parent node.
1912 * Pointer to device node.
1914 * Pointer to parent node to retrieve child node configuration for.
1917 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1918 * when we reach a device node which is not a direct child of the device
1919 * node for which we configure child services for. Any errors that occur is
1920 * logged instead so that all child services have a chance of beeing
1925 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1928 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1929 PDEVICE_NODE ParentDeviceNode
;
1930 PUNICODE_STRING Service
;
1931 UNICODE_STRING ClassGUID
;
1932 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
1935 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1937 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1940 * We are called for the parent too, but we don't need to do special
1941 * handling for this node
1943 if (DeviceNode
== ParentDeviceNode
)
1945 DPRINT("Success\n");
1946 return STATUS_SUCCESS
;
1950 * Make sure this device node is a direct child of the parent device node
1951 * that is given as an argument
1953 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1955 /* Stop the traversal immediately and indicate successful operation */
1957 return STATUS_UNSUCCESSFUL
;
1960 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1962 WCHAR RegKeyBuffer
[MAX_PATH
];
1963 UNICODE_STRING RegKey
;
1966 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1967 RegKey
.Buffer
= RegKeyBuffer
;
1970 * Retrieve configuration from Enum key
1973 Service
= &DeviceNode
->ServiceName
;
1975 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1976 RtlInitUnicodeString(Service
, NULL
);
1977 RtlInitUnicodeString(&ClassGUID
, NULL
);
1979 QueryTable
[0].Name
= L
"Service";
1980 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1981 QueryTable
[0].EntryContext
= Service
;
1983 QueryTable
[1].Name
= L
"ClassGUID";
1984 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1985 QueryTable
[1].EntryContext
= &ClassGUID
;
1986 QueryTable
[1].DefaultType
= REG_SZ
;
1987 QueryTable
[1].DefaultData
= &NullString
;
1988 QueryTable
[1].DefaultLength
= 0;
1990 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1991 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1993 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1994 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1996 if (!NT_SUCCESS(Status
))
1998 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1999 /* FIXME: Log the error */
2000 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2001 DeviceNode
->InstancePath
.Buffer
, Status
);
2002 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2003 return STATUS_SUCCESS
;
2006 if (Service
->Buffer
== NULL
)
2008 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2010 if (ClassGUID
.Length
!= 0)
2012 /* Device has a ClassGUID value, but no Service value.
2013 * Suppose it is using the NULL driver, so state the
2014 * device is started */
2015 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2016 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2018 return STATUS_SUCCESS
;
2021 DPRINT("Got Service %S\n", Service
->Buffer
);
2024 return STATUS_SUCCESS
;
2028 * IopActionInitChildServices
2030 * Initialize the service for all (direct) child nodes of a parent node
2034 * Pointer to device node.
2036 * Pointer to parent node to initialize child node services for.
2038 * Load only driver marked as boot start.
2041 * If the driver image for a service is not loaded and initialized
2042 * it is done here too. We only return a status code indicating an
2043 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2044 * not a direct child of the device node for which we initialize
2045 * child services for. Any errors that occur is logged instead so
2046 * that all child services have a chance of being initialized.
2050 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2052 BOOLEAN BootDrivers
)
2054 PDEVICE_NODE ParentDeviceNode
;
2057 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2060 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2063 * We are called for the parent too, but we don't need to do special
2064 * handling for this node
2066 if (DeviceNode
== ParentDeviceNode
)
2068 DPRINT("Success\n");
2069 return STATUS_SUCCESS
;
2073 * Make sure this device node is a direct child of the parent device node
2074 * that is given as an argument
2077 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2080 * Stop the traversal immediately and indicate unsuccessful operation
2083 return STATUS_UNSUCCESSFUL
;
2087 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2088 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2089 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2091 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2092 PDRIVER_OBJECT DriverObject
;
2094 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2095 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2097 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2098 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2099 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2102 /* get existing DriverObject pointer */
2103 Status
= IopGetDriverObject(
2105 &DeviceNode
->ServiceName
,
2108 if (NT_SUCCESS(Status
))
2110 /* Attach lower level filter drivers. */
2111 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2112 /* Initialize the function driver for the device node */
2113 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2114 if (NT_SUCCESS(Status
))
2116 /* Attach upper level filter drivers. */
2117 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2118 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2120 Status
= IopStartDevice(DeviceNode
);
2127 * Don't disable when trying to load only boot drivers
2131 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2132 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2134 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2135 CPRINT("Initialization of service %S failed (Status %x)\n",
2136 DeviceNode
->ServiceName
.Buffer
, Status
);
2140 DPRINT("Service %S is disabled or already initialized\n",
2141 DeviceNode
->ServiceName
.Buffer
);
2144 return STATUS_SUCCESS
;
2148 * IopActionInitAllServices
2150 * Initialize the service for all (direct) child nodes of a parent node. This
2151 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2155 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2158 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2162 * IopActionInitBootServices
2164 * Initialize the boot start services for all (direct) child nodes of a
2165 * parent node. This function just calls IopActionInitChildServices with
2166 * BootDrivers = TRUE.
2169 IopActionInitBootServices(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(IN PDEVICE_NODE DeviceNode
,
2193 IN BOOLEAN BootDrivers
)
2195 DEVICETREE_TRAVERSE_CONTEXT Context
;
2197 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2201 IopInitDeviceTreeTraverseContext(
2204 IopActionInitBootServices
,
2209 IopInitDeviceTreeTraverseContext(
2212 IopActionInitAllServices
,
2216 return IopTraverseDeviceTree(&Context
);
2221 IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode
,
2222 IN DEVICE_RELATION_TYPE Type
)
2224 DEVICETREE_TRAVERSE_CONTEXT Context
;
2225 PDEVICE_RELATIONS DeviceRelations
;
2226 IO_STATUS_BLOCK IoStatusBlock
;
2227 PDEVICE_NODE ChildDeviceNode
;
2228 IO_STACK_LOCATION Stack
;
2230 OBJECT_ATTRIBUTES ObjectAttributes
;
2231 UNICODE_STRING LinkName
;
2236 DPRINT("DeviceNode 0x%p\n", DeviceNode
);
2238 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2240 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
2242 Status
= IopInitiatePnpIrp(
2243 DeviceNode
->PhysicalDeviceObject
,
2245 IRP_MN_QUERY_DEVICE_RELATIONS
,
2247 if (!NT_SUCCESS(Status
))
2249 DPRINT("IopInitiatePnpIrp() failed\n");
2253 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2255 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
2257 DPRINT("No PDOs\n");
2258 if (DeviceRelations
)
2260 ExFreePool(DeviceRelations
);
2262 return STATUS_SUCCESS
;
2265 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2268 * Create device nodes for all discovered devices
2271 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2273 Status
= IopCreateDeviceNode(
2275 DeviceRelations
->Objects
[i
],
2277 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2278 if (!NT_SUCCESS(Status
))
2280 DPRINT("No resources\n");
2281 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2282 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2283 ExFreePool(DeviceRelations
);
2284 return STATUS_INSUFFICIENT_RESOURCES
;
2287 ExFreePool(DeviceRelations
);
2290 * Retrieve information about all discovered children from the bus driver
2293 IopInitDeviceTreeTraverseContext(
2296 IopActionInterrogateDeviceStack
,
2299 Status
= IopTraverseDeviceTree(&Context
);
2300 if (!NT_SUCCESS(Status
))
2302 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2307 * Retrieve configuration from the registry for discovered children
2310 IopInitDeviceTreeTraverseContext(
2313 IopActionConfigureChildServices
,
2316 Status
= IopTraverseDeviceTree(&Context
);
2317 if (!NT_SUCCESS(Status
))
2319 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2324 * Get the state of the system boot. If the \\SystemRoot link isn't
2325 * created yet, we will assume that it's possible to load only boot
2329 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
2331 InitializeObjectAttributes(
2338 Status
= ZwOpenFile(
2345 if(NT_SUCCESS(Status
))
2347 BootDrivers
= FALSE
;
2354 * Initialize services for discovered children. Only boot drivers will
2355 * be loaded from boot driver!
2358 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2359 if (!NT_SUCCESS(Status
))
2361 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2365 return STATUS_SUCCESS
;
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);