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 *****************************************************************/
112 PDEVICE_NODE FASTCALL
114 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(
151 IN PDEVICE_OBJECT DeviceObject
,
152 IN DEVICE_RELATION_TYPE Type
)
154 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Type
);
163 IN PDEVICE_OBJECT DeviceObject
,
164 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
165 IN ULONG BufferLength
,
166 OUT PVOID PropertyBuffer
,
167 OUT PULONG ResultLength
)
169 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
170 DEVICE_CAPABILITIES DeviceCaps
;
176 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
178 if (DeviceNode
== NULL
)
179 return STATUS_INVALID_DEVICE_REQUEST
;
181 switch (DeviceProperty
)
183 case DevicePropertyBusNumber
:
184 Length
= sizeof(ULONG
);
185 Data
= &DeviceNode
->ChildBusNumber
;
188 /* Complete, untested */
189 case DevicePropertyBusTypeGuid
:
191 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
192 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
194 /* Return the GUID */
195 *ResultLength
= sizeof(GUID
);
197 /* Check if the buffer given was large enough */
198 if (BufferLength
< *ResultLength
)
200 return STATUS_BUFFER_TOO_SMALL
;
204 RtlCopyMemory(PropertyBuffer
,
205 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
207 return STATUS_SUCCESS
;
211 return STATUS_OBJECT_NAME_NOT_FOUND
;
215 case DevicePropertyLegacyBusType
:
216 Length
= sizeof(INTERFACE_TYPE
);
217 Data
= &DeviceNode
->ChildInterfaceType
;
220 case DevicePropertyAddress
:
222 /* Query the device caps */
223 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
224 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= -1))
227 *ResultLength
= sizeof(ULONG
);
229 /* Check if the buffer given was large enough */
230 if (BufferLength
< *ResultLength
)
232 return STATUS_BUFFER_TOO_SMALL
;
236 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
237 return STATUS_SUCCESS
;
241 return STATUS_OBJECT_NAME_NOT_FOUND
;
245 // case DevicePropertyUINumber:
246 // if (DeviceNode->CapabilityFlags == NULL)
247 // return STATUS_INVALID_DEVICE_REQUEST;
248 // Length = sizeof(ULONG);
249 // Data = &DeviceNode->CapabilityFlags->UINumber;
252 case DevicePropertyClassName
:
253 case DevicePropertyClassGuid
:
254 case DevicePropertyDriverKeyName
:
255 case DevicePropertyManufacturer
:
256 case DevicePropertyFriendlyName
:
257 case DevicePropertyHardwareID
:
258 case DevicePropertyCompatibleIDs
:
259 case DevicePropertyDeviceDescription
:
260 case DevicePropertyLocationInformation
:
261 case DevicePropertyUINumber
:
263 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
264 UNICODE_STRING KeyName
, ValueName
;
265 OBJECT_ATTRIBUTES ObjectAttributes
;
266 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
267 ULONG ValueInformationLength
;
271 switch (DeviceProperty
)
273 case DevicePropertyClassName
:
274 RegistryPropertyName
= L
"Class"; break;
275 case DevicePropertyClassGuid
:
276 RegistryPropertyName
= L
"ClassGuid"; break;
277 case DevicePropertyDriverKeyName
:
278 RegistryPropertyName
= L
"Driver"; break;
279 case DevicePropertyManufacturer
:
280 RegistryPropertyName
= L
"Mfg"; break;
281 case DevicePropertyFriendlyName
:
282 RegistryPropertyName
= L
"FriendlyName"; break;
283 case DevicePropertyHardwareID
:
284 RegistryPropertyName
= L
"HardwareID"; break;
285 case DevicePropertyCompatibleIDs
:
286 RegistryPropertyName
= L
"CompatibleIDs"; break;
287 case DevicePropertyDeviceDescription
:
288 RegistryPropertyName
= L
"DeviceDesc"; break;
289 case DevicePropertyLocationInformation
:
290 RegistryPropertyName
= L
"LocationInformation"; break;
291 case DevicePropertyUINumber
:
292 RegistryPropertyName
= L
"UINumber"; break;
294 RegistryPropertyName
= NULL
; break;
297 KeyNameBuffer
= ExAllocatePool(PagedPool
,
298 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
300 DPRINT("KeyNameBuffer: 0x%p, value %S\n",
301 KeyNameBuffer
, RegistryPropertyName
);
303 if (KeyNameBuffer
== NULL
)
304 return STATUS_INSUFFICIENT_RESOURCES
;
306 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
307 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
308 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
309 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
310 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
312 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
313 ExFreePool(KeyNameBuffer
);
314 if (!NT_SUCCESS(Status
))
317 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
318 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
319 Data
[0]) + BufferLength
;
320 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
321 if (ValueInformation
== NULL
)
324 return STATUS_INSUFFICIENT_RESOURCES
;
327 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
328 KeyValuePartialInformation
, ValueInformation
,
329 ValueInformationLength
,
330 &ValueInformationLength
);
331 *ResultLength
= ValueInformation
->DataLength
;
334 if (!NT_SUCCESS(Status
))
336 ExFreePool(ValueInformation
);
337 if (Status
== STATUS_BUFFER_OVERFLOW
)
338 return STATUS_BUFFER_TOO_SMALL
;
343 /* FIXME: Verify the value (NULL-terminated, correct format). */
345 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
346 ValueInformation
->DataLength
);
347 ExFreePool(ValueInformation
);
349 return STATUS_SUCCESS
;
352 case DevicePropertyBootConfiguration
:
354 if (DeviceNode
->BootResources
->Count
!= 0)
356 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
358 Data
= &DeviceNode
->BootResources
;
361 /* FIXME: use a translated boot configuration instead */
362 case DevicePropertyBootConfigurationTranslated
:
364 if (DeviceNode
->BootResources
->Count
!= 0)
366 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
368 Data
= &DeviceNode
->BootResources
;
371 case DevicePropertyEnumeratorName
:
372 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
375 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
376 Data
= DeviceNode
->InstancePath
.Buffer
;
385 case DevicePropertyPhysicalDeviceObjectName
:
386 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
387 Data
= DeviceNode
->InstancePath
.Buffer
;
391 return STATUS_INVALID_PARAMETER_2
;
394 *ResultLength
= Length
;
395 if (BufferLength
< Length
)
396 return STATUS_BUFFER_TOO_SMALL
;
397 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
399 /* Terminate the string */
400 if (DeviceProperty
== DevicePropertyEnumeratorName
401 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
403 Ptr
= (PWSTR
)PropertyBuffer
;
404 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
407 return STATUS_SUCCESS
;
415 IoInvalidateDeviceState(
416 IN PDEVICE_OBJECT PhysicalDeviceObject
)
421 * @name IoOpenDeviceRegistryKey
423 * Open a registry key unique for a specified driver or device instance.
425 * @param DeviceObject Device to get the registry key for.
426 * @param DevInstKeyType Type of the key to return.
427 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
428 * @param DevInstRegKey Handle to the opened registry key on
437 IoOpenDeviceRegistryKey(
438 IN PDEVICE_OBJECT DeviceObject
,
439 IN ULONG DevInstKeyType
,
440 IN ACCESS_MASK DesiredAccess
,
441 OUT PHANDLE DevInstRegKey
)
443 static WCHAR RootKeyName
[] =
444 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
445 static WCHAR ProfileKeyName
[] =
446 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
447 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
448 static WCHAR EnumKeyName
[] = L
"Enum\\";
449 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
451 LPWSTR KeyNameBuffer
;
452 UNICODE_STRING KeyName
;
453 ULONG DriverKeyLength
;
454 OBJECT_ATTRIBUTES ObjectAttributes
;
455 PDEVICE_NODE DeviceNode
= NULL
;
458 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
459 return STATUS_INVALID_PARAMETER
;
462 * Calculate the length of the base key name. This is the full
463 * name for driver key or the name excluding "Device Parameters"
464 * subkey for device key.
467 KeyNameLength
= sizeof(RootKeyName
);
468 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
469 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
470 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
472 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
473 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
474 0, NULL
, &DriverKeyLength
);
475 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
477 KeyNameLength
+= DriverKeyLength
;
481 DeviceNode
= IopGetDeviceNode(DeviceObject
);
482 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
483 DeviceNode
->InstancePath
.Length
;
487 * Now allocate the buffer for the key name...
490 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
491 if (KeyNameBuffer
== NULL
)
492 return STATUS_INSUFFICIENT_RESOURCES
;
495 KeyName
.MaximumLength
= KeyNameLength
;
496 KeyName
.Buffer
= KeyNameBuffer
;
499 * ...and build the key name.
502 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
503 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
505 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
506 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
508 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
510 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
511 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
512 DriverKeyLength
, KeyNameBuffer
+
513 (KeyName
.Length
/ sizeof(WCHAR
)),
515 if (!NT_SUCCESS(Status
))
517 ExFreePool(KeyNameBuffer
);
520 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
524 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
525 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
526 if (DeviceNode
->InstancePath
.Length
== 0)
528 ExFreePool(KeyNameBuffer
);
537 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
538 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
539 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
540 ExFreePool(KeyNameBuffer
);
543 * For driver key we're done now. Also if the base key doesn't
544 * exist we can bail out with error...
547 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
551 * Let's go further. For device key we must open "Device Parameters"
552 * subkey and create it if it doesn't exist yet.
555 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
556 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
557 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
558 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
559 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
560 ZwClose(ObjectAttributes
.RootDirectory
);
570 IoRequestDeviceEject(
571 IN PDEVICE_OBJECT PhysicalDeviceObject
579 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
583 if (PopSystemPowerDeviceNode
)
585 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
586 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
587 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
589 return STATUS_SUCCESS
;
592 return STATUS_UNSUCCESSFUL
;
597 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
599 USHORT i
= 0, FoundIndex
= 0xFFFF;
603 /* Acquire the lock */
604 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
606 /* Loop all entries */
607 while (i
< IopBusTypeGuidList
->GuidCount
)
609 /* Try to find a match */
610 if (RtlCompareMemory(BusTypeGuid
,
611 &IopBusTypeGuidList
->Guids
[i
],
621 /* Check if we have to grow the list */
622 if (IopBusTypeGuidList
->GuidCount
)
624 /* Calculate the new size */
625 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
626 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
628 /* Allocate the new copy */
629 NewList
= ExAllocatePool(PagedPool
, NewSize
);
631 /* Now copy them, decrease the size too */
632 NewSize
-= sizeof(GUID
);
633 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
635 /* Free the old list */
636 ExFreePool(IopBusTypeGuidList
);
638 /* Use the new buffer */
639 IopBusTypeGuidList
= NewList
;
642 /* Copy the new GUID */
643 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
647 /* The new entry is the index */
648 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
649 IopBusTypeGuidList
->GuidCount
++;
652 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
658 * Creates a device node
661 * ParentNode = Pointer to parent device node
662 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
663 * to have the root device node create one
664 * (eg. for legacy drivers)
665 * DeviceNode = Pointer to storage for created device node
671 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
672 PDEVICE_OBJECT PhysicalDeviceObject
,
673 PDEVICE_NODE
*DeviceNode
)
679 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
680 ParentNode
, PhysicalDeviceObject
);
682 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
685 return STATUS_INSUFFICIENT_RESOURCES
;
688 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
690 if (!PhysicalDeviceObject
)
692 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
693 if (!NT_SUCCESS(Status
))
699 /* This is for drivers passed on the command line to ntoskrnl.exe */
700 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
701 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
704 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
706 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
710 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
711 Node
->Parent
= ParentNode
;
712 Node
->NextSibling
= ParentNode
->Child
;
713 if (ParentNode
->Child
!= NULL
)
715 ParentNode
->Child
->PrevSibling
= Node
;
717 ParentNode
->Child
= Node
;
718 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
719 Node
->Level
= ParentNode
->Level
+ 1;
724 return STATUS_SUCCESS
;
728 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
732 /* All children must be deleted before a parent is deleted */
733 ASSERT(!DeviceNode
->Child
);
735 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
737 ASSERT(DeviceNode
->PhysicalDeviceObject
);
739 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
741 /* Unlink from parent if it exists */
743 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
745 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
748 /* Unlink from sibling list */
750 if (DeviceNode
->PrevSibling
)
752 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
755 if (DeviceNode
->NextSibling
)
757 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
760 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
762 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
764 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
766 if (DeviceNode
->ResourceList
)
768 ExFreePool(DeviceNode
->ResourceList
);
771 if (DeviceNode
->ResourceListTranslated
)
773 ExFreePool(DeviceNode
->ResourceListTranslated
);
776 if (DeviceNode
->ResourceRequirements
)
778 ExFreePool(DeviceNode
->ResourceRequirements
);
781 if (DeviceNode
->BootResources
)
783 ExFreePool(DeviceNode
->BootResources
);
786 ExFreePool(DeviceNode
);
788 return STATUS_SUCCESS
;
793 PDEVICE_OBJECT DeviceObject
,
794 PIO_STATUS_BLOCK IoStatusBlock
,
796 PIO_STACK_LOCATION Stack OPTIONAL
)
798 PDEVICE_OBJECT TopDeviceObject
;
799 PIO_STACK_LOCATION IrpSp
;
804 /* Always call the top of the device stack */
805 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
812 Irp
= IoBuildSynchronousFsdRequest(
821 /* PNP IRPs are always initialized with a status code of
822 STATUS_NOT_IMPLEMENTED */
823 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
824 Irp
->IoStatus
.Information
= 0;
826 IrpSp
= IoGetNextIrpStackLocation(Irp
);
827 IrpSp
->MinorFunction
= MinorFunction
;
834 sizeof(Stack
->Parameters
));
837 Status
= IoCallDriver(TopDeviceObject
, Irp
);
838 if (Status
== STATUS_PENDING
)
840 KeWaitForSingleObject(
846 Status
= IoStatusBlock
->Status
;
849 ObDereferenceObject(TopDeviceObject
);
856 IopTraverseDeviceTreeNode(
857 PDEVICETREE_TRAVERSE_CONTEXT Context
)
859 PDEVICE_NODE ParentDeviceNode
;
860 PDEVICE_NODE ChildDeviceNode
;
863 /* Copy context data so we don't overwrite it in subsequent calls to this function */
864 ParentDeviceNode
= Context
->DeviceNode
;
866 /* Call the action routine */
867 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
868 if (!NT_SUCCESS(Status
))
873 /* Traversal of all children nodes */
874 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
875 ChildDeviceNode
!= NULL
;
876 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
878 /* Pass the current device node to the action routine */
879 Context
->DeviceNode
= ChildDeviceNode
;
881 Status
= IopTraverseDeviceTreeNode(Context
);
882 if (!NT_SUCCESS(Status
))
893 IopTraverseDeviceTree(
894 PDEVICETREE_TRAVERSE_CONTEXT Context
)
898 DPRINT("Context 0x%p\n", Context
);
900 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
901 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
903 /* Start from the specified device node */
904 Context
->DeviceNode
= Context
->FirstDeviceNode
;
906 /* Recursively traverse the device tree */
907 Status
= IopTraverseDeviceTreeNode(Context
);
908 if (Status
== STATUS_UNSUCCESSFUL
)
910 /* The action routine just wanted to terminate the traversal with status
911 code STATUS_SUCCESS */
912 Status
= STATUS_SUCCESS
;
920 IopCreateDeviceKeyPath(PWSTR Path
,
923 OBJECT_ATTRIBUTES ObjectAttributes
;
924 WCHAR KeyBuffer
[MAX_PATH
];
925 UNICODE_STRING KeyName
;
933 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
935 return STATUS_INVALID_PARAMETER
;
938 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
940 /* Skip \\Registry\\ */
942 Current
= wcschr (Current
, L
'\\') + 1;
943 Current
= wcschr (Current
, L
'\\') + 1;
947 Next
= wcschr (Current
, L
'\\');
957 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
958 InitializeObjectAttributes (&ObjectAttributes
,
960 OBJ_CASE_INSENSITIVE
,
964 DPRINT("Create '%S'\n", KeyName
.Buffer
);
966 Status
= ZwCreateKey (&KeyHandle
,
973 if (!NT_SUCCESS (Status
))
975 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
982 return STATUS_SUCCESS
;
993 return STATUS_UNSUCCESSFUL
;
998 IopSetDeviceInstanceData(HANDLE InstanceKey
,
999 PDEVICE_NODE DeviceNode
)
1001 OBJECT_ATTRIBUTES ObjectAttributes
;
1002 UNICODE_STRING KeyName
;
1008 DPRINT("IopSetDeviceInstanceData() called\n");
1010 /* Create the 'LogConf' key */
1011 RtlInitUnicodeString(&KeyName
,
1013 InitializeObjectAttributes(&ObjectAttributes
,
1015 OBJ_CASE_INSENSITIVE
,
1018 Status
= ZwCreateKey(&LogConfKey
,
1025 if (NT_SUCCESS(Status
))
1027 /* Set 'BootConfig' value */
1028 if (DeviceNode
->BootResources
!= NULL
)
1030 ResCount
= DeviceNode
->BootResources
->Count
;
1033 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1035 RtlInitUnicodeString(&KeyName
,
1037 Status
= ZwSetValueKey(LogConfKey
,
1041 &DeviceNode
->BootResources
,
1046 /* Set 'BasicConfigVector' value */
1047 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1048 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1050 RtlInitUnicodeString(&KeyName
,
1051 L
"BasicConfigVector");
1052 Status
= ZwSetValueKey(LogConfKey
,
1055 REG_RESOURCE_REQUIREMENTS_LIST
,
1056 DeviceNode
->ResourceRequirements
,
1057 DeviceNode
->ResourceRequirements
->ListSize
);
1060 ZwClose(LogConfKey
);
1064 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1066 /* Create the 'Control' key */
1067 RtlInitUnicodeString(&KeyName
,
1069 InitializeObjectAttributes(&ObjectAttributes
,
1071 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1074 Status
= ZwCreateKey(&LogConfKey
,
1079 REG_OPTION_VOLATILE
,
1081 if (NT_SUCCESS(Status
))
1083 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1084 RtlInitUnicodeString(&KeyName
,
1085 L
"DeviceReference");
1086 Status
= ZwSetValueKey(LogConfKey
,
1093 ZwClose(LogConfKey
);
1098 DPRINT("IopSetDeviceInstanceData() done\n");
1100 return STATUS_SUCCESS
;
1105 IopAssignDeviceResources(
1106 PDEVICE_NODE DeviceNode
)
1108 PIO_RESOURCE_LIST ResourceList
;
1109 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1110 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1111 ULONG NumberOfResources
= 0;
1115 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
1116 * by using DeviceNode->ResourceRequirements */
1118 if (!DeviceNode
->ResourceRequirements
1119 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
1121 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
1122 return STATUS_SUCCESS
;
1125 /* FIXME: that's here that PnP arbiter should go */
1126 /* Actually, simply use resource list #0 as assigned resource list */
1127 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1128 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1130 Status
= STATUS_REVISION_MISMATCH
;
1134 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
1135 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1136 if (!DeviceNode
->ResourceList
)
1138 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1142 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
1143 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1144 if (!DeviceNode
->ResourceListTranslated
)
1146 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1150 DeviceNode
->ResourceList
->Count
= 1;
1151 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1152 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1153 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1154 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1156 DeviceNode
->ResourceListTranslated
->Count
= 1;
1157 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1158 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1159 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
1160 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
1162 for (i
= 0; i
< ResourceList
->Count
; i
++)
1164 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1166 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1168 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1169 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1170 NumberOfResources
++;
1172 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1173 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1174 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1175 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1176 switch (ResourceDescriptor
->Type
)
1178 case CmResourceTypePort
:
1180 ULONG AddressSpace
= 0; /* IO space */
1181 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1182 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1183 = ResourceDescriptor
->u
.Port
.Length
;
1184 if (!HalTranslateBusAddress(
1185 DeviceNode
->ResourceRequirements
->InterfaceType
,
1186 DeviceNode
->ResourceRequirements
->BusNumber
,
1187 DescriptorRaw
->u
.Port
.Start
,
1189 &DescriptorTranslated
->u
.Port
.Start
))
1191 Status
= STATUS_UNSUCCESSFUL
;
1196 case CmResourceTypeInterrupt
:
1198 INTERFACE_TYPE BusType
;
1203 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1204 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1205 /* FIXME: HACK: if we have a PCI device, we try
1206 * to keep the IRQ assigned by the BIOS */
1207 if (NT_SUCCESS(IoGetDeviceProperty(
1208 DeviceNode
->PhysicalDeviceObject
,
1209 DevicePropertyLegacyBusType
,
1210 sizeof(INTERFACE_TYPE
),
1212 &ret
)) && BusType
== PCIBus
)
1214 /* We have a PCI bus */
1215 if (NT_SUCCESS(IoGetDeviceProperty(
1216 DeviceNode
->PhysicalDeviceObject
,
1217 DevicePropertyAddress
,
1220 &ret
)) && SlotNumber
> 0)
1222 /* We have a good slot number */
1223 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1224 DeviceNode
->ResourceRequirements
->BusNumber
,
1227 0x3c /* PCI_INTERRUPT_LINE */,
1229 if (ret
!= 0 && ret
!= 2
1230 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1231 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1233 /* The device already has an assigned IRQ */
1234 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1238 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1239 DescriptorRaw
->u
.Interrupt
.Vector
,
1240 &DeviceNode
->InstancePath
);
1241 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1242 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1243 DeviceNode
->ResourceRequirements
->BusNumber
,
1246 0x3c /* PCI_INTERRUPT_LINE */,
1248 if (ret
== 0 || ret
== 2)
1254 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1255 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1256 DeviceNode
->ResourceRequirements
->InterfaceType
,
1257 DeviceNode
->ResourceRequirements
->BusNumber
,
1258 DescriptorRaw
->u
.Interrupt
.Level
,
1259 DescriptorRaw
->u
.Interrupt
.Vector
,
1260 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1261 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1262 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1265 case CmResourceTypeMemory
:
1267 ULONG AddressSpace
= 1; /* Memory space */
1268 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1269 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1270 = ResourceDescriptor
->u
.Memory
.Length
;
1271 if (!HalTranslateBusAddress(
1272 DeviceNode
->ResourceRequirements
->InterfaceType
,
1273 DeviceNode
->ResourceRequirements
->BusNumber
,
1274 DescriptorRaw
->u
.Memory
.Start
,
1276 &DescriptorTranslated
->u
.Memory
.Start
))
1278 Status
= STATUS_UNSUCCESSFUL
;
1283 case CmResourceTypeDma
:
1285 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1286 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1287 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1289 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1293 case CmResourceTypeBusNumber
:
1295 DescriptorRaw
->u
.BusNumber
.Start
= DescriptorTranslated
->u
.BusNumber
.Start
1296 = ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1297 DescriptorRaw
->u
.BusNumber
.Length
= DescriptorTranslated
->u
.BusNumber
.Length
1298 = ResourceDescriptor
->u
.BusNumber
.Length
;
1299 DescriptorRaw
->u
.BusNumber
.Reserved
= DescriptorTranslated
->u
.BusNumber
.Reserved
1300 = ResourceDescriptor
->u
.BusNumber
.Reserved
;
1303 /*CmResourceTypeDevicePrivate:
1304 case CmResourceTypePcCardConfig:
1305 case CmResourceTypeMfCardConfig:
1308 &DescriptorRaw->u.DevicePrivate,
1309 &ResourceDescriptor->u.DevicePrivate,
1310 sizeof(ResourceDescriptor->u.DevicePrivate));
1312 &DescriptorTranslated->u.DevicePrivate,
1313 &ResourceDescriptor->u.DevicePrivate,
1314 sizeof(ResourceDescriptor->u.DevicePrivate));
1318 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1319 NumberOfResources
--;
1325 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1326 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1328 return STATUS_SUCCESS
;
1331 if (DeviceNode
->ResourceList
)
1333 ExFreePool(DeviceNode
->ResourceList
);
1334 DeviceNode
->ResourceList
= NULL
;
1336 if (DeviceNode
->ResourceListTranslated
)
1338 ExFreePool(DeviceNode
->ResourceListTranslated
);
1339 DeviceNode
->ResourceListTranslated
= NULL
;
1347 * IopGetParentIdPrefix
1349 * Retrieve (or create) a string which identifies a device.
1353 * Pointer to device node.
1355 * Pointer to the string where is returned the parent node identifier
1358 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1359 * valid and its Buffer field is NULL-terminated. The caller needs to
1360 * to free the string with RtlFreeUnicodeString when it is no longer
1365 IopGetParentIdPrefix(
1366 PDEVICE_NODE DeviceNode
,
1367 PUNICODE_STRING ParentIdPrefix
)
1369 ULONG KeyNameBufferLength
;
1370 PWSTR KeyNameBuffer
= NULL
;
1371 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1372 UNICODE_STRING KeyName
;
1373 UNICODE_STRING KeyValue
;
1374 UNICODE_STRING ValueName
;
1375 OBJECT_ATTRIBUTES ObjectAttributes
;
1376 HANDLE hKey
= INVALID_HANDLE_VALUE
;
1382 /* HACK: As long as some devices have a NULL device
1383 * instance path, the following test is required :(
1385 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1386 return STATUS_UNSUCCESSFUL
;
1388 /* 1. Try to retrieve ParentIdPrefix from registry */
1389 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1390 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1391 if (!ParentIdPrefixInformation
)
1393 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1396 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1399 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1402 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1403 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1404 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1405 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1406 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1407 if (!NT_SUCCESS(Status
))
1409 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1410 Status
= ZwQueryValueKey(
1412 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1413 KeyNameBufferLength
, &KeyNameBufferLength
);
1414 if (NT_SUCCESS(Status
))
1416 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1417 Status
= STATUS_UNSUCCESSFUL
;
1420 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1421 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1425 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1427 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1428 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1432 /* 2. Create the ParentIdPrefix value */
1433 currentByte
= (PBYTE
)DeviceNode
->Parent
->InstancePath
.Buffer
;
1434 for (i
= 0; i
< DeviceNode
->Parent
->InstancePath
.Length
; i
++, currentByte
++)
1435 crc32
= (crc32
>> 8) ^ crc32Table
[*currentByte
^ (crc32
& 0xff)];
1437 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1438 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1440 /* 3. Try to write the ParentIdPrefix to registry */
1441 Status
= ZwSetValueKey(
1444 (PVOID
)KeyValue
.Buffer
,
1445 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1448 if (NT_SUCCESS(Status
))
1450 /* Duplicate the string to return it */
1451 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1453 ExFreePool(ParentIdPrefixInformation
);
1454 ExFreePool(KeyNameBuffer
);
1455 if (hKey
!= INVALID_HANDLE_VALUE
)
1462 * IopActionInterrogateDeviceStack
1464 * Retrieve information for all (direct) child nodes of a parent node.
1468 * Pointer to device node.
1470 * Pointer to parent node to retrieve child node information for.
1473 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1474 * when we reach a device node which is not a direct child of the device
1475 * node for which we retrieve information of child nodes for. Any errors
1476 * that occur is logged instead so that all child services have a chance
1477 * of being interrogated.
1481 IopActionInterrogateDeviceStack(
1482 PDEVICE_NODE DeviceNode
,
1485 IO_STATUS_BLOCK IoStatusBlock
;
1486 PDEVICE_NODE ParentDeviceNode
;
1487 WCHAR InstancePath
[MAX_PATH
];
1488 IO_STACK_LOCATION Stack
;
1494 ULONG RequiredLength
;
1496 HANDLE InstanceKey
= NULL
;
1497 UNICODE_STRING ValueName
;
1498 UNICODE_STRING ParentIdPrefix
= { 0 };
1499 DEVICE_CAPABILITIES DeviceCapabilities
;
1501 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1502 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1504 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1507 * We are called for the parent too, but we don't need to do special
1508 * handling for this node
1511 if (DeviceNode
== ParentDeviceNode
)
1513 DPRINT("Success\n");
1514 return STATUS_SUCCESS
;
1518 * Make sure this device node is a direct child of the parent device node
1519 * that is given as an argument
1522 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1524 /* Stop the traversal immediately and indicate successful operation */
1526 return STATUS_UNSUCCESSFUL
;
1530 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1531 if (!NT_SUCCESS(Status
))
1533 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1538 * FIXME: For critical errors, cleanup and disable device, but always
1539 * return STATUS_SUCCESS.
1542 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1544 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1545 Status
= IopInitiatePnpIrp(
1546 DeviceNode
->PhysicalDeviceObject
,
1550 if (NT_SUCCESS(Status
))
1552 /* Copy the device id string */
1553 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1556 * FIXME: Check for valid characters, if there is invalid characters
1562 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1565 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1567 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1568 if (!NT_SUCCESS(Status
))
1570 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1573 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1575 if (!DeviceCapabilities
.UniqueID
)
1577 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1578 DPRINT("Instance ID is not unique\n");
1579 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1580 if (!NT_SUCCESS(Status
))
1582 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1586 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1588 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1589 Status
= IopInitiatePnpIrp(
1590 DeviceNode
->PhysicalDeviceObject
,
1594 if (NT_SUCCESS(Status
))
1596 /* Append the instance id string */
1597 wcscat(InstancePath
, L
"\\");
1598 if (ParentIdPrefix
.Length
> 0)
1600 /* Add information from parent bus device to InstancePath */
1601 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1602 if (*(PWSTR
)IoStatusBlock
.Information
)
1603 wcscat(InstancePath
, L
"&");
1605 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1608 * FIXME: Check for valid characters, if there is invalid characters
1614 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1616 RtlFreeUnicodeString(&ParentIdPrefix
);
1618 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1620 DPRINT("No resources\n");
1621 /* FIXME: Cleanup and disable device */
1624 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1627 * Create registry key for the instance id, if it doesn't exist yet
1629 KeyBuffer
= ExAllocatePool(
1631 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1632 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1633 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1634 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1636 ExFreePool(KeyBuffer
);
1637 if (!NT_SUCCESS(Status
))
1639 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1644 /* Set 'Capabilities' value */
1645 RtlInitUnicodeString(&ValueName
,
1647 Status
= ZwSetValueKey(InstanceKey
,
1651 (PVOID
)&DeviceNode
->CapabilityFlags
,
1654 /* Set 'UINumber' value */
1655 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1657 RtlInitUnicodeString(&ValueName
,
1659 Status
= ZwSetValueKey(InstanceKey
,
1663 &DeviceCapabilities
.UINumber
,
1668 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1670 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1671 Status
= IopInitiatePnpIrp(
1672 DeviceNode
->PhysicalDeviceObject
,
1676 if (NT_SUCCESS(Status
))
1679 * FIXME: Check for valid characters, if there is invalid characters
1683 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1684 DPRINT("Hardware IDs:\n");
1687 DPRINT(" %S\n", Ptr
);
1688 Length
= wcslen(Ptr
) + 1;
1691 TotalLength
+= Length
;
1693 DPRINT("TotalLength: %hu\n", TotalLength
);
1696 RtlInitUnicodeString(&ValueName
,
1698 Status
= ZwSetValueKey(InstanceKey
,
1702 (PVOID
)IoStatusBlock
.Information
,
1703 (TotalLength
+ 1) * sizeof(WCHAR
));
1704 if (!NT_SUCCESS(Status
))
1706 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1711 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1714 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1716 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1717 Status
= IopInitiatePnpIrp(
1718 DeviceNode
->PhysicalDeviceObject
,
1722 if (NT_SUCCESS(Status
))
1725 * FIXME: Check for valid characters, if there is invalid characters
1729 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1730 DPRINT("Compatible IDs:\n");
1733 DPRINT(" %S\n", Ptr
);
1734 Length
= wcslen(Ptr
) + 1;
1737 TotalLength
+= Length
;
1739 DPRINT("TotalLength: %hu\n", TotalLength
);
1742 RtlInitUnicodeString(&ValueName
,
1744 Status
= ZwSetValueKey(InstanceKey
,
1748 (PVOID
)IoStatusBlock
.Information
,
1749 (TotalLength
+ 1) * sizeof(WCHAR
));
1750 if (!NT_SUCCESS(Status
))
1752 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1757 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1761 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1763 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1764 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1765 Status
= IopInitiatePnpIrp(
1766 DeviceNode
->PhysicalDeviceObject
,
1768 IRP_MN_QUERY_DEVICE_TEXT
,
1770 if (NT_SUCCESS(Status
))
1772 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1773 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1775 /* This key is overriden when a driver is installed. Don't write the
1776 * new description if another one already exists */
1777 Status
= ZwSetValueKey(InstanceKey
,
1781 (PVOID
)IoStatusBlock
.Information
,
1782 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1784 if (!NT_SUCCESS(Status
))
1786 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1791 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1794 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1796 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1797 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1798 Status
= IopInitiatePnpIrp(
1799 DeviceNode
->PhysicalDeviceObject
,
1801 IRP_MN_QUERY_DEVICE_TEXT
,
1803 if (NT_SUCCESS(Status
))
1805 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1806 RtlInitUnicodeString(&ValueName
,
1807 L
"LocationInformation");
1808 Status
= ZwSetValueKey(InstanceKey
,
1812 (PVOID
)IoStatusBlock
.Information
,
1813 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1814 if (!NT_SUCCESS(Status
))
1816 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1821 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1824 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1826 Status
= IopInitiatePnpIrp(
1827 DeviceNode
->PhysicalDeviceObject
,
1829 IRP_MN_QUERY_BUS_INFORMATION
,
1831 if (NT_SUCCESS(Status
))
1833 PPNP_BUS_INFORMATION BusInformation
=
1834 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1836 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1837 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1838 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1839 ExFreePool(BusInformation
);
1843 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1845 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1846 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1847 DeviceNode
->ChildBusTypeIndex
= -1;
1850 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1852 Status
= IopInitiatePnpIrp(
1853 DeviceNode
->PhysicalDeviceObject
,
1855 IRP_MN_QUERY_RESOURCES
,
1857 if (NT_SUCCESS(Status
))
1859 DeviceNode
->BootResources
=
1860 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1861 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1865 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1866 DeviceNode
->BootResources
= NULL
;
1869 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1871 Status
= IopInitiatePnpIrp(
1872 DeviceNode
->PhysicalDeviceObject
,
1874 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1876 if (NT_SUCCESS(Status
))
1878 DeviceNode
->ResourceRequirements
=
1879 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1883 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1884 DeviceNode
->ResourceRequirements
= NULL
;
1888 if (InstanceKey
!= NULL
)
1890 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1893 ZwClose(InstanceKey
);
1895 Status
= IopAssignDeviceResources(DeviceNode
);
1896 if (!NT_SUCCESS(Status
))
1898 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1901 DeviceNode
->Flags
|= DNF_PROCESSED
;
1903 /* Report the device to the user-mode pnp manager */
1904 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1905 &DeviceNode
->InstancePath
);
1907 return STATUS_SUCCESS
;
1911 * IopActionConfigureChildServices
1913 * Retrieve configuration for all (direct) child nodes of a parent node.
1917 * Pointer to device node.
1919 * Pointer to parent node to retrieve child node configuration for.
1922 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1923 * when we reach a device node which is not a direct child of the device
1924 * node for which we configure child services for. Any errors that occur is
1925 * logged instead so that all child services have a chance of beeing
1930 IopActionConfigureChildServices(
1931 PDEVICE_NODE DeviceNode
,
1934 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1935 PDEVICE_NODE ParentDeviceNode
;
1936 PUNICODE_STRING Service
;
1937 UNICODE_STRING ClassGUID
;
1938 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
1941 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1943 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1946 * We are called for the parent too, but we don't need to do special
1947 * handling for this node
1949 if (DeviceNode
== ParentDeviceNode
)
1951 DPRINT("Success\n");
1952 return STATUS_SUCCESS
;
1956 * Make sure this device node is a direct child of the parent device node
1957 * that is given as an argument
1959 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1961 /* Stop the traversal immediately and indicate successful operation */
1963 return STATUS_UNSUCCESSFUL
;
1966 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1968 WCHAR RegKeyBuffer
[MAX_PATH
];
1969 UNICODE_STRING RegKey
;
1972 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1973 RegKey
.Buffer
= RegKeyBuffer
;
1976 * Retrieve configuration from Enum key
1979 Service
= &DeviceNode
->ServiceName
;
1981 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1982 RtlInitUnicodeString(Service
, NULL
);
1983 RtlInitUnicodeString(&ClassGUID
, NULL
);
1985 QueryTable
[0].Name
= L
"Service";
1986 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1987 QueryTable
[0].EntryContext
= Service
;
1989 QueryTable
[1].Name
= L
"ClassGUID";
1990 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1991 QueryTable
[1].EntryContext
= &ClassGUID
;
1992 QueryTable
[1].DefaultType
= REG_SZ
;
1993 QueryTable
[1].DefaultData
= &NullString
;
1994 QueryTable
[1].DefaultLength
= 0;
1996 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1997 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1999 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2000 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2002 if (!NT_SUCCESS(Status
))
2004 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
2005 /* FIXME: Log the error */
2006 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2007 DeviceNode
->InstancePath
.Buffer
, Status
);
2008 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2009 return STATUS_SUCCESS
;
2012 if (Service
->Buffer
== NULL
)
2014 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2016 if (ClassGUID
.Length
!= 0)
2018 /* Device has a ClassGUID value, but no Service value.
2019 * Suppose it is using the NULL driver, so state the
2020 * device is started */
2021 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2022 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2024 return STATUS_SUCCESS
;
2027 DPRINT("Got Service %S\n", Service
->Buffer
);
2030 return STATUS_SUCCESS
;
2034 * IopActionInitChildServices
2036 * Initialize the service for all (direct) child nodes of a parent node
2040 * Pointer to device node.
2042 * Pointer to parent node to initialize child node services for.
2044 * Load only driver marked as boot start.
2047 * If the driver image for a service is not loaded and initialized
2048 * it is done here too. We only return a status code indicating an
2049 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2050 * not a direct child of the device node for which we initialize
2051 * child services for. Any errors that occur is logged instead so
2052 * that all child services have a chance of being initialized.
2056 IopActionInitChildServices(
2057 PDEVICE_NODE DeviceNode
,
2059 BOOLEAN BootDrivers
)
2061 PDEVICE_NODE ParentDeviceNode
;
2064 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2067 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2070 * We are called for the parent too, but we don't need to do special
2071 * handling for this node
2073 if (DeviceNode
== ParentDeviceNode
)
2075 DPRINT("Success\n");
2076 return STATUS_SUCCESS
;
2080 * Make sure this device node is a direct child of the parent device node
2081 * that is given as an argument
2084 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2087 * Stop the traversal immediately and indicate unsuccessful operation
2090 return STATUS_UNSUCCESSFUL
;
2094 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2095 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2096 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2098 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2099 PDRIVER_OBJECT DriverObject
;
2101 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2102 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2104 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2105 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2106 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2109 /* get existing DriverObject pointer */
2110 Status
= IopGetDriverObject(
2112 &DeviceNode
->ServiceName
,
2115 if (NT_SUCCESS(Status
))
2117 /* Attach lower level filter drivers. */
2118 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2119 /* Initialize the function driver for the device node */
2120 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2121 if (NT_SUCCESS(Status
))
2123 /* Attach upper level filter drivers. */
2124 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2125 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2127 Status
= IopStartDevice(DeviceNode
);
2134 * Don't disable when trying to load only boot drivers
2138 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2139 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2141 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2142 CPRINT("Initialization of service %S failed (Status %x)\n",
2143 DeviceNode
->ServiceName
.Buffer
, Status
);
2147 DPRINT("Service %S is disabled or already initialized\n",
2148 DeviceNode
->ServiceName
.Buffer
);
2151 return STATUS_SUCCESS
;
2155 * IopActionInitAllServices
2157 * Initialize the service for all (direct) child nodes of a parent node. This
2158 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2162 IopActionInitAllServices(
2163 PDEVICE_NODE DeviceNode
,
2166 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2170 * IopActionInitBootServices
2172 * Initialize the boot start services for all (direct) child nodes of a
2173 * parent node. This function just calls IopActionInitChildServices with
2174 * BootDrivers = TRUE.
2177 IopActionInitBootServices(
2178 PDEVICE_NODE DeviceNode
,
2181 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2185 * IopInitializePnpServices
2187 * Initialize services for discovered children
2191 * Top device node to start initializing services.
2194 * When set to TRUE, only drivers marked as boot start will
2195 * be loaded. Otherwise, all drivers will be loaded.
2201 IopInitializePnpServices(
2202 IN PDEVICE_NODE DeviceNode
,
2203 IN BOOLEAN BootDrivers
)
2205 DEVICETREE_TRAVERSE_CONTEXT Context
;
2207 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2211 IopInitDeviceTreeTraverseContext(
2214 IopActionInitBootServices
,
2219 IopInitDeviceTreeTraverseContext(
2222 IopActionInitAllServices
,
2226 return IopTraverseDeviceTree(&Context
);
2231 IopInvalidateDeviceRelations(
2232 IN PDEVICE_NODE DeviceNode
,
2233 IN DEVICE_RELATION_TYPE Type
)
2235 DEVICETREE_TRAVERSE_CONTEXT Context
;
2236 PDEVICE_RELATIONS DeviceRelations
;
2237 IO_STATUS_BLOCK IoStatusBlock
;
2238 PDEVICE_NODE ChildDeviceNode
;
2239 IO_STACK_LOCATION Stack
;
2241 OBJECT_ATTRIBUTES ObjectAttributes
;
2242 UNICODE_STRING LinkName
;
2247 DPRINT("DeviceNode 0x%p\n", DeviceNode
);
2249 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2251 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
2253 Status
= IopInitiatePnpIrp(
2254 DeviceNode
->PhysicalDeviceObject
,
2256 IRP_MN_QUERY_DEVICE_RELATIONS
,
2258 if (!NT_SUCCESS(Status
))
2260 DPRINT("IopInitiatePnpIrp() failed\n");
2264 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2266 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
2268 DPRINT("No PDOs\n");
2269 if (DeviceRelations
)
2271 ExFreePool(DeviceRelations
);
2273 return STATUS_SUCCESS
;
2276 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2279 * Create device nodes for all discovered devices
2282 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2284 Status
= IopCreateDeviceNode(
2286 DeviceRelations
->Objects
[i
],
2288 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2289 if (!NT_SUCCESS(Status
))
2291 DPRINT("No resources\n");
2292 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2293 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2294 ExFreePool(DeviceRelations
);
2295 return STATUS_INSUFFICIENT_RESOURCES
;
2298 ExFreePool(DeviceRelations
);
2301 * Retrieve information about all discovered children from the bus driver
2304 IopInitDeviceTreeTraverseContext(
2307 IopActionInterrogateDeviceStack
,
2310 Status
= IopTraverseDeviceTree(&Context
);
2311 if (!NT_SUCCESS(Status
))
2313 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2318 * Retrieve configuration from the registry for discovered children
2321 IopInitDeviceTreeTraverseContext(
2324 IopActionConfigureChildServices
,
2327 Status
= IopTraverseDeviceTree(&Context
);
2328 if (!NT_SUCCESS(Status
))
2330 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2335 * Get the state of the system boot. If the \\SystemRoot link isn't
2336 * created yet, we will assume that it's possible to load only boot
2340 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
2342 InitializeObjectAttributes(
2349 Status
= ZwOpenFile(
2356 if(NT_SUCCESS(Status
))
2358 BootDrivers
= FALSE
;
2365 * Initialize services for discovered children. Only boot drivers will
2366 * be loaded from boot driver!
2369 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2370 if (!NT_SUCCESS(Status
))
2372 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2376 return STATUS_SUCCESS
;
2380 static NTSTATUS INIT_FUNCTION
2381 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
2385 HANDLE InstanceKey
= NULL
;
2388 /* Create registry key for the instance id, if it doesn't exist yet */
2389 KeyBuffer
= ExAllocatePool(PagedPool
,
2390 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
2391 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2392 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2393 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2395 ExFreePool(KeyBuffer
);
2396 if (!NT_SUCCESS(Status
))
2398 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2402 /* FIXME: Set 'ConfigFlags' value */
2404 ZwClose(InstanceKey
);
2408 return STATUS_SUCCESS
;
2418 DPRINT("PnpInit()\n");
2420 KeInitializeSpinLock(&IopDeviceTreeLock
);
2422 /* Initialize the Bus Type GUID List */
2423 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2424 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2425 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2427 /* Initialize PnP-Event notification support */
2428 Status
= IopInitPlugPlayEvents();
2429 if (!NT_SUCCESS(Status
))
2431 CPRINT("IopInitPlugPlayEvents() failed\n");
2432 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2436 * Create root device node
2439 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2440 if (!NT_SUCCESS(Status
))
2442 CPRINT("IoCreateDriverObject() failed\n");
2443 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2446 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2448 if (!NT_SUCCESS(Status
))
2450 CPRINT("IoCreateDevice() failed\n");
2451 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2454 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2455 if (!NT_SUCCESS(Status
))
2457 CPRINT("Insufficient resources\n");
2458 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2461 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2464 CPRINT("Failed to create the instance path!\n");
2465 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2468 /* Report the device to the user-mode pnp manager */
2469 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2470 &IopRootDeviceNode
->InstancePath
);
2472 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2473 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2474 IopRootDriverObject
->DriverExtension
->AddDevice(
2475 IopRootDriverObject
,
2476 IopRootDeviceNode
->PhysicalDeviceObject
);
2485 /* Set root device instance data */
2486 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
2487 if (!NT_SUCCESS(Status
))
2489 CPRINT("Failed to set instance data\n");
2490 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);