[TASKMGR] Process page: Allow using "Open File Location" functionality without runnin...
[reactos.git] / ntoskrnl / config / cmconfig.c
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "ntoskrnl.h"
12 #define NDEBUG
13 #include "debug.h"
14
15 /* FUNCTIONS *****************************************************************/
16
17 CODE_SEG("INIT")
18 NTSTATUS
19 NTAPI
20 CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
21 IN HANDLE NodeHandle,
22 OUT PHANDLE NewHandle,
23 IN INTERFACE_TYPE InterfaceType,
24 IN ULONG BusNumber,
25 IN PUSHORT DeviceIndexTable)
26 {
27 NTSTATUS Status;
28 OBJECT_ATTRIBUTES ObjectAttributes;
29 UNICODE_STRING KeyName, ValueName, ValueData;
30 HANDLE KeyHandle, ParentHandle;
31 ANSI_STRING TempString;
32 CHAR TempBuffer[12];
33 WCHAR Buffer[12];
34 PCONFIGURATION_COMPONENT Component;
35 ULONG Disposition, Length = 0;
36
37 /* Get the component */
38 Component = &CurrentEntry->ComponentEntry;
39
40 /* Set system class components to ARC system type */
41 if (Component->Class == SystemClass) Component->Type = ArcSystem;
42
43 /* Create a key for the component */
44 InitializeObjectAttributes(&ObjectAttributes,
45 &CmTypeName[Component->Type],
46 OBJ_CASE_INSENSITIVE,
47 NodeHandle,
48 NULL);
49 Status = NtCreateKey(&KeyHandle,
50 KEY_READ | KEY_WRITE,
51 &ObjectAttributes,
52 0,
53 NULL,
54 0,
55 &Disposition);
56 if (!NT_SUCCESS(Status)) return Status;
57
58 /* Check if this is anything but a system class component */
59 if (Component->Class != SystemClass)
60 {
61 /* Build the sub-component string */
62 RtlIntegerToChar(DeviceIndexTable[Component->Type]++,
63 10,
64 12,
65 TempBuffer);
66 RtlInitAnsiString(&TempString, TempBuffer);
67
68 /* Convert it to Unicode */
69 RtlInitEmptyUnicodeString(&KeyName, Buffer, sizeof(Buffer));
70 Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
71 if (!NT_SUCCESS(Status))
72 {
73 NtClose(KeyHandle);
74 return Status;
75 }
76
77 /* Create the key */
78 ParentHandle = KeyHandle;
79 InitializeObjectAttributes(&ObjectAttributes,
80 &KeyName,
81 OBJ_CASE_INSENSITIVE,
82 ParentHandle,
83 NULL);
84 Status = NtCreateKey(&KeyHandle,
85 KEY_READ | KEY_WRITE,
86 &ObjectAttributes,
87 0,
88 NULL,
89 0,
90 &Disposition);
91 NtClose(ParentHandle);
92
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);
96 }
97
98 /* Setup the component information key */
99 RtlInitUnicodeString(&ValueName, L"Component Information");
100 Status = NtSetValueKey(KeyHandle,
101 &ValueName,
102 0,
103 REG_BINARY,
104 &Component->Flags,
105 FIELD_OFFSET(CONFIGURATION_COMPONENT,
106 ConfigurationDataLength) -
107 FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags));
108 if (!NT_SUCCESS(Status))
109 {
110 /* Fail */
111 NtClose(KeyHandle);
112 return Status;
113 }
114
115 /* Check if we have an identifier */
116 if (Component->IdentifierLength)
117 {
118 /* Build the string and convert it to Unicode */
119 RtlInitUnicodeString(&ValueName, L"Identifier");
120 RtlInitAnsiString(&TempString, Component->Identifier);
121 Status = RtlAnsiStringToUnicodeString(&ValueData,
122 &TempString,
123 TRUE);
124 if (NT_SUCCESS(Status))
125 {
126 /* Save the identifier in the registry */
127 Status = NtSetValueKey(KeyHandle,
128 &ValueName,
129 0,
130 REG_SZ,
131 ValueData.Buffer,
132 ValueData.Length + sizeof(UNICODE_NULL));
133 RtlFreeUnicodeString(&ValueData);
134 }
135
136 /* Check for failure during conversion or registry write */
137 if (!NT_SUCCESS(Status))
138 {
139 /* Fail */
140 NtClose(KeyHandle);
141 return Status;
142 }
143 }
144
145 /* Setup the configuration data string */
146 RtlInitUnicodeString(&ValueName, L"Configuration Data");
147
148 /* Check if we got configuration data */
149 if (CurrentEntry->ConfigurationData)
150 {
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)
155 {
156 ASSERTMSG("Component too large -- need reallocation!\n", FALSE);
157 }
158 else
159 {
160 /* Copy the data */
161 RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version,
162 CurrentEntry->ConfigurationData,
163 Component->ConfigurationDataLength);
164 }
165 }
166 else
167 {
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);
174 }
175
176 /* Set the interface type and bus number */
177 CmpConfigurationData->InterfaceType = InterfaceType;
178 CmpConfigurationData->BusNumber = BusNumber;
179
180 /* Save the actual data */
181 Status = NtSetValueKey(KeyHandle,
182 &ValueName,
183 0,
184 REG_FULL_RESOURCE_DESCRIPTOR,
185 CmpConfigurationData,
186 Length);
187 if (!NT_SUCCESS(Status))
188 {
189 /* Fail */
190 NtClose(KeyHandle);
191 }
192 else
193 {
194 /* Return the new handle */
195 *NewHandle = KeyHandle;
196 }
197
198 /* Return status */
199 return Status;
200 }
201
202 CODE_SEG("INIT")
203 NTSTATUS
204 NTAPI
205 CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
206 IN HANDLE ParentHandle,
207 IN INTERFACE_TYPE InterfaceType,
208 IN ULONG BusNumber)
209 {
210 PCONFIGURATION_COMPONENT Component;
211 USHORT DeviceIndexTable[MaximumType + 1] = {0};
212 INTERFACE_TYPE Interface = InterfaceType;
213 ULONG Bus = BusNumber, i;
214 NTSTATUS Status;
215 HANDLE NewHandle;
216
217 /* Loop each entry */
218 while (CurrentEntry)
219 {
220 /* Check if this is an adapter */
221 Component = &CurrentEntry->ComponentEntry;
222 if ((Component->Class == AdapterClass) &&
223 (CurrentEntry->Parent->ComponentEntry.Class == SystemClass))
224 {
225 /* Check what kind of adapter it is */
226 switch (Component->Type)
227 {
228 /* EISA */
229 case EisaAdapter:
230 {
231 /* Fixup information */
232 Interface = Eisa;
233 Bus = CmpTypeCount[EisaAdapter]++;
234 break;
235 }
236
237 /* Turbo-channel */
238 case TcAdapter:
239 {
240 /* Fixup information */
241 Interface = TurboChannel;
242 Bus = CmpTypeCount[TurboChannel]++;
243 break;
244 }
245
246 /* ISA, PCI, etc busses */
247 case MultiFunctionAdapter:
248 {
249 /* Check if we have an identifier */
250 if (Component->Identifier)
251 {
252 /* Loop each multi-function adapter type */
253 for (i = 0; CmpMultifunctionTypes[i].Identifier; i++)
254 {
255 /* Check for a name match */
256 if (!_stricmp(CmpMultifunctionTypes[i].Identifier,
257 Component->Identifier))
258 {
259 /* Match found */
260 break;
261 }
262 }
263
264 /* Fix up information */
265 Interface = CmpMultifunctionTypes[i].InterfaceType;
266 Bus = CmpMultifunctionTypes[i].Count++;
267 }
268 break;
269 }
270
271 /* SCSI Bus */
272 case ScsiAdapter:
273 {
274 /* Fix up */
275 Interface = Internal;
276 Bus = CmpTypeCount[ScsiAdapter]++;
277 break;
278 }
279
280 /* Unknown */
281 default:
282 {
283 Interface = InterfaceTypeUndefined;
284 Bus = CmpUnknownBusCount++;
285 break;
286 }
287 }
288 }
289
290 /* Dump information on the component */
291
292 /* Setup the hardware node */
293 Status = CmpInitializeRegistryNode(CurrentEntry,
294 ParentHandle,
295 &NewHandle,
296 Interface,
297 Bus,
298 DeviceIndexTable);
299 if (!NT_SUCCESS(Status)) return Status;
300
301 /* Check for children */
302 if (CurrentEntry->Child)
303 {
304 /* Recurse child */
305 Status = CmpSetupConfigurationTree(CurrentEntry->Child,
306 NewHandle,
307 Interface,
308 Bus);
309 if (!NT_SUCCESS(Status))
310 {
311 /* Fail */
312 NtClose(NewHandle);
313 return Status;
314 }
315 }
316
317 /* Get to the next entry */
318 NtClose(NewHandle);
319 CurrentEntry = CurrentEntry->Sibling;
320 }
321
322 /* We're done */
323 return STATUS_SUCCESS;
324 }
325
326 CODE_SEG("INIT")
327 NTSTATUS
328 NTAPI
329 CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
330 {
331 NTSTATUS Status;
332 OBJECT_ATTRIBUTES ObjectAttributes;
333 HANDLE KeyHandle;
334 ULONG Disposition;
335 UNICODE_STRING KeyName;
336
337 /* Set the alternative system architecture information */
338 #if defined(SARCH_PC98)
339 SharedUserData->AlternativeArchitecture = NEC98x86;
340 #endif
341
342 /* Setup the key name */
343 RtlInitUnicodeString(&KeyName,
344 L"\\Registry\\Machine\\Hardware\\DeviceMap");
345 InitializeObjectAttributes(&ObjectAttributes,
346 &KeyName,
347 OBJ_CASE_INSENSITIVE,
348 NULL,
349 NULL);
350
351 /* Create the device map key */
352 Status = NtCreateKey(&KeyHandle,
353 KEY_READ | KEY_WRITE,
354 &ObjectAttributes,
355 0,
356 NULL,
357 0,
358 &Disposition);
359 if (!NT_SUCCESS(Status))
360 return Status;
361 NtClose(KeyHandle);
362
363 /* Nobody should've created this key yet! */
364 ASSERT(Disposition == REG_CREATED_NEW_KEY);
365
366 /* Setup the key name */
367 RtlInitUnicodeString(&KeyName,
368 L"\\Registry\\Machine\\Hardware\\Description");
369 InitializeObjectAttributes(&ObjectAttributes,
370 &KeyName,
371 OBJ_CASE_INSENSITIVE,
372 NULL,
373 NULL);
374
375 /* Create the description key */
376 Status = NtCreateKey(&KeyHandle,
377 KEY_READ | KEY_WRITE,
378 &ObjectAttributes,
379 0,
380 NULL,
381 0,
382 &Disposition);
383 if (!NT_SUCCESS(Status))
384 return Status;
385
386 /* Nobody should've created this key yet! */
387 ASSERT(Disposition == REG_CREATED_NEW_KEY);
388
389 /* Allocate the configuration data buffer */
390 CmpConfigurationData = ExAllocatePoolWithTag(PagedPool,
391 CmpConfigurationAreaSize,
392 TAG_CM);
393 if (!CmpConfigurationData)
394 {
395 NtClose(KeyHandle);
396 return STATUS_INSUFFICIENT_RESOURCES;
397 }
398
399 /* Check if we got anything from NTLDR */
400 if (LoaderBlock->ConfigurationRoot)
401 {
402 /* Setup the configuration tree */
403 Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot,
404 KeyHandle,
405 InterfaceTypeUndefined,
406 -1);
407 }
408 else
409 {
410 /* Nothing else to do */
411 Status = STATUS_SUCCESS;
412 }
413
414 /* Free the buffer, close our handle and return status */
415 ExFreePoolWithTag(CmpConfigurationData, TAG_CM);
416 NtClose(KeyHandle);
417 return Status;
418 }