[NTOSKRNL] Add and call the CmpSaveBootControlSet() stub.
[reactos.git] / ntoskrnl / config / cmcontrl.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmcontrl.c
5 * PURPOSE: Configuration Manager - Control Set Management
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 /* GLOBALS *******************************************************************/
16
17 /* FUNCTIONS *****************************************************************/
18
19 LANGID
20 NTAPI
21 INIT_FUNCTION
22 CmpConvertLangId(IN LPWSTR Name,
23 IN ULONG NameLength)
24 {
25 ULONG i;
26 WCHAR p;
27 LANGID LangId = 0;
28 ULONG IdCode;
29
30 /* Convert the length in chars and loop */
31 NameLength = NameLength / sizeof(WCHAR);
32 for (i = 0; i < NameLength; i++)
33 {
34 /* Get the character */
35 p = Name[i];
36
37 /* Handle each case */
38 if ((p >= L'0') && (p <= L'9'))
39 {
40 /* Handle digits*/
41 IdCode = p - L'0';
42 }
43 else if ((p >= L'A') && (p <= L'F'))
44 {
45 /* Handle upper-case letters */
46 IdCode = p - L'A' + 10;
47 }
48 else if ((p >= L'a') && (p <= L'f'))
49 {
50 /* Handle lower-case letters */
51 IdCode = p - L'a' + 10;
52 }
53 else
54 {
55 /* Unhandled case, return what we have till now */
56 break;
57 }
58
59 /* If the ID Code is >= 16, then we're done */
60 if (IdCode >= 16) break;
61
62 /* Build the Language ID */
63 LangId = (LangId << 4) | (LANGID)IdCode;
64 }
65
66 /* Return the Language ID */
67 return LangId;
68 }
69
70 HCELL_INDEX
71 NTAPI
72 INIT_FUNCTION
73 CmpWalkPath(IN PHHIVE SystemHive,
74 IN HCELL_INDEX ParentCell,
75 IN LPWSTR Path)
76 {
77 UNICODE_STRING UnicodePath, NextName;
78 BOOLEAN LastName;
79 HCELL_INDEX CurrentCell = ParentCell;
80 PCM_KEY_NODE Node;
81
82 /* We shouldn't have a release routine at this point */
83 ASSERT(SystemHive->ReleaseCellRoutine == NULL);
84
85 /* Initialize the Unicode path and start looping */
86 RtlInitUnicodeString(&UnicodePath, Path);
87 while (TRUE)
88 {
89 /* Get the next name */
90 CmpGetNextName(&UnicodePath, &NextName, &LastName);
91 if (!NextName.Length) return CurrentCell;
92
93 /* Get the subkey */
94 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, CurrentCell);
95 if (!Node) return HCELL_NIL;
96 CurrentCell = CmpFindSubKeyByName(SystemHive, Node, &NextName);
97 if (CurrentCell == HCELL_NIL) return CurrentCell;
98 }
99 }
100
101 VOID
102 NTAPI
103 INIT_FUNCTION
104 CmGetSystemControlValues(IN PVOID SystemHiveData,
105 IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
106 {
107 PHHIVE SystemHive = (PHHIVE)&CmControlHive;
108 NTSTATUS Status;
109 HCELL_INDEX RootCell, BaseCell, KeyCell, ValueCell;
110 ULONG Length, DataSize;
111 PCM_KEY_NODE Node;
112 PCM_KEY_VALUE ValueData;
113 UNICODE_STRING KeyName;
114 BOOLEAN Auto, IsSmallKey;
115 PVOID Buffer;
116
117 /* LUDDDIIIICRROOOUUSSSS KI^H^H HACKKKK */
118 if (!SystemHiveData) return;
119
120 /* Initialize the Hive View List and the security cache */
121 RtlZeroMemory(SystemHive, sizeof(*SystemHive));
122 CmpInitHiveViewList((PCMHIVE)SystemHive);
123 CmpInitSecurityCache((PCMHIVE)SystemHive);
124
125 /* Initialize the Hive */
126 Status = HvInitialize(SystemHive,
127 HINIT_FLAT,
128 HIVE_VOLATILE,
129 HFILE_TYPE_PRIMARY,
130 SystemHiveData,
131 NULL,
132 NULL,
133 NULL,
134 NULL,
135 NULL,
136 NULL,
137 1,
138 NULL);
139 if (!NT_SUCCESS(Status)) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 1, 0, 0);
140
141 /* Sanity check, flat hives don't have release routines */
142 ASSERT(SystemHive->ReleaseCellRoutine == NULL);
143
144 /* Set the Root Cell */
145 RootCell = ((PHBASE_BLOCK)SystemHiveData)->RootCell;
146
147 /* Find the current control set */
148 RtlInitUnicodeString(&KeyName, L"current");
149 BaseCell = CmpFindControlSet(SystemHive, RootCell, &KeyName, &Auto);
150 if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 2, 0, 0);
151
152 /* Find the control subkey */
153 RtlInitUnicodeString(&KeyName, L"control");
154 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, BaseCell);
155 BaseCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
156 if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO,1 , 3, 0, 0);
157
158 /* Loop each key */
159 while (ControlVector->KeyPath)
160 {
161 /* Assume failure */
162 Length = -1;
163
164 /* Get the cell for this key */
165 KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);
166 if (KeyCell != HCELL_NIL)
167 {
168 /* Now get the cell for the value */
169 RtlInitUnicodeString(&KeyName, ControlVector->ValueName);
170 Node = (PCM_KEY_NODE)HvGetCell(SystemHive, KeyCell);
171 ValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
172 if (ValueCell != HCELL_NIL)
173 {
174 /* Check if there's any data */
175 if (!ControlVector->BufferLength)
176 {
177 /* No, the buffer will only be large enough for a ULONG */
178 DataSize = sizeof(ULONG);
179 }
180 else
181 {
182 /* Yes, save the data size */
183 DataSize = *ControlVector->BufferLength;
184 }
185
186 /* Get the actual data */
187 ValueData = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
188
189 /* Check if this is a small key */
190 IsSmallKey = CmpIsKeyValueSmall(&Length, ValueData->DataLength);
191
192 /* If the length is bigger then our buffer, normalize it */
193 if (DataSize < Length) Length = DataSize;
194
195 /* Make sure we have some data */
196 if (Length > 0)
197 {
198 /* Check if this was a small key */
199 if (IsSmallKey)
200 {
201 /* The buffer is directly safe to read */
202 Buffer = (PVOID)(&(ValueData->Data));
203 }
204 else
205 {
206 /* Use the longer path */
207 Buffer = (PVOID)HvGetCell(SystemHive, ValueData->Data);
208 }
209
210 /* Sanity check if this is a small key */
211 ASSERT((IsSmallKey ?
212 (Length <= CM_KEY_VALUE_SMALL) : TRUE));
213
214 /* Copy the data in the buffer */
215 RtlCopyMemory(ControlVector->Buffer, Buffer, Length);
216 }
217
218 /* Check if we should return the data type */
219 if (ControlVector->Type)
220 {
221 /* Return the type that we read */
222 *ControlVector->Type = ValueData->Type;
223 }
224 }
225 }
226
227 /* Return the size that we read */
228 if (ControlVector->BufferLength) *ControlVector->BufferLength = Length;
229
230 /* Go to the next entry */
231 ControlVector++;
232 }
233
234 /* Check if the ID is in the registry */
235 if (CmDefaultLanguageIdType == REG_SZ)
236 {
237 /* Read it */
238 PsDefaultSystemLocaleId =
239 (LCID)CmpConvertLangId(CmDefaultLanguageId,
240 CmDefaultLanguageIdLength);
241 }
242 else
243 {
244 /* Use EN_US by default */
245 PsDefaultSystemLocaleId = 0x409;
246 }
247
248 /* Check if the ID Is in the registry */
249 if (CmInstallUILanguageIdType == REG_SZ)
250 {
251 /* Read it */
252 PsInstallUILanguageId = CmpConvertLangId(CmInstallUILanguageId,
253 CmInstallUILanguageIdLength);
254 }
255 else
256 {
257 /* Otherwise, use the default */
258 PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
259 }
260
261 /* Set the defaults for the Thread UI */
262 PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
263 PsDefaultUILanguageId = PsInstallUILanguageId;
264 }
265
266 NTSTATUS
267 NTAPI
268 CmpSaveBootControlSet(IN USHORT ControlSet)
269 {
270 DPRINT1("CmpSaveBootControlSet(%lu)\n", ControlSet);
271 return STATUS_SUCCESS;
272 }