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.
19 /* $Id: registry.c,v 1.9 2004/05/29 21:15:58 navaraf Exp $
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().
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 SOFTWARE key */
104 RegCreateKey(RootKey
,
105 "Registry\\Machine\\SOFTWARE",
108 /* Create DEFAULT key */
109 RegCreateKey(RootKey
,
110 "Registry\\User\\.DEFAULT",
116 RegCreateKey(HKEY ParentKey
,
121 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
129 DPRINT ("KeyName '%s'\n", KeyName
);
131 if (*KeyName
== '\\')
134 CurrentKey
= RootKey
;
136 else if (ParentKey
== NULL
)
138 CurrentKey
= RootKey
;
142 CurrentKey
= ParentKey
;
145 /* Check whether current key is a link */
146 if (CurrentKey
->DataType
== REG_LINK
)
148 CurrentKey
= (HKEY
)CurrentKey
->Data
;
151 while (*KeyName
!= 0)
153 DPRINT ("KeyName '%s'\n", KeyName
);
155 if (*KeyName
== '\\')
157 p
= strchr (KeyName
, '\\');
158 if ((p
!= NULL
) && (p
!= KeyName
))
160 subkeyLength
= p
- KeyName
;
161 stringLength
= subkeyLength
+ 1;
166 subkeyLength
= strlen (KeyName
);
167 stringLength
= subkeyLength
;
171 Ptr
= CurrentKey
->SubKeyList
.Flink
;
172 while (Ptr
!= &CurrentKey
->SubKeyList
)
174 DPRINT ("Ptr 0x%p\n", Ptr
);
176 SearchKey
= CONTAINING_RECORD(Ptr
,
179 DPRINT ("SearchKey 0x%p\n", SearchKey
);
180 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
181 if (strncasecmp (SearchKey
->Name
, name
, subkeyLength
) == 0)
187 if (Ptr
== &CurrentKey
->SubKeyList
)
189 /* no key found -> create new subkey */
190 NewKey
= (HKEY
)malloc (sizeof(KEY
));
192 return ERROR_OUTOFMEMORY
;
194 InitializeListHead (&NewKey
->SubKeyList
);
195 InitializeListHead (&NewKey
->ValueList
);
197 NewKey
->SubKeyCount
= 0;
198 NewKey
->ValueCount
= 0;
200 NewKey
->DataType
= 0;
201 NewKey
->DataSize
= 0;
204 InsertTailList (&CurrentKey
->SubKeyList
, &NewKey
->KeyList
);
205 CurrentKey
->SubKeyCount
++;
207 NewKey
->NameSize
= subkeyLength
+ 1;
208 NewKey
->Name
= (PCHAR
)malloc (NewKey
->NameSize
);
209 if (NewKey
->Name
== NULL
)
210 return(ERROR_OUTOFMEMORY
);
211 memcpy(NewKey
->Name
, name
, subkeyLength
);
212 NewKey
->Name
[subkeyLength
] = 0;
214 DPRINT ("NewKey 0x%p\n", NewKey
);
215 DPRINT ("NewKey '%s' Length %ld\n", NewKey
->Name
, NewKey
->NameSize
);
221 CurrentKey
= SearchKey
;
223 /* Check whether current key is a link */
224 if (CurrentKey
->DataType
== REG_LINK
)
226 CurrentKey
= (HKEY
)CurrentKey
->Data
;
230 KeyName
= KeyName
+ stringLength
;
236 return ERROR_SUCCESS
;
241 RegDeleteKey(HKEY Key
,
245 if (strchr(Name
, '\\') != NULL
)
246 return(ERROR_INVALID_PARAMETER
);
250 return(ERROR_SUCCESS
);
265 Ptr
= Key
->SubKeyList
.Flink
;
266 while (Ptr
!= &Key
->SubKeyList
)
275 if (Ptr
== &Key
->SubKeyList
)
276 return(ERROR_NO_MORE_ITEMS
);
278 SearchKey
= CONTAINING_RECORD(Ptr
,
282 DPRINT ("Name '%s' Length %ld\n", SearchKey
->Name
, SearchKey
->NameSize
);
284 Size
= min(SearchKey
->NameSize
, *NameSize
);
286 memcpy(Name
, SearchKey
->Name
, Size
);
288 return(ERROR_SUCCESS
);
293 RegOpenKey(HKEY ParentKey
,
298 HKEY SearchKey
= INVALID_HANDLE_VALUE
;
305 DPRINT("KeyName '%s'\n", KeyName
);
309 if (*KeyName
== '\\')
312 CurrentKey
= RootKey
;
314 else if (ParentKey
== NULL
)
316 CurrentKey
= RootKey
;
320 CurrentKey
= ParentKey
;
323 /* Check whether current key is a link */
324 if (CurrentKey
->DataType
== REG_LINK
)
326 CurrentKey
= (HKEY
)CurrentKey
->Data
;
329 while (*KeyName
!= 0)
331 DPRINT ("KeyName '%s'\n", KeyName
);
333 if (*KeyName
== '\\')
335 p
= strchr(KeyName
, '\\');
336 if ((p
!= NULL
) && (p
!= KeyName
))
338 subkeyLength
= p
- KeyName
;
339 stringLength
= subkeyLength
+ 1;
344 subkeyLength
= strlen(KeyName
);
345 stringLength
= subkeyLength
;
349 Ptr
= CurrentKey
->SubKeyList
.Flink
;
350 while (Ptr
!= &CurrentKey
->SubKeyList
)
352 DPRINT ("Ptr 0x%p\n", Ptr
);
354 SearchKey
= CONTAINING_RECORD(Ptr
,
358 DPRINT ("SearchKey 0x%p\n", SearchKey
);
359 DPRINT ("Searching '%s'\n", SearchKey
->Name
);
361 if (strncasecmp(SearchKey
->Name
, name
, subkeyLength
) == 0)
367 if (Ptr
== &CurrentKey
->SubKeyList
)
369 return(ERROR_PATH_NOT_FOUND
);
373 CurrentKey
= SearchKey
;
375 /* Check whether current key is a link */
376 if (CurrentKey
->DataType
== REG_LINK
)
378 CurrentKey
= (HKEY
)CurrentKey
->Data
;
382 KeyName
= KeyName
+ stringLength
;
388 return(ERROR_SUCCESS
);
393 RegSetValue(HKEY Key
,
402 DPRINT ("Key 0x%x, ValueName '%s', Type %d, Data 0x%x, DataSize %d\n",
403 (int)Key
, ValueName
, (int)Type
, (int)Data
, (int)DataSize
);
405 if ((ValueName
== NULL
) || (*ValueName
== 0))
407 /* set default value */
408 if ((Key
->Data
!= NULL
) && (Key
->DataSize
> sizeof(PUCHAR
)))
413 if (DataSize
<= sizeof(PUCHAR
))
415 Key
->DataSize
= DataSize
;
416 Key
->DataType
= Type
;
417 memcpy(&Key
->Data
, Data
, DataSize
);
421 Key
->Data
= (PUCHAR
)malloc(DataSize
);
422 Key
->DataSize
= DataSize
;
423 Key
->DataType
= Type
;
424 memcpy(Key
->Data
, Data
, DataSize
);
429 /* set non-default value */
430 Ptr
= Key
->ValueList
.Flink
;
431 while (Ptr
!= &Key
->ValueList
)
433 Value
= CONTAINING_RECORD(Ptr
,
437 DPRINT ("Value->Name '%s'\n", Value
->Name
);
439 if (strcasecmp(Value
->Name
, ValueName
) == 0)
445 if (Ptr
== &Key
->ValueList
)
448 DPRINT("No value found - adding new value\n");
450 Value
= (PVALUE
)malloc(sizeof(VALUE
));
452 return(ERROR_OUTOFMEMORY
);
453 InsertTailList(&Key
->ValueList
, &Value
->ValueList
);
455 Value
->NameSize
= strlen(ValueName
)+1;
456 Value
->Name
= (PCHAR
)malloc(Value
->NameSize
);
457 if (Value
->Name
== NULL
)
458 return(ERROR_OUTOFMEMORY
);
459 strcpy(Value
->Name
, ValueName
);
460 Value
->DataType
= REG_NONE
;
466 if ((Value
->Data
!= NULL
) && (Value
->DataSize
> sizeof(PUCHAR
)))
471 if (DataSize
<= sizeof(PUCHAR
))
473 Value
->DataSize
= DataSize
;
474 Value
->DataType
= Type
;
475 memcpy(&Value
->Data
, Data
, DataSize
);
479 Value
->Data
= (PUCHAR
)malloc(DataSize
);
480 if (Value
->Data
== NULL
)
481 return(ERROR_OUTOFMEMORY
);
482 Value
->DataType
= Type
;
483 Value
->DataSize
= DataSize
;
484 memcpy(Value
->Data
, Data
, DataSize
);
487 return(ERROR_SUCCESS
);
492 RegQueryValue(HKEY Key
,
502 if ((ValueName
== NULL
) || (*ValueName
== 0))
504 /* query default value */
505 if (Key
->Data
== NULL
)
506 return(ERROR_INVALID_PARAMETER
);
509 *Type
= Key
->DataType
;
510 if ((Data
!= NULL
) && (DataSize
!= NULL
))
512 if (Key
->DataSize
<= sizeof(PUCHAR
))
514 Size
= min(Key
->DataSize
, *DataSize
);
515 memcpy(Data
, &Key
->Data
, Size
);
520 Size
= min(Key
->DataSize
, *DataSize
);
521 memcpy(Data
, Key
->Data
, Size
);
525 else if ((Data
== NULL
) && (DataSize
!= NULL
))
527 *DataSize
= Key
->DataSize
;
532 /* query non-default value */
533 Ptr
= Key
->ValueList
.Flink
;
534 while (Ptr
!= &Key
->ValueList
)
536 Value
= CONTAINING_RECORD(Ptr
,
540 DPRINT("Searching for '%s'. Value name '%s'\n", ValueName
, Value
->Name
);
542 if (strcasecmp(Value
->Name
, ValueName
) == 0)
548 if (Ptr
== &Key
->ValueList
)
549 return(ERROR_INVALID_PARAMETER
);
552 *Type
= Value
->DataType
;
553 if ((Data
!= NULL
) && (DataSize
!= NULL
))
555 if (Value
->DataSize
<= sizeof(PUCHAR
))
557 Size
= min(Value
->DataSize
, *DataSize
);
558 memcpy(Data
, &Value
->Data
, Size
);
563 Size
= min(Value
->DataSize
, *DataSize
);
564 memcpy(Data
, Value
->Data
, Size
);
568 else if ((Data
== NULL
) && (DataSize
!= NULL
))
570 *DataSize
= Value
->DataSize
;
574 return(ERROR_SUCCESS
);
579 RegDeleteValue(HKEY Key
,
585 if ((ValueName
== NULL
) || (*ValueName
== 0))
587 /* delete default value */
588 if (Key
->Data
!= NULL
)
596 /* delete non-default value */
597 Ptr
= Key
->ValueList
.Flink
;
598 while (Ptr
!= &Key
->ValueList
)
600 Value
= CONTAINING_RECORD(Ptr
,
603 if (strcasecmp(Value
->Name
, ValueName
) == 0)
609 if (Ptr
== &Key
->ValueList
)
610 return(ERROR_INVALID_PARAMETER
);
614 if (Value
->Name
!= NULL
)
619 if (Value
->DataSize
> sizeof(PUCHAR
))
621 if (Value
->Data
!= NULL
)
628 RemoveEntryList(&Value
->ValueList
);
631 return(ERROR_SUCCESS
);
636 RegEnumValue(HKEY Key
,
648 if (Key
->Data
!= NULL
)
656 /* enumerate default value */
657 if (ValueName
!= NULL
)
660 *Type
= Key
->DataType
;
661 if (DataSize
!= NULL
)
662 *DataSize
= Key
->DataSize
;
664 /* FIXME: return more values */
668 Ptr
= Key
->ValueList
.Flink
;
669 while (Ptr
!= &Key
->ValueList
)
678 if (Ptr
== &Key
->ValueList
)
679 return(ERROR_NO_MORE_ITEMS
);
681 Value
= CONTAINING_RECORD(Ptr
,
685 /* FIXME: return values */
687 return(ERROR_SUCCESS
);
692 RegGetSubKeyCount (HKEY Key
)
694 return Key
->SubKeyCount
;
699 RegGetValueCount (HKEY Key
)
701 if (Key
->DataSize
!= 0)
702 return Key
->ValueCount
+ 1;
704 return Key
->ValueCount
;