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 CODE_SEG("INIT")
20 LANGID
21 NTAPI
CmpConvertLangId(IN LPWSTR Name,IN ULONG NameLength)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 CODE_SEG("INIT")
71 HCELL_INDEX
72 NTAPI
CmpWalkPath(IN PHHIVE SystemHive,IN HCELL_INDEX ParentCell,IN LPWSTR Path)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 CODE_SEG("INIT")
102 VOID
103 NTAPI
CmGetSystemControlValues(IN PVOID SystemHiveData,IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)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 ? (Length <= CM_KEY_VALUE_SMALL) : TRUE);
212
213 /* Copy the data in the buffer */
214 RtlCopyMemory(ControlVector->Buffer, Buffer, Length);
215 }
216
217 /* Check if we should return the data type */
218 if (ControlVector->Type)
219 {
220 /* Return the type that we read */
221 *ControlVector->Type = ValueData->Type;
222 }
223 }
224 }
225
226 /* Return the size that we read */
227 if (ControlVector->BufferLength) *ControlVector->BufferLength = Length;
228
229 /* Go to the next entry */
230 ControlVector++;
231 }
232
233 /* Check if the ID is in the registry */
234 if (CmDefaultLanguageIdType == REG_SZ)
235 {
236 /* Read it */
237 PsDefaultSystemLocaleId =
238 (LCID)CmpConvertLangId(CmDefaultLanguageId,
239 CmDefaultLanguageIdLength);
240 }
241 else
242 {
243 /* Use EN_US by default */
244 PsDefaultSystemLocaleId = 0x409;
245 }
246
247 /* Check if the ID Is in the registry */
248 if (CmInstallUILanguageIdType == REG_SZ)
249 {
250 /* Read it */
251 PsInstallUILanguageId = CmpConvertLangId(CmInstallUILanguageId,
252 CmInstallUILanguageIdLength);
253 }
254 else
255 {
256 /* Otherwise, use the default */
257 PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
258 }
259
260 /* Set the defaults for the Thread UI */
261 PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
262 PsDefaultUILanguageId = PsInstallUILanguageId;
263 }
264
265 NTSTATUS
266 NTAPI
CmpSaveBootControlSet(IN USHORT ControlSet)267 CmpSaveBootControlSet(IN USHORT ControlSet)
268 {
269 DPRINT1("CmpSaveBootControlSet(%lu)\n", ControlSet);
270 return STATUS_SUCCESS;
271 }
272