1 /* 2 * ReactOS kernel 3 * Copyright (C) 2006 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * COPYRIGHT: See COPYING in the top level directory 21 * PROJECT: ReactOS hive maker 22 * FILE: tools/mkhive/registry.c 23 * PURPOSE: Registry code 24 * PROGRAMMERS: Hervé Poussineau 25 * Hermès Bélusca-Maïto 26 */ 27 28 /* INCLUDES *****************************************************************/ 29 30 #define NDEBUG 31 #include "mkhive.h" 32 33 /* DATA *********************************************************************/ 34 35 typedef struct _REPARSE_POINT 36 { 37 LIST_ENTRY ListEntry; 38 PCMHIVE SourceHive; 39 HCELL_INDEX SourceKeyCellOffset; 40 PCMHIVE DestinationHive; 41 HCELL_INDEX DestinationKeyCellOffset; 42 } REPARSE_POINT, *PREPARSE_POINT; 43 44 typedef struct _MEMKEY 45 { 46 /* Information on hard disk structure */ 47 HCELL_INDEX KeyCellOffset; 48 PCMHIVE RegistryHive; 49 } MEMKEY, *PMEMKEY; 50 51 #define HKEY_TO_MEMKEY(hKey) ((PMEMKEY)(hKey)) 52 #define MEMKEY_TO_HKEY(memKey) ((HKEY)(memKey)) 53 54 static CMHIVE RootHive; 55 static PMEMKEY RootKey; 56 57 static CMHIVE SystemHive; /* \Registry\Machine\SYSTEM */ 58 static CMHIVE SoftwareHive; /* \Registry\Machine\SOFTWARE */ 59 static CMHIVE DefaultHive; /* \Registry\User\.DEFAULT */ 60 static CMHIVE SamHive; /* \Registry\Machine\SAM */ 61 static CMHIVE SecurityHive; /* \Registry\Machine\SECURITY */ 62 static CMHIVE BcdHive; /* \Registry\Machine\BCD00000000 */ 63 64 // 65 // TODO: Write these values in a more human-readable form. 66 // See http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/Registry%20Structure%20-%20Appendices%20V4.pdf 67 // Appendix 12 "The Registry NT Security Descriptor" for more information. 68 // 69 // These SECURITY_DESCRIPTORs were obtained by dumping the security block "sk" 70 // of registry hives created by setting their permissions to be the same as 71 // the ones of the BCD, SOFTWARE, or SYSTEM, SAM and .DEFAULT system hives. 72 // A cross-check was subsequently done with the system hives to verify that 73 // the security descriptors were the same. 74 // 75 static UCHAR BcdSecurity[] = 76 { 77 // SECURITY_DESCRIPTOR_RELATIVE 78 0x01, // Revision 79 0x00, // Sbz1 80 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) | 81 // SE_DACL_PROTECTED (0x1000) | 82 // SE_DACL_AUTO_INHERITED (0x0400) | 83 // SE_DACL_PRESENT (0x0004) 84 0x48, 0x00, 0x00, 0x00, // Owner 85 0x58, 0x00, 0x00, 0x00, // Group 86 0x00, 0x00, 0x00, 0x00, // Sacl (None) 87 0x14, 0x00, 0x00, 0x00, // Dacl 88 89 // DACL 90 0x02, // AclRevision 91 0x00, // Sbz1 92 0x34, 0x00, // AclSize 93 0x02, 0x00, // AceCount 94 0x00, 0x00, // Sbz2 95 96 // (1st ACE) 97 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 98 0x02, // AceFlags: CONTAINER_INHERIT_ACE 99 0x18, 0x00, // AceSize 100 0x19, 0x00, 0x06, 0x00, // ACCESS_MASK: "Write DAC" (0x00040000) | 101 // "Read Control" (0x00020000) | 102 // "Notify" (0x00000010) | 103 // "Enumerate Subkeys" (0x00000008) | 104 // "Query Value" (0x00000001) 105 // (SidStart: S-1-5-32-544 "Administrators") 106 0x01, 0x02, 0x00, 0x00, 107 0x00, 0x00, 0x00, 0x05, 108 0x20, 0x00, 0x00, 0x00, 109 0x20, 0x02, 0x00, 0x00, 110 111 // (2nd ACE) 112 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 113 0x02, // AceFlags: CONTAINER_INHERIT_ACE 114 0x14, 0x00, // AceSize 115 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) 116 // (SidStart: S-1-5-18 "Local System") 117 0x01, 0x01, 0x00, 0x00, 118 0x00, 0x00, 0x00, 0x05, 119 0x12, 0x00, 0x00, 0x00, 120 121 // Owner SID (S-1-5-32-544 "Administrators") 122 0x01, 0x02, 0x00, 0x00, 123 0x00, 0x00, 0x00, 0x05, 124 0x20, 0x00, 0x00, 0x00, 125 0x20, 0x02, 0x00, 0x00, 126 127 // Group SID (S-1-5-21-domain-513 "Domain Users") 128 0x01, 0x05, 0x00, 0x00, 129 0x00, 0x00, 0x00, 0x05, 130 0x15, 0x00, 0x00, 0x00, 131 0xAC, 0xD0, 0x49, 0xCB, 132 0xE6, 0x52, 0x47, 0x9C, 133 0xE4, 0x31, 0xDB, 0x5C, 134 0x01, 0x02, 0x00, 0x00 135 }; 136 137 static UCHAR SoftwareSecurity[] = 138 { 139 // SECURITY_DESCRIPTOR_RELATIVE 140 0x01, // Revision 141 0x00, // Sbz1 142 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) | 143 // SE_DACL_PROTECTED (0x1000) | 144 // SE_DACL_AUTO_INHERITED (0x0400) | 145 // SE_DACL_PRESENT (0x0004) 146 0xA0, 0x00, 0x00, 0x00, // Owner 147 0xB0, 0x00, 0x00, 0x00, // Group 148 0x00, 0x00, 0x00, 0x00, // Sacl (None) 149 0x14, 0x00, 0x00, 0x00, // Dacl 150 151 // DACL 152 0x02, // AclRevision 153 0x00, // Sbz1 154 0x8C, 0x00, // AclSize 155 0x06, 0x00, // AceCount 156 0x00, 0x00, // Sbz2 157 158 // (1st ACE) 159 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 160 0x02, // AceFlags: CONTAINER_INHERIT_ACE 161 0x18, 0x00, // AceSize 162 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) 163 // (SidStart: S-1-5-32-544 "Administrators") 164 0x01, 0x02, 0x00, 0x00, 165 0x00, 0x00, 0x00, 0x05, 166 0x20, 0x00, 0x00, 0x00, 167 0x20, 0x02, 0x00, 0x00, 168 169 // (2nd ACE) 170 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 171 0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE 172 0x14, 0x00, // AceSize 173 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) 174 // (SidStart: S-1-3-0 "Creator Owner") 175 0x01, 0x01, 0x00, 0x00, 176 0x00, 0x00, 0x00, 0x03, 177 0x00, 0x00, 0x00, 0x00, 178 179 // (3rd ACE) 180 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 181 0x02, // AceFlags: CONTAINER_INHERIT_ACE 182 0x14, 0x00, // AceSize 183 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) 184 // (SidStart: S-1-5-18 "Local System") 185 0x01, 0x01, 0x00, 0x00, 186 0x00, 0x00, 0x00, 0x05, 187 0x12, 0x00, 0x00, 0x00, 188 189 // (4th ACE) 190 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 191 0x02, // AceFlags: CONTAINER_INHERIT_ACE 192 0x14, 0x00, // AceSize 193 0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | 194 // "Delete" (0x00010000) | 195 // "Notify" (0x00000010) | 196 // "Enumerate Subkeys" (0x00000008) | 197 // "Create Subkey" (0x00000004) | 198 // "Set Value" (0x00000002) | 199 // "Query Value" (0x00000001) 200 // (SidStart: S-1-5-13 "Terminal Server Users") 201 0x01, 0x01, 0x00, 0x00, 202 0x00, 0x00, 0x00, 0x05, 203 0x0D, 0x00, 0x00, 0x00, 204 205 // (5th ACE) 206 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 207 0x02, // AceFlags: CONTAINER_INHERIT_ACE 208 0x18, 0x00, // AceSize 209 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | 210 // "Notify" (0x00000010) | 211 // "Enumerate Subkeys" (0x00000008) | 212 // "Query Value" (0x00000001) 213 // (SidStart: S-1-5-32-545 "Users") 214 0x01, 0x02, 0x00, 0x00, 215 0x00, 0x00, 0x00, 0x05, 216 0x20, 0x00, 0x00, 0x00, 217 0x21, 0x02, 0x00, 0x00, 218 219 // (6th ACE) 220 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 221 0x02, // AceFlags: CONTAINER_INHERIT_ACE 222 0x18, 0x00, // AceSize 223 0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | 224 // "Delete" (0x00010000) | 225 // "Notify" (0x00000010) | 226 // "Enumerate Subkeys" (0x00000008) | 227 // "Create Subkey" (0x00000004) | 228 // "Set Value" (0x00000002) | 229 // "Query Value" (0x00000001) 230 // (SidStart: S-1-5-32-547 "Power Users") 231 0x01, 0x02, 0x00, 0x00, 232 0x00, 0x00, 0x00, 0x05, 233 0x20, 0x00, 0x00, 0x00, 234 0x23, 0x02, 0x00, 0x00, 235 236 // Owner SID (S-1-5-32-544 "Administrators") 237 0x01, 0x02, 0x00, 0x00, 238 0x00, 0x00, 0x00, 0x05, 239 0x20, 0x00, 0x00, 0x00, 240 0x20, 0x02, 0x00, 0x00, 241 242 // Group SID (S-1-5-21-domain-513 "Domain Users") 243 0x01, 0x05, 0x00, 0x00, 244 0x00, 0x00, 0x00, 0x05, 245 0x15, 0x00, 0x00, 0x00, 246 0xAC, 0xD0, 0x49, 0xCB, 247 0xE6, 0x52, 0x47, 0x9C, 248 0xE4, 0x31, 0xDB, 0x5C, 249 0x01, 0x02, 0x00, 0x00 250 }; 251 252 // Same security for SYSTEM, SAM and .DEFAULT 253 static UCHAR SystemSecurity[] = 254 { 255 // SECURITY_DESCRIPTOR_RELATIVE 256 0x01, // Revision 257 0x00, // Sbz1 258 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) | 259 // SE_DACL_PROTECTED (0x1000) | 260 // SE_DACL_AUTO_INHERITED (0x0400) | 261 // SE_DACL_PRESENT (0x0004) 262 0x8C, 0x00, 0x00, 0x00, // Owner 263 0x9C, 0x00, 0x00, 0x00, // Group 264 0x00, 0x00, 0x00, 0x00, // Sacl (None) 265 0x14, 0x00, 0x00, 0x00, // Dacl 266 267 // DACL 268 0x02, // AclRevision 269 0x00, // Sbz1 270 0x78, 0x00, // AclSize 271 0x05, 0x00, // AceCount 272 0x00, 0x00, // Sbz2 273 274 // (1st ACE) 275 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 276 0x02, // AceFlags: CONTAINER_INHERIT_ACE 277 0x18, 0x00, // AceSize 278 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) 279 // (SidStart: S-1-5-32-544 "Administrators") 280 0x01, 0x02, 0x00, 0x00, 281 0x00, 0x00, 0x00, 0x05, 282 0x20, 0x00, 0x00, 0x00, 283 0x20, 0x02, 0x00, 0x00, 284 285 // (2nd ACE) 286 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 287 0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE 288 0x14, 0x00, // AceSize 289 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) 290 // (SidStart: S-1-3-0 "Creator Owner") 291 0x01, 0x01, 0x00, 0x00, 292 0x00, 0x00, 0x00, 0x03, 293 0x00, 0x00, 0x00, 0x00, 294 295 // (3rd ACE) 296 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 297 0x02, // AceFlags: CONTAINER_INHERIT_ACE 298 0x14, 0x00, // AceSize 299 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F) 300 // (SidStart: S-1-5-18 "Local System") 301 0x01, 0x01, 0x00, 0x00, 302 0x00, 0x00, 0x00, 0x05, 303 0x12, 0x00, 0x00, 0x00, 304 305 // (4th ACE) 306 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 307 0x02, // AceFlags: CONTAINER_INHERIT_ACE 308 0x18, 0x00, // AceSize 309 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | 310 // "Notify" (0x00000010) | 311 // "Enumerate Subkeys" (0x00000008) | 312 // "Query Value" (0x00000001) 313 // (SidStart: S-1-5-32-545 "Users") 314 0x01, 0x02, 0x00, 0x00, 315 0x00, 0x00, 0x00, 0x05, 316 0x20, 0x00, 0x00, 0x00, 317 0x21, 0x02, 0x00, 0x00, 318 319 // (5th ACE) 320 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE 321 0x02, // AceFlags: CONTAINER_INHERIT_ACE 322 0x18, 0x00, // AceSize 323 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) | 324 // "Notify" (0x00000010) | 325 // "Enumerate Subkeys" (0x00000008) | 326 // "Query Value" (0x00000001) 327 // (SidStart: S-1-5-32-547 "Power Users") 328 0x01, 0x02, 0x00, 0x00, 329 0x00, 0x00, 0x00, 0x05, 330 0x20, 0x00, 0x00, 0x00, 331 0x23, 0x02, 0x00, 0x00, 332 333 // Owner SID (S-1-5-32-544 "Administrators") 334 0x01, 0x02, 0x00, 0x00, 335 0x00, 0x00, 0x00, 0x05, 336 0x20, 0x00, 0x00, 0x00, 337 0x20, 0x02, 0x00, 0x00, 338 339 // Group SID (S-1-5-21-domain-513 "Domain Users") 340 0x01, 0x05, 0x00, 0x00, 341 0x00, 0x00, 0x00, 0x05, 342 0x15, 0x00, 0x00, 0x00, 343 0xAC, 0xD0, 0x49, 0xCB, 344 0xE6, 0x52, 0x47, 0x9C, 345 0xE4, 0x31, 0xDB, 0x5C, 346 0x01, 0x02, 0x00, 0x00 347 }; 348 349 /* GLOBALS ******************************************************************/ 350 351 HIVE_LIST_ENTRY RegistryHives[/*MAX_NUMBER_OF_REGISTRY_HIVES*/] = 352 { 353 /* Special Setup system registry hive */ 354 // WARNING: Please *keep* it in first position! 355 { "SETUPREG", L"Registry\\Machine\\SYSTEM" , &SystemHive , SystemSecurity , sizeof(SystemSecurity) }, 356 357 /* Regular registry hives */ 358 { "SYSTEM" , L"Registry\\Machine\\SYSTEM" , &SystemHive , SystemSecurity , sizeof(SystemSecurity) }, 359 { "SOFTWARE", L"Registry\\Machine\\SOFTWARE" , &SoftwareHive, SoftwareSecurity, sizeof(SoftwareSecurity) }, 360 { "DEFAULT" , L"Registry\\User\\.DEFAULT" , &DefaultHive , SystemSecurity , sizeof(SystemSecurity) }, 361 { "SAM" , L"Registry\\Machine\\SAM" , &SamHive , SystemSecurity , sizeof(SystemSecurity) }, 362 { "SECURITY", L"Registry\\Machine\\SECURITY" , &SecurityHive, NULL , 0 }, 363 { "BCD" , L"Registry\\Machine\\BCD00000000", &BcdHive , BcdSecurity , sizeof(BcdSecurity) }, 364 }; 365 C_ASSERT(_countof(RegistryHives) == MAX_NUMBER_OF_REGISTRY_HIVES); 366 367 /* FUNCTIONS ****************************************************************/ 368 369 static PMEMKEY 370 CreateInMemoryStructure( 371 IN PCMHIVE RegistryHive, 372 IN HCELL_INDEX KeyCellOffset) 373 { 374 PMEMKEY Key; 375 376 Key = (PMEMKEY)malloc(sizeof(MEMKEY)); 377 if (!Key) 378 return NULL; 379 380 Key->RegistryHive = RegistryHive; 381 Key->KeyCellOffset = KeyCellOffset; 382 return Key; 383 } 384 385 LIST_ENTRY CmiHiveListHead; 386 LIST_ENTRY CmiReparsePointsHead; 387 388 static LONG 389 RegpCreateOrOpenKey( 390 IN HKEY hParentKey, 391 IN PCWSTR KeyName, 392 IN BOOL AllowCreation, 393 IN BOOL Volatile, 394 OUT PHKEY Key) 395 { 396 NTSTATUS Status; 397 PWSTR LocalKeyName; 398 PWSTR End; 399 UNICODE_STRING KeyString; 400 PREPARSE_POINT CurrentReparsePoint; 401 PMEMKEY CurrentKey; 402 PCMHIVE ParentRegistryHive; 403 HCELL_INDEX ParentCellOffset; 404 PCM_KEY_NODE ParentKeyCell; 405 PLIST_ENTRY Ptr; 406 HCELL_INDEX BlockOffset; 407 408 DPRINT("RegpCreateOrOpenKey('%S')\n", KeyName); 409 410 if (*KeyName == OBJ_NAME_PATH_SEPARATOR) 411 { 412 KeyName++; 413 ParentRegistryHive = RootKey->RegistryHive; 414 ParentCellOffset = RootKey->KeyCellOffset; 415 } 416 else if (hParentKey == NULL) 417 { 418 ParentRegistryHive = RootKey->RegistryHive; 419 ParentCellOffset = RootKey->KeyCellOffset; 420 } 421 else 422 { 423 ParentRegistryHive = HKEY_TO_MEMKEY(hParentKey)->RegistryHive; 424 ParentCellOffset = HKEY_TO_MEMKEY(hParentKey)->KeyCellOffset; 425 } 426 427 LocalKeyName = (PWSTR)KeyName; 428 for (;;) 429 { 430 End = (PWSTR)strchrW(LocalKeyName, OBJ_NAME_PATH_SEPARATOR); 431 if (End) 432 { 433 KeyString.Buffer = LocalKeyName; 434 KeyString.Length = KeyString.MaximumLength = 435 (USHORT)((ULONG_PTR)End - (ULONG_PTR)LocalKeyName); 436 } 437 else 438 { 439 RtlInitUnicodeString(&KeyString, LocalKeyName); 440 if (KeyString.Length == 0) 441 { 442 /* Trailing path separator: we're done */ 443 break; 444 } 445 } 446 447 ParentKeyCell = (PCM_KEY_NODE)HvGetCell(&ParentRegistryHive->Hive, ParentCellOffset); 448 if (!ParentKeyCell) 449 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 450 451 VERIFY_KEY_CELL(ParentKeyCell); 452 453 BlockOffset = CmpFindSubKeyByName(&ParentRegistryHive->Hive, ParentKeyCell, &KeyString); 454 if (BlockOffset != HCELL_NIL) 455 { 456 Status = STATUS_SUCCESS; 457 458 /* Search for a possible reparse point */ 459 Ptr = CmiReparsePointsHead.Flink; 460 while (Ptr != &CmiReparsePointsHead) 461 { 462 CurrentReparsePoint = CONTAINING_RECORD(Ptr, REPARSE_POINT, ListEntry); 463 if (CurrentReparsePoint->SourceHive == ParentRegistryHive && 464 CurrentReparsePoint->SourceKeyCellOffset == BlockOffset) 465 { 466 ParentRegistryHive = CurrentReparsePoint->DestinationHive; 467 BlockOffset = CurrentReparsePoint->DestinationKeyCellOffset; 468 break; 469 } 470 Ptr = Ptr->Flink; 471 } 472 } 473 else if (AllowCreation) // && (BlockOffset == HCELL_NIL) 474 { 475 Status = CmiAddSubKey(ParentRegistryHive, 476 ParentCellOffset, 477 &KeyString, 478 Volatile, 479 &BlockOffset); 480 } 481 else // if (BlockOffset == HCELL_NIL) 482 { 483 Status = STATUS_OBJECT_NAME_NOT_FOUND; 484 } 485 486 HvReleaseCell(&ParentRegistryHive->Hive, ParentCellOffset); 487 488 if (!NT_SUCCESS(Status)) 489 { 490 DPRINT("RegpCreateOrOpenKey('%S'): Could not create or open subkey '%.*S', Status 0x%08x\n", 491 KeyName, (int)(KeyString.Length / sizeof(WCHAR)), KeyString.Buffer, Status); 492 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 493 } 494 495 ParentCellOffset = BlockOffset; 496 if (End) 497 LocalKeyName = End + 1; 498 else 499 break; 500 } 501 502 CurrentKey = CreateInMemoryStructure(ParentRegistryHive, ParentCellOffset); 503 if (!CurrentKey) 504 return ERROR_NOT_ENOUGH_MEMORY; // STATUS_NO_MEMORY; 505 506 *Key = MEMKEY_TO_HKEY(CurrentKey); 507 508 return ERROR_SUCCESS; 509 } 510 511 LONG WINAPI 512 RegCloseKey( 513 IN HKEY hKey) 514 { 515 PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey 516 517 /* Free the object */ 518 free(Key); 519 520 return ERROR_SUCCESS; 521 } 522 523 LONG WINAPI 524 RegCreateKeyW( 525 IN HKEY hKey, 526 IN LPCWSTR lpSubKey, 527 OUT PHKEY phkResult) 528 { 529 return RegpCreateOrOpenKey(hKey, lpSubKey, TRUE, FALSE, phkResult); 530 } 531 532 LONG WINAPI 533 RegCreateKeyExW( 534 IN HKEY hKey, 535 IN LPCWSTR lpSubKey, 536 IN DWORD Reserved, 537 IN LPWSTR lpClass OPTIONAL, 538 IN DWORD dwOptions, 539 IN REGSAM samDesired, 540 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL, 541 OUT PHKEY phkResult, 542 OUT LPDWORD lpdwDisposition OPTIONAL) 543 { 544 return RegpCreateOrOpenKey(hKey, 545 lpSubKey, 546 TRUE, 547 (dwOptions & REG_OPTION_VOLATILE) != 0, 548 phkResult); 549 } 550 551 LONG WINAPI 552 RegDeleteKeyW( 553 IN HKEY hKey, 554 IN LPCWSTR lpSubKey) 555 { 556 LONG rc; 557 NTSTATUS Status; 558 HKEY hTargetKey; 559 PMEMKEY Key; // ParentKey 560 PHHIVE Hive; 561 PCM_KEY_NODE KeyNode; // ParentNode 562 PCM_KEY_NODE Parent; 563 HCELL_INDEX ParentCell; 564 565 if (lpSubKey) 566 { 567 rc = RegOpenKeyW(hKey, lpSubKey, &hTargetKey); 568 if (rc != ERROR_SUCCESS) 569 return rc; 570 } 571 else 572 { 573 hTargetKey = hKey; 574 rc = ERROR_SUCCESS; 575 } 576 577 /* Don't allow deleting the root */ 578 if (hTargetKey == RootKey) 579 { 580 /* Fail */ 581 rc = ERROR_ACCESS_DENIED; // STATUS_CANNOT_DELETE; 582 goto Quit; 583 } 584 585 /* Get the hive and node */ 586 Key = HKEY_TO_MEMKEY(hTargetKey); 587 Hive = &Key->RegistryHive->Hive; 588 589 /* Get the key node */ 590 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Key->KeyCellOffset); 591 if (!KeyNode) 592 { 593 rc = ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 594 goto Quit; 595 } 596 597 ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); 598 599 /* Check if we don't have any children */ 600 if (!(KeyNode->SubKeyCounts[Stable] + KeyNode->SubKeyCounts[Volatile]) && 601 !(KeyNode->Flags & KEY_NO_DELETE)) 602 { 603 /* Get the parent and free the cell */ 604 ParentCell = KeyNode->Parent; 605 Status = CmpFreeKeyByCell(Hive, Key->KeyCellOffset, TRUE); 606 if (NT_SUCCESS(Status)) 607 { 608 /* Get the parent node */ 609 Parent = (PCM_KEY_NODE)HvGetCell(Hive, ParentCell); 610 if (Parent) 611 { 612 /* Make sure we're dirty */ 613 ASSERT(HvIsCellDirty(Hive, ParentCell)); 614 615 /* Update the write time */ 616 KeQuerySystemTime(&Parent->LastWriteTime); 617 618 /* Release the cell */ 619 HvReleaseCell(Hive, ParentCell); 620 } 621 622 rc = ERROR_SUCCESS; 623 } 624 else 625 { 626 /* Fail */ 627 rc = ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 628 } 629 } 630 else 631 { 632 /* Fail */ 633 rc = ERROR_ACCESS_DENIED; // STATUS_CANNOT_DELETE; 634 } 635 636 /* Release the cell */ 637 HvReleaseCell(Hive, Key->KeyCellOffset); 638 639 Quit: 640 if (lpSubKey) 641 RegCloseKey(hTargetKey); 642 643 return rc; 644 } 645 646 LONG WINAPI 647 RegOpenKeyW( 648 IN HKEY hKey, 649 IN LPCWSTR lpSubKey, 650 OUT PHKEY phkResult) 651 { 652 return RegpCreateOrOpenKey(hKey, lpSubKey, FALSE, FALSE, phkResult); 653 } 654 655 LONG WINAPI 656 RegSetValueExW( 657 IN HKEY hKey, 658 IN LPCWSTR lpValueName OPTIONAL, 659 IN ULONG Reserved, 660 IN ULONG dwType, 661 IN const UCHAR* lpData, 662 IN ULONG cbData) 663 { 664 PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey 665 PHHIVE Hive; 666 PCM_KEY_NODE KeyNode; // ParentNode 667 PCM_KEY_VALUE ValueCell; 668 ULONG ChildIndex; 669 HCELL_INDEX CellIndex; 670 UNICODE_STRING ValueNameString; 671 672 PVOID DataCell; 673 ULONG DataCellSize; 674 NTSTATUS Status; 675 676 if (dwType == REG_LINK) 677 { 678 PMEMKEY DestKey; 679 680 /* Special handling of registry links */ 681 if (cbData != sizeof(PVOID)) 682 return ERROR_INVALID_PARAMETER; // STATUS_INVALID_PARAMETER; 683 684 DestKey = HKEY_TO_MEMKEY(*(PHKEY)lpData); 685 686 // FIXME: Add additional checks for the validity of DestKey 687 688 /* Create the link in registry hive (if applicable) */ 689 if (Key->RegistryHive != DestKey->RegistryHive) 690 return ERROR_SUCCESS; 691 692 DPRINT1("Save link to registry\n"); 693 return ERROR_INVALID_FUNCTION; // STATUS_NOT_IMPLEMENTED; 694 } 695 696 if ((cbData & ~CM_KEY_VALUE_SPECIAL_SIZE) != cbData) 697 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 698 699 Hive = &Key->RegistryHive->Hive; 700 701 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Key->KeyCellOffset); 702 if (!KeyNode) 703 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 704 705 ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); 706 707 /* Mark the parent as dirty since we are going to create a new value in it */ 708 HvMarkCellDirty(Hive, Key->KeyCellOffset, FALSE); 709 710 /* Initialize value name string */ 711 RtlInitUnicodeString(&ValueNameString, lpValueName); 712 if (!CmpFindNameInList(Hive, 713 &KeyNode->ValueList, 714 &ValueNameString, 715 &ChildIndex, 716 &CellIndex)) 717 { 718 /* Sanity check */ 719 ASSERT(CellIndex == HCELL_NIL); 720 /* Fail */ 721 Status = STATUS_INSUFFICIENT_RESOURCES; 722 } 723 if (CellIndex == HCELL_NIL) 724 { 725 /* The value doesn't exist, create a new one */ 726 Status = CmiAddValueKey(Key->RegistryHive, 727 KeyNode, 728 ChildIndex, 729 &ValueNameString, 730 &ValueCell, 731 &CellIndex); 732 } 733 else 734 { 735 /* The value already exists, use it. Get the value cell. */ 736 ValueCell = HvGetCell(&Key->RegistryHive->Hive, CellIndex); 737 ASSERT(ValueCell != NULL); 738 Status = STATUS_SUCCESS; 739 } 740 741 // /**/HvReleaseCell(Hive, CellIndex);/**/ 742 743 if (!NT_SUCCESS(Status)) 744 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 745 746 /* Get size of the allocated cell (if any) */ 747 if (!(ValueCell->DataLength & CM_KEY_VALUE_SPECIAL_SIZE) && 748 (ValueCell->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE) != 0) 749 { 750 DataCell = HvGetCell(Hive, ValueCell->Data); 751 if (!DataCell) 752 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 753 754 DataCellSize = (ULONG)(-HvGetCellSize(Hive, DataCell)); 755 } 756 else 757 { 758 DataCell = NULL; 759 DataCellSize = 0; 760 } 761 762 if (cbData <= sizeof(HCELL_INDEX)) 763 { 764 /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */ 765 DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength); 766 if (DataCell) 767 HvFreeCell(Hive, ValueCell->Data); 768 769 RtlCopyMemory(&ValueCell->Data, lpData, cbData); 770 ValueCell->DataLength = (cbData | CM_KEY_VALUE_SPECIAL_SIZE); 771 ValueCell->Type = dwType; 772 } 773 else 774 { 775 if (cbData > DataCellSize) 776 { 777 /* New data size is larger than the current, destroy current 778 * data block and allocate a new one. */ 779 HCELL_INDEX NewOffset; 780 781 DPRINT("ValueCell->DataLength %u\n", ValueCell->DataLength); 782 783 NewOffset = HvAllocateCell(Hive, cbData, Stable, HCELL_NIL); 784 if (NewOffset == HCELL_NIL) 785 { 786 DPRINT("HvAllocateCell() has failed!\n"); 787 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 788 } 789 790 if (DataCell) 791 HvFreeCell(Hive, ValueCell->Data); 792 793 ValueCell->Data = NewOffset; 794 DataCell = (PVOID)HvGetCell(Hive, NewOffset); 795 } 796 797 /* Copy new contents to cell */ 798 RtlCopyMemory(DataCell, lpData, cbData); 799 ValueCell->DataLength = (cbData & ~CM_KEY_VALUE_SPECIAL_SIZE); 800 ValueCell->Type = dwType; 801 HvMarkCellDirty(Hive, ValueCell->Data, FALSE); 802 } 803 804 HvMarkCellDirty(Hive, CellIndex, FALSE); 805 806 /* Check if the maximum value name length changed, update it if so */ 807 if (KeyNode->MaxValueNameLen < ValueNameString.Length) 808 KeyNode->MaxValueNameLen = ValueNameString.Length; 809 810 /* Check if the maximum data length changed, update it if so */ 811 if (KeyNode->MaxValueDataLen < cbData) 812 KeyNode->MaxValueDataLen = cbData; 813 814 /* Save the write time */ 815 KeQuerySystemTime(&KeyNode->LastWriteTime); 816 817 return ERROR_SUCCESS; 818 } 819 820 821 // Synced with freeldr/ntldr/registry.c 822 static 823 VOID 824 RepGetValueData( 825 IN PHHIVE Hive, 826 IN PCM_KEY_VALUE ValueCell, 827 OUT PULONG Type OPTIONAL, 828 OUT PUCHAR Data OPTIONAL, 829 IN OUT PULONG DataSize OPTIONAL) 830 { 831 ULONG DataLength; 832 PVOID DataCell; 833 834 /* Does the caller want the type? */ 835 if (Type != NULL) 836 *Type = ValueCell->Type; 837 838 /* Does the caller provide DataSize? */ 839 if (DataSize != NULL) 840 { 841 // NOTE: CmpValueToData doesn't support big data (the function will 842 // bugcheck if so), FreeLdr is not supposed to read such data. 843 // If big data is needed, use instead CmpGetValueData. 844 // CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...); 845 DataCell = CmpValueToData(Hive, ValueCell, &DataLength); 846 847 /* Does the caller want the data? */ 848 if ((Data != NULL) && (*DataSize != 0)) 849 { 850 RtlCopyMemory(Data, 851 DataCell, 852 min(*DataSize, DataLength)); 853 } 854 855 /* Return the actual data length */ 856 *DataSize = DataLength; 857 } 858 } 859 860 // Similar to RegQueryValue in freeldr/ntldr/registry.c 861 LONG WINAPI 862 RegQueryValueExW( 863 IN HKEY hKey, 864 IN LPCWSTR lpValueName, 865 IN PULONG lpReserved, 866 OUT PULONG lpType OPTIONAL, 867 OUT PUCHAR lpData OPTIONAL, 868 IN OUT PULONG lpcbData OPTIONAL) 869 { 870 PMEMKEY ParentKey = HKEY_TO_MEMKEY(hKey); 871 PHHIVE Hive = &ParentKey->RegistryHive->Hive; 872 PCM_KEY_NODE KeyNode; 873 PCM_KEY_VALUE ValueCell; 874 HCELL_INDEX CellIndex; 875 UNICODE_STRING ValueNameString; 876 877 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, ParentKey->KeyCellOffset); 878 if (!KeyNode) 879 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 880 881 ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); 882 883 /* Initialize value name string */ 884 RtlInitUnicodeString(&ValueNameString, lpValueName); 885 CellIndex = CmpFindValueByName(Hive, KeyNode, &ValueNameString); 886 if (CellIndex == HCELL_NIL) 887 return ERROR_FILE_NOT_FOUND; // STATUS_OBJECT_NAME_NOT_FOUND; 888 889 /* Get the value cell */ 890 ValueCell = HvGetCell(Hive, CellIndex); 891 ASSERT(ValueCell != NULL); 892 893 RepGetValueData(Hive, ValueCell, lpType, lpData, lpcbData); 894 895 HvReleaseCell(Hive, CellIndex); 896 897 return ERROR_SUCCESS; 898 } 899 900 LONG WINAPI 901 RegDeleteValueW( 902 IN HKEY hKey, 903 IN LPCWSTR lpValueName OPTIONAL) 904 { 905 LONG rc; 906 NTSTATUS Status; 907 PMEMKEY Key = HKEY_TO_MEMKEY(hKey); // ParentKey 908 PHHIVE Hive = &Key->RegistryHive->Hive; 909 PCM_KEY_NODE KeyNode; // ParentNode 910 PCM_KEY_VALUE ValueCell; 911 HCELL_INDEX CellIndex; 912 ULONG ChildIndex; 913 UNICODE_STRING ValueNameString; 914 915 KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Key->KeyCellOffset); 916 if (!KeyNode) 917 return ERROR_GEN_FAILURE; // STATUS_UNSUCCESSFUL; 918 919 ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE); 920 921 /* Initialize value name string */ 922 RtlInitUnicodeString(&ValueNameString, lpValueName); 923 if (!CmpFindNameInList(Hive, 924 &KeyNode->ValueList, 925 &ValueNameString, 926 &ChildIndex, 927 &CellIndex)) 928 { 929 /* Sanity check */ 930 ASSERT(CellIndex == HCELL_NIL); 931 } 932 if (CellIndex == HCELL_NIL) 933 { 934 rc = ERROR_FILE_NOT_FOUND; // STATUS_OBJECT_NAME_NOT_FOUND; 935 goto Quit; 936 } 937 938 /* We found the value, mark all relevant cells dirty */ 939 HvMarkCellDirty(Hive, Key->KeyCellOffset, FALSE); 940 HvMarkCellDirty(Hive, KeyNode->ValueList.List, FALSE); 941 HvMarkCellDirty(Hive, CellIndex, FALSE); 942 943 /* Get the key value */ 944 ValueCell = (PCM_KEY_VALUE)HvGetCell(Hive, CellIndex); 945 ASSERT(ValueCell); 946 947 /* Mark it and all related data as dirty */ 948 if (!CmpMarkValueDataDirty(Hive, ValueCell)) 949 { 950 /* Not enough log space, fail */ 951 rc = ERROR_NO_LOG_SPACE; // STATUS_NO_LOG_SPACE; 952 goto Quit; 953 } 954 955 /* Sanity checks */ 956 ASSERT(HvIsCellDirty(Hive, KeyNode->ValueList.List)); 957 ASSERT(HvIsCellDirty(Hive, CellIndex)); 958 959 /* Remove the value from the child list */ 960 Status = CmpRemoveValueFromList(Hive, ChildIndex, &KeyNode->ValueList); 961 if (!NT_SUCCESS(Status)) 962 { 963 /* Set known error */ 964 rc = ERROR_NO_SYSTEM_RESOURCES; // STATUS_INSUFFICIENT_RESOURCES; 965 goto Quit; 966 } 967 968 /* Remove the value and its data itself */ 969 if (!CmpFreeValue(Hive, CellIndex)) 970 { 971 /* Failed to free the value, fail */ 972 rc = ERROR_NO_SYSTEM_RESOURCES; // STATUS_INSUFFICIENT_RESOURCES; 973 goto Quit; 974 } 975 976 /* Set the last write time */ 977 KeQuerySystemTime(&KeyNode->LastWriteTime); 978 979 /* Sanity check */ 980 ASSERT(HvIsCellDirty(Hive, Key->KeyCellOffset)); 981 982 /* Check if the value list is empty now */ 983 if (!KeyNode->ValueList.Count) 984 { 985 /* Then clear key node data */ 986 KeyNode->MaxValueNameLen = 0; 987 KeyNode->MaxValueDataLen = 0; 988 } 989 990 /* Change default Status to success */ 991 rc = ERROR_SUCCESS; 992 993 Quit: 994 /* Check if we had a value */ 995 if (ValueCell) 996 { 997 /* Release the child cell */ 998 ASSERT(CellIndex != HCELL_NIL); 999 HvReleaseCell(Hive, CellIndex); 1000 } 1001 1002 /* Release the parent cell, if any */ 1003 if (KeyNode) 1004 HvReleaseCell(Hive, Key->KeyCellOffset); 1005 1006 return rc; 1007 } 1008 1009 1010 static BOOL 1011 ConnectRegistry( 1012 IN HKEY RootKey, 1013 IN PCWSTR Path, 1014 IN PCMHIVE HiveToConnect, 1015 IN PUCHAR SecurityDescriptor, 1016 IN ULONG SecurityDescriptorLength) 1017 { 1018 NTSTATUS Status; 1019 LONG rc; 1020 PREPARSE_POINT ReparsePoint; 1021 PMEMKEY NewKey; 1022 1023 ReparsePoint = (PREPARSE_POINT)malloc(sizeof(*ReparsePoint)); 1024 if (!ReparsePoint) 1025 return FALSE; 1026 1027 /* 1028 * Use a dummy root key name: 1029 * - On 2k/XP/2k3, this is "$$$PROTO.HIV" 1030 * - On Vista+, this is "CMI-CreateHive{guid}" 1031 * See https://github.com/libyal/winreg-kb/blob/master/documentation/Registry%20files.asciidoc 1032 * for more information. 1033 */ 1034 Status = CmiInitializeHive(HiveToConnect, L"$$$PROTO.HIV"); 1035 if (!NT_SUCCESS(Status)) 1036 { 1037 DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status); 1038 free(ReparsePoint); 1039 return FALSE; 1040 } 1041 1042 /* 1043 * Add security to the root key. 1044 * NOTE: One can implement this using the lpSecurityAttributes 1045 * parameter of RegCreateKeyExW. 1046 */ 1047 Status = CmiCreateSecurityKey(&HiveToConnect->Hive, 1048 HiveToConnect->Hive.BaseBlock->RootCell, 1049 SecurityDescriptor, SecurityDescriptorLength); 1050 if (!NT_SUCCESS(Status)) 1051 DPRINT1("Failed to add security for root key '%S'\n", Path); 1052 1053 /* Create the key */ 1054 rc = RegCreateKeyExW(RootKey, 1055 Path, 1056 0, 1057 NULL, 1058 REG_OPTION_VOLATILE, 1059 0, 1060 NULL, 1061 (PHKEY)&NewKey, 1062 NULL); 1063 if (rc != ERROR_SUCCESS) 1064 { 1065 free(ReparsePoint); 1066 return FALSE; 1067 } 1068 1069 ReparsePoint->SourceHive = NewKey->RegistryHive; 1070 ReparsePoint->SourceKeyCellOffset = NewKey->KeyCellOffset; 1071 NewKey->RegistryHive = HiveToConnect; 1072 NewKey->KeyCellOffset = HiveToConnect->Hive.BaseBlock->RootCell; 1073 ReparsePoint->DestinationHive = NewKey->RegistryHive; 1074 ReparsePoint->DestinationKeyCellOffset = NewKey->KeyCellOffset; 1075 InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry); 1076 1077 return TRUE; 1078 } 1079 1080 static BOOL 1081 CreateSymLink( 1082 IN PCWSTR LinkKeyPath OPTIONAL, 1083 IN OUT PHKEY LinkKeyHandle OPTIONAL, 1084 // IN PCWSTR TargetKeyPath OPTIONAL, 1085 IN HKEY TargetKeyHandle) 1086 { 1087 LONG rc; 1088 PMEMKEY LinkKey, TargetKey; 1089 PREPARSE_POINT ReparsePoint; 1090 1091 ReparsePoint = (PREPARSE_POINT)malloc(sizeof(*ReparsePoint)); 1092 if (!ReparsePoint) 1093 return FALSE; 1094 1095 if (LinkKeyPath && !(LinkKeyHandle && *LinkKeyHandle)) 1096 { 1097 /* Create the link key */ 1098 rc = RegCreateKeyExW(NULL, 1099 LinkKeyPath, 1100 0, 1101 NULL, 1102 REG_OPTION_VOLATILE, 1103 0, 1104 NULL, 1105 (PHKEY)&LinkKey, 1106 NULL); 1107 if (rc != ERROR_SUCCESS) 1108 { 1109 free(ReparsePoint); 1110 return FALSE; 1111 } 1112 } 1113 else if (LinkKeyHandle) 1114 { 1115 /* Use the user-provided link key handle */ 1116 LinkKey = HKEY_TO_MEMKEY(*LinkKeyHandle); 1117 } 1118 1119 if (LinkKeyHandle) 1120 *LinkKeyHandle = MEMKEY_TO_HKEY(LinkKey); 1121 1122 TargetKey = HKEY_TO_MEMKEY(TargetKeyHandle); 1123 1124 ReparsePoint->SourceHive = LinkKey->RegistryHive; 1125 ReparsePoint->SourceKeyCellOffset = LinkKey->KeyCellOffset; 1126 ReparsePoint->DestinationHive = TargetKey->RegistryHive; 1127 ReparsePoint->DestinationKeyCellOffset = TargetKey->KeyCellOffset; 1128 InsertTailList(&CmiReparsePointsHead, &ReparsePoint->ListEntry); 1129 1130 return TRUE; 1131 } 1132 1133 VOID 1134 RegInitializeRegistry( 1135 IN PCSTR HiveList) 1136 { 1137 NTSTATUS Status; 1138 UINT i; 1139 HKEY ControlSetKey; 1140 1141 InitializeListHead(&CmiHiveListHead); 1142 InitializeListHead(&CmiReparsePointsHead); 1143 1144 Status = CmiInitializeHive(&RootHive, L""); 1145 if (!NT_SUCCESS(Status)) 1146 { 1147 DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status); 1148 return; 1149 } 1150 1151 RootKey = CreateInMemoryStructure(&RootHive, 1152 RootHive.Hive.BaseBlock->RootCell); 1153 1154 for (i = 0; i < _countof(RegistryHives); ++i) 1155 { 1156 /* Skip this registry hive if it's not in the list */ 1157 if (!strstr(HiveList, RegistryHives[i].HiveName)) 1158 continue; 1159 1160 /* Create the registry key */ 1161 ConnectRegistry(NULL, 1162 RegistryHives[i].HiveRegistryPath, 1163 RegistryHives[i].CmHive, 1164 RegistryHives[i].SecurityDescriptor, 1165 RegistryHives[i].SecurityDescriptorLength); 1166 1167 /* If we happen to deal with the special setup registry hive, stop there */ 1168 // if (strcmp(RegistryHives[i].HiveName, "SETUPREG") == 0) 1169 if (i == 0) 1170 break; 1171 } 1172 1173 /* Create the 'ControlSet001' key */ 1174 RegCreateKeyW(NULL, 1175 L"Registry\\Machine\\SYSTEM\\ControlSet001", 1176 &ControlSetKey); 1177 1178 /* Create the 'CurrentControlSet' key as a symlink to 'ControlSet001' */ 1179 CreateSymLink(L"Registry\\Machine\\SYSTEM\\CurrentControlSet", 1180 NULL, ControlSetKey); 1181 1182 RegCloseKey(ControlSetKey); 1183 1184 #if 0 1185 /* Link SECURITY to SAM */ 1186 CmpLinkKeyToHive(L"\\Registry\\Machine\\Security\\SAM", L"\\Registry\\Machine\\SAM\\SAM"); 1187 /* Link S-1-5-18 to .Default */ 1188 CmpLinkKeyToHive(L"\\Registry\\User\\S-1-5-18", L"\\Registry\\User\\.Default"); 1189 #endif 1190 } 1191 1192 VOID 1193 RegShutdownRegistry(VOID) 1194 { 1195 PLIST_ENTRY Entry; 1196 PREPARSE_POINT ReparsePoint; 1197 1198 /* Clean up the reparse points list */ 1199 while (!IsListEmpty(&CmiReparsePointsHead)) 1200 { 1201 Entry = RemoveHeadList(&CmiReparsePointsHead); 1202 ReparsePoint = CONTAINING_RECORD(Entry, REPARSE_POINT, ListEntry); 1203 free(ReparsePoint); 1204 } 1205 1206 /* FIXME: clean up the complete hive */ 1207 1208 free(RootKey); 1209 } 1210 1211 /* EOF */ 1212