Added a first-cut version of MapVirtualKeyExW() that has the same
[wine] / misc / registry.c
1 /*
2  *      Registry Functions
3  *
4  * Copyright 1996 Marcus Meissner
5  * Copyright 1998 Matthew Becker
6  * Copyright 1999 Sylvain St-Germain
7  *
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.
11  *
12  * NOTES
13  *    When changing this file, please re-run the regtest program to ensure
14  *    the conditions are handled properly.
15  *
16  * TODO
17  *    Security access
18  *    Option handling
19  *    Time for RegEnumKey*, RegQueryInfoKey*
20  */
21
22 #include "config.h"
23
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 "winnls.h"
42 #include "wine/winbase16.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"
51
52 DEFAULT_DEBUG_CHANNEL(reg);
53
54 static void REGISTRY_Init(void);
55 /* FIXME: following defines should be configured global ... */
56
57 #define SAVE_USERS_DEFAULT          ETCDIR"/wine.userreg"
58 #define SAVE_LOCAL_MACHINE_DEFAULT  ETCDIR"/wine.systemreg"
59
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"
65
66
67 static void *xmalloc( size_t size )
68 {
69     void *res;
70  
71     res = malloc (size ? size : 1);
72     if (res == NULL) {
73         WARN("Virtual memory exhausted.\n");
74         exit (1);
75     }
76     return res;
77 }                                                                              
78
79
80 /******************************************************************************
81  * REGISTRY_Init [Internal]
82  * Registry initialisation, allocates some default keys. 
83  */
84 static void REGISTRY_Init(void) {
85         HKEY    hkey;
86         char    buf[200];
87
88         TRACE("(void)\n");
89
90         RegCreateKeyA(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
91         RegCloseKey(hkey);
92
93         /* This was an Open, but since it is called before the real registries
94            are loaded, it was changed to a Create - MTB 980507*/
95         RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
96         RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
97         RegCloseKey(hkey);
98
99         /* \\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion
100          *                                              CurrentVersion
101          *                                              CurrentBuildNumber
102          *                                              CurrentType
103          *                                      string  RegisteredOwner
104          *                                      string  RegisteredOrganization
105          *
106          */
107         /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
108          *                                      string  SysContact
109          *                                      string  SysLocation
110          *                                              SysServices
111          */
112         if (-1!=gethostname(buf,200)) {
113                 RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
114                 RegSetValueExA(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
115                 RegCloseKey(hkey);
116         }
117 }
118
119
120 /************************ LOAD Registry Function ****************************/
121
122
123
124 /******************************************************************************
125  * _find_or_add_key [Internal]
126  */
127 static inline HKEY _find_or_add_key( HKEY hkey, LPWSTR keyname )
128 {
129     HKEY subkey;
130     if (RegCreateKeyW( hkey, keyname, &subkey ) != ERROR_SUCCESS) subkey = 0;
131     if (keyname) free( keyname );
132     return subkey;
133 }
134
135 /******************************************************************************
136  * _find_or_add_value [Internal]
137  */
138 static void _find_or_add_value( HKEY hkey, LPWSTR name, DWORD type, LPBYTE data, DWORD len )
139 {
140     RegSetValueExW( hkey, name, 0, type, data, len );
141     if (name) free( name );
142     if (data) free( data );
143 }
144
145
146 /******************************************************************************
147  * _wine_read_line [Internal]
148  *
149  * reads a line including dynamically enlarging the readbuffer and throwing
150  * away comments
151  */
152 static int _wine_read_line( FILE *F, char **buf, int *len )
153 {
154         char    *s,*curread;
155         int     mylen,curoff;
156
157         curread = *buf;
158         mylen   = *len;
159         **buf   = '\0';
160         while (1) {
161                 while (1) {
162                         s=fgets(curread,mylen,F);
163                         if (s==NULL)
164                                 return 0; /* EOF */
165                         if (NULL==(s=strchr(curread,'\n'))) {
166                                 /* buffer wasn't large enough */
167                                 curoff  = strlen(*buf);
168                                 curread = realloc(*buf,*len*2);
169                                 if(curread == NULL) {
170                                     WARN("Out of memory");
171                                     return 0;
172                                 }
173                                 *buf    = curread;
174                                 curread+= curoff;
175                                 mylen   = *len; /* we filled up the buffer and 
176                                                  * got new '*len' bytes to fill
177                                                  */
178                                 *len    = *len * 2;
179                         } else {
180                                 *s='\0';
181                                 break;
182                         }
183                 }
184                 /* throw away comments */
185                 if (**buf=='#' || **buf==';') {
186                         curread = *buf;
187                         mylen   = *len;
188                         continue;
189                 }
190                 if (s)  /* got end of line */
191                         break;
192         }
193         return 1;
194 }
195
196
197 /******************************************************************************
198  * _wine_read_USTRING [Internal]
199  *
200  * converts a char* into a UNICODE string (up to a special char)
201  * and returns the position exactly after that string
202  */
203 static char* _wine_read_USTRING( char *buf, LPWSTR *str )
204 {
205         char    *s;
206         LPWSTR  ws;
207
208         /* read up to "=" or "\0" or "\n" */
209         s       = buf;
210         *str    = (LPWSTR)xmalloc(2*strlen(buf)+2);
211         ws      = *str;
212         while (*s && (*s!='\n') && (*s!='=')) {
213                 if (*s!='\\')
214                         *ws++=*((unsigned char*)s++);
215                 else {
216                         s++;
217                         if (!*s) {
218                                 /* Dangling \ ... may only happen if a registry
219                                  * write was short. FIXME: What to do?
220                                  */
221                                  break;
222                         }
223                         if (*s=='\\') {
224                                 *ws++='\\';
225                                 s++;
226                                 continue;
227                         }
228                         if (*s!='u') {
229                                 WARN("Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
230                                 *ws++='\\';
231                                 *ws++=*s++;
232                         } else {
233                                 char    xbuf[5];
234                                 int     wc;
235
236                                 s++;
237                                 memcpy(xbuf,s,4);xbuf[4]='\0';
238                                 if (!sscanf(xbuf,"%x",&wc))
239                                         WARN("Strange escape sequence %s found in |%s|\n",xbuf,buf);
240                                 s+=4;
241                                 *ws++   =(unsigned short)wc;
242                         }
243                 }
244         }
245         *ws     = 0;
246         return s;
247 }
248
249
250 /******************************************************************************
251  * _wine_loadsubkey [Internal]
252  *
253  * NOTES
254  *    It seems like this is returning a boolean.  Should it?
255  *
256  * RETURNS
257  *    Success: 1
258  *    Failure: 0
259  */
260 static int _wine_loadsubkey( FILE *F, HKEY hkey, int level, char **buf, int *buflen )
261 {
262         HKEY subkey;
263         int             i;
264         char            *s;
265         LPWSTR          name;
266
267     TRACE("(%p,%x,%d,%s,%d)\n", F, hkey, level, debugstr_a(*buf), *buflen);
268
269     /* Good.  We already got a line here ... so parse it */
270     subkey = 0;
271     while (1) {
272         i=0;s=*buf;
273         while (*s=='\t') {
274             s++;
275             i++;
276         }
277         if (i>level) {
278             if (!subkey) {
279                 WARN("Got a subhierarchy without resp. key?\n");
280                 return 0;
281             }
282             if (!_wine_loadsubkey(F,subkey,level+1,buf,buflen))
283                if (!_wine_read_line(F,buf,buflen))
284                   goto done;
285             continue;
286         }
287
288                 /* let the caller handle this line */
289                 if (i<level || **buf=='\0')
290                         goto done;
291
292                 /* it can be: a value or a keyname. Parse the name first */
293                 s=_wine_read_USTRING(s,&name);
294
295                 /* switch() default: hack to avoid gotos */
296                 switch (0) {
297                 default:
298                         if (*s=='\0') {
299                                 if (subkey) RegCloseKey( subkey );
300                                 subkey=_find_or_add_key(hkey,name);
301                         } else {
302                                 LPBYTE          data;
303                                 int             len,lastmodified,type;
304
305                                 if (*s!='=') {
306                                         WARN("Unexpected character: %c\n",*s);
307                                         break;
308                                 }
309                                 s++;
310                                 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
311                                         WARN("Haven't understood possible value in |%s|, skipping.\n",*buf);
312                                         break;
313                                 }
314                                 /* skip the 2 , */
315                                 s=strchr(s,',');s++;
316                                 s=strchr(s,',');
317                                 if (!s++) {
318                                         WARN("Haven't understood possible value in |%s|, skipping.\n",*buf);
319                                         break;
320                                 }
321                                 if (type == REG_SZ || type == REG_EXPAND_SZ) {
322                                         s=_wine_read_USTRING(s,(LPWSTR*)&data);
323                                         len = lstrlenW((LPWSTR)data)*2+2;
324                                 } else {
325                                         len=strlen(s)/2;
326                                         data = (LPBYTE)xmalloc(len+1);
327                                         for (i=0;i<len;i++) {
328                                                 data[i]=0;
329                                                 if (*s>='0' && *s<='9')
330                                                         data[i]=(*s-'0')<<4;
331                                                 if (*s>='a' && *s<='f')
332                                                         data[i]=(*s-'a'+'\xa')<<4;
333                                                 if (*s>='A' && *s<='F')
334                                                         data[i]=(*s-'A'+'\xa')<<4;
335                                                 s++;
336                                                 if (*s>='0' && *s<='9')
337                                                         data[i]|=*s-'0';
338                                                 if (*s>='a' && *s<='f')
339                                                         data[i]|=*s-'a'+'\xa';
340                                                 if (*s>='A' && *s<='F')
341                                                         data[i]|=*s-'A'+'\xa';
342                                                 s++;
343                                         }
344                                 }
345                                 _find_or_add_value(hkey,name,type,data,len);
346                         }
347                 }
348                 /* read the next line */
349                 if (!_wine_read_line(F,buf,buflen))
350                         goto done;
351     }
352  done:
353     if (subkey) RegCloseKey( subkey );
354     return 1;
355 }
356
357
358 /******************************************************************************
359  * _wine_loadsubreg [Internal]
360  */
361 static int _wine_loadsubreg( FILE *F, HKEY hkey, const char *fn )
362 {
363         int     ver;
364         char    *buf;
365         int     buflen;
366
367         buf=xmalloc(10);buflen=10;
368         if (!_wine_read_line(F,&buf,&buflen)) {
369                 free(buf);
370                 return 0;
371         }
372         if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
373                 free(buf);
374                 return 0;
375         }
376         if (ver!=1) {
377             if (ver == 2)  /* new version */
378             {
379                 HANDLE file;
380                 if ((file = FILE_CreateFile( fn, GENERIC_READ, 0, NULL, OPEN_EXISTING,
381                                       FILE_ATTRIBUTE_NORMAL, -1, TRUE )) != INVALID_HANDLE_VALUE)
382                 {
383                     SERVER_START_REQ
384                     {
385                         struct load_registry_request *req = server_alloc_req( sizeof(*req), 0 );
386                         req->hkey    = hkey;
387                         req->file    = file;
388                         server_call( REQ_LOAD_REGISTRY );
389                     }
390                     SERVER_END_REQ;
391                     CloseHandle( file );
392                 }
393                 free( buf );
394                 return 1;
395             }
396             else
397             {
398                 TRACE("Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
399                 free(buf);
400                 return 0;
401             }
402         }
403         if (!_wine_read_line(F,&buf,&buflen)) {
404                 free(buf);
405                 return 0;
406         }
407         if (!_wine_loadsubkey(F,hkey,0,&buf,&buflen)) {
408                 free(buf);
409                 return 0;
410         }
411         free(buf);
412         return 1;
413 }
414
415
416 /******************************************************************************
417  * _wine_loadreg [Internal]
418  */
419 static int _wine_loadreg( HKEY hkey, char *fn )
420 {
421     FILE *F;
422
423     TRACE("(%x,%s)\n",hkey,debugstr_a(fn));
424
425     F = fopen(fn,"rb");
426     if (F==NULL) {
427         WARN("Couldn't open %s for reading: %s\n",fn,strerror(errno) );
428         return -1;
429     }
430     _wine_loadsubreg(F,hkey,fn);
431     fclose(F);
432     return 0;
433 }
434
435 /* NT REGISTRY LOADER */
436
437 #ifdef HAVE_SYS_MMAN_H
438 # include <sys/mman.h>
439 #endif
440
441 #ifndef MAP_FAILED
442 #define MAP_FAILED ((LPVOID)-1)
443 #endif
444
445 #define  NT_REG_BLOCK_SIZE              0x1000
446
447 #define NT_REG_HEADER_BLOCK_ID       0x66676572 /* regf */
448 #define NT_REG_POOL_BLOCK_ID         0x6E696268 /* hbin */
449 #define NT_REG_KEY_BLOCK_ID          0x6b6e /* nk */
450 #define NT_REG_VALUE_BLOCK_ID        0x6b76 /* vk */
451
452 /* subblocks of nk */
453 #define NT_REG_HASH_BLOCK_ID         0x666c /* lf */
454 #define NT_REG_NOHASH_BLOCK_ID       0x696c /* li */
455 #define NT_REG_RI_BLOCK_ID           0x6972 /* ri */
456
457 #define NT_REG_KEY_BLOCK_TYPE        0x20
458 #define NT_REG_ROOT_KEY_BLOCK_TYPE   0x2c
459
460 typedef struct 
461 {
462         DWORD   id;             /* 0x66676572 'regf'*/
463         DWORD   uk1;            /* 0x04 */
464         DWORD   uk2;            /* 0x08 */
465         FILETIME        DateModified;   /* 0x0c */
466         DWORD   uk3;            /* 0x14 */
467         DWORD   uk4;            /* 0x18 */
468         DWORD   uk5;            /* 0x1c */
469         DWORD   uk6;            /* 0x20 */
470         DWORD   RootKeyBlock;   /* 0x24 */
471         DWORD   BlockSize;      /* 0x28 */
472         DWORD   uk7[116];       
473         DWORD   Checksum; /* at offset 0x1FC */
474 } nt_regf;
475
476 typedef struct
477 {
478         DWORD   blocksize;
479         BYTE    data[1];
480 } nt_hbin_sub;
481
482 typedef struct
483 {
484         DWORD   id;             /* 0x6E696268 'hbin' */
485         DWORD   off_prev;
486         DWORD   off_next;
487         DWORD   uk1;
488         DWORD   uk2;            /* 0x10 */
489         DWORD   uk3;            /* 0x14 */
490         DWORD   uk4;            /* 0x18 */
491         DWORD   size;           /* 0x1C */
492         nt_hbin_sub     hbin_sub;       /* 0x20 */
493 } nt_hbin;
494
495 /*
496  * the value_list consists of offsets to the values (vk)
497  */
498 typedef struct
499 {
500         WORD    SubBlockId;             /* 0x00 0x6B6E */
501         WORD    Type;                   /* 0x02 for the root-key: 0x2C, otherwise 0x20*/
502         FILETIME        writetime;      /* 0x04 */
503         DWORD   uk1;                    /* 0x0C */
504         DWORD   parent_off;             /* 0x10 Offset of Owner/Parent key */
505         DWORD   nr_subkeys;             /* 0x14 number of sub-Keys */
506         DWORD   uk8;                    /* 0x18 */
507         DWORD   lf_off;                 /* 0x1C Offset of the sub-key lf-Records */
508         DWORD   uk2;                    /* 0x20 */
509         DWORD   nr_values;              /* 0x24 number of values */
510         DWORD   valuelist_off;          /* 0x28 Offset of the Value-List */
511         DWORD   off_sk;                 /* 0x2c Offset of the sk-Record */
512         DWORD   off_class;              /* 0x30 Offset of the Class-Name */
513         DWORD   uk3;                    /* 0x34 */
514         DWORD   uk4;                    /* 0x38 */
515         DWORD   uk5;                    /* 0x3c */
516         DWORD   uk6;                    /* 0x40 */
517         DWORD   uk7;                    /* 0x44 */
518         WORD    name_len;               /* 0x48 name-length */
519         WORD    class_len;              /* 0x4a class-name length */
520         char    name[1];                /* 0x4c key-name */
521 } nt_nk;
522
523 typedef struct
524 {
525         DWORD   off_nk; /* 0x00 */
526         DWORD   name;   /* 0x04 */
527 } hash_rec;
528
529 typedef struct
530 {
531         WORD    id;             /* 0x00 0x666c */
532         WORD    nr_keys;        /* 0x06 */
533         hash_rec        hash_rec[1];
534 } nt_lf;
535
536 /*
537  list of subkeys without hash
538
539  li --+-->nk
540       |
541       +-->nk
542  */
543 typedef struct
544 {
545         WORD    id;             /* 0x00 0x696c */
546         WORD    nr_keys;
547         DWORD   off_nk[1];
548 } nt_li;
549
550 /*
551  this is a intermediate node
552
553  ri --+-->li--+-->nk
554       |       +
555       |       +-->nk
556       |
557       +-->li--+-->nk
558               +
559               +-->nk
560  */
561 typedef struct
562 {
563         WORD    id;             /* 0x00 0x6972 */
564         WORD    nr_li;          /* 0x02 number off offsets */
565         DWORD   off_li[1];      /* 0x04 points to li */
566 } nt_ri;
567
568 typedef struct
569 {
570         WORD    id;             /* 0x00 'vk' */
571         WORD    nam_len;
572         DWORD   data_len;
573         DWORD   data_off;
574         DWORD   type;
575         WORD    flag;
576         WORD    uk1;
577         char    name[1];
578 } nt_vk;
579
580 LPSTR _strdupnA( LPCSTR str, int len )
581 {
582     LPSTR ret;
583
584     if (!str) return NULL;
585     ret = xmalloc( len + 1 );
586     memcpy( ret, str, len );
587     ret[len] = 0x00;
588     return ret;
589 }
590
591 static int _nt_parse_nk(HKEY hkey, char * base, nt_nk * nk, int level);
592 static int _nt_parse_vk(HKEY hkey, char * base, nt_vk * vk);
593 static int _nt_parse_lf(HKEY hkey, char * base, int subkeys, nt_lf * lf, int level);
594
595
596 /*
597  * gets a value
598  *
599  * vk->flag:
600  *  0 value is a default value
601  *  1 the value has a name
602  *
603  * vk->data_len
604  *  len of the whole data block
605  *  - reg_sz (unicode)
606  *    bytes including the terminating \0 = 2*(number_of_chars+1)
607  *  - reg_dword, reg_binary:
608  *    if highest bit of data_len is set data_off contains the value
609  */
610 static int _nt_parse_vk(HKEY hkey, char * base, nt_vk * vk)
611 {
612         WCHAR name [256];
613         DWORD len, ret;
614         BYTE * pdata = (BYTE *)(base+vk->data_off+4); /* start of data */
615
616         if(vk->id != NT_REG_VALUE_BLOCK_ID) goto error;
617
618         if (!(len = MultiByteToWideChar( CP_ACP, 0, vk->name, vk->nam_len, name, 256 )) && vk->nam_len)
619         {
620             ERR("name too large '%.*s' (%d)\n", vk->nam_len, vk->name, vk->nam_len );
621             return FALSE;
622         }
623         name[len] = 0;
624
625         ret = RegSetValueExW( hkey, (vk->flag & 0x00000001) ? name : NULL, 0, vk->type,
626                         (vk->data_len & 0x80000000) ? (LPBYTE)&(vk->data_off): pdata,
627                         (vk->data_len & 0x7fffffff) );
628         if (ret) ERR("RegSetValueEx failed (0x%08lx)\n", ret);
629         return TRUE;
630 error:
631         ERR("unknown block found (0x%04x), please report!\n", vk->id);
632         return FALSE;
633 }
634
635 /*
636  * get the subkeys
637  *
638  * this structure contains the hash of a keyname and points to all
639  * subkeys
640  *
641  * exception: if the id is 'il' there are no hash values and every 
642  * dword is a offset
643  */
644 static int _nt_parse_lf(HKEY hkey, char * base, int subkeys, nt_lf * lf, int level)
645 {
646         int i;
647
648         if (lf->id == NT_REG_HASH_BLOCK_ID)
649         {
650           if (subkeys != lf->nr_keys) goto error1;
651
652           for (i=0; i<lf->nr_keys; i++)
653           {
654             if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+lf->hash_rec[i].off_nk+4), level)) goto error;
655           }
656         }
657         else if (lf->id == NT_REG_NOHASH_BLOCK_ID)
658         {
659           nt_li * li = (nt_li*)lf;
660           if (subkeys != li->nr_keys) goto error1;
661
662           for (i=0; i<li->nr_keys; i++)
663           {
664             if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+li->off_nk[i]+4), level)) goto error;
665           }
666         }
667         else if (lf->id == NT_REG_RI_BLOCK_ID) /* ri */
668         {
669           nt_ri * ri = (nt_ri*)lf;
670           int li_subkeys = 0;
671
672           /* count all subkeys */
673           for (i=0; i<ri->nr_li; i++)
674           {
675             nt_li * li = (nt_li*)(base+ri->off_li[i]+4);
676             if(li->id != NT_REG_NOHASH_BLOCK_ID) goto error2;
677             li_subkeys += li->nr_keys;
678           }
679
680           /* check number */
681           if (subkeys != li_subkeys) goto error1;
682
683           /* loop through the keys */
684           for (i=0; i<ri->nr_li; i++)
685           {
686             nt_li * li = (nt_li*)(base+ri->off_li[i]+4);
687             if (!_nt_parse_lf(hkey, base, li->nr_keys, (nt_lf*)li, level)) goto error;
688           }
689         }
690         else 
691         {
692           goto error2;
693         }
694         return TRUE;
695
696 error2: ERR("unknown node id 0x%04x, please report!\n", lf->id);
697         return TRUE;
698         
699 error1: ERR("registry file corrupt! (inconsistent number of subkeys)\n");
700         return FALSE;
701
702 error:  ERR("error reading lf block\n");
703         return FALSE;
704 }
705
706 static int _nt_parse_nk(HKEY hkey, char * base, nt_nk * nk, int level)
707 {
708         char * name;
709         unsigned int n;
710         DWORD * vl;
711         HKEY subkey = hkey;
712
713         if(nk->SubBlockId != NT_REG_KEY_BLOCK_ID)
714         {
715           ERR("unknown node id 0x%04x, please report!\n", nk->SubBlockId);
716           goto error;
717         }
718
719         if((nk->Type!=NT_REG_ROOT_KEY_BLOCK_TYPE) &&
720            (((nt_nk*)(base+nk->parent_off+4))->SubBlockId != NT_REG_KEY_BLOCK_ID))
721         {
722           ERR("registry file corrupt!\n");
723           goto error;
724         }
725
726         /* create the new key */
727         if(level <= 0)
728         {
729           name = _strdupnA( nk->name, nk->name_len);
730           if(RegCreateKeyA( hkey, name, &subkey )) { free(name); goto error; }
731           free(name);
732         }
733
734         /* loop through the subkeys */
735         if (nk->nr_subkeys)
736         {
737           nt_lf * lf = (nt_lf*)(base+nk->lf_off+4);
738           if (!_nt_parse_lf(subkey, base, nk->nr_subkeys, lf, level-1)) goto error1;
739         }
740
741         /* loop trough the value list */
742         vl = (DWORD *)(base+nk->valuelist_off+4);
743         for (n=0; n<nk->nr_values; n++)
744         {
745           nt_vk * vk = (nt_vk*)(base+vl[n]+4);
746           if (!_nt_parse_vk(subkey, base, vk)) goto error1;
747         }
748
749         /* Don't close the subkey if it is the hkey that was passed
750          * (i.e. Level was <= 0)
751          */
752         if( subkey!=hkey ) RegCloseKey(subkey);
753         return TRUE;
754         
755 error1: RegCloseKey(subkey);
756 error:  return FALSE;
757 }
758
759 /* end nt loader */
760
761 /* windows 95 registry loader */
762
763 /* SECTION 1: main header
764  *
765  * once at offset 0
766  */
767 #define W95_REG_CREG_ID 0x47455243
768
769 typedef struct 
770 {
771         DWORD   id;             /* "CREG" = W95_REG_CREG_ID */
772         DWORD   version;        /* ???? 0x00010000 */
773         DWORD   rgdb_off;       /* 0x08 Offset of 1st RGDB-block */
774         DWORD   uk2;            /* 0x0c */
775         WORD    rgdb_num;       /* 0x10 # of RGDB-blocks */
776         WORD    uk3;
777         DWORD   uk[3];
778         /* rgkn */
779 } _w95creg;
780
781 /* SECTION 2: Directory information (tree structure)
782  *
783  * once on offset 0x20
784  *
785  * structure: [rgkn][dke]*      (repeat till last_dke is reached)
786  */
787 #define W95_REG_RGKN_ID 0x4e4b4752
788
789 typedef struct
790 {
791         DWORD   id;             /*"RGKN" = W95_REG_RGKN_ID */
792         DWORD   size;           /* Size of the RGKN-block */
793         DWORD   root_off;       /* Rel. Offset of the root-record */
794         DWORD   last_dke;       /* Offset to last DKE ? */
795         DWORD   uk[4];
796 } _w95rgkn;
797
798 /* Disk Key Entry Structure
799  *
800  * the 1st entry in a "usual" registry file is a nul-entry with subkeys: the
801  * hive itself. It looks the same like other keys. Even the ID-number can
802  * be any value.
803  *
804  * The "hash"-value is a value representing the key's name. Windows will not
805  * search for the name, but for a matching hash-value. if it finds one, it
806  * will compare the actual string info, otherwise continue with the next key.
807  * To calculate the hash initialize a D-Word with 0 and add all ASCII-values 
808  * of the string which are smaller than 0x80 (128) to this D-Word.   
809  *
810  * If you want to modify key names, also modify the hash-values, since they
811  * cannot be found again (although they would be displayed in REGEDIT)
812  * End of list-pointers are filled with 0xFFFFFFFF
813  *
814  * Disk keys are layed out flat ... But, sometimes, nrLS and nrMS are both
815  * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
816  * structure) and reading another RGDB_section.
817  *
818  * The last DKE (see field last_dke in _w95_rgkn) has only 3 DWORDs with
819  * 0x80000000 (EOL indicator ?) as x1, the hash value and 0xFFFFFFFF as x3.
820  * The remaining space between last_dke and the offset calculated from
821  * rgkn->size seems to be free for use for more dke:s.
822  * So it seems if more dke:s are added, they are added to that space and
823  * last_dke is grown, and in case that "free" space is out, the space
824  * gets grown and rgkn->size gets adjusted.
825  *
826  * there is a one to one relationship between dke and dkh
827  */
828  /* key struct, once per key */
829 typedef struct
830 {
831         DWORD   x1;             /* Free entry indicator(?) */
832         DWORD   hash;           /* sum of bytes of keyname */
833         DWORD   x3;             /* Root key indicator? usually 0xFFFFFFFF */
834         DWORD   prevlvl;        /* offset of previous key */
835         DWORD   nextsub;        /* offset of child key */
836         DWORD   next;           /* offset of sibling key */
837         WORD    nrLS;           /* id inside the rgdb block */
838         WORD    nrMS;           /* number of the rgdb block */
839 } _w95dke;
840
841 /* SECTION 3: key information, values and data
842  *
843  * structure:
844  *  section:    [blocks]*               (repeat creg->rgdb_num times)
845  *  blocks:     [rgdb] [subblocks]*     (repeat till block size reached )
846  *  subblocks:  [dkh] [dkv]*            (repeat dkh->values times )
847  *
848  * An interesting relationship exists in RGDB_section. The DWORD value
849  * at offset 0x10 equals the one at offset 0x04 minus the one at offset 0x08.
850  * I have no idea at the moment what this means.  (Kevin Cozens)
851  */
852
853 /* block header, once per block */
854 #define W95_REG_RGDB_ID 0x42444752
855
856 typedef struct
857 {
858         DWORD   id;     /* 0x00 'RGDB' = W95_REG_RGDB_ID */
859         DWORD   size;   /* 0x04 */
860         DWORD   uk1;    /* 0x08 */
861         DWORD   uk2;    /* 0x0c */
862         DWORD   uk3;    /* 0x10 */
863         DWORD   uk4;    /* 0x14 */
864         DWORD   uk5;    /* 0x18 */
865         DWORD   uk6;    /* 0x1c */
866         /* dkh */
867 } _w95rgdb;
868
869 /* Disk Key Header structure (RGDB part), once per key */
870 typedef struct 
871 {
872         DWORD   nextkeyoff;     /* 0x00 offset to next dkh */
873         WORD    nrLS;           /* 0x04 id inside the rgdb block */
874         WORD    nrMS;           /* 0x06 number of the rgdb block */
875         DWORD   bytesused;      /* 0x08 */
876         WORD    keynamelen;     /* 0x0c len of name */
877         WORD    values;         /* 0x0e number of values */
878         DWORD   xx1;            /* 0x10 */
879         char    name[1];        /* 0x14 */
880         /* dkv */               /* 0x14 + keynamelen */
881 } _w95dkh;
882
883 /* Disk Key Value structure, once per value */
884 typedef struct
885 {
886         DWORD   type;           /* 0x00 */
887         DWORD   x1;             /* 0x04 */
888         WORD    valnamelen;     /* 0x08 length of name, 0 is default key */
889         WORD    valdatalen;     /* 0x0A length of data */
890         char    name[1];        /* 0x0c */
891         /* raw data */          /* 0x0c + valnamelen */
892 } _w95dkv;
893
894 /******************************************************************************
895  * _w95_lookup_dkh [Internal]
896  *
897  * seeks the dkh belonging to a dke
898  */
899 static _w95dkh * _w95_lookup_dkh (_w95creg *creg, int nrLS, int nrMS)
900 {
901         _w95rgdb * rgdb;
902         _w95dkh * dkh;
903         int i;
904         
905         /* get the beginning of the rgdb datastore */
906         rgdb = (_w95rgdb*)((char*)creg+creg->rgdb_off);
907
908         /* check: requested block < last_block) */
909         if (creg->rgdb_num <= nrMS)                             
910         {
911           ERR("registry file corrupt! requested block no. beyond end.\n");
912           goto error;
913         }
914         
915         /* find the right block */
916         for(i=0; i<nrMS ;i++)
917         {
918           if(rgdb->id != W95_REG_RGDB_ID)                       /* check the magic */
919           {
920             ERR("registry file corrupt! bad magic 0x%08lx\n", rgdb->id);
921             goto error;
922           }
923           rgdb = (_w95rgdb*) ((char*)rgdb+rgdb->size);          /* find next block */
924         }
925
926         dkh = (_w95dkh*)(rgdb + 1);                             /* first sub block within the rgdb */
927
928         do
929         {
930           if(nrLS==dkh->nrLS ) return dkh;
931           dkh = (_w95dkh*)((char*)dkh + dkh->nextkeyoff);       /* find next subblock */
932         } while ((char *)dkh < ((char*)rgdb+rgdb->size));
933
934 error:  return NULL;
935 }       
936  
937 /******************************************************************************
938  * _w95_parse_dkv [Internal]
939  */
940 static int _w95_parse_dkv (
941         HKEY hkey,
942         _w95dkh * dkh,
943         int nrLS,
944         int nrMS )
945 {
946         _w95dkv * dkv;
947         int i;
948         DWORD ret;
949         char * name;
950                         
951         /* first value block */
952         dkv = (_w95dkv*)((char*)dkh+dkh->keynamelen+0x14);
953
954         /* loop trought the values */
955         for (i=0; i< dkh->values; i++)
956         {
957           name = _strdupnA(dkv->name, dkv->valnamelen);
958           ret = RegSetValueExA(hkey, name, 0, dkv->type, &(dkv->name[dkv->valnamelen]),dkv->valdatalen); 
959           if (ret) FIXME("RegSetValueEx returned: 0x%08lx\n", ret);
960           free (name);
961
962           /* next value */
963           dkv = (_w95dkv*)((char*)dkv+dkv->valnamelen+dkv->valdatalen+0x0c);
964         }
965         return TRUE;
966 }
967
968 /******************************************************************************
969  * _w95_parse_dke [Internal]
970  */
971 static int _w95_parse_dke( 
972         HKEY hkey,
973         _w95creg * creg,
974         _w95rgkn *rgkn,
975         _w95dke * dke,
976         int level )
977 {
978         _w95dkh * dkh;
979         HKEY hsubkey = hkey;
980         char * name;
981         int ret = FALSE;
982
983         /* special root key */
984         if (dke->nrLS == 0xffff || dke->nrMS==0xffff)           /* eg. the root key has no name */
985         {
986           /* parse the one subkey */
987           if (dke->nextsub != 0xffffffff) 
988           {
989             return _w95_parse_dke(hsubkey, creg, rgkn, (_w95dke*)((char*)rgkn+dke->nextsub), level);
990           }
991           /* has no sibling keys */
992           goto error;
993         }
994
995         /* search subblock */
996         if (!(dkh = _w95_lookup_dkh(creg, dke->nrLS, dke->nrMS)))
997         {
998           fprintf(stderr, "dke pointing to missing dkh !\n");
999           goto error;
1000         }
1001
1002         if ( level <= 0 )
1003         {
1004           /* walk sibling keys */
1005           if (dke->next != 0xffffffff )
1006           {
1007             if (!_w95_parse_dke(hkey, creg, rgkn, (_w95dke*)((char*)rgkn+dke->next), level)) goto error;
1008           }
1009
1010           /* create subkey and insert values */
1011           name = _strdupnA( dkh->name, dkh->keynamelen);
1012           if (RegCreateKeyA(hkey, name, &hsubkey)) { free(name); goto error; }
1013           free(name);
1014           if (!_w95_parse_dkv(hsubkey, dkh, dke->nrLS, dke->nrMS)) goto error1;
1015         }  
1016         
1017         /* next sub key */
1018         if (dke->nextsub != 0xffffffff) 
1019         {
1020           if (!_w95_parse_dke(hsubkey, creg, rgkn, (_w95dke*)((char*)rgkn+dke->nextsub), level-1)) goto error1;
1021         }
1022
1023         ret = TRUE;
1024 error1: if (hsubkey != hkey) RegCloseKey(hsubkey);
1025 error:  return ret;
1026 }
1027 /* end windows 95 loader */
1028
1029 /******************************************************************************
1030  *      NativeRegLoadKey [Internal]
1031  *
1032  * Loads a native registry file (win95/nt)
1033  *      hkey    root key
1034  *      fn      filename
1035  *      level   number of levels to cut away (eg. ".Default" in user.dat)
1036  *
1037  * this function intentionally uses unix file functions to make it possible
1038  * to move it to a seperate registry helper programm
1039  */
1040 static int NativeRegLoadKey( HKEY hkey, char* fn, int level )
1041 {
1042         int fd = 0;
1043         struct stat st;
1044         DOS_FULL_NAME full_name;
1045         int ret = FALSE;
1046         void * base;
1047         char *filetype = "unknown";
1048                         
1049         if (!DOSFS_GetFullName( fn, 0, &full_name )) return FALSE;
1050         
1051         /* map the registry into the memory */
1052         if ((fd = open(full_name.long_name, O_RDONLY | O_NONBLOCK)) == -1) return FALSE;
1053         if ((fstat(fd, &st) == -1)) goto error;
1054         if (!st.st_size) goto error;
1055         if ((base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto error;
1056
1057         switch (*(LPDWORD)base)
1058         {
1059           /* windows 95 'CREG' */
1060           case W95_REG_CREG_ID:
1061             {
1062               _w95creg *creg;
1063               _w95rgkn *rgkn;
1064               _w95dke *dke, *root_dke;
1065               creg = base;
1066               filetype = "win95";
1067               TRACE("Loading %s registry '%s' '%s'\n", filetype, fn, full_name.long_name);
1068
1069               /* load the header (rgkn) */
1070               rgkn = (_w95rgkn*)(creg + 1);
1071               if (rgkn->id != W95_REG_RGKN_ID) 
1072               {
1073                 ERR("second IFF header not RGKN, but %lx\n", rgkn->id);
1074                 goto error1;
1075               }
1076               if (rgkn->root_off != 0x20)
1077               {
1078                 ERR("rgkn->root_off not 0x20, please report !\n");
1079                 goto error1;
1080               }
1081               if (rgkn->last_dke > rgkn->size)
1082               {
1083                 ERR("registry file corrupt! last_dke > size!\n");
1084                 goto error1;
1085               }
1086               /* verify last dke */
1087               dke = (_w95dke*)((char*)rgkn + rgkn->last_dke);
1088               if (dke->x1 != 0x80000000)
1089               { /* wrong magic */
1090                 ERR("last dke invalid !\n");
1091                 goto error1;
1092               }
1093               if (rgkn->size > creg->rgdb_off)
1094               {
1095                 ERR("registry file corrupt! rgkn size > rgdb_off !\n");
1096                 goto error1;
1097               }
1098               root_dke = (_w95dke*)((char*)rgkn + rgkn->root_off);
1099               if ( (root_dke->prevlvl != 0xffffffff)
1100                 || (root_dke->next != 0xffffffff) )
1101               {
1102                 ERR("registry file corrupt! invalid root dke !\n");
1103                 goto error1;
1104               }
1105
1106               ret = _w95_parse_dke(hkey, creg, rgkn, root_dke, level);
1107             }
1108             break;
1109           /* nt 'regf'*/
1110           case NT_REG_HEADER_BLOCK_ID:
1111             {
1112               nt_regf * regf;
1113               nt_hbin * hbin;
1114               nt_hbin_sub * hbin_sub;
1115               nt_nk* nk;
1116
1117               filetype = "NT";
1118               TRACE("Loading %s registry '%s' '%s'\n", filetype, fn, full_name.long_name);
1119
1120               /* start block */
1121               regf = base;
1122
1123               /* hbin block */
1124               hbin = (nt_hbin*)((char*) base + 0x1000);
1125               if (hbin->id != NT_REG_POOL_BLOCK_ID)
1126               {
1127                 ERR( "hbin block invalid\n");
1128                 goto error1;
1129               }
1130
1131               /* hbin_sub block */
1132               hbin_sub = (nt_hbin_sub*)&(hbin->hbin_sub);
1133               if ((hbin_sub->data[0] != 'n') || (hbin_sub->data[1] != 'k'))
1134               {
1135                 ERR( "hbin_sub block invalid\n");
1136                 goto error1;
1137               }
1138
1139               /* nk block */
1140               nk = (nt_nk*)&(hbin_sub->data[0]);
1141               if (nk->Type != NT_REG_ROOT_KEY_BLOCK_TYPE)
1142               {
1143                 ERR( "special nk block not found\n");
1144                 goto error1;
1145               }
1146
1147               ret = _nt_parse_nk (hkey, (char *) base + 0x1000, nk, level);
1148             }
1149             break;
1150           default:
1151             {
1152               ERR("unknown registry signature !\n");
1153               goto error1;
1154             }
1155         }
1156 error1: if(!ret)
1157         {
1158           ERR("error loading %s registry file %s\n",
1159                                                 filetype, full_name.long_name);
1160           if (!strcmp(filetype, "win95"))
1161             ERR("Please report to a.mohr@mailto.de.\n");
1162           ERR("Make a backup of the file, run a good reg cleaner program and try again !\n");
1163         }
1164         munmap(base, st.st_size);
1165 error:  close(fd);
1166         return ret;     
1167 }
1168
1169 /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1170 /*
1171     reghack - windows 3.11 registry data format demo program.
1172
1173     The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1174     a combined hash table and tree description, and finally a text table.
1175
1176     The header is obvious from the struct header. The taboff1 and taboff2
1177     fields are always 0x20, and their usage is unknown.
1178
1179     The 8-byte entry table has various entry types.
1180
1181     tabent[0] is a root index. The second word has the index of the root of
1182             the directory.
1183     tabent[1..hashsize] is a hash table. The first word in the hash entry is
1184             the index of the key/value that has that hash. Data with the same
1185             hash value are on a circular list. The other three words in the
1186             hash entry are always zero.
1187     tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1188             entry: dirent and keyent/valent. They are identified by context.
1189     tabent[freeidx] is the first free entry. The first word in a free entry
1190             is the index of the next free entry. The last has 0 as a link.
1191             The other three words in the free list are probably irrelevant.
1192
1193     Entries in text table are preceded by a word at offset-2. This word
1194     has the value (2*index)+1, where index is the referring keyent/valent
1195     entry in the table. I have no suggestion for the 2* and the +1.
1196     Following the word, there are N bytes of data, as per the keyent/valent
1197     entry length. The offset of the keyent/valent entry is from the start
1198     of the text table to the first data byte.
1199
1200     This information is not available from Microsoft. The data format is
1201     deduced from the reg.dat file by me. Mistakes may
1202     have been made. I claim no rights and give no guarantees for this program.
1203
1204     Tor Sjøwall, tor@sn.no
1205 */
1206
1207 /* reg.dat header format */
1208 struct _w31_header {
1209         char            cookie[8];      /* 'SHCC3.10' */
1210         unsigned long   taboff1;        /* offset of hash table (??) = 0x20 */
1211         unsigned long   taboff2;        /* offset of index table (??) = 0x20 */
1212         unsigned long   tabcnt;         /* number of entries in index table */
1213         unsigned long   textoff;        /* offset of text part */
1214         unsigned long   textsize;       /* byte size of text part */
1215         unsigned short  hashsize;       /* hash size */
1216         unsigned short  freeidx;        /* free index */
1217 };
1218
1219 /* generic format of table entries */
1220 struct _w31_tabent {
1221         unsigned short w0, w1, w2, w3;
1222 };
1223
1224 /* directory tabent: */
1225 struct _w31_dirent {
1226         unsigned short  sibling_idx;    /* table index of sibling dirent */
1227         unsigned short  child_idx;      /* table index of child dirent */
1228         unsigned short  key_idx;        /* table index of key keyent */
1229         unsigned short  value_idx;      /* table index of value valent */
1230 };
1231
1232 /* key tabent: */
1233 struct _w31_keyent {
1234         unsigned short  hash_idx;       /* hash chain index for string */
1235         unsigned short  refcnt;         /* reference count */
1236         unsigned short  length;         /* length of string */
1237         unsigned short  string_off;     /* offset of string in text table */
1238 };
1239
1240 /* value tabent: */
1241 struct _w31_valent {
1242         unsigned short  hash_idx;       /* hash chain index for string */
1243         unsigned short  refcnt;         /* reference count */
1244         unsigned short  length;         /* length of string */
1245         unsigned short  string_off;     /* offset of string in text table */
1246 };
1247
1248 /* recursive helper function to display a directory tree */
1249 void
1250 __w31_dumptree( unsigned short idx,
1251                 unsigned char *txt,
1252                 struct _w31_tabent *tab,
1253                 struct _w31_header *head,
1254                 HKEY hkey,
1255                 time_t          lastmodified,
1256                 int             level
1257 ) {
1258         struct _w31_dirent      *dir;
1259         struct _w31_keyent      *key;
1260         struct _w31_valent      *val;
1261         HKEY subkey = 0;
1262         static char             tail[400];
1263
1264         while (idx!=0) {
1265                 dir=(struct _w31_dirent*)&tab[idx];
1266
1267                 if (dir->key_idx) {
1268                         key = (struct _w31_keyent*)&tab[dir->key_idx];
1269
1270                         memcpy(tail,&txt[key->string_off],key->length);
1271                         tail[key->length]='\0';
1272                         /* all toplevel entries AND the entries in the 
1273                          * toplevel subdirectory belong to \SOFTWARE\Classes
1274                          */
1275                         if (!level && !strcmp(tail,".classes")) {
1276                                 __w31_dumptree(dir->child_idx,txt,tab,head,hkey,lastmodified,level+1);
1277                                 idx=dir->sibling_idx;
1278                                 continue;
1279                         }
1280                         if (subkey) RegCloseKey( subkey );
1281                         if (RegCreateKeyA( hkey, tail, &subkey ) != ERROR_SUCCESS) subkey = 0;
1282                         /* only add if leaf node or valued node */
1283                         if (dir->value_idx!=0||dir->child_idx==0) {
1284                                 if (dir->value_idx) {
1285                                         val=(struct _w31_valent*)&tab[dir->value_idx];
1286                                         memcpy(tail,&txt[val->string_off],val->length);
1287                                         tail[val->length]='\0';
1288                                         RegSetValueA( subkey, NULL, REG_SZ, tail, 0 );
1289                                 }
1290                         }
1291                 } else {
1292                         TRACE("strange: no directory key name, idx=%04x\n", idx);
1293                 }
1294                 __w31_dumptree(dir->child_idx,txt,tab,head,subkey,lastmodified,level+1);
1295                 idx=dir->sibling_idx;
1296         }
1297         if (subkey) RegCloseKey( subkey );
1298 }
1299
1300
1301 /******************************************************************************
1302  * _w31_loadreg [Internal]
1303  */
1304 void _w31_loadreg(void) {
1305         HFILE                   hf;
1306         struct _w31_header      head;
1307         struct _w31_tabent      *tab;
1308         unsigned char           *txt;
1309         unsigned int            len;
1310         OFSTRUCT                ofs;
1311         BY_HANDLE_FILE_INFORMATION hfinfo;
1312         time_t                  lastmodified;
1313
1314         TRACE("(void)\n");
1315
1316         hf = OpenFile("reg.dat",&ofs,OF_READ);
1317         if (hf==HFILE_ERROR)
1318                 return;
1319
1320         /* read & dump header */
1321         if (sizeof(head)!=_lread(hf,&head,sizeof(head))) {
1322                 ERR("reg.dat is too short.\n");
1323                 _lclose(hf);
1324                 return;
1325         }
1326         if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
1327                 ERR("reg.dat has bad signature.\n");
1328                 _lclose(hf);
1329                 return;
1330         }
1331
1332         len = head.tabcnt * sizeof(struct _w31_tabent);
1333         /* read and dump index table */
1334         tab = xmalloc(len);
1335         if (len!=_lread(hf,tab,len)) {
1336                 ERR("couldn't read %d bytes.\n",len); 
1337                 free(tab);
1338                 _lclose(hf);
1339                 return;
1340         }
1341
1342         /* read text */
1343         txt = xmalloc(head.textsize);
1344         if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
1345                 ERR("couldn't seek to textblock.\n"); 
1346                 free(tab);
1347                 free(txt);
1348                 _lclose(hf);
1349                 return;
1350         }
1351         if (head.textsize!=_lread(hf,txt,head.textsize)) {
1352                 ERR("textblock too short (%d instead of %ld).\n",len,head.textsize); 
1353                 free(tab);
1354                 free(txt);
1355                 _lclose(hf);
1356                 return;
1357         }
1358
1359         if (!GetFileInformationByHandle(hf,&hfinfo)) {
1360                 ERR("GetFileInformationByHandle failed?.\n"); 
1361                 free(tab);
1362                 free(txt);
1363                 _lclose(hf);
1364                 return;
1365         }
1366         lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
1367         __w31_dumptree(tab[0].w1,txt,tab,&head,HKEY_CLASSES_ROOT,lastmodified,0);
1368         free(tab);
1369         free(txt);
1370         _lclose(hf);
1371         return;
1372 }
1373
1374
1375 static void save_at_exit( HKEY hkey, const char *path )
1376 {
1377     const char *confdir = get_config_dir();
1378     size_t len = strlen(confdir) + strlen(path) + 2;
1379     if (len > REQUEST_MAX_VAR_SIZE)
1380     {
1381         ERR( "config dir '%s' too long\n", confdir );
1382         return;
1383     }
1384     SERVER_START_REQ
1385     {
1386         struct save_registry_atexit_request *req = server_alloc_req( sizeof(*req), len );
1387         sprintf( server_data_ptr(req), "%s/%s", confdir, path );
1388         req->hkey = hkey;
1389         server_call( REQ_SAVE_REGISTRY_ATEXIT );
1390     }
1391     SERVER_END_REQ;
1392 }
1393
1394 /* configure save files and start the periodic saving timer */
1395 static void SHELL_InitRegistrySaving( HKEY hkey_users_default )
1396 {
1397     int all = PROFILE_GetWineIniBool( "registry", "SaveOnlyUpdatedKeys", 1 );
1398     int period = PROFILE_GetWineIniInt( "registry", "PeriodicSave", 0 );
1399
1400     /* set saving level (0 for saving everything, 1 for saving only modified keys) */
1401     SERVER_START_REQ
1402     {
1403         struct set_registry_levels_request *req = server_alloc_req( sizeof(*req), 0 );
1404         req->current = 1;
1405         req->saving  = !all;
1406         req->period  = period * 1000;
1407         server_call( REQ_SET_REGISTRY_LEVELS );
1408     }
1409     SERVER_END_REQ;
1410
1411     if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1))
1412     {
1413         save_at_exit( HKEY_CURRENT_USER, SAVE_CURRENT_USER );
1414         save_at_exit( HKEY_LOCAL_MACHINE, SAVE_LOCAL_MACHINE );
1415         save_at_exit( hkey_users_default, SAVE_DEFAULT_USER );
1416     }
1417 }
1418
1419
1420 /**********************************************************************************
1421  * SetLoadLevel [Internal]
1422  *
1423  * set level to 0 for loading system files
1424  * set level to 1 for loading user files
1425  */
1426 static void SetLoadLevel(int level)
1427 {
1428     SERVER_START_REQ
1429     {
1430         struct set_registry_levels_request *req = server_alloc_req( sizeof(*req), 0 );
1431
1432         req->current = level;
1433         req->saving  = 0;
1434         req->period  = 0;
1435         server_call( REQ_SET_REGISTRY_LEVELS );
1436     }
1437     SERVER_END_REQ;
1438 }
1439
1440 /**********************************************************************************
1441  * SHELL_LoadRegistry [Internal]
1442  */
1443 #define REG_DONTLOAD -1
1444 #define REG_WIN31  0
1445 #define REG_WIN95  1
1446 #define REG_WINNT  2
1447
1448 void SHELL_LoadRegistry( void )
1449 {
1450   HKEY  hkey;
1451   char windir[MAX_PATHNAME_LEN];
1452   char path[MAX_PATHNAME_LEN];
1453   int  systemtype = REG_WIN31;
1454   HKEY hkey_users_default;
1455
1456   TRACE("(void)\n");
1457
1458   if (!CLIENT_IsBootThread()) return;  /* already loaded */
1459
1460   REGISTRY_Init();
1461   SetLoadLevel(0);
1462
1463   if (RegCreateKeyA(HKEY_USERS, ".Default", &hkey_users_default))
1464           hkey_users_default = 0;
1465
1466   GetWindowsDirectoryA( windir, MAX_PATHNAME_LEN );
1467
1468   if (PROFILE_GetWineIniBool( "Registry", "LoadWindowsRegistryFiles", 1))
1469   {
1470     /* test %windir%/system32/config/system --> winnt */
1471     strcpy(path, windir);
1472     strncat(path, "\\system32\\config\\system", MAX_PATHNAME_LEN - strlen(path) - 1);
1473     if(GetFileAttributesA(path) != (DWORD)-1) 
1474     {
1475       systemtype = REG_WINNT;
1476     }
1477     else
1478     {
1479        /* test %windir%/system.dat --> win95 */
1480       strcpy(path, windir);
1481       strncat(path, "\\system.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1482       if(GetFileAttributesA(path) != (DWORD)-1)
1483       {
1484         systemtype = REG_WIN95;
1485       }
1486     }
1487
1488     if ((systemtype==REG_WINNT)
1489       && (! PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN)))
1490     {
1491        MESSAGE("When you are running with a native NT directory specify\n");
1492        MESSAGE("'Profile=<profiledirectory>' or disable loading of Windows\n");
1493        MESSAGE("registry (LoadWindowsRegistryFiles=N)\n");
1494        systemtype = REG_DONTLOAD;
1495     }
1496   }
1497   else
1498   {
1499     /* only wine registry */
1500     systemtype = REG_DONTLOAD;
1501   }  
1502
1503   switch (systemtype)
1504   {
1505     case REG_WIN31:
1506       _w31_loadreg();
1507       break;
1508
1509     case REG_WIN95:  
1510       /* Load windows 95 entries */
1511       NativeRegLoadKey(HKEY_LOCAL_MACHINE, "C:\\system.1st", 0);
1512
1513       strcpy(path, windir);
1514       strncat(path, "\\system.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1515       NativeRegLoadKey(HKEY_LOCAL_MACHINE, path, 0);
1516
1517       if (PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN))
1518       {
1519         /* user specific user.dat */
1520         strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1521         if (!NativeRegLoadKey( HKEY_CURRENT_USER, path, 1 ))
1522         {
1523           MESSAGE("can't load win95 user-registry %s\n", path);
1524           MESSAGE("check wine.conf, section [Wine], value 'Profile'\n");
1525         }
1526         /* default user.dat */
1527         if (hkey_users_default)
1528         {
1529           strcpy(path, windir);
1530           strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1531           NativeRegLoadKey(hkey_users_default, path, 1);
1532         }
1533       }
1534       else
1535       {
1536         /* global user.dat */
1537         strcpy(path, windir);
1538         strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1539         NativeRegLoadKey(HKEY_CURRENT_USER, path, 1);
1540       }
1541       break;
1542
1543     case REG_WINNT:  
1544       /* default user.dat */
1545       if (PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN))
1546       {
1547         strncat(path, "\\ntuser.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1548         if(!NativeRegLoadKey( HKEY_CURRENT_USER, path, 1 ))
1549         {
1550            MESSAGE("can't load NT user-registry %s\n", path);
1551            MESSAGE("check wine.conf, section [Wine], value 'Profile'\n");
1552         }
1553       }
1554
1555       /* default user.dat */
1556       if (hkey_users_default)
1557       {
1558         strcpy(path, windir);
1559         strncat(path, "\\system32\\config\\default", MAX_PATHNAME_LEN - strlen(path) - 1);
1560         NativeRegLoadKey(hkey_users_default, path, 1);
1561       }
1562
1563       /*
1564       * FIXME
1565       *  map HLM\System\ControlSet001 to HLM\System\CurrentControlSet
1566       */
1567
1568       if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SYSTEM", &hkey))
1569       {
1570         strcpy(path, windir);
1571         strncat(path, "\\system32\\config\\system", MAX_PATHNAME_LEN - strlen(path) - 1);
1572         NativeRegLoadKey(hkey, path, 1);
1573         RegCloseKey(hkey);
1574       }
1575
1576       if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE", &hkey))
1577       {
1578         strcpy(path, windir);
1579         strncat(path, "\\system32\\config\\software", MAX_PATHNAME_LEN - strlen(path) - 1);
1580         NativeRegLoadKey(hkey, path, 1);
1581         RegCloseKey(hkey);
1582       }
1583
1584       strcpy(path, windir);
1585       strncat(path, "\\system32\\config\\sam", MAX_PATHNAME_LEN - strlen(path) - 1);
1586       NativeRegLoadKey(HKEY_LOCAL_MACHINE, path, 0);
1587
1588       strcpy(path, windir);
1589       strncat(path, "\\system32\\config\\security", MAX_PATHNAME_LEN - strlen(path) - 1);
1590       NativeRegLoadKey(HKEY_LOCAL_MACHINE, path, 0);
1591
1592       /* this key is generated when the nt-core booted successfully */
1593       if (!RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\Clone",&hkey))
1594         RegCloseKey(hkey);
1595       break;
1596   } /* switch */
1597   
1598   if (PROFILE_GetWineIniBool ("registry","LoadGlobalRegistryFiles", 1))
1599   {
1600       /* 
1601        * Load the global HKU hive directly from sysconfdir
1602        */ 
1603       _wine_loadreg( HKEY_USERS, SAVE_USERS_DEFAULT );
1604
1605       /* 
1606        * Load the global machine defaults directly from sysconfdir
1607        */
1608       _wine_loadreg( HKEY_LOCAL_MACHINE, SAVE_LOCAL_MACHINE_DEFAULT );
1609   }
1610
1611   SetLoadLevel(1);
1612
1613   /*
1614    * Load the user saved registries 
1615    */
1616   if (PROFILE_GetWineIniBool("registry", "LoadHomeRegistryFiles", 1))
1617   {
1618       const char *confdir = get_config_dir();
1619       unsigned int len = strlen(confdir) + 20;
1620       char *fn = path;
1621
1622       if (len > sizeof(path)) fn = HeapAlloc( GetProcessHeap(), 0, len );
1623       /* 
1624        * Load user's personal versions of global HKU/.Default keys
1625        */
1626       if (fn)
1627       {
1628           char *str;
1629           strcpy( fn, confdir );
1630           str = fn + strlen(fn);
1631           *str++ = '/';
1632
1633           /* try to load HKU\.Default key only */
1634           strcpy( str, SAVE_DEFAULT_USER );
1635           if (_wine_loadreg( hkey_users_default, fn ))
1636           {
1637               /* if not found load old file containing both HKU\.Default and HKU\user */
1638               strcpy( str, SAVE_LOCAL_USERS_DEFAULT );
1639               _wine_loadreg( HKEY_USERS, fn ); 
1640           }
1641
1642           strcpy( str, SAVE_CURRENT_USER );
1643           _wine_loadreg( HKEY_CURRENT_USER, fn );
1644
1645           strcpy( str, SAVE_LOCAL_MACHINE );
1646           _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
1647
1648           if (fn != path) HeapFree( GetProcessHeap(), 0, fn );
1649       }
1650   }
1651   SHELL_InitRegistrySaving( hkey_users_default );
1652   RegCloseKey( hkey_users_default );
1653 }
1654
1655 /********************* API FUNCTIONS ***************************************/
1656
1657
1658
1659
1660 /******************************************************************************
1661  * RegFlushKey [KERNEL.227] [ADVAPI32.143]
1662  * Immediately writes key to registry.
1663  * Only returns after data has been written to disk.
1664  *
1665  * FIXME: does it really wait until data is written ?
1666  *
1667  * PARAMS
1668  *    hkey [I] Handle of key to write
1669  *
1670  * RETURNS
1671  *    Success: ERROR_SUCCESS
1672  *    Failure: Error code
1673  */
1674 DWORD WINAPI RegFlushKey( HKEY hkey )
1675 {
1676     FIXME( "(%x): stub\n", hkey );
1677     return ERROR_SUCCESS;
1678 }
1679
1680
1681 /******************************************************************************
1682  * RegUnLoadKeyA [ADVAPI32.172]
1683  */
1684 LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
1685 {
1686     FIXME("(%x,%s): stub\n",hkey, debugstr_a(lpSubKey));
1687     return ERROR_SUCCESS;
1688 }
1689
1690
1691 /******************************************************************************
1692  * RegRestoreKeyW [ADVAPI32.164]
1693  *
1694  * PARAMS
1695  *    hkey    [I] Handle of key where restore begins
1696  *    lpFile  [I] Address of filename containing saved tree
1697  *    dwFlags [I] Optional flags
1698  */
1699 LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
1700 {
1701     TRACE("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
1702
1703     /* It seems to do this check before the hkey check */
1704     if (!lpFile || !*lpFile)
1705         return ERROR_INVALID_PARAMETER;
1706
1707     FIXME("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
1708
1709     /* Check for file existence */
1710
1711     return ERROR_SUCCESS;
1712 }
1713
1714
1715 /******************************************************************************
1716  * RegRestoreKeyA [ADVAPI32.163]
1717  */
1718 LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
1719 {
1720     LPWSTR lpFileW = HEAP_strdupAtoW( GetProcessHeap(), 0, lpFile );
1721     LONG ret = RegRestoreKeyW( hkey, lpFileW, dwFlags );
1722     HeapFree( GetProcessHeap(), 0, lpFileW );
1723     return ret;
1724 }
1725
1726
1727 /******************************************************************************
1728  * RegReplaceKeyA [ADVAPI32.161]
1729  */
1730 LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
1731                               LPCSTR lpOldFile )
1732 {
1733     FIXME("(%x,%s,%s,%s): stub\n", hkey, debugstr_a(lpSubKey),
1734           debugstr_a(lpNewFile),debugstr_a(lpOldFile));
1735     return ERROR_SUCCESS;
1736 }
1737
1738
1739
1740
1741
1742
1743 /* 16-bit functions */
1744
1745 /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
1746  * some programs. Do not remove those cases. -MM
1747  */
1748 static inline void fix_win16_hkey( HKEY *hkey )
1749 {
1750     if (*hkey == 0 || *hkey == 1) *hkey = HKEY_CLASSES_ROOT;
1751 }
1752
1753 /******************************************************************************
1754  *           RegEnumKey16   [KERNEL.216] [SHELL.7]
1755  */
1756 DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
1757 {
1758     fix_win16_hkey( &hkey );
1759     return RegEnumKeyA( hkey, index, name, name_len );
1760 }
1761
1762 /******************************************************************************
1763  *           RegOpenKey16   [KERNEL.217] [SHELL.1]
1764  */
1765 DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
1766 {
1767     fix_win16_hkey( &hkey );
1768     return RegOpenKeyA( hkey, name, retkey );
1769 }
1770
1771 /******************************************************************************
1772  *           RegCreateKey16   [KERNEL.218] [SHELL.2]
1773  */
1774 DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
1775 {
1776     fix_win16_hkey( &hkey );
1777     return RegCreateKeyA( hkey, name, retkey );
1778 }
1779
1780 /******************************************************************************
1781  *           RegDeleteKey16   [KERNEL.219] [SHELL.4]
1782  */
1783 DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name )
1784 {
1785     fix_win16_hkey( &hkey );
1786     return RegDeleteKeyA( hkey, name );
1787 }
1788
1789 /******************************************************************************
1790  *           RegCloseKey16   [KERNEL.220] [SHELL.3]
1791  */
1792 DWORD WINAPI RegCloseKey16( HKEY hkey )
1793 {
1794     fix_win16_hkey( &hkey );
1795     return RegCloseKey( hkey );
1796 }
1797
1798 /******************************************************************************
1799  *           RegSetValue16   [KERNEL.221] [SHELL.5]
1800  */
1801 DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
1802 {
1803     fix_win16_hkey( &hkey );
1804     return RegSetValueA( hkey, name, type, data, count );
1805 }
1806
1807 /******************************************************************************
1808  *           RegDeleteValue16  [KERNEL.222]
1809  */
1810 DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR name )
1811 {
1812     fix_win16_hkey( &hkey );
1813     return RegDeleteValueA( hkey, name );
1814 }
1815
1816 /******************************************************************************
1817  *           RegEnumValue16   [KERNEL.223]
1818  */
1819 DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1820                              LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
1821 {
1822     fix_win16_hkey( &hkey );
1823     return RegEnumValueA( hkey, index, value, val_count, reserved, type, data, count );
1824 }
1825
1826 /******************************************************************************
1827  *           RegQueryValue16   [KERNEL.224] [SHELL.6]
1828  *
1829  * NOTES
1830  *    Is this HACK still applicable?
1831  *
1832  * HACK
1833  *    The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
1834  *    mask out the high 16 bit.  This (not so much incidently) hopefully fixes
1835  *    Aldus FH4)
1836  */
1837 DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count )
1838 {
1839     fix_win16_hkey( &hkey );
1840     if (count) *count &= 0xffff;
1841     return RegQueryValueA( hkey, name, data, count );
1842 }
1843
1844 /******************************************************************************
1845  *           RegQueryValueEx16   [KERNEL.225]
1846  */
1847 DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
1848                                 LPBYTE data, LPDWORD count )
1849 {
1850     fix_win16_hkey( &hkey );
1851     return RegQueryValueExA( hkey, name, reserved, type, data, count );
1852 }
1853
1854 /******************************************************************************
1855  *           RegSetValueEx16   [KERNEL.226]
1856  */
1857 DWORD WINAPI RegSetValueEx16( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
1858                               CONST BYTE *data, DWORD count )
1859 {
1860     fix_win16_hkey( &hkey );
1861     if (!count && (type==REG_SZ)) count = strlen(data);
1862     return RegSetValueExA( hkey, name, reserved, type, data, count );
1863 }
1864
1865 /******************************************************************************
1866  *           RegFlushKey16   [KERNEL.227]
1867  */
1868 DWORD WINAPI RegFlushKey16( HKEY hkey )
1869 {
1870     fix_win16_hkey( &hkey );
1871     return RegFlushKey( hkey );
1872 }