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 Status
= RtlAnsiStringToUnicodeString(&KeyName
, &TempString
, FALSE
);
71 if (!NT_SUCCESS(Status
))
78 ParentHandle
= KeyHandle
;
79 InitializeObjectAttributes(&ObjectAttributes
,
84 Status
= NtCreateKey(&KeyHandle
,
91 NtClose(ParentHandle
);
93 /* Fail if the key couldn't be created, and make sure it's a new key */
94 if (!NT_SUCCESS(Status
)) return Status
;
95 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
98 /* Setup the component information key */
99 RtlInitUnicodeString(&ValueName
, L
"Component Information");
100 Status
= NtSetValueKey(KeyHandle
,
105 FIELD_OFFSET(CONFIGURATION_COMPONENT
,
106 ConfigurationDataLength
) -
107 FIELD_OFFSET(CONFIGURATION_COMPONENT
, Flags
));
108 if (!NT_SUCCESS(Status
))
115 /* Check if we have an identifier */
116 if (Component
->IdentifierLength
)
118 /* Build the string and convert it to Unicode */
119 RtlInitUnicodeString(&ValueName
, L
"Identifier");
120 RtlInitAnsiString(&TempString
, Component
->Identifier
);
121 Status
= RtlAnsiStringToUnicodeString(&ValueData
,
124 if (NT_SUCCESS(Status
))
126 /* Save the identifier in the registry */
127 Status
= NtSetValueKey(KeyHandle
,
132 ValueData
.Length
+ sizeof(UNICODE_NULL
));
133 RtlFreeUnicodeString(&ValueData
);
136 /* Check for failure during conversion or registry write */
137 if (!NT_SUCCESS(Status
))
145 /* Setup the configuration data string */
146 RtlInitUnicodeString(&ValueName
, L
"Configuration Data");
148 /* Check if we got configuration data */
149 if (CurrentEntry
->ConfigurationData
)
151 /* Calculate the total length and check if it fits into our buffer */
152 Length
= Component
->ConfigurationDataLength
+
153 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
);
154 if (Length
> CmpConfigurationAreaSize
)
156 ASSERTMSG("Component too large -- need reallocation!", FALSE
);
161 RtlCopyMemory(&CmpConfigurationData
->PartialResourceList
.Version
,
162 CurrentEntry
->ConfigurationData
,
163 Component
->ConfigurationDataLength
);
168 /* No configuration data, setup defaults */
169 CmpConfigurationData
->PartialResourceList
.Version
= 0;
170 CmpConfigurationData
->PartialResourceList
.Revision
= 0;
171 CmpConfigurationData
->PartialResourceList
.Count
= 0;
172 Length
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
) +
173 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
);
176 /* Set the interface type and bus number */
177 CmpConfigurationData
->InterfaceType
= InterfaceType
;
178 CmpConfigurationData
->BusNumber
= BusNumber
;
180 /* Save the actual data */
181 Status
= NtSetValueKey(KeyHandle
,
184 REG_FULL_RESOURCE_DESCRIPTOR
,
185 CmpConfigurationData
,
187 if (!NT_SUCCESS(Status
))
194 /* Return the new handle */
195 *NewHandle
= KeyHandle
;
205 CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
,
206 IN HANDLE ParentHandle
,
207 IN INTERFACE_TYPE InterfaceType
,
210 PCONFIGURATION_COMPONENT Component
;
211 USHORT DeviceIndexTable
[MaximumType
+ 1] = {0};
212 ULONG Interface
= InterfaceType
, Bus
= BusNumber
, i
;
216 /* Loop each entry */
219 /* Check if this is an adapter */
220 Component
= &CurrentEntry
->ComponentEntry
;
221 if ((Component
->Class
== AdapterClass
) &&
222 (CurrentEntry
->Parent
->ComponentEntry
.Class
== SystemClass
))
224 /* Check what kind of adapter it is */
225 switch (Component
->Type
)
230 /* Fixup information */
232 Bus
= CmpTypeCount
[EisaAdapter
]++;
238 /* Fixup information */
239 Interface
= TurboChannel
;
240 Bus
= CmpTypeCount
[TurboChannel
]++;
243 /* ISA, PCI, etc busses */
244 case MultiFunctionAdapter
:
246 /* Check if we have an identifier */
247 if (Component
->Identifier
)
249 /* Loop each multi-function adapter type */
250 for (i
= 0; CmpMultifunctionTypes
[i
].Identifier
; i
++)
252 /* Check for a name match */
253 if (!_stricmp(CmpMultifunctionTypes
[i
].Identifier
,
254 Component
->Identifier
))
261 /* Fix up information */
262 Interface
= CmpMultifunctionTypes
[i
].InterfaceType
;
263 Bus
= CmpMultifunctionTypes
[i
].Count
++;
271 Interface
= Internal
;
272 Bus
= CmpTypeCount
[ScsiAdapter
]++;
278 Bus
= CmpUnknownBusCount
++;
283 /* Dump information on the component */
285 /* Setup the hardware node */
286 Status
= CmpInitializeRegistryNode(CurrentEntry
,
292 if (!NT_SUCCESS(Status
)) return Status
;
294 /* Check for children */
295 if (CurrentEntry
->Child
)
298 Status
= CmpSetupConfigurationTree(CurrentEntry
->Child
,
302 if (!NT_SUCCESS(Status
))
310 /* Get to the next entry */
312 CurrentEntry
= CurrentEntry
->Sibling
;
316 return STATUS_SUCCESS
;
322 CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
325 OBJECT_ATTRIBUTES ObjectAttributes
;
328 UNICODE_STRING KeyName
;
330 /* Setup the key name */
331 RtlInitUnicodeString(&KeyName
,
332 L
"\\Registry\\Machine\\Hardware\\DeviceMap");
333 InitializeObjectAttributes(&ObjectAttributes
,
335 OBJ_CASE_INSENSITIVE
,
339 /* Create the device map key */
340 Status
= NtCreateKey(&KeyHandle
,
341 KEY_READ
| KEY_WRITE
,
347 if (!NT_SUCCESS(Status
)) return Status
;
350 /* Nobody should've created this key yet! */
351 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
353 /* Setup the key name */
354 RtlInitUnicodeString(&KeyName
,
355 L
"\\Registry\\Machine\\Hardware\\Description");
356 InitializeObjectAttributes(&ObjectAttributes
,
358 OBJ_CASE_INSENSITIVE
,
362 /* Create the description key */
363 Status
= NtCreateKey(&KeyHandle
,
364 KEY_READ
| KEY_WRITE
,
370 if (!NT_SUCCESS(Status
)) return Status
;
372 /* Nobody should've created this key yet! */
373 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
375 /* Allocate the configuration data buffer */
376 CmpConfigurationData
= ExAllocatePoolWithTag(PagedPool
,
377 CmpConfigurationAreaSize
,
379 if (!CmpConfigurationData
) return STATUS_INSUFFICIENT_RESOURCES
;
381 /* Check if we got anything from NTLDR */
382 if (LoaderBlock
->ConfigurationRoot
)
384 /* Setup the configuration tree */
385 Status
= CmpSetupConfigurationTree(LoaderBlock
->ConfigurationRoot
,
392 /* Nothing else to do */
393 Status
= STATUS_SUCCESS
;
396 /* Close our handle, free the buffer and return status */
397 ExFreePoolWithTag(CmpConfigurationData
, TAG_CM
);