Update nItemWidth in LISTVIEW_SetItem() if LVS_LIST or LVS_SMALLICON
[wine/multimedia.git] / misc / registry.c
blob01b9645f5e4f0f2665dc17a19044f01f3a5bcf8d
1 /*
2 * Registry Functions
4 * Copyright 1996 Marcus Meissner
5 * Copyright 1998 Matthew Becker
6 * Copyright 1999 Sylvain St-Germain
8 * December 21, 1997 - Kevin Cozens
9 * Fixed bugs in the _w95_loadreg() function. Added extra information
10 * regarding the format of the Windows '95 registry files.
12 * NOTES
13 * When changing this file, please re-run the regtest program to ensure
14 * the conditions are handled properly.
16 * TODO
17 * Security access
18 * Option handling
19 * Time for RegEnumKey*, RegQueryInfoKey*
22 #include "config.h"
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <limits.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #ifdef HAVE_SYS_ERRNO_H
32 #include <sys/errno.h>
33 #endif
34 #include <sys/types.h>
35 #include <fcntl.h>
36 #include <sys/fcntl.h>
37 #include <sys/stat.h>
38 #include <time.h>
39 #include "windef.h"
40 #include "winbase.h"
41 #include "wine/winbase16.h"
42 #include "wine/winestring.h"
43 #include "winerror.h"
44 #include "file.h"
45 #include "heap.h"
46 #include "debugtools.h"
47 #include "options.h"
48 #include "winreg.h"
49 #include "server.h"
50 #include "services.h"
52 DEFAULT_DEBUG_CHANNEL(reg);
54 static void REGISTRY_Init(void);
55 /* FIXME: following defines should be configured global ... */
57 #define SAVE_USERS_DEFAULT ETCDIR"/wine.userreg"
58 #define SAVE_LOCAL_MACHINE_DEFAULT ETCDIR"/wine.systemreg"
60 /* relative in ~user/.wine/ : */
61 #define SAVE_CURRENT_USER "user.reg"
62 #define SAVE_DEFAULT_USER "userdef.reg"
63 #define SAVE_LOCAL_USERS_DEFAULT "wine.userreg"
64 #define SAVE_LOCAL_MACHINE "system.reg"
66 /* what valuetypes do we need to convert? */
67 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
70 static void *xmalloc( size_t size )
72 void *res;
74 res = malloc (size ? size : 1);
75 if (res == NULL) {
76 WARN("Virtual memory exhausted.\n");
77 exit (1);
79 return res;
83 * QUESTION
84 * Are these doing the same as HEAP_strdupAtoW and HEAP_strdupWtoA?
85 * If so, can we remove them?
86 * ANSWER
87 * No, the memory handling functions are called very often in here,
88 * just replacing them by HeapAlloc(SystemHeap,...) makes registry
89 * loading 100 times slower. -MM
91 static LPWSTR strdupA2W(LPCSTR src)
93 if(src) {
94 LPWSTR dest=xmalloc(2*strlen(src)+2);
95 lstrcpyAtoW(dest,src);
96 return dest;
98 return NULL;
101 LPWSTR strcvtA2W(LPCSTR src, int nchars)
104 LPWSTR dest = xmalloc (2 * nchars + 2);
106 lstrcpynAtoW(dest,src,nchars+1);
107 return dest;
112 /******************************************************************************
113 * REGISTRY_Init [Internal]
114 * Registry initialisation, allocates some default keys.
116 static void REGISTRY_Init(void) {
117 HKEY hkey;
118 char buf[200];
120 TRACE("(void)\n");
122 RegCreateKeyA(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
123 RegCloseKey(hkey);
125 /* This was an Open, but since it is called before the real registries
126 are loaded, it was changed to a Create - MTB 980507*/
127 RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
128 RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
129 RegCloseKey(hkey);
131 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
132 * CurrentVersion
133 * CurrentBuildNumber
134 * CurrentType
135 * string RegisteredOwner
136 * string RegisteredOrganization
139 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
140 * string SysContact
141 * string SysLocation
142 * SysServices
144 if (-1!=gethostname(buf,200)) {
145 RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
146 RegSetValueExA(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
147 RegCloseKey(hkey);
152 /************************ LOAD Registry Function ****************************/
156 /******************************************************************************
157 * _find_or_add_key [Internal]
159 static inline HKEY _find_or_add_key( HKEY hkey, LPWSTR keyname )
161 HKEY subkey;
162 if (RegCreateKeyW( hkey, keyname, &subkey ) != ERROR_SUCCESS) subkey = 0;
163 if (keyname) free( keyname );
164 return subkey;
167 /******************************************************************************
168 * _find_or_add_value [Internal]
170 static void _find_or_add_value( HKEY hkey, LPWSTR name, DWORD type, LPBYTE data, DWORD len )
172 RegSetValueExW( hkey, name, 0, type, data, len );
173 if (name) free( name );
174 if (data) free( data );
178 /******************************************************************************
179 * _wine_read_line [Internal]
181 * reads a line including dynamically enlarging the readbuffer and throwing
182 * away comments
184 static int _wine_read_line( FILE *F, char **buf, int *len )
186 char *s,*curread;
187 int mylen,curoff;
189 curread = *buf;
190 mylen = *len;
191 **buf = '\0';
192 while (1) {
193 while (1) {
194 s=fgets(curread,mylen,F);
195 if (s==NULL)
196 return 0; /* EOF */
197 if (NULL==(s=strchr(curread,'\n'))) {
198 /* buffer wasn't large enough */
199 curoff = strlen(*buf);
200 curread = realloc(*buf,*len*2);
201 if(curread == NULL) {
202 WARN("Out of memory");
203 return 0;
205 *buf = curread;
206 curread+= curoff;
207 mylen = *len; /* we filled up the buffer and
208 * got new '*len' bytes to fill
210 *len = *len * 2;
211 } else {
212 *s='\0';
213 break;
216 /* throw away comments */
217 if (**buf=='#' || **buf==';') {
218 curread = *buf;
219 mylen = *len;
220 continue;
222 if (s) /* got end of line */
223 break;
225 return 1;
229 /******************************************************************************
230 * _wine_read_USTRING [Internal]
232 * converts a char* into a UNICODE string (up to a special char)
233 * and returns the position exactly after that string
235 static char* _wine_read_USTRING( char *buf, LPWSTR *str )
237 char *s;
238 LPWSTR ws;
240 /* read up to "=" or "\0" or "\n" */
241 s = buf;
242 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
243 ws = *str;
244 while (*s && (*s!='\n') && (*s!='=')) {
245 if (*s!='\\')
246 *ws++=*((unsigned char*)s++);
247 else {
248 s++;
249 if (!*s) {
250 /* Dangling \ ... may only happen if a registry
251 * write was short. FIXME: What do to?
253 break;
255 if (*s=='\\') {
256 *ws++='\\';
257 s++;
258 continue;
260 if (*s!='u') {
261 WARN("Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
262 *ws++='\\';
263 *ws++=*s++;
264 } else {
265 char xbuf[5];
266 int wc;
268 s++;
269 memcpy(xbuf,s,4);xbuf[4]='\0';
270 if (!sscanf(xbuf,"%x",&wc))
271 WARN("Strange escape sequence %s found in |%s|\n",xbuf,buf);
272 s+=4;
273 *ws++ =(unsigned short)wc;
277 *ws = 0;
278 return s;
282 /******************************************************************************
283 * _wine_loadsubkey [Internal]
285 * NOTES
286 * It seems like this is returning a boolean. Should it?
288 * RETURNS
289 * Success: 1
290 * Failure: 0
292 static int _wine_loadsubkey( FILE *F, HKEY hkey, int level, char **buf, int *buflen )
294 HKEY subkey;
295 int i;
296 char *s;
297 LPWSTR name;
299 TRACE("(%p,%x,%d,%s,%d)\n", F, hkey, level, debugstr_a(*buf), *buflen);
301 /* Good. We already got a line here ... so parse it */
302 subkey = 0;
303 while (1) {
304 i=0;s=*buf;
305 while (*s=='\t') {
306 s++;
307 i++;
309 if (i>level) {
310 if (!subkey) {
311 WARN("Got a subhierarchy without resp. key?\n");
312 return 0;
314 if (!_wine_loadsubkey(F,subkey,level+1,buf,buflen))
315 if (!_wine_read_line(F,buf,buflen))
316 goto done;
317 continue;
320 /* let the caller handle this line */
321 if (i<level || **buf=='\0')
322 goto done;
324 /* it can be: a value or a keyname. Parse the name first */
325 s=_wine_read_USTRING(s,&name);
327 /* switch() default: hack to avoid gotos */
328 switch (0) {
329 default:
330 if (*s=='\0') {
331 if (subkey) RegCloseKey( subkey );
332 subkey=_find_or_add_key(hkey,name);
333 } else {
334 LPBYTE data;
335 int len,lastmodified,type;
337 if (*s!='=') {
338 WARN("Unexpected character: %c\n",*s);
339 break;
341 s++;
342 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
343 WARN("Haven't understood possible value in |%s|, skipping.\n",*buf);
344 break;
346 /* skip the 2 , */
347 s=strchr(s,',');s++;
348 s=strchr(s,',');
349 if (!s++) {
350 WARN("Haven't understood possible value in |%s|, skipping.\n",*buf);
351 break;
353 if (type == REG_SZ || type == REG_EXPAND_SZ) {
354 s=_wine_read_USTRING(s,(LPWSTR*)&data);
355 len = lstrlenW((LPWSTR)data)*2+2;
356 } else {
357 len=strlen(s)/2;
358 data = (LPBYTE)xmalloc(len+1);
359 for (i=0;i<len;i++) {
360 data[i]=0;
361 if (*s>='0' && *s<='9')
362 data[i]=(*s-'0')<<4;
363 if (*s>='a' && *s<='f')
364 data[i]=(*s-'a'+'\xa')<<4;
365 if (*s>='A' && *s<='F')
366 data[i]=(*s-'A'+'\xa')<<4;
367 s++;
368 if (*s>='0' && *s<='9')
369 data[i]|=*s-'0';
370 if (*s>='a' && *s<='f')
371 data[i]|=*s-'a'+'\xa';
372 if (*s>='A' && *s<='F')
373 data[i]|=*s-'A'+'\xa';
374 s++;
377 _find_or_add_value(hkey,name,type,data,len);
380 /* read the next line */
381 if (!_wine_read_line(F,buf,buflen))
382 goto done;
384 done:
385 if (subkey) RegCloseKey( subkey );
386 return 1;
390 /******************************************************************************
391 * _wine_loadsubreg [Internal]
393 static int _wine_loadsubreg( FILE *F, HKEY hkey, const char *fn )
395 int ver;
396 char *buf;
397 int buflen;
399 buf=xmalloc(10);buflen=10;
400 if (!_wine_read_line(F,&buf,&buflen)) {
401 free(buf);
402 return 0;
404 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
405 free(buf);
406 return 0;
408 if (ver!=1) {
409 if (ver == 2) /* new version */
411 HANDLE file;
412 if ((file = FILE_CreateFile( fn, GENERIC_READ, 0, NULL, OPEN_EXISTING,
413 FILE_ATTRIBUTE_NORMAL, -1, TRUE )) != INVALID_HANDLE_VALUE)
415 struct load_registry_request *req = get_req_buffer();
416 req->hkey = hkey;
417 req->file = file;
418 req->name[0] = 0;
419 server_call( REQ_LOAD_REGISTRY );
420 CloseHandle( file );
422 free( buf );
423 return 1;
425 else
427 TRACE("Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
428 free(buf);
429 return 0;
432 if (!_wine_read_line(F,&buf,&buflen)) {
433 free(buf);
434 return 0;
436 if (!_wine_loadsubkey(F,hkey,0,&buf,&buflen)) {
437 free(buf);
438 return 0;
440 free(buf);
441 return 1;
445 /******************************************************************************
446 * _wine_loadreg [Internal]
448 static int _wine_loadreg( HKEY hkey, char *fn )
450 FILE *F;
452 TRACE("(%x,%s)\n",hkey,debugstr_a(fn));
454 F = fopen(fn,"rb");
455 if (F==NULL) {
456 WARN("Couldn't open %s for reading: %s\n",fn,strerror(errno) );
457 return -1;
459 _wine_loadsubreg(F,hkey,fn);
460 fclose(F);
461 return 0;
464 /* NT REGISTRY LOADER */
466 #ifdef HAVE_SYS_MMAN_H
467 # include <sys/mman.h>
468 #endif
470 #ifndef MAP_FAILED
471 #define MAP_FAILED ((LPVOID)-1)
472 #endif
474 #define NT_REG_BLOCK_SIZE 0x1000
476 #define NT_REG_HEADER_BLOCK_ID 0x66676572 /* regf */
477 #define NT_REG_POOL_BLOCK_ID 0x6E696268 /* hbin */
478 #define NT_REG_KEY_BLOCK_ID 0x6b6e /* nk */
479 #define NT_REG_VALUE_BLOCK_ID 0x6b76 /* vk */
481 /* subblocks of nk */
482 #define NT_REG_HASH_BLOCK_ID 0x666c /* lf */
483 #define NT_REG_NOHASH_BLOCK_ID 0x696c /* li */
484 #define NT_REG_RI_BLOCK_ID 0x6972 /* ri */
486 #define NT_REG_KEY_BLOCK_TYPE 0x20
487 #define NT_REG_ROOT_KEY_BLOCK_TYPE 0x2c
489 typedef struct
491 DWORD id; /* 0x66676572 'regf'*/
492 DWORD uk1; /* 0x04 */
493 DWORD uk2; /* 0x08 */
494 FILETIME DateModified; /* 0x0c */
495 DWORD uk3; /* 0x14 */
496 DWORD uk4; /* 0x18 */
497 DWORD uk5; /* 0x1c */
498 DWORD uk6; /* 0x20 */
499 DWORD RootKeyBlock; /* 0x24 */
500 DWORD BlockSize; /* 0x28 */
501 DWORD uk7[116];
502 DWORD Checksum; /* at offset 0x1FC */
503 } nt_regf;
505 typedef struct
507 DWORD blocksize;
508 BYTE data[1];
509 } nt_hbin_sub;
511 typedef struct
513 DWORD id; /* 0x6E696268 'hbin' */
514 DWORD off_prev;
515 DWORD off_next;
516 DWORD uk1;
517 DWORD uk2; /* 0x10 */
518 DWORD uk3; /* 0x14 */
519 DWORD uk4; /* 0x18 */
520 DWORD size; /* 0x1C */
521 nt_hbin_sub hbin_sub; /* 0x20 */
522 } nt_hbin;
525 * the value_list consists of offsets to the values (vk)
527 typedef struct
529 WORD SubBlockId; /* 0x00 0x6B6E */
530 WORD Type; /* 0x02 for the root-key: 0x2C, otherwise 0x20*/
531 FILETIME writetime; /* 0x04 */
532 DWORD uk1; /* 0x0C */
533 DWORD parent_off; /* 0x10 Offset of Owner/Parent key */
534 DWORD nr_subkeys; /* 0x14 number of sub-Keys */
535 DWORD uk8; /* 0x18 */
536 DWORD lf_off; /* 0x1C Offset of the sub-key lf-Records */
537 DWORD uk2; /* 0x20 */
538 DWORD nr_values; /* 0x24 number of values */
539 DWORD valuelist_off; /* 0x28 Offset of the Value-List */
540 DWORD off_sk; /* 0x2c Offset of the sk-Record */
541 DWORD off_class; /* 0x30 Offset of the Class-Name */
542 DWORD uk3; /* 0x34 */
543 DWORD uk4; /* 0x38 */
544 DWORD uk5; /* 0x3c */
545 DWORD uk6; /* 0x40 */
546 DWORD uk7; /* 0x44 */
547 WORD name_len; /* 0x48 name-length */
548 WORD class_len; /* 0x4a class-name length */
549 char name[1]; /* 0x4c key-name */
550 } nt_nk;
552 typedef struct
554 DWORD off_nk; /* 0x00 */
555 DWORD name; /* 0x04 */
556 } hash_rec;
558 typedef struct
560 WORD id; /* 0x00 0x666c */
561 WORD nr_keys; /* 0x06 */
562 hash_rec hash_rec[1];
563 } nt_lf;
566 list of subkeys without hash
568 li --+-->nk
570 +-->nk
572 typedef struct
574 WORD id; /* 0x00 0x696c */
575 WORD nr_keys;
576 DWORD off_nk[1];
577 } nt_li;
580 this is a intermediate node
582 ri --+-->li--+-->nk
584 | +-->nk
586 +-->li--+-->nk
588 +-->nk
590 typedef struct
592 WORD id; /* 0x00 0x6972 */
593 WORD nr_li; /* 0x02 number off offsets */
594 DWORD off_li[1]; /* 0x04 points to li */
595 } nt_ri;
597 typedef struct
599 WORD id; /* 0x00 'vk' */
600 WORD nam_len;
601 DWORD data_len;
602 DWORD data_off;
603 DWORD type;
604 WORD flag;
605 WORD uk1;
606 char name[1];
607 } nt_vk;
609 LPSTR _strdupnA( LPCSTR str, int len )
611 LPSTR ret;
613 if (!str) return NULL;
614 ret = malloc( len + 1 );
615 lstrcpynA( ret, str, len );
616 ret[len] = 0x00;
617 return ret;
620 static int _nt_parse_nk(HKEY hkey, char * base, nt_nk * nk, int level);
621 static int _nt_parse_vk(HKEY hkey, char * base, nt_vk * vk);
622 static int _nt_parse_lf(HKEY hkey, char * base, int subkeys, nt_lf * lf, int level);
626 * gets a value
628 * vk->flag:
629 * 0 value is a default value
630 * 1 the value has a name
632 * vk->data_len
633 * len of the whole data block
634 * - reg_sz (unicode)
635 * bytes including the terminating \0 = 2*(number_of_chars+1)
636 * - reg_dword, reg_binary:
637 * if highest bit of data_len is set data_off contains the value
639 static int _nt_parse_vk(HKEY hkey, char * base, nt_vk * vk)
641 WCHAR name [256];
642 DWORD ret;
643 BYTE * pdata = (BYTE *)(base+vk->data_off+4); /* start of data */
645 if(vk->id != NT_REG_VALUE_BLOCK_ID) goto error;
647 lstrcpynAtoW(name, vk->name, vk->nam_len+1);
649 ret = RegSetValueExW( hkey, (vk->flag & 0x00000001) ? name : NULL, 0, vk->type,
650 (vk->data_len & 0x80000000) ? (LPBYTE)&(vk->data_off): pdata,
651 (vk->data_len & 0x7fffffff) );
652 if (ret) ERR("RegSetValueEx failed (0x%08lx)\n", ret);
653 return TRUE;
654 error:
655 ERR_(reg)("unknown block found (0x%04x), please report!\n", vk->id);
656 return FALSE;
660 * get the subkeys
662 * this structure contains the hash of a keyname and points to all
663 * subkeys
665 * exception: if the id is 'il' there are no hash values and every
666 * dword is a offset
668 static int _nt_parse_lf(HKEY hkey, char * base, int subkeys, nt_lf * lf, int level)
670 int i;
672 if (lf->id == NT_REG_HASH_BLOCK_ID)
674 if (subkeys != lf->nr_keys) goto error1;
676 for (i=0; i<lf->nr_keys; i++)
678 if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+lf->hash_rec[i].off_nk+4), level)) goto error;
681 else if (lf->id == NT_REG_NOHASH_BLOCK_ID)
683 nt_li * li = (nt_li*)lf;
684 if (subkeys != li->nr_keys) goto error1;
686 for (i=0; i<li->nr_keys; i++)
688 if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+li->off_nk[i]+4), level)) goto error;
691 else if (lf->id == NT_REG_RI_BLOCK_ID) /* ri */
693 nt_ri * ri = (nt_ri*)lf;
694 int li_subkeys = 0;
696 /* count all subkeys */
697 for (i=0; i<ri->nr_li; i++)
699 nt_li * li = (nt_li*)(base+ri->off_li[i]+4);
700 if(li->id != NT_REG_NOHASH_BLOCK_ID) goto error2;
701 li_subkeys += li->nr_keys;
704 /* check number */
705 if (subkeys != li_subkeys) goto error1;
707 /* loop through the keys */
708 for (i=0; i<ri->nr_li; i++)
710 nt_li * li = (nt_li*)(base+ri->off_li[i]+4);
711 if (!_nt_parse_lf(hkey, base, li->nr_keys, (nt_lf*)li, level)) goto error;
714 else
716 goto error2;
718 return TRUE;
720 error2: ERR("unknown node id 0x%04x, please report!\n", lf->id);
721 return TRUE;
723 error1: ERR_(reg)("registry file corrupt! (inconsistent number of subkeys)\n");
724 return FALSE;
726 error: ERR_(reg)("error reading lf block\n");
727 return FALSE;
730 static int _nt_parse_nk(HKEY hkey, char * base, nt_nk * nk, int level)
732 char * name;
733 int i;
734 DWORD * vl;
735 HKEY subkey = hkey;
737 if(nk->SubBlockId != NT_REG_KEY_BLOCK_ID)
739 ERR("unknown node id 0x%04x, please report!\n", nk->SubBlockId);
740 goto error;
743 if((nk->Type!=NT_REG_ROOT_KEY_BLOCK_TYPE) &&
744 (((nt_nk*)(base+nk->parent_off+4))->SubBlockId != NT_REG_KEY_BLOCK_ID))
746 ERR_(reg)("registry file corrupt!\n");
747 goto error;
750 /* create the new key */
751 if(level <= 0)
753 name = _strdupnA( nk->name, nk->name_len+1);
754 if(RegCreateKeyA( hkey, name, &subkey )) { free(name); goto error; }
755 free(name);
758 /* loop through the subkeys */
759 if (nk->nr_subkeys)
761 nt_lf * lf = (nt_lf*)(base+nk->lf_off+4);
762 if (!_nt_parse_lf(subkey, base, nk->nr_subkeys, lf, level-1)) goto error1;
765 /* loop trough the value list */
766 vl = (DWORD *)(base+nk->valuelist_off+4);
767 for (i=0; i<nk->nr_values; i++)
769 nt_vk * vk = (nt_vk*)(base+vl[i]+4);
770 if (!_nt_parse_vk(subkey, base, vk)) goto error1;
773 RegCloseKey(subkey);
774 return TRUE;
776 error1: RegCloseKey(subkey);
777 error: return FALSE;
780 /* end nt loader */
782 /* windows 95 registry loader */
784 /* SECTION 1: main header
786 * once at offset 0
788 #define W95_REG_CREG_ID 0x47455243
790 typedef struct
792 DWORD id; /* "CREG" = W95_REG_CREG_ID */
793 DWORD version; /* ???? 0x00010000 */
794 DWORD rgdb_off; /* 0x08 Offset of 1st RGDB-block */
795 DWORD uk2; /* 0x0c */
796 WORD rgdb_num; /* 0x10 # of RGDB-blocks */
797 WORD uk3;
798 DWORD uk[3];
799 /* rgkn */
800 } _w95creg;
802 /* SECTION 2: Directory information (tree structure)
804 * once on offset 0x20
806 * structure: [rgkn][dke]* (repeat till rgkn->size is reached)
808 #define W95_REG_RGKN_ID 0x4e4b4752
810 typedef struct
812 DWORD id; /*"RGKN" = W95_REG_RGKN_ID */
813 DWORD size; /* Size of the RGKN-block */
814 DWORD root_off; /* Rel. Offset of the root-record */
815 DWORD uk[5];
816 } _w95rgkn;
818 /* Disk Key Entry Structure
820 * the 1st entry in a "usual" registry file is a nul-entry with subkeys: the
821 * hive itself. It looks the same like other keys. Even the ID-number can
822 * be any value.
824 * The "hash"-value is a value representing the key's name. Windows will not
825 * search for the name, but for a matching hash-value. if it finds one, it
826 * will compare the actual string info, otherwise continue with the next key.
827 * To calculate the hash initialize a D-Word with 0 and add all ASCII-values
828 * of the string which are smaller than 0x80 (128) to this D-Word.
830 * If you want to modify key names, also modify the hash-values, since they
831 * cannot be found again (although they would be displayed in REGEDIT)
832 * End of list-pointers are filled with 0xFFFFFFFF
834 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
835 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
836 * structure) and reading another RGDB_section.
838 * there is a one to one relationship between dke and dkh
840 /* key struct, once per key */
841 typedef struct
843 DWORD x1; /* Free entry indicator(?) */
844 DWORD hash; /* sum of bytes of keyname */
845 DWORD x3; /* Root key indicator? usually 0xFFFFFFFF */
846 DWORD prevlvl; /* offset of previous key */
847 DWORD nextsub; /* offset of child key */
848 DWORD next; /* offset of sibling key */
849 WORD nrLS; /* id inside the rgdb block */
850 WORD nrMS; /* number of the rgdb block */
851 } _w95dke;
853 /* SECTION 3: key information, values and data
855 * structure:
856 * section: [blocks]* (repeat creg->rgdb_num times)
857 * blocks: [rgdb] [subblocks]* (repeat till block size reached )
858 * subblocks: [dkh] [dkv]* (repeat dkh->values times )
860 * An interesting relationship exists in RGDB_section. The value at offset
861 * 10 equals the value at offset 4 minus the value at offset 8. I have no
862 * idea at the moment what this means. (Kevin Cozens)
865 /* block header, once per block */
866 #define W95_REG_RGDB_ID 0x42444752
868 typedef struct
870 DWORD id; /* 0x00 'rgdb' = W95_REG_RGDB_ID */
871 DWORD size; /* 0x04 */
872 DWORD uk1; /* 0x08 */
873 DWORD uk2; /* 0x0c */
874 DWORD uk3; /* 0x10 */
875 DWORD uk4; /* 0x14 */
876 DWORD uk5; /* 0x18 */
877 DWORD uk6; /* 0x1c */
878 /* dkh */
879 } _w95rgdb;
881 /* Disk Key Header structure (RGDB part), once per key */
882 typedef struct
884 DWORD nextkeyoff; /* 0x00 offset to next dkh*/
885 WORD nrLS; /* 0x04 id inside the rgdb block */
886 WORD nrMS; /* 0x06 number of the rgdb block */
887 DWORD bytesused; /* 0x08 */
888 WORD keynamelen; /* 0x0c len of name */
889 WORD values; /* 0x0e number of values */
890 DWORD xx1; /* 0x10 */
891 char name[1]; /* 0x14 */
892 /* dkv */ /* 0x14 + keynamelen */
893 } _w95dkh;
895 /* Disk Key Value structure, once per value */
896 typedef struct
898 DWORD type; /* 0x00 */
899 DWORD x1; /* 0x04 */
900 WORD valnamelen; /* 0x08 length of name, 0 is default key */
901 WORD valdatalen; /* 0x0A length of data */
902 char name[1]; /* 0x0c */
903 /* raw data */ /* 0x0c + valnamelen */
904 } _w95dkv;
906 /******************************************************************************
907 * _w95_lookup_dkh [Internal]
909 * seeks the dkh belonging to a dke
911 static _w95dkh * _w95_lookup_dkh (_w95creg *creg, int nrLS, int nrMS)
913 _w95rgdb * rgdb;
914 _w95dkh * dkh;
915 int i;
917 /* get the beginning of the rgdb datastore */
918 rgdb = (_w95rgdb*)((char*)creg+creg->rgdb_off);
920 /* check: requested block < last_block) */
921 if (creg->rgdb_num <= nrMS)
923 ERR("registry file corrupt! requested block no. beyond end.\n");
924 goto error;
927 /* find the right block */
928 for(i=0; i<nrMS ;i++)
930 if(rgdb->id != W95_REG_RGDB_ID) /* check the magic */
932 ERR("registry file corrupt! bad magic 0x%08lx\n", rgdb->id);
933 goto error;
935 rgdb = (_w95rgdb*) ((char*)rgdb+rgdb->size); /* find next block */
938 dkh = (_w95dkh*)(rgdb + 1); /* first sub block within the rgdb */
942 if(nrLS==dkh->nrLS ) return dkh;
943 dkh = (_w95dkh*)((char*)dkh + dkh->nextkeyoff); /* find next subblock */
944 } while ((char *)dkh < ((char*)rgdb+rgdb->size));
946 error: return NULL;
949 /******************************************************************************
950 * _w95_parse_dkv [Internal]
952 static int _w95_parse_dkv (
953 HKEY hkey,
954 _w95dkh * dkh,
955 int nrLS,
956 int nrMS )
958 _w95dkv * dkv;
959 int i;
960 DWORD ret;
961 char * name;
963 /* first value block */
964 dkv = (_w95dkv*)((char*)dkh+dkh->keynamelen+0x14);
966 /* loop trought the values */
967 for (i=0; i< dkh->values; i++)
969 name = _strdupnA(dkv->name, dkv->valnamelen+1);
970 ret = RegSetValueExA(hkey, name, 0, dkv->type, &(dkv->name[dkv->valnamelen]),dkv->valdatalen);
971 if (ret) FIXME("RegSetValueEx returned: 0x%08lx\n", ret);
972 free (name);
974 /* next value */
975 dkv = (_w95dkv*)((char*)dkv+dkv->valnamelen+dkv->valdatalen+0x0c);
977 return TRUE;
980 /******************************************************************************
981 * _w95_parse_dke [Internal]
983 static int _w95_parse_dke(
984 HKEY hkey,
985 _w95creg * creg,
986 _w95rgkn *rgkn,
987 _w95dke * dke,
988 int level )
990 _w95dkh * dkh;
991 HKEY hsubkey = hkey;
992 char * name;
993 int ret = FALSE;
995 /* get start address of root key block */
996 if (!dke) dke = (_w95dke*)((char*)rgkn + rgkn->root_off);
998 /* special root key */
999 if (dke->nrLS == 0xffff || dke->nrMS==0xffff) /* eg. the root key has no name */
1001 /* parse the one subkey*/
1002 if (dke->nextsub != 0xffffffff)
1004 return _w95_parse_dke(hsubkey, creg, rgkn, (_w95dke*)((char*)rgkn+dke->nextsub), level);
1006 /* has no sibling keys */
1007 goto error;
1010 /* search subblock */
1011 if (!(dkh = _w95_lookup_dkh(creg, dke->nrLS, dke->nrMS)))
1013 fprintf(stderr, "dke pointing to missing dkh !\n");
1014 goto error;
1017 if ( level <= 0 )
1019 /* walk sibling keys */
1020 if (dke->next != 0xffffffff )
1022 if (!_w95_parse_dke(hkey, creg, rgkn, (_w95dke*)((char*)rgkn+dke->next), level)) goto error;
1025 /* create subkey and insert values */
1026 name = _strdupnA( dkh->name, dkh->keynamelen+1);
1027 if (RegCreateKeyA(hkey, name, &hsubkey)) { free(name); goto error; }
1028 free(name);
1029 if (!_w95_parse_dkv(hsubkey, dkh, dke->nrLS, dke->nrMS)) goto error1;
1032 /* next sub key */
1033 if (dke->nextsub != 0xffffffff)
1035 if (!_w95_parse_dke(hsubkey, creg, rgkn, (_w95dke*)((char*)rgkn+dke->nextsub), level-1)) goto error1;
1038 ret = TRUE;
1039 error1: if (hsubkey != hkey) RegCloseKey(hsubkey);
1040 error: return ret;
1042 /* end windows 95 loader */
1044 /******************************************************************************
1045 * NativeRegLoadKey [Internal]
1047 * Loads a native registry file (win95/nt)
1048 * hkey root key
1049 * fn filename
1050 * level number of levels to cut away (eg. ".Default" in user.dat)
1052 * this function intentionally uses unix file functions to make it possible
1053 * to move it to a seperate registry helper programm
1055 static int NativeRegLoadKey( HKEY hkey, char* fn, int level )
1057 int fd = 0;
1058 struct stat st;
1059 DOS_FULL_NAME full_name;
1060 int ret = FALSE;
1061 void * base;
1063 if (!DOSFS_GetFullName( fn, 0, &full_name )) return FALSE;
1065 /* map the registry into the memory */
1066 if ((fd = open(full_name.long_name, O_RDONLY | O_NONBLOCK)) == -1) return FALSE;
1067 if ((fstat(fd, &st) == -1)) goto error;
1068 if (!st.st_size) goto error;
1069 if ((base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto error;
1071 switch (*(LPDWORD)base)
1073 /* windows 95 'creg' */
1074 case W95_REG_CREG_ID:
1076 _w95creg * creg;
1077 _w95rgkn * rgkn;
1078 creg = base;
1079 TRACE_(reg)("Loading win95 registry '%s' '%s'\n",fn, full_name.long_name);
1081 /* load the header (rgkn) */
1082 rgkn = (_w95rgkn*)(creg + 1);
1083 if (rgkn->id != W95_REG_RGKN_ID)
1085 ERR("second IFF header not RGKN, but %lx\n", rgkn->id);
1086 goto error1;
1089 ret = _w95_parse_dke(hkey, creg, rgkn, NULL, level);
1091 break;
1092 /* nt 'regf'*/
1093 case NT_REG_HEADER_BLOCK_ID:
1095 nt_regf * regf;
1096 nt_hbin * hbin;
1097 nt_hbin_sub * hbin_sub;
1098 nt_nk* nk;
1100 TRACE_(reg)("Loading nt registry '%s' '%s'\n",fn, full_name.long_name);
1102 /* start block */
1103 regf = base;
1105 /* hbin block */
1106 hbin = (nt_hbin*)((char*) base + 0x1000);
1107 if (hbin->id != NT_REG_POOL_BLOCK_ID)
1109 ERR_(reg)( "%s hbin block invalid\n", fn);
1110 goto error1;
1113 /* hbin_sub block */
1114 hbin_sub = (nt_hbin_sub*)&(hbin->hbin_sub);
1115 if ((hbin_sub->data[0] != 'n') || (hbin_sub->data[1] != 'k'))
1117 ERR_(reg)( "%s hbin_sub block invalid\n", fn);
1118 goto error1;
1121 /* nk block */
1122 nk = (nt_nk*)&(hbin_sub->data[0]);
1123 if (nk->Type != NT_REG_ROOT_KEY_BLOCK_TYPE)
1125 ERR_(reg)( "%s special nk block not found\n", fn);
1126 goto error1;
1129 ret = _nt_parse_nk (hkey, (char *) base + 0x1000, nk, level);
1131 break;
1132 default:
1134 ERR("unknown signature in registry file %s.\n",fn);
1135 goto error1;
1138 if(!ret) ERR("error loading registry file %s\n", fn);
1139 error1: munmap(base, st.st_size);
1140 error: close(fd);
1141 return ret;
1144 /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1146 reghack - windows 3.11 registry data format demo program.
1148 The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1149 a combined hash table and tree description, and finally a text table.
1151 The header is obvious from the struct header. The taboff1 and taboff2
1152 fields are always 0x20, and their usage is unknown.
1154 The 8-byte entry table has various entry types.
1156 tabent[0] is a root index. The second word has the index of the root of
1157 the directory.
1158 tabent[1..hashsize] is a hash table. The first word in the hash entry is
1159 the index of the key/value that has that hash. Data with the same
1160 hash value are on a circular list. The other three words in the
1161 hash entry are always zero.
1162 tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1163 entry: dirent and keyent/valent. They are identified by context.
1164 tabent[freeidx] is the first free entry. The first word in a free entry
1165 is the index of the next free entry. The last has 0 as a link.
1166 The other three words in the free list are probably irrelevant.
1168 Entries in text table are preceeded by a word at offset-2. This word
1169 has the value (2*index)+1, where index is the referring keyent/valent
1170 entry in the table. I have no suggestion for the 2* and the +1.
1171 Following the word, there are N bytes of data, as per the keyent/valent
1172 entry length. The offset of the keyent/valent entry is from the start
1173 of the text table to the first data byte.
1175 This information is not available from Microsoft. The data format is
1176 deduced from the reg.dat file by me. Mistakes may
1177 have been made. I claim no rights and give no guarantees for this program.
1179 Tor Sjøwall, tor@sn.no
1182 /* reg.dat header format */
1183 struct _w31_header {
1184 char cookie[8]; /* 'SHCC3.10' */
1185 unsigned long taboff1; /* offset of hash table (??) = 0x20 */
1186 unsigned long taboff2; /* offset of index table (??) = 0x20 */
1187 unsigned long tabcnt; /* number of entries in index table */
1188 unsigned long textoff; /* offset of text part */
1189 unsigned long textsize; /* byte size of text part */
1190 unsigned short hashsize; /* hash size */
1191 unsigned short freeidx; /* free index */
1194 /* generic format of table entries */
1195 struct _w31_tabent {
1196 unsigned short w0, w1, w2, w3;
1199 /* directory tabent: */
1200 struct _w31_dirent {
1201 unsigned short sibling_idx; /* table index of sibling dirent */
1202 unsigned short child_idx; /* table index of child dirent */
1203 unsigned short key_idx; /* table index of key keyent */
1204 unsigned short value_idx; /* table index of value valent */
1207 /* key tabent: */
1208 struct _w31_keyent {
1209 unsigned short hash_idx; /* hash chain index for string */
1210 unsigned short refcnt; /* reference count */
1211 unsigned short length; /* length of string */
1212 unsigned short string_off; /* offset of string in text table */
1215 /* value tabent: */
1216 struct _w31_valent {
1217 unsigned short hash_idx; /* hash chain index for string */
1218 unsigned short refcnt; /* reference count */
1219 unsigned short length; /* length of string */
1220 unsigned short string_off; /* offset of string in text table */
1223 /* recursive helper function to display a directory tree */
1224 void
1225 __w31_dumptree( unsigned short idx,
1226 unsigned char *txt,
1227 struct _w31_tabent *tab,
1228 struct _w31_header *head,
1229 HKEY hkey,
1230 time_t lastmodified,
1231 int level
1233 struct _w31_dirent *dir;
1234 struct _w31_keyent *key;
1235 struct _w31_valent *val;
1236 HKEY subkey = 0;
1237 static char tail[400];
1239 while (idx!=0) {
1240 dir=(struct _w31_dirent*)&tab[idx];
1242 if (dir->key_idx) {
1243 key = (struct _w31_keyent*)&tab[dir->key_idx];
1245 memcpy(tail,&txt[key->string_off],key->length);
1246 tail[key->length]='\0';
1247 /* all toplevel entries AND the entries in the
1248 * toplevel subdirectory belong to \SOFTWARE\Classes
1250 if (!level && !lstrcmpA(tail,".classes")) {
1251 __w31_dumptree(dir->child_idx,txt,tab,head,hkey,lastmodified,level+1);
1252 idx=dir->sibling_idx;
1253 continue;
1255 if (subkey) RegCloseKey( subkey );
1256 if (RegCreateKeyA( hkey, tail, &subkey ) != ERROR_SUCCESS) subkey = 0;
1257 /* only add if leaf node or valued node */
1258 if (dir->value_idx!=0||dir->child_idx==0) {
1259 if (dir->value_idx) {
1260 val=(struct _w31_valent*)&tab[dir->value_idx];
1261 memcpy(tail,&txt[val->string_off],val->length);
1262 tail[val->length]='\0';
1263 RegSetValueA( subkey, NULL, REG_SZ, tail, 0 );
1266 } else {
1267 TRACE("strange: no directory key name, idx=%04x\n", idx);
1269 __w31_dumptree(dir->child_idx,txt,tab,head,subkey,lastmodified,level+1);
1270 idx=dir->sibling_idx;
1272 if (subkey) RegCloseKey( subkey );
1276 /******************************************************************************
1277 * _w31_loadreg [Internal]
1279 void _w31_loadreg(void) {
1280 HFILE hf;
1281 struct _w31_header head;
1282 struct _w31_tabent *tab;
1283 unsigned char *txt;
1284 int len;
1285 OFSTRUCT ofs;
1286 BY_HANDLE_FILE_INFORMATION hfinfo;
1287 time_t lastmodified;
1289 TRACE("(void)\n");
1291 hf = OpenFile("reg.dat",&ofs,OF_READ);
1292 if (hf==HFILE_ERROR)
1293 return;
1295 /* read & dump header */
1296 if (sizeof(head)!=_lread(hf,&head,sizeof(head))) {
1297 ERR("reg.dat is too short.\n");
1298 _lclose(hf);
1299 return;
1301 if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
1302 ERR("reg.dat has bad signature.\n");
1303 _lclose(hf);
1304 return;
1307 len = head.tabcnt * sizeof(struct _w31_tabent);
1308 /* read and dump index table */
1309 tab = xmalloc(len);
1310 if (len!=_lread(hf,tab,len)) {
1311 ERR("couldn't read %d bytes.\n",len);
1312 free(tab);
1313 _lclose(hf);
1314 return;
1317 /* read text */
1318 txt = xmalloc(head.textsize);
1319 if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
1320 ERR("couldn't seek to textblock.\n");
1321 free(tab);
1322 free(txt);
1323 _lclose(hf);
1324 return;
1326 if (head.textsize!=_lread(hf,txt,head.textsize)) {
1327 ERR("textblock too short (%d instead of %ld).\n",len,head.textsize);
1328 free(tab);
1329 free(txt);
1330 _lclose(hf);
1331 return;
1334 if (!GetFileInformationByHandle(hf,&hfinfo)) {
1335 ERR("GetFileInformationByHandle failed?.\n");
1336 free(tab);
1337 free(txt);
1338 _lclose(hf);
1339 return;
1341 lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
1342 __w31_dumptree(tab[0].w1,txt,tab,&head,HKEY_CLASSES_ROOT,lastmodified,0);
1343 free(tab);
1344 free(txt);
1345 _lclose(hf);
1346 return;
1350 /* configure save files and start the periodic saving timer */
1351 static void SHELL_InitRegistrySaving( HKEY hkey_users_default )
1353 struct set_registry_levels_request *req = get_req_buffer();
1355 int all = PROFILE_GetWineIniBool( "registry", "SaveOnlyUpdatedKeys", 1 );
1356 int period = PROFILE_GetWineIniInt( "registry", "PeriodicSave", 0 );
1358 /* set saving level (0 for saving everything, 1 for saving only modified keys) */
1359 req->current = 1;
1360 req->saving = !all;
1361 req->period = period * 1000;
1362 server_call( REQ_SET_REGISTRY_LEVELS );
1364 if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1))
1366 struct save_registry_atexit_request *req = get_req_buffer();
1367 const char *confdir = get_config_dir();
1368 char *str = req->file + strlen(confdir);
1370 if (str + 20 > req->file + server_remaining(req->file))
1372 ERR("config dir '%s' too long\n", confdir );
1373 return;
1376 strcpy( req->file, confdir );
1377 strcpy( str, "/" SAVE_CURRENT_USER );
1378 req->hkey = HKEY_CURRENT_USER;
1379 server_call( REQ_SAVE_REGISTRY_ATEXIT );
1381 strcpy( req->file, confdir );
1382 strcpy( str, "/" SAVE_LOCAL_MACHINE );
1383 req->hkey = HKEY_LOCAL_MACHINE;
1384 server_call( REQ_SAVE_REGISTRY_ATEXIT );
1386 strcpy( req->file, confdir );
1387 strcpy( str, "/" SAVE_DEFAULT_USER );
1388 req->hkey = hkey_users_default;
1389 server_call( REQ_SAVE_REGISTRY_ATEXIT );
1391 strcpy( req->file, confdir );
1392 strcpy( str, "/" SAVE_LOCAL_USERS_DEFAULT );
1393 req->hkey = HKEY_USERS;
1394 server_call( REQ_SAVE_REGISTRY_ATEXIT );
1399 /**********************************************************************************
1400 * SetLoadLevel [Internal]
1402 * set level to 0 for loading system files
1403 * set level to 1 for loading user files
1405 static void SetLoadLevel(int level)
1407 struct set_registry_levels_request *req = get_req_buffer();
1409 req->current = level;
1410 req->saving = 0;
1411 req->period = 0;
1412 server_call( REQ_SET_REGISTRY_LEVELS );
1415 /**********************************************************************************
1416 * SHELL_LoadRegistry [Internal]
1418 #define REG_DONTLOAD -1
1419 #define REG_WIN31 0
1420 #define REG_WIN95 1
1421 #define REG_WINNT 2
1423 void SHELL_LoadRegistry( void )
1425 HKEY hkey;
1426 char windir[MAX_PATHNAME_LEN];
1427 char path[MAX_PATHNAME_LEN];
1428 int systemtype = REG_WIN31;
1429 HKEY hkey_users_default;
1431 TRACE("(void)\n");
1433 if (!CLIENT_IsBootThread()) return; /* already loaded */
1435 REGISTRY_Init();
1436 SetLoadLevel(0);
1438 if (RegCreateKeyA(HKEY_USERS, ".Default", &hkey_users_default)) hkey_users_default = 0;
1440 GetWindowsDirectoryA( windir, MAX_PATHNAME_LEN );
1442 if (PROFILE_GetWineIniBool( "Registry", "LoadWindowsRegistryFiles", 1))
1444 /* test %windir%/system32/config/system --> winnt */
1445 strcpy(path, windir);
1446 strncat(path, "\\system32\\config\\system", MAX_PATHNAME_LEN - strlen(path) - 1);
1447 if(GetFileAttributesA(path) != -1)
1449 systemtype = REG_WINNT;
1451 else
1453 /* test %windir%/system.dat --> win95 */
1454 strcpy(path, windir);
1455 strncat(path, "\\system.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1456 if(GetFileAttributesA(path) != -1)
1458 systemtype = REG_WIN95;
1462 if ((systemtype==REG_WINNT)
1463 && (! PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN)))
1465 MESSAGE("When you are running with a native NT directory specify\n");
1466 MESSAGE("'Profile=<profiledirectory>' or disable loading of Windows\n");
1467 MESSAGE("registry (LoadWindowsRegistryFiles=N)\n");
1468 systemtype = REG_DONTLOAD;
1471 else
1473 /* only wine registry */
1474 systemtype = REG_DONTLOAD;
1477 switch (systemtype)
1479 case REG_WIN31:
1480 _w31_loadreg();
1481 break;
1483 case REG_WIN95:
1484 /* Load windows 95 entries */
1485 NativeRegLoadKey(HKEY_LOCAL_MACHINE, "C:\\system.1st", 0);
1487 strcpy(path, windir);
1488 strncat(path, "\\system.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1489 NativeRegLoadKey(HKEY_LOCAL_MACHINE, path, 0);
1491 if (PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN))
1493 /* user specific user.dat */
1494 strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1495 if (!NativeRegLoadKey( HKEY_CURRENT_USER, path, 1 ))
1497 MESSAGE("can't load win95 user-registry %s\n", path);
1498 MESSAGE("check wine.conf, section [Wine], value 'Profile'\n");
1500 /* default user.dat */
1501 if (hkey_users_default)
1503 strcpy(path, windir);
1504 strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1505 NativeRegLoadKey(hkey_users_default, path, 1);
1508 else
1510 /* global user.dat */
1511 strcpy(path, windir);
1512 strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1513 NativeRegLoadKey(HKEY_CURRENT_USER, path, 1);
1515 break;
1517 case REG_WINNT:
1518 /* default user.dat */
1519 if (PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN))
1521 strncat(path, "\\ntuser.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1522 if(!NativeRegLoadKey( HKEY_CURRENT_USER, path, 1 ))
1524 MESSAGE("can't load NT user-registry %s\n", path);
1525 MESSAGE("check wine.conf, section [Wine], value 'Profile'\n");
1529 /* default user.dat */
1530 if (hkey_users_default)
1532 strcpy(path, windir);
1533 strncat(path, "\\system32\\config\\default", MAX_PATHNAME_LEN - strlen(path) - 1);
1534 NativeRegLoadKey(hkey_users_default, path, 1);
1538 * FIXME
1539 * map HLM\System\ControlSet001 to HLM\System\CurrentControlSet
1542 if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SYSTEM", &hkey))
1544 strcpy(path, windir);
1545 strncat(path, "\\system32\\config\\system", MAX_PATHNAME_LEN - strlen(path) - 1);
1546 NativeRegLoadKey(hkey, path, 1);
1547 RegCloseKey(hkey);
1550 if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE", &hkey))
1552 strcpy(path, windir);
1553 strncat(path, "\\system32\\config\\software", MAX_PATHNAME_LEN - strlen(path) - 1);
1554 NativeRegLoadKey(hkey, path, 1);
1555 RegCloseKey(hkey);
1558 strcpy(path, windir);
1559 strncat(path, "\\system32\\config\\sam", MAX_PATHNAME_LEN - strlen(path) - 1);
1560 NativeRegLoadKey(HKEY_LOCAL_MACHINE, path, 0);
1562 strcpy(path, windir);
1563 strncat(path, "\\system32\\config\\security", MAX_PATHNAME_LEN - strlen(path) - 1);
1564 NativeRegLoadKey(HKEY_LOCAL_MACHINE, path, 0);
1566 /* this key is generated when the nt-core booted successfully */
1567 if (!RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\Clone",&hkey))
1568 RegCloseKey(hkey);
1569 break;
1570 } /* switch */
1572 if (PROFILE_GetWineIniBool ("registry","LoadGlobalRegistryFiles", 1))
1575 * Load the global HKU hive directly from sysconfdir
1577 _wine_loadreg( HKEY_USERS, SAVE_USERS_DEFAULT );
1580 * Load the global machine defaults directly form sysconfdir
1582 _wine_loadreg( HKEY_LOCAL_MACHINE, SAVE_LOCAL_MACHINE_DEFAULT );
1585 SetLoadLevel(1);
1588 * Load the user saved registries
1590 if (PROFILE_GetWineIniBool("registry", "LoadHomeRegistryFiles", 1))
1592 const char *confdir = get_config_dir();
1593 int len = strlen(confdir) + 20;
1594 char *fn = path;
1596 if (len > sizeof(path)) fn = HeapAlloc( GetProcessHeap(), 0, len );
1598 * Load user's personal versions of global HKU/.Default keys
1600 if (fn)
1602 char *str;
1603 strcpy( fn, confdir );
1604 str = fn + strlen(fn);
1605 *str++ = '/';
1607 /* try to load HKU\.Default key only */
1608 strcpy( str, SAVE_DEFAULT_USER );
1609 if (_wine_loadreg( hkey_users_default, fn ))
1611 /* if not found load old file containing both HKU\.Default and HKU\user */
1612 strcpy( str, SAVE_LOCAL_USERS_DEFAULT );
1613 _wine_loadreg( HKEY_USERS, fn );
1616 strcpy( str, SAVE_CURRENT_USER );
1617 _wine_loadreg( HKEY_CURRENT_USER, fn );
1619 strcpy( str, SAVE_LOCAL_MACHINE );
1620 _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
1622 if (fn != path) HeapFree( GetProcessHeap(), 0, fn );
1625 SHELL_InitRegistrySaving( hkey_users_default );
1626 RegCloseKey( hkey_users_default );
1629 /********************* API FUNCTIONS ***************************************/
1634 /******************************************************************************
1635 * RegFlushKey [KERNEL.227] [ADVAPI32.143]
1636 * Immediately writes key to registry.
1637 * Only returns after data has been written to disk.
1639 * FIXME: does it really wait until data is written ?
1641 * PARAMS
1642 * hkey [I] Handle of key to write
1644 * RETURNS
1645 * Success: ERROR_SUCCESS
1646 * Failure: Error code
1648 DWORD WINAPI RegFlushKey( HKEY hkey )
1650 FIXME( "(%x): stub\n", hkey );
1651 return ERROR_SUCCESS;
1654 /******************************************************************************
1655 * RegConnectRegistryW [ADVAPI32.128]
1657 * PARAMS
1658 * lpMachineName [I] Address of name of remote computer
1659 * hHey [I] Predefined registry handle
1660 * phkResult [I] Address of buffer for remote registry handle
1662 LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey,
1663 LPHKEY phkResult )
1665 TRACE("(%s,%x,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
1667 if (!lpMachineName || !*lpMachineName) {
1668 /* Use the local machine name */
1669 return RegOpenKey16( hKey, "", phkResult );
1672 FIXME("Cannot connect to %s\n",debugstr_w(lpMachineName));
1673 return ERROR_BAD_NETPATH;
1677 /******************************************************************************
1678 * RegConnectRegistryA [ADVAPI32.127]
1680 LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, LPHKEY reskey )
1682 DWORD ret;
1683 LPWSTR machineW = strdupA2W(machine);
1684 ret = RegConnectRegistryW( machineW, hkey, reskey );
1685 free(machineW);
1686 return ret;
1690 /******************************************************************************
1691 * RegGetKeySecurity [ADVAPI32.144]
1692 * Retrieves a copy of security descriptor protecting the registry key
1694 * PARAMS
1695 * hkey [I] Open handle of key to set
1696 * SecurityInformation [I] Descriptor contents
1697 * pSecurityDescriptor [O] Address of descriptor for key
1698 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
1700 * RETURNS
1701 * Success: ERROR_SUCCESS
1702 * Failure: Error code
1704 LONG WINAPI RegGetKeySecurity( HKEY hkey,
1705 SECURITY_INFORMATION SecurityInformation,
1706 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1707 LPDWORD lpcbSecurityDescriptor )
1709 TRACE("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
1710 lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1712 /* FIXME: Check for valid SecurityInformation values */
1714 if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
1715 return ERROR_INSUFFICIENT_BUFFER;
1717 FIXME("(%x,%ld,%p,%ld): stub\n",hkey,SecurityInformation,
1718 pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1720 return ERROR_SUCCESS;
1724 /******************************************************************************
1725 * RegNotifyChangeKeyValue [ADVAPI32.???]
1727 * PARAMS
1728 * hkey [I] Handle of key to watch
1729 * fWatchSubTree [I] Flag for subkey notification
1730 * fdwNotifyFilter [I] Changes to be reported
1731 * hEvent [I] Handle of signaled event
1732 * fAsync [I] Flag for asynchronous reporting
1734 LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
1735 DWORD fdwNotifyFilter, HANDLE hEvent,
1736 BOOL fAsync )
1738 FIXME("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter,
1739 hEvent,fAsync);
1740 return ERROR_SUCCESS;
1744 /******************************************************************************
1745 * RegUnLoadKeyW [ADVAPI32.173]
1747 * PARAMS
1748 * hkey [I] Handle of open key
1749 * lpSubKey [I] Address of name of subkey to unload
1751 LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey )
1753 FIXME("(%x,%s): stub\n",hkey, debugstr_w(lpSubKey));
1754 return ERROR_SUCCESS;
1758 /******************************************************************************
1759 * RegUnLoadKeyA [ADVAPI32.172]
1761 LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
1763 LONG ret;
1764 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
1765 ret = RegUnLoadKeyW( hkey, lpSubKeyW );
1766 if(lpSubKeyW) free(lpSubKeyW);
1767 return ret;
1771 /******************************************************************************
1772 * RegSetKeySecurity [ADVAPI32.167]
1774 * PARAMS
1775 * hkey [I] Open handle of key to set
1776 * SecurityInfo [I] Descriptor contents
1777 * pSecurityDesc [I] Address of descriptor for key
1779 LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
1780 PSECURITY_DESCRIPTOR pSecurityDesc )
1782 TRACE("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
1784 /* It seems to perform this check before the hkey check */
1785 if ((SecurityInfo & OWNER_SECURITY_INFORMATION) ||
1786 (SecurityInfo & GROUP_SECURITY_INFORMATION) ||
1787 (SecurityInfo & DACL_SECURITY_INFORMATION) ||
1788 (SecurityInfo & SACL_SECURITY_INFORMATION)) {
1789 /* Param OK */
1790 } else
1791 return ERROR_INVALID_PARAMETER;
1793 if (!pSecurityDesc)
1794 return ERROR_INVALID_PARAMETER;
1796 FIXME(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
1798 return ERROR_SUCCESS;
1802 /******************************************************************************
1803 * RegRestoreKeyW [ADVAPI32.164]
1805 * PARAMS
1806 * hkey [I] Handle of key where restore begins
1807 * lpFile [I] Address of filename containing saved tree
1808 * dwFlags [I] Optional flags
1810 LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
1812 TRACE("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
1814 /* It seems to do this check before the hkey check */
1815 if (!lpFile || !*lpFile)
1816 return ERROR_INVALID_PARAMETER;
1818 FIXME("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
1820 /* Check for file existence */
1822 return ERROR_SUCCESS;
1826 /******************************************************************************
1827 * RegRestoreKeyA [ADVAPI32.163]
1829 LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
1831 LONG ret;
1832 LPWSTR lpFileW = strdupA2W(lpFile);
1833 ret = RegRestoreKeyW( hkey, lpFileW, dwFlags );
1834 if(lpFileW) free(lpFileW);
1835 return ret;
1839 /******************************************************************************
1840 * RegReplaceKeyW [ADVAPI32.162]
1842 * PARAMS
1843 * hkey [I] Handle of open key
1844 * lpSubKey [I] Address of name of subkey
1845 * lpNewFile [I] Address of filename for file with new data
1846 * lpOldFile [I] Address of filename for backup file
1848 LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
1849 LPCWSTR lpOldFile )
1851 FIXME("(%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey),
1852 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
1853 return ERROR_SUCCESS;
1857 /******************************************************************************
1858 * RegReplaceKeyA [ADVAPI32.161]
1860 LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
1861 LPCSTR lpOldFile )
1863 LONG ret;
1864 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
1865 LPWSTR lpNewFileW = strdupA2W(lpNewFile);
1866 LPWSTR lpOldFileW = strdupA2W(lpOldFile);
1867 ret = RegReplaceKeyW( hkey, lpSubKeyW, lpNewFileW, lpOldFileW );
1868 free(lpOldFileW);
1869 free(lpNewFileW);
1870 free(lpSubKeyW);
1871 return ret;
1879 /* 16-bit functions */
1881 /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
1882 * some programs. Do not remove those cases. -MM
1884 static inline void fix_win16_hkey( HKEY *hkey )
1886 if (*hkey == 0 || *hkey == 1) *hkey = HKEY_CLASSES_ROOT;
1889 /******************************************************************************
1890 * RegEnumKey16 [KERNEL.216] [SHELL.7]
1892 DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
1894 fix_win16_hkey( &hkey );
1895 return RegEnumKeyA( hkey, index, name, name_len );
1898 /******************************************************************************
1899 * RegOpenKey16 [KERNEL.217] [SHELL.1]
1901 DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
1903 fix_win16_hkey( &hkey );
1904 return RegOpenKeyA( hkey, name, retkey );
1907 /******************************************************************************
1908 * RegCreateKey16 [KERNEL.218] [SHELL.2]
1910 DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
1912 fix_win16_hkey( &hkey );
1913 return RegCreateKeyA( hkey, name, retkey );
1916 /******************************************************************************
1917 * RegDeleteKey16 [KERNEL.219] [SHELL.4]
1919 DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name )
1921 fix_win16_hkey( &hkey );
1922 return RegDeleteKeyA( hkey, name );
1925 /******************************************************************************
1926 * RegCloseKey16 [KERNEL.220] [SHELL.3]
1928 DWORD WINAPI RegCloseKey16( HKEY hkey )
1930 fix_win16_hkey( &hkey );
1931 return RegCloseKey( hkey );
1934 /******************************************************************************
1935 * RegSetValue16 [KERNEL.221] [SHELL.5]
1937 DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
1939 fix_win16_hkey( &hkey );
1940 return RegSetValueA( hkey, name, type, data, count );
1943 /******************************************************************************
1944 * RegDeleteValue16 [KERNEL.222]
1946 DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR name )
1948 fix_win16_hkey( &hkey );
1949 return RegDeleteValueA( hkey, name );
1952 /******************************************************************************
1953 * RegEnumValue16 [KERNEL.223]
1955 DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1956 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
1958 fix_win16_hkey( &hkey );
1959 return RegEnumValueA( hkey, index, value, val_count, reserved, type, data, count );
1962 /******************************************************************************
1963 * RegQueryValue16 [KERNEL.224] [SHELL.6]
1965 * NOTES
1966 * Is this HACK still applicable?
1968 * HACK
1969 * The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
1970 * mask out the high 16 bit. This (not so much incidently) hopefully fixes
1971 * Aldus FH4)
1973 DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count )
1975 fix_win16_hkey( &hkey );
1976 if (count) *count &= 0xffff;
1977 return RegQueryValueA( hkey, name, data, count );
1980 /******************************************************************************
1981 * RegQueryValueEx16 [KERNEL.225]
1983 DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
1984 LPBYTE data, LPDWORD count )
1986 fix_win16_hkey( &hkey );
1987 return RegQueryValueExA( hkey, name, reserved, type, data, count );
1990 /******************************************************************************
1991 * RegSetValueEx16 [KERNEL.226]
1993 DWORD WINAPI RegSetValueEx16( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
1994 CONST BYTE *data, DWORD count )
1996 fix_win16_hkey( &hkey );
1997 return RegSetValueExA( hkey, name, reserved, type, data, count );