3 * Copyright (C) 2003 ReactOS Team
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 * PROGRAMMER: Eric Kohl
29 * - Implement RegDeleteKey().
30 * - Fix RegEnumValue().
44 RegInitializeRegistry(VOID)
50 RootKey = (HKEY)malloc(sizeof(KEY));
52 InitializeListHead(&RootKey->SubKeyList);
53 InitializeListHead(&RootKey->ValueList);
54 InitializeListHead(&RootKey->KeyList);
56 RootKey->SubKeyCount = 0;
57 RootKey->ValueCount = 0;
59 RootKey->NameSize = 2;
60 RootKey->Name = (PUCHAR)malloc(2);
61 strcpy(RootKey->Name, "\\");
63 RootKey->DataType = 0;
64 RootKey->DataSize = 0;
67 /* Create SYSTEM key */
69 "Registry\\Machine\\SYSTEM",
72 /* Create link 'CurrentControlSet' --> 'ControlSet001' */
74 "Registry\\Machine\\SYSTEM\\ControlSet001",
78 "Registry\\Machine\\SYSTEM\\CurrentControlSet",
84 (PUCHAR)&ControlSetKey,
87 /* Create HARDWARE key */
89 "Registry\\Machine\\HARDWARE",
94 "Registry\\Machine\\SAM",
97 /* Create SECURITY key */
99 "Registry\\Machine\\SECURITY",
102 /* Create DEFAULT key */
103 RegCreateKey(RootKey,
104 "Registry\\User\\.DEFAULT",
110 RegCreateKey(HKEY ParentKey,
115 HKEY SearchKey = INVALID_HANDLE_VALUE;
123 DPRINT ("KeyName '%s'\n", KeyName);
125 if (*KeyName == '\\')
128 CurrentKey = RootKey;
130 else if (ParentKey == NULL)
132 CurrentKey = RootKey;
136 CurrentKey = ParentKey;
139 /* Check whether current key is a link */
140 if (CurrentKey->DataType == REG_LINK)
142 CurrentKey = (HKEY)CurrentKey->Data;
145 while (*KeyName != 0)
147 DPRINT ("KeyName '%s'\n", KeyName);
149 if (*KeyName == '\\')
151 p = strchr (KeyName, '\\');
152 if ((p != NULL) && (p != KeyName))
154 subkeyLength = p - KeyName;
155 stringLength = subkeyLength + 1;
160 subkeyLength = strlen (KeyName);
161 stringLength = subkeyLength;
165 Ptr = CurrentKey->SubKeyList.Flink;
166 while (Ptr != &CurrentKey->SubKeyList)
168 DPRINT ("Ptr 0x%x\n", Ptr);
170 SearchKey = CONTAINING_RECORD(Ptr,
173 DPRINT ("SearchKey 0x%x\n", SearchKey);
174 DPRINT ("Searching '%s'\n", SearchKey->Name);
175 if (strncmp (SearchKey->Name, name, subkeyLength) == 0)
181 if (Ptr == &CurrentKey->SubKeyList)
183 /* no key found -> create new subkey */
184 NewKey = (HKEY)malloc (sizeof(KEY));
186 return ERROR_OUTOFMEMORY;
188 InitializeListHead (&NewKey->SubKeyList);
189 InitializeListHead (&NewKey->ValueList);
191 NewKey->SubKeyCount = 0;
192 NewKey->ValueCount = 0;
194 NewKey->DataType = 0;
195 NewKey->DataSize = 0;
198 InsertTailList (&CurrentKey->SubKeyList, &NewKey->KeyList);
199 CurrentKey->SubKeyCount++;
201 NewKey->NameSize = subkeyLength + 1;
202 NewKey->Name = (PCHAR)malloc (NewKey->NameSize);
203 if (NewKey->Name == NULL)
204 return(ERROR_OUTOFMEMORY);
205 memcpy(NewKey->Name, name, subkeyLength);
206 NewKey->Name[subkeyLength] = 0;
208 DPRINT ("NewKey 0x%x\n", NewKey);
209 DPRINT ("NewKey '%s' Length %d\n", NewKey->Name, NewKey->NameSize);
215 CurrentKey = SearchKey;
217 /* Check whether current key is a link */
218 if (CurrentKey->DataType == REG_LINK)
220 CurrentKey = (HKEY)CurrentKey->Data;
224 KeyName = KeyName + stringLength;
230 return ERROR_SUCCESS;
235 RegDeleteKey(HKEY Key,
239 if (strchr(Name, '\\') != NULL)
240 return(ERROR_INVALID_PARAMETER);
244 return(ERROR_SUCCESS);
259 Ptr = Key->SubKeyList.Flink;
260 while (Ptr != &Key->SubKeyList)
269 if (Ptr == &Key->SubKeyList)
270 return(ERROR_NO_MORE_ITEMS);
272 SearchKey = CONTAINING_RECORD(Ptr,
276 DPRINT ("Name '%s' Length %d\n", SearchKey->Name, SearchKey->NameSize);
278 Size = min(SearchKey->NameSize, *NameSize);
280 memcpy(Name, SearchKey->Name, Size);
282 return(ERROR_SUCCESS);
287 RegOpenKey(HKEY ParentKey,
292 HKEY SearchKey = INVALID_HANDLE_VALUE;
299 DPRINT("KeyName '%s'\n", KeyName);
303 if (*KeyName == '\\')
306 CurrentKey = RootKey;
308 else if (ParentKey == NULL)
310 CurrentKey = RootKey;
314 CurrentKey = ParentKey;
317 /* Check whether current key is a link */
318 if (CurrentKey->DataType == REG_LINK)
320 CurrentKey = (HKEY)CurrentKey->Data;
323 while (*KeyName != 0)
325 DPRINT ("KeyName '%s'\n", KeyName);
327 if (*KeyName == '\\')
329 p = strchr(KeyName, '\\');
330 if ((p != NULL) && (p != KeyName))
332 subkeyLength = p - KeyName;
333 stringLength = subkeyLength + 1;
338 subkeyLength = strlen(KeyName);
339 stringLength = subkeyLength;
343 Ptr = CurrentKey->SubKeyList.Flink;
344 while (Ptr != &CurrentKey->SubKeyList)
346 DPRINT ("Ptr 0x%x\n", Ptr);
348 SearchKey = CONTAINING_RECORD(Ptr,
352 DPRINT ("SearchKey 0x%x\n", SearchKey);
353 DPRINT ("Searching '%s'\n", SearchKey->Name);
355 if (strncmp(SearchKey->Name, name, subkeyLength) == 0)
361 if (Ptr == &CurrentKey->SubKeyList)
363 return(ERROR_PATH_NOT_FOUND);
367 CurrentKey = SearchKey;
369 /* Check whether current key is a link */
370 if (CurrentKey->DataType == REG_LINK)
372 CurrentKey = (HKEY)CurrentKey->Data;
376 KeyName = KeyName + stringLength;
382 return(ERROR_SUCCESS);
387 RegSetValue(HKEY Key,
396 DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
397 (int)Key, ValueName, (int)Type, (int)Data, (int)DataSize);
399 if ((ValueName == NULL) || (*ValueName == 0))
401 /* set default value */
402 if ((Key->Data != NULL) && (Key->DataSize > sizeof(PUCHAR)))
407 if (DataSize <= sizeof(PUCHAR))
409 Key->DataSize = DataSize;
410 Key->DataType = Type;
411 memcpy(&Key->Data, Data, DataSize);
415 Key->Data = (PUCHAR)malloc(DataSize);
416 Key->DataSize = DataSize;
417 Key->DataType = Type;
418 memcpy(Key->Data, Data, DataSize);
423 /* set non-default value */
424 Ptr = Key->ValueList.Flink;
425 while (Ptr != &Key->ValueList)
427 Value = CONTAINING_RECORD(Ptr,
431 DPRINT ("Value->Name '%s'\n", Value->Name);
433 if (strcasecmp(Value->Name, ValueName) == 0)
439 if (Ptr == &Key->ValueList)
442 DPRINT("No value found - adding new value\n");
444 Value = (PVALUE)malloc(sizeof(VALUE));
446 return(ERROR_OUTOFMEMORY);
447 InsertTailList(&Key->ValueList, &Value->ValueList);
449 Value->NameSize = strlen(ValueName)+1;
450 Value->Name = (PCHAR)malloc(Value->NameSize);
451 if (Value->Name == NULL)
452 return(ERROR_OUTOFMEMORY);
453 strcpy(Value->Name, ValueName);
454 Value->DataType = REG_NONE;
460 if ((Value->Data != NULL) && (Value->DataSize > sizeof(PUCHAR)))
465 if (DataSize <= sizeof(PUCHAR))
467 Value->DataSize = DataSize;
468 Value->DataType = Type;
469 memcpy(&Value->Data, Data, DataSize);
473 Value->Data = (PUCHAR)malloc(DataSize);
474 if (Value->Data == NULL)
475 return(ERROR_OUTOFMEMORY);
476 Value->DataType = Type;
477 Value->DataSize = DataSize;
478 memcpy(Value->Data, Data, DataSize);
481 return(ERROR_SUCCESS);
486 RegQueryValue(HKEY Key,
496 if ((ValueName == NULL) || (*ValueName == 0))
498 /* query default value */
499 if (Key->Data == NULL)
500 return(ERROR_INVALID_PARAMETER);
503 *Type = Key->DataType;
504 if ((Data != NULL) && (DataSize != NULL))
506 if (Key->DataSize <= sizeof(PUCHAR))
508 Size = min(Key->DataSize, *DataSize);
509 memcpy(Data, &Key->Data, Size);
514 Size = min(Key->DataSize, *DataSize);
515 memcpy(Data, Key->Data, Size);
519 else if ((Data == NULL) && (DataSize != NULL))
521 *DataSize = Key->DataSize;
526 /* query non-default value */
527 Ptr = Key->ValueList.Flink;
528 while (Ptr != &Key->ValueList)
530 Value = CONTAINING_RECORD(Ptr,
534 DPRINT("Searching for '%s'. Value name '%s'\n", ValueName, Value->Name);
536 if (strcasecmp(Value->Name, ValueName) == 0)
542 if (Ptr == &Key->ValueList)
543 return(ERROR_INVALID_PARAMETER);
546 *Type = Value->DataType;
547 if ((Data != NULL) && (DataSize != NULL))
549 if (Value->DataSize <= sizeof(PUCHAR))
551 Size = min(Value->DataSize, *DataSize);
552 memcpy(Data, &Value->Data, Size);
557 Size = min(Value->DataSize, *DataSize);
558 memcpy(Data, Value->Data, Size);
562 else if ((Data == NULL) && (DataSize != NULL))
564 *DataSize = Value->DataSize;
568 return(ERROR_SUCCESS);
573 RegDeleteValue(HKEY Key,
579 if ((ValueName == NULL) || (*ValueName == 0))
581 /* delete default value */
582 if (Key->Data != NULL)
590 /* delete non-default value */
591 Ptr = Key->ValueList.Flink;
592 while (Ptr != &Key->ValueList)
594 Value = CONTAINING_RECORD(Ptr,
597 if (strcmp(Value->Name, ValueName) == 0)
603 if (Ptr == &Key->ValueList)
604 return(ERROR_INVALID_PARAMETER);
608 if (Value->Name != NULL)
613 if (Value->DataSize > sizeof(PUCHAR))
615 if (Value->Data != NULL)
622 RemoveEntryList(&Value->ValueList);
625 return(ERROR_SUCCESS);
630 RegEnumValue(HKEY Key,
642 if (Key->Data != NULL)
650 /* enumerate default value */
651 if (ValueName != NULL)
654 *Type = Key->DataType;
655 if (DataSize != NULL)
656 *DataSize = Key->DataSize;
658 /* FIXME: return more values */
662 Ptr = Key->ValueList.Flink;
663 while (Ptr != &Key->ValueList)
672 if (Ptr == &Key->ValueList)
673 return(ERROR_NO_MORE_ITEMS);
675 Value = CONTAINING_RECORD(Ptr,
679 /* FIXME: return values */
681 return(ERROR_SUCCESS);
686 RegGetSubKeyCount (HKEY Key)
688 return Key->SubKeyCount;
693 RegGetValueCount (HKEY Key)
695 if (Key->DataSize != 0)
696 return Key->ValueCount + 1;
698 return Key->ValueCount;