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