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 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 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 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 267 CmpSaveBootControlSet(IN USHORT ControlSet) 268 { 269 DPRINT1("CmpSaveBootControlSet(%lu)\n", ControlSet); 270 return STATUS_SUCCESS; 271 } 272