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 * - Implement RegQueryMultipleValue().
31 * - Fix RegEnumValue().
45 RegInitializeRegistry(VOID)
51 RootKey = (HKEY)malloc(sizeof(KEY));
53 InitializeListHead(&RootKey->SubKeyList);
54 InitializeListHead(&RootKey->ValueList);
55 InitializeListHead(&RootKey->KeyList);
57 RootKey->SubKeyCount = 0;
58 RootKey->ValueCount = 0;
60 RootKey->NameSize = 2;
61 RootKey->Name = (PUCHAR)malloc(2);
62 strcpy(RootKey->Name, "\\");
64 RootKey->DataType = 0;
65 RootKey->DataSize = 0;
68 /* Create SYSTEM key */
70 "Registry\\Machine\\SYSTEM",
73 /* Create link 'CurrentControlSet' --> 'ControlSet001' */
75 "Registry\\Machine\\SYSTEM\\ControlSet001",
79 "Registry\\Machine\\SYSTEM\\CurrentControlSet",
85 (PUCHAR)&ControlSetKey,
88 /* Create HARDWARE key */
90 "Registry\\Machine\\HARDWARE",
95 "Registry\\Machine\\SAM",
98 /* Create SECURITY key */
100 "Registry\\Machine\\SECURITY",
103 /* Create DEFAULT key */
104 RegCreateKey(RootKey,
105 "Registry\\User\\.DEFAULT",
111 RegCreateKey(HKEY ParentKey,
116 HKEY SearchKey = INVALID_HANDLE_VALUE;
124 DPRINT ("KeyName '%s'\n", KeyName);
126 if (*KeyName == '\\')
129 CurrentKey = RootKey;
131 else if (ParentKey == NULL)
133 CurrentKey = RootKey;
137 CurrentKey = ParentKey;
140 /* Check whether current key is a link */
141 if (CurrentKey->DataType == REG_LINK)
143 CurrentKey = (HKEY)CurrentKey->Data;
146 while (*KeyName != 0)
148 DPRINT ("KeyName '%s'\n", KeyName);
150 if (*KeyName == '\\')
152 p = strchr (KeyName, '\\');
153 if ((p != NULL) && (p != KeyName))
155 subkeyLength = p - KeyName;
156 stringLength = subkeyLength + 1;
161 subkeyLength = strlen (KeyName);
162 stringLength = subkeyLength;
166 Ptr = CurrentKey->SubKeyList.Flink;
167 while (Ptr != &CurrentKey->SubKeyList)
169 DPRINT ("Ptr 0x%x\n", Ptr);
171 SearchKey = CONTAINING_RECORD(Ptr,
174 DPRINT ("SearchKey 0x%x\n", SearchKey);
175 DPRINT ("Searching '%s'\n", SearchKey->Name);
176 if (strncmp (SearchKey->Name, name, subkeyLength) == 0)
182 if (Ptr == &CurrentKey->SubKeyList)
184 /* no key found -> create new subkey */
185 NewKey = (HKEY)malloc (sizeof(KEY));
187 return ERROR_OUTOFMEMORY;
189 InitializeListHead (&NewKey->SubKeyList);
190 InitializeListHead (&NewKey->ValueList);
192 NewKey->SubKeyCount = 0;
193 NewKey->ValueCount = 0;
195 NewKey->DataType = 0;
196 NewKey->DataSize = 0;
199 InsertTailList (&CurrentKey->SubKeyList, &NewKey->KeyList);
200 CurrentKey->SubKeyCount++;
202 NewKey->NameSize = subkeyLength + 1;
203 NewKey->Name = (PCHAR)malloc (NewKey->NameSize);
204 if (NewKey->Name == NULL)
205 return(ERROR_OUTOFMEMORY);
206 memcpy(NewKey->Name, name, subkeyLength);
207 NewKey->Name[subkeyLength] = 0;
209 DPRINT ("NewKey 0x%x\n", NewKey);
210 DPRINT ("NewKey '%s' Length %d\n", NewKey->Name, NewKey->NameSize);
216 CurrentKey = SearchKey;
218 /* Check whether current key is a link */
219 if (CurrentKey->DataType == REG_LINK)
221 CurrentKey = (HKEY)CurrentKey->Data;
225 KeyName = KeyName + stringLength;
231 return ERROR_SUCCESS;
236 RegDeleteKey(HKEY Key,
241 if (strchr(Name, '\\') != NULL)
242 return(ERROR_INVALID_PARAMETER);
246 return(ERROR_SUCCESS);
261 Ptr = Key->SubKeyList.Flink;
262 while (Ptr != &Key->SubKeyList)
271 if (Ptr == &Key->SubKeyList)
272 return(ERROR_NO_MORE_ITEMS);
274 SearchKey = CONTAINING_RECORD(Ptr,
278 DPRINT ("Name '%s' Length %d\n", SearchKey->Name, SearchKey->NameSize);
280 Size = min(SearchKey->NameSize, *NameSize);
282 memcpy(Name, SearchKey->Name, Size);
284 return(ERROR_SUCCESS);
289 RegOpenKey(HKEY ParentKey,
294 HKEY SearchKey = INVALID_HANDLE_VALUE;
301 DPRINT("KeyName '%s'\n", KeyName);
305 if (*KeyName == '\\')
308 CurrentKey = RootKey;
310 else if (ParentKey == NULL)
312 CurrentKey = RootKey;
316 CurrentKey = ParentKey;
319 /* Check whether current key is a link */
320 if (CurrentKey->DataType == REG_LINK)
322 CurrentKey = (HKEY)CurrentKey->Data;
325 while (*KeyName != 0)
327 DPRINT ("KeyName '%s'\n", KeyName);
329 if (*KeyName == '\\')
331 p = strchr(KeyName, '\\');
332 if ((p != NULL) && (p != KeyName))
334 subkeyLength = p - KeyName;
335 stringLength = subkeyLength + 1;
340 subkeyLength = strlen(KeyName);
341 stringLength = subkeyLength;
345 Ptr = CurrentKey->SubKeyList.Flink;
346 while (Ptr != &CurrentKey->SubKeyList)
348 DPRINT ("Ptr 0x%x\n", Ptr);
350 SearchKey = CONTAINING_RECORD(Ptr,
354 DPRINT ("SearchKey 0x%x\n", SearchKey);
355 DPRINT ("Searching '%s'\n", SearchKey->Name);
357 if (strncmp(SearchKey->Name, name, subkeyLength) == 0)
363 if (Ptr == &CurrentKey->SubKeyList)
365 return(ERROR_PATH_NOT_FOUND);
369 CurrentKey = SearchKey;
371 /* Check whether current key is a link */
372 if (CurrentKey->DataType == REG_LINK)
374 CurrentKey = (HKEY)CurrentKey->Data;
378 KeyName = KeyName + stringLength;
384 return(ERROR_SUCCESS);
389 RegSetValue(HKEY Key,
398 DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
399 (int)Key, ValueName, (int)Type, (int)Data, (int)DataSize);
401 if ((ValueName == NULL) || (*ValueName == 0))
403 /* set default value */
404 if ((Key->Data != NULL) && (Key->DataSize > sizeof(PUCHAR)))
409 if (DataSize <= sizeof(PUCHAR))
411 Key->DataSize = DataSize;
412 Key->DataType = Type;
413 memcpy(&Key->Data, Data, DataSize);
417 Key->Data = (PUCHAR)malloc(DataSize);
418 Key->DataSize = DataSize;
419 Key->DataType = Type;
420 memcpy(Key->Data, Data, DataSize);
425 /* set non-default value */
426 Ptr = Key->ValueList.Flink;
427 while (Ptr != &Key->ValueList)
429 Value = CONTAINING_RECORD(Ptr,
433 DPRINT ("Value->Name '%s'\n", Value->Name);
435 if (strcasecmp(Value->Name, ValueName) == 0)
441 if (Ptr == &Key->ValueList)
444 DPRINT("No value found - adding new value\n");
446 Value = (PVALUE)malloc(sizeof(VALUE));
448 return(ERROR_OUTOFMEMORY);
449 InsertTailList(&Key->ValueList, &Value->ValueList);
451 Value->NameSize = strlen(ValueName)+1;
452 Value->Name = (PCHAR)malloc(Value->NameSize);
453 if (Value->Name == NULL)
454 return(ERROR_OUTOFMEMORY);
455 strcpy(Value->Name, ValueName);
456 Value->DataType = REG_NONE;
462 if ((Value->Data != NULL) && (Value->DataSize > sizeof(PUCHAR)))
467 if (DataSize <= sizeof(PUCHAR))
469 Value->DataSize = DataSize;
470 Value->DataType = Type;
471 memcpy(&Value->Data, Data, DataSize);
475 Value->Data = (PUCHAR)malloc(DataSize);
476 if (Value->Data == NULL)
477 return(ERROR_OUTOFMEMORY);
478 Value->DataType = Type;
479 Value->DataSize = DataSize;
480 memcpy(Value->Data, Data, DataSize);
483 return(ERROR_SUCCESS);
488 RegQueryValue(HKEY Key,
498 if ((ValueName == NULL) || (*ValueName == 0))
500 /* query default value */
501 if (Key->Data == NULL)
502 return(ERROR_INVALID_PARAMETER);
505 *Type = Key->DataType;
506 if ((Data != NULL) && (DataSize != NULL))
508 if (Key->DataSize <= sizeof(PUCHAR))
510 Size = min(Key->DataSize, *DataSize);
511 memcpy(Data, &Key->Data, Size);
516 Size = min(Key->DataSize, *DataSize);
517 memcpy(Data, Key->Data, Size);
521 else if ((Data == NULL) && (DataSize != NULL))
523 *DataSize = Key->DataSize;
528 /* query non-default value */
529 Ptr = Key->ValueList.Flink;
530 while (Ptr != &Key->ValueList)
532 Value = CONTAINING_RECORD(Ptr,
536 DPRINT("Searching for '%s'. Value name '%s'\n", ValueName, Value->Name);
538 if (strcasecmp(Value->Name, ValueName) == 0)
544 if (Ptr == &Key->ValueList)
545 return(ERROR_INVALID_PARAMETER);
548 *Type = Value->DataType;
549 if ((Data != NULL) && (DataSize != NULL))
551 if (Value->DataSize <= sizeof(PUCHAR))
553 Size = min(Value->DataSize, *DataSize);
554 memcpy(Data, &Value->Data, Size);
559 Size = min(Value->DataSize, *DataSize);
560 memcpy(Data, Value->Data, Size);
564 else if ((Data == NULL) && (DataSize != NULL))
566 *DataSize = Value->DataSize;
570 return(ERROR_SUCCESS);
575 RegDeleteValue(HKEY Key,
581 if ((ValueName == NULL) || (*ValueName == 0))
583 /* delete default value */
584 if (Key->Data != NULL)
592 /* delete non-default value */
593 Ptr = Key->ValueList.Flink;
594 while (Ptr != &Key->ValueList)
596 Value = CONTAINING_RECORD(Ptr,
599 if (strcmp(Value->Name, ValueName) == 0)
605 if (Ptr == &Key->ValueList)
606 return(ERROR_INVALID_PARAMETER);
610 if (Value->Name != NULL)
615 if (Value->DataSize > sizeof(PUCHAR))
617 if (Value->Data != NULL)
624 RemoveEntryList(&Value->ValueList);
627 return(ERROR_SUCCESS);
632 RegEnumValue(HKEY Key,
644 if (Key->Data != NULL)
652 /* enumerate default value */
653 if (ValueName != NULL)
656 *Type = Key->DataType;
657 if (DataSize != NULL)
658 *DataSize = Key->DataSize;
660 /* FIXME: return more values */
664 Ptr = Key->ValueList.Flink;
665 while (Ptr != &Key->ValueList)
674 if (Ptr == &Key->ValueList)
675 return(ERROR_NO_MORE_ITEMS);
677 Value = CONTAINING_RECORD(Ptr,
681 /* FIXME: return values */
683 return(ERROR_SUCCESS);
688 RegGetSubKeyCount (HKEY Key)
690 return Key->SubKeyCount;
695 RegGetValueCount (HKEY Key)
697 if (Key->DataSize != 0)
698 return Key->ValueCount + 1;
700 return Key->ValueCount;
707 RegQueryMultipleValue(HKEY Key,
710 return(ERROR_SUCCESS);