xref: /reactos/ntoskrnl/config/cmcontrl.c (revision 76f1da56)
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