2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmconfig.c
5 * PURPOSE: Configuration Manager - System Configuration Routines
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
19 CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
,
21 OUT PHANDLE NewHandle
,
22 IN INTERFACE_TYPE InterfaceType
,
24 IN PUSHORT DeviceIndexTable
)
27 OBJECT_ATTRIBUTES ObjectAttributes
;
28 UNICODE_STRING KeyName
, ValueName
, ValueData
;
29 HANDLE KeyHandle
, ParentHandle
;
30 ANSI_STRING TempString
;
33 PCONFIGURATION_COMPONENT Component
;
34 ULONG Disposition
, Length
= 0;
36 /* Get the component */
37 Component
= &CurrentEntry
->ComponentEntry
;
39 /* Set system class components to ARC system type */
40 if (Component
->Class
== SystemClass
) Component
->Type
= ArcSystem
;
42 /* Create a key for the component */
43 InitializeObjectAttributes(&ObjectAttributes
,
44 &CmTypeName
[Component
->Type
],
48 Status
= NtCreateKey(&KeyHandle
,
55 if (!NT_SUCCESS(Status
)) return Status
;
57 /* Check if this is anything but a system class component */
58 if (Component
->Class
!= SystemClass
)
60 /* Build the sub-component string */
61 RtlIntegerToChar(DeviceIndexTable
[Component
->Type
]++,
65 RtlInitAnsiString(&TempString
, TempBuffer
);
67 /* Convert it to Unicode */
68 RtlInitEmptyUnicodeString(&KeyName
, Buffer
, sizeof(Buffer
));
69 RtlAnsiStringToUnicodeString(&KeyName
, &TempString
, FALSE
);
72 ParentHandle
= KeyHandle
;
73 InitializeObjectAttributes(&ObjectAttributes
,
78 Status
= NtCreateKey(&KeyHandle
,
85 NtClose(ParentHandle
);
87 /* Fail if the key couldn't be created, and make sure it's a new key */
88 if (!NT_SUCCESS(Status
)) return Status
;
89 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
92 /* Setup the component information key */
93 RtlInitUnicodeString(&ValueName
, L
"Component Information");
94 Status
= NtSetValueKey(KeyHandle
,
99 FIELD_OFFSET(CONFIGURATION_COMPONENT
,
100 ConfigurationDataLength
) -
101 FIELD_OFFSET(CONFIGURATION_COMPONENT
, Flags
));
102 if (!NT_SUCCESS(Status
))
109 /* Check if we have an identifier */
110 if (Component
->IdentifierLength
)
112 /* Build the string and convert it to Unicode */
113 RtlInitUnicodeString(&ValueName
, L
"Identifier");
114 RtlInitAnsiString(&TempString
, Component
->Identifier
);
115 Status
= RtlAnsiStringToUnicodeString(&ValueData
,
118 if (NT_SUCCESS(Status
))
120 /* Save the identifier in the registry */
121 Status
= NtSetValueKey(KeyHandle
,
126 ValueData
.Length
+ sizeof(UNICODE_NULL
));
127 RtlFreeUnicodeString(&ValueData
);
130 /* Check for failure during conversion or registry write */
131 if (!NT_SUCCESS(Status
))
139 /* Setup the configuration data string */
140 RtlInitUnicodeString(&ValueName
, L
"Configuration Data");
142 /* Check if we got configuration data */
143 if (CurrentEntry
->ConfigurationData
)
145 /* Calculate the total length and check if it fits into our buffer */
146 Length
= Component
->ConfigurationDataLength
+
147 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
);
148 if (Length
> CmpConfigurationAreaSize
)
150 ASSERTMSG("Component too large -- need reallocation!", FALSE
);
155 RtlCopyMemory(&CmpConfigurationData
->PartialResourceList
.Version
,
156 CurrentEntry
->ConfigurationData
,
157 Component
->ConfigurationDataLength
);
162 /* No configuration data, setup defaults */
163 CmpConfigurationData
->PartialResourceList
.Version
= 0;
164 CmpConfigurationData
->PartialResourceList
.Revision
= 0;
165 CmpConfigurationData
->PartialResourceList
.Count
= 0;
166 Length
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
) +
167 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
);
170 /* Set the interface type and bus number */
171 CmpConfigurationData
->InterfaceType
= InterfaceType
;
172 CmpConfigurationData
->BusNumber
= BusNumber
;
174 /* Save the actual data */
175 Status
= NtSetValueKey(KeyHandle
,
178 REG_FULL_RESOURCE_DESCRIPTOR
,
179 CmpConfigurationData
,
181 if (!NT_SUCCESS(Status
))
188 /* Return the new handle */
189 *NewHandle
= KeyHandle
;
198 CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
,
199 IN HANDLE ParentHandle
,
200 IN INTERFACE_TYPE InterfaceType
,
203 PCONFIGURATION_COMPONENT Component
;
204 USHORT DeviceIndexTable
[MaximumType
+ 1] = {0};
205 ULONG Interface
= InterfaceType
, Bus
= BusNumber
, i
;
209 /* Loop each entry */
212 /* Check if this is an adapter */
213 Component
= &CurrentEntry
->ComponentEntry
;
214 if ((Component
->Class
== AdapterClass
) &&
215 (CurrentEntry
->Parent
->ComponentEntry
.Class
== SystemClass
))
217 /* Check what kind of adapter it is */
218 switch (Component
->Type
)
223 /* Fixup information */
225 Bus
= CmpTypeCount
[EisaAdapter
]++;
231 /* Fixup information */
232 Interface
= TurboChannel
;
233 Bus
= CmpTypeCount
[TurboChannel
]++;
236 /* ISA, PCI, etc busses */
237 case MultiFunctionAdapter
:
239 /* Check if we have an identifier */
240 if (Component
->Identifier
)
242 /* Loop each multi-function adapter type */
243 for (i
= 0; CmpMultifunctionTypes
[i
].Identifier
; i
++)
245 /* Check for a name match */
246 if (!_stricmp(CmpMultifunctionTypes
[i
].Identifier
,
247 Component
->Identifier
))
254 /* Fix up information */
255 Interface
= CmpMultifunctionTypes
[i
].InterfaceType
;
256 Bus
= CmpMultifunctionTypes
[i
].Count
++;
264 Interface
= Internal
;
265 Bus
= CmpTypeCount
[ScsiAdapter
]++;
271 Bus
= CmpUnknownBusCount
++;
276 /* Dump information on the component */
278 /* Setup the hardware node */
279 Status
= CmpInitializeRegistryNode(CurrentEntry
,
285 if (!NT_SUCCESS(Status
)) return Status
;
287 /* Check for children */
288 if (CurrentEntry
->Child
)
291 Status
= CmpSetupConfigurationTree(CurrentEntry
->Child
,
295 if (!NT_SUCCESS(Status
))
303 /* Get to the next entry */
305 CurrentEntry
= CurrentEntry
->Sibling
;
309 return STATUS_SUCCESS
;
314 CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
317 OBJECT_ATTRIBUTES ObjectAttributes
;
320 UNICODE_STRING KeyName
;
322 /* Setup the key name */
323 RtlInitUnicodeString(&KeyName
,
324 L
"\\Registry\\Machine\\Hardware\\DeviceMap");
325 InitializeObjectAttributes(&ObjectAttributes
,
327 OBJ_CASE_INSENSITIVE
,
331 /* Create the device map key */
332 Status
= NtCreateKey(&KeyHandle
,
333 KEY_READ
| KEY_WRITE
,
339 if (!NT_SUCCESS(Status
)) return Status
;
342 /* Nobody should've created this key yet! */
343 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
345 /* Setup the key name */
346 RtlInitUnicodeString(&KeyName
,
347 L
"\\Registry\\Machine\\Hardware\\Description");
348 InitializeObjectAttributes(&ObjectAttributes
,
350 OBJ_CASE_INSENSITIVE
,
354 /* Create the description key */
355 Status
= NtCreateKey(&KeyHandle
,
356 KEY_READ
| KEY_WRITE
,
362 if (!NT_SUCCESS(Status
)) return Status
;
364 /* Nobody should've created this key yet! */
365 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
367 /* Allocate the configuration data buffer */
368 CmpConfigurationData
= ExAllocatePoolWithTag(PagedPool
,
369 CmpConfigurationAreaSize
,
371 if (!CmpConfigurationData
) return STATUS_INSUFFICIENT_RESOURCES
;
373 /* Check if we got anything from NTLDR */
374 if (LoaderBlock
->ConfigurationRoot
)
376 /* Setup the configuration tree */
377 Status
= CmpSetupConfigurationTree(LoaderBlock
->ConfigurationRoot
,
384 /* Nothing else to do */
385 Status
= STATUS_SUCCESS
;
388 /* Close our handle, free the buffer and return status */
389 ExFreePoolWithTag(CmpConfigurationData
, TAG_CM
);