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 *****************************************************************/
20 CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
,
22 OUT PHANDLE NewHandle
,
23 IN INTERFACE_TYPE InterfaceType
,
25 IN PUSHORT DeviceIndexTable
)
28 OBJECT_ATTRIBUTES ObjectAttributes
;
29 UNICODE_STRING KeyName
, ValueName
, ValueData
;
30 HANDLE KeyHandle
, ParentHandle
;
31 ANSI_STRING TempString
;
34 PCONFIGURATION_COMPONENT Component
;
35 ULONG Disposition
, Length
= 0;
37 /* Get the component */
38 Component
= &CurrentEntry
->ComponentEntry
;
40 /* Set system class components to ARC system type */
41 if (Component
->Class
== SystemClass
) Component
->Type
= ArcSystem
;
43 /* Create a key for the component */
44 InitializeObjectAttributes(&ObjectAttributes
,
45 &CmTypeName
[Component
->Type
],
49 Status
= NtCreateKey(&KeyHandle
,
56 if (!NT_SUCCESS(Status
)) return Status
;
58 /* Check if this is anything but a system class component */
59 if (Component
->Class
!= SystemClass
)
61 /* Build the sub-component string */
62 RtlIntegerToChar(DeviceIndexTable
[Component
->Type
]++,
66 RtlInitAnsiString(&TempString
, TempBuffer
);
68 /* Convert it to Unicode */
69 RtlInitEmptyUnicodeString(&KeyName
, Buffer
, sizeof(Buffer
));
70 RtlAnsiStringToUnicodeString(&KeyName
, &TempString
, FALSE
);
73 ParentHandle
= KeyHandle
;
74 InitializeObjectAttributes(&ObjectAttributes
,
79 Status
= NtCreateKey(&KeyHandle
,
86 NtClose(ParentHandle
);
88 /* Fail if the key couldn't be created, and make sure it's a new key */
89 if (!NT_SUCCESS(Status
)) return Status
;
90 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
93 /* Setup the component information key */
94 RtlInitUnicodeString(&ValueName
, L
"Component Information");
95 Status
= NtSetValueKey(KeyHandle
,
100 FIELD_OFFSET(CONFIGURATION_COMPONENT
,
101 ConfigurationDataLength
) -
102 FIELD_OFFSET(CONFIGURATION_COMPONENT
, Flags
));
103 if (!NT_SUCCESS(Status
))
110 /* Check if we have an identifier */
111 if (Component
->IdentifierLength
)
113 /* Build the string and convert it to Unicode */
114 RtlInitUnicodeString(&ValueName
, L
"Identifier");
115 RtlInitAnsiString(&TempString
, Component
->Identifier
);
116 Status
= RtlAnsiStringToUnicodeString(&ValueData
,
119 if (NT_SUCCESS(Status
))
121 /* Save the identifier in the registry */
122 Status
= NtSetValueKey(KeyHandle
,
127 ValueData
.Length
+ sizeof(UNICODE_NULL
));
128 RtlFreeUnicodeString(&ValueData
);
131 /* Check for failure during conversion or registry write */
132 if (!NT_SUCCESS(Status
))
140 /* Setup the configuration data string */
141 RtlInitUnicodeString(&ValueName
, L
"Configuration Data");
143 /* Check if we got configuration data */
144 if (CurrentEntry
->ConfigurationData
)
146 /* Calculate the total length and check if it fits into our buffer */
147 Length
= Component
->ConfigurationDataLength
+
148 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
);
149 if (Length
> CmpConfigurationAreaSize
)
151 ASSERTMSG("Component too large -- need reallocation!", FALSE
);
156 RtlCopyMemory(&CmpConfigurationData
->PartialResourceList
.Version
,
157 CurrentEntry
->ConfigurationData
,
158 Component
->ConfigurationDataLength
);
163 /* No configuration data, setup defaults */
164 CmpConfigurationData
->PartialResourceList
.Version
= 0;
165 CmpConfigurationData
->PartialResourceList
.Revision
= 0;
166 CmpConfigurationData
->PartialResourceList
.Count
= 0;
167 Length
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
) +
168 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
);
171 /* Set the interface type and bus number */
172 CmpConfigurationData
->InterfaceType
= InterfaceType
;
173 CmpConfigurationData
->BusNumber
= BusNumber
;
175 /* Save the actual data */
176 Status
= NtSetValueKey(KeyHandle
,
179 REG_FULL_RESOURCE_DESCRIPTOR
,
180 CmpConfigurationData
,
182 if (!NT_SUCCESS(Status
))
189 /* Return the new handle */
190 *NewHandle
= KeyHandle
;
200 CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
,
201 IN HANDLE ParentHandle
,
202 IN INTERFACE_TYPE InterfaceType
,
205 PCONFIGURATION_COMPONENT Component
;
206 USHORT DeviceIndexTable
[MaximumType
+ 1] = {0};
207 ULONG Interface
= InterfaceType
, Bus
= BusNumber
, i
;
211 /* Loop each entry */
214 /* Check if this is an adapter */
215 Component
= &CurrentEntry
->ComponentEntry
;
216 if ((Component
->Class
== AdapterClass
) &&
217 (CurrentEntry
->Parent
->ComponentEntry
.Class
== SystemClass
))
219 /* Check what kind of adapter it is */
220 switch (Component
->Type
)
225 /* Fixup information */
227 Bus
= CmpTypeCount
[EisaAdapter
]++;
233 /* Fixup information */
234 Interface
= TurboChannel
;
235 Bus
= CmpTypeCount
[TurboChannel
]++;
238 /* ISA, PCI, etc busses */
239 case MultiFunctionAdapter
:
241 /* Check if we have an identifier */
242 if (Component
->Identifier
)
244 /* Loop each multi-function adapter type */
245 for (i
= 0; CmpMultifunctionTypes
[i
].Identifier
; i
++)
247 /* Check for a name match */
248 if (!_stricmp(CmpMultifunctionTypes
[i
].Identifier
,
249 Component
->Identifier
))
256 /* Fix up information */
257 Interface
= CmpMultifunctionTypes
[i
].InterfaceType
;
258 Bus
= CmpMultifunctionTypes
[i
].Count
++;
266 Interface
= Internal
;
267 Bus
= CmpTypeCount
[ScsiAdapter
]++;
273 Bus
= CmpUnknownBusCount
++;
278 /* Dump information on the component */
280 /* Setup the hardware node */
281 Status
= CmpInitializeRegistryNode(CurrentEntry
,
287 if (!NT_SUCCESS(Status
)) return Status
;
289 /* Check for children */
290 if (CurrentEntry
->Child
)
293 Status
= CmpSetupConfigurationTree(CurrentEntry
->Child
,
297 if (!NT_SUCCESS(Status
))
305 /* Get to the next entry */
307 CurrentEntry
= CurrentEntry
->Sibling
;
311 return STATUS_SUCCESS
;
317 CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
320 OBJECT_ATTRIBUTES ObjectAttributes
;
323 UNICODE_STRING KeyName
;
325 /* Setup the key name */
326 RtlInitUnicodeString(&KeyName
,
327 L
"\\Registry\\Machine\\Hardware\\DeviceMap");
328 InitializeObjectAttributes(&ObjectAttributes
,
330 OBJ_CASE_INSENSITIVE
,
334 /* Create the device map key */
335 Status
= NtCreateKey(&KeyHandle
,
336 KEY_READ
| KEY_WRITE
,
342 if (!NT_SUCCESS(Status
)) return Status
;
345 /* Nobody should've created this key yet! */
346 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
348 /* Setup the key name */
349 RtlInitUnicodeString(&KeyName
,
350 L
"\\Registry\\Machine\\Hardware\\Description");
351 InitializeObjectAttributes(&ObjectAttributes
,
353 OBJ_CASE_INSENSITIVE
,
357 /* Create the description key */
358 Status
= NtCreateKey(&KeyHandle
,
359 KEY_READ
| KEY_WRITE
,
365 if (!NT_SUCCESS(Status
)) return Status
;
367 /* Nobody should've created this key yet! */
368 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
370 /* Allocate the configuration data buffer */
371 CmpConfigurationData
= ExAllocatePoolWithTag(PagedPool
,
372 CmpConfigurationAreaSize
,
374 if (!CmpConfigurationData
) return STATUS_INSUFFICIENT_RESOURCES
;
376 /* Check if we got anything from NTLDR */
377 if (LoaderBlock
->ConfigurationRoot
)
379 /* Setup the configuration tree */
380 Status
= CmpSetupConfigurationTree(LoaderBlock
->ConfigurationRoot
,
387 /* Nothing else to do */
388 Status
= STATUS_SUCCESS
;
391 /* Close our handle, free the buffer and return status */
392 ExFreePoolWithTag(CmpConfigurationData
, TAG_CM
);