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