Replaced pointers to external functions by a DLL import.
[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
1000     {
1001         struct set_registry_levels_request *req = server_alloc_req( sizeof(*req), 0 );
1002
1003         req->current = level;
1004         req->saving  = saving;
1005         req->period  = period;
1006         server_call( REQ_SET_REGISTRY_LEVELS );
1007     }
1008     SERVER_END_REQ;
1009 }
1010
1011 /* _save_at_exit [Internal] */
1012 static void _save_at_exit(HKEY hkey,LPCSTR path)
1013 {
1014     LPCSTR confdir = get_config_dir();
1015     size_t len = strlen(confdir) + strlen(path) + 2;
1016
1017     if (len > REQUEST_MAX_VAR_SIZE) {
1018         ERR( "config dir '%s' too long\n", confdir );
1019         return;
1020     }
1021     SERVER_START_REQ
1022     {
1023         struct save_registry_atexit_request *req = server_alloc_req( sizeof(*req), len );
1024         sprintf( server_data_ptr(req), "%s/%s", confdir, path );
1025         req->hkey = hkey;
1026         server_call( REQ_SAVE_REGISTRY_ATEXIT );
1027     }
1028     SERVER_END_REQ;
1029 }
1030
1031 /* configure save files and start the periodic saving timer [Internal] */
1032 static void _init_registry_saving( HKEY hkey_users_default )
1033 {
1034     int all;
1035     int period;
1036
1037     all  = PROFILE_GetWineIniBool("registry","SaveOnlyUpdatedKeys",1);
1038     period = PROFILE_GetWineIniInt("registry","PeriodicSave",0);
1039
1040     /* set saving level (0 for saving everything, 1 for saving only modified keys) */
1041     _set_registry_levels(1,!all,period*1000);
1042
1043     if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1))
1044     {
1045         _save_at_exit(HKEY_CURRENT_USER,SAVE_LOCAL_REGBRANCH_CURRENT_USER );
1046         _save_at_exit(HKEY_LOCAL_MACHINE,SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
1047         _save_at_exit(hkey_users_default,SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
1048     }
1049
1050 }
1051
1052 /******************************************************************************
1053  * _allocate_default_keys [Internal]
1054  * Registry initialisation, allocates some default keys. 
1055  */
1056 static void _allocate_default_keys(void) {
1057         HKEY    hkey;
1058         char    buf[200];
1059
1060         TRACE("(void)\n");
1061
1062         RegCreateKeyA(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
1063         RegCloseKey(hkey);
1064
1065         /* This was an Open, but since it is called before the real registries
1066            are loaded, it was changed to a Create - MTB 980507*/
1067         RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
1068         RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
1069         RegCloseKey(hkey);
1070
1071         /* \\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion
1072          *                                              CurrentVersion
1073          *                                              CurrentBuildNumber
1074          *                                              CurrentType
1075          *                                      string  RegisteredOwner
1076          *                                      string  RegisteredOrganization
1077          *
1078          */
1079         /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
1080          *                                      string  SysContact
1081          *                                      string  SysLocation
1082          *                                              SysServices
1083          */
1084         if (-1!=gethostname(buf,200)) {
1085                 RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
1086                 RegSetValueExA(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
1087                 RegCloseKey(hkey);
1088         }
1089
1090         RegCreateKeyA(HKEY_USERS,".Default",&hkey);
1091         RegCloseKey(hkey);
1092 }
1093
1094 #define REG_DONTLOAD -1
1095 #define REG_WIN31     0
1096 #define REG_WIN95     1
1097 #define REG_WINNT     2
1098
1099 /* return the type of native registry [Internal] */
1100 static int _get_reg_type(void)
1101 {
1102     char windir[MAX_PATHNAME_LEN];
1103     char tmp[MAX_PATHNAME_LEN];
1104     int ret = REG_WIN31;
1105
1106     GetWindowsDirectoryA(windir,MAX_PATHNAME_LEN);
1107
1108     /* test %windir%/system32/config/system --> winnt */
1109     strcpy(tmp, windir);
1110     strncat(tmp, "\\system32\\config\\system", MAX_PATHNAME_LEN - strlen(tmp) - 1);
1111     if(GetFileAttributesA(tmp) != (DWORD)-1) {
1112       ret = REG_WINNT;
1113     }
1114     else
1115     {
1116        /* test %windir%/system.dat --> win95 */
1117       strcpy(tmp, windir);
1118       strncat(tmp, "\\system.dat", MAX_PATHNAME_LEN - strlen(tmp) - 1);
1119       if(GetFileAttributesA(tmp) != (DWORD)-1) {
1120         ret = REG_WIN95;
1121       }
1122     }
1123
1124     if ((ret == REG_WINNT) && (!PROFILE_GetWineIniString( "Wine", "Profile", "", tmp, MAX_PATHNAME_LEN))) {
1125        MESSAGE("When you are running with a native NT directory specify\n");
1126        MESSAGE("'Profile=<profiledirectory>' or disable loading of Windows\n");
1127        MESSAGE("registry (LoadWindowsRegistryFiles=N)\n");
1128        ret = REG_DONTLOAD;
1129     }
1130
1131     return ret;
1132 }
1133
1134 #define WINE_REG_VER_ERROR  -1
1135 #define WINE_REG_VER_1       0
1136 #define WINE_REG_VER_2       1
1137 #define WINE_REG_VER_OLD     2
1138 #define WINE_REG_VER_UNKNOWN 3
1139
1140 /* return the version of wine registry file [Internal] */
1141 static int _get_wine_registry_file_format_version(LPCSTR fn)
1142 {
1143     FILE *f;
1144     char tmp[50];
1145     int ver;
1146
1147     if ((f=fopen(fn,"rt")) == NULL) {
1148         WARN("Couldn't open %s for reading: %s\n",fn,strerror(errno));
1149         return WINE_REG_VER_ERROR;
1150     }
1151
1152     if (fgets(tmp,50,f) == NULL) {
1153         WARN("Error reading %s: %s\n",fn,strerror(errno));
1154         fclose(f);
1155         return WINE_REG_VER_ERROR;
1156     }
1157     fclose(f);
1158
1159     if (sscanf(tmp,"WINE REGISTRY Version %d",&ver) != 1) return WINE_REG_VER_UNKNOWN;
1160     switch (ver) {
1161         case 1:
1162             return WINE_REG_VER_1;
1163             break;
1164         case 2:
1165             return WINE_REG_VER_2;
1166             break;
1167         default:
1168             return WINE_REG_VER_UNKNOWN;
1169     }
1170 }
1171
1172 /* load the registry file in wine format [Internal] */
1173 static void load_wine_registry(HKEY hkey,LPCSTR fn)
1174 {
1175     int file_format;
1176
1177     file_format = _get_wine_registry_file_format_version(fn);
1178     switch (file_format) {
1179
1180         case WINE_REG_VER_1:
1181             WARN("Unable to load registry file %s: old format which is no longer supported.\n",fn);
1182             break;
1183
1184         case WINE_REG_VER_2: {
1185             HANDLE file;
1186             if ((file = FILE_CreateFile( fn, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1187                                               FILE_ATTRIBUTE_NORMAL, -1, TRUE )) != INVALID_HANDLE_VALUE)
1188             {
1189                 SERVER_START_REQ
1190                 {
1191                     struct load_registry_request *req = server_alloc_req( sizeof(*req), 0 );
1192                     req->hkey    = hkey;
1193                     req->file    = file;
1194                     server_call( REQ_LOAD_REGISTRY );
1195                 }
1196                 SERVER_END_REQ;
1197                 CloseHandle( file );
1198             }
1199             break;
1200         }
1201
1202         case WINE_REG_VER_UNKNOWN:
1203             WARN("Unable to load registry file %s: unknown format.\n",fn);
1204             break;
1205
1206         case WINE_REG_VER_ERROR:
1207             break;
1208     }
1209 }
1210
1211 /* generate and return the name of the tmp file and associated stream [Internal] */
1212 static LPSTR _get_tmp_fn(FILE **f)
1213 {
1214     LPSTR ret;
1215     int tmp_fd,count;
1216
1217     ret = _xmalloc(50);
1218     for (count = 0;;) {
1219         sprintf(ret,"/tmp/reg%lx%04x.tmp",(long)getpid(),count++);
1220         if ((tmp_fd = open(ret,O_CREAT | O_EXCL | O_WRONLY,0666)) != -1) break;
1221         if (errno != EEXIST) {
1222             ERR("Unexpected error while open() call: %s\n",strerror(errno));
1223             free(ret);
1224             *f = NULL;
1225             return NULL;
1226         }
1227     }
1228
1229     if ((*f = fdopen(tmp_fd,"w")) == NULL) {
1230         ERR("Unexpected error while fdopen() call: %s\n",strerror(errno));
1231         close(tmp_fd);
1232         free(ret);
1233         return NULL;
1234     }
1235
1236     return ret;
1237 }
1238
1239 /* convert win95 native registry file to wine format [Internal] */
1240 static LPSTR _convert_win95_registry_to_wine_format(LPCSTR fn,int level)
1241 {
1242     int fd;
1243     FILE *f;
1244     DOS_FULL_NAME full_name;
1245     void *base;
1246     LPSTR ret = NULL;
1247     struct stat st;
1248
1249     _w95creg *creg;
1250     _w95rgkn *rgkn;
1251     _w95dke *dke, *root_dke;
1252
1253     if (!DOSFS_GetFullName( fn, 0, &full_name )) return NULL;
1254
1255     /* map the registry into the memory */
1256     if ((fd = open(full_name.long_name, O_RDONLY | O_NONBLOCK)) == -1) return NULL;
1257     if ((fstat(fd, &st) == -1)) goto error1;
1258     if (!st.st_size) goto error1;
1259     if ((base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto error1;
1260
1261     /* control signature */
1262     if (*(LPDWORD)base != W95_REG_CREG_ID) {
1263         ERR("unable to load native win95 registry file %s: unknown signature.\n",fn);
1264         goto error;
1265     }
1266
1267     creg = base;
1268     /* load the header (rgkn) */
1269     rgkn = (_w95rgkn*)(creg + 1);
1270     if (rgkn->id != W95_REG_RGKN_ID) {
1271         ERR("second IFF header not RGKN, but %lx\n", rgkn->id);
1272         goto error;
1273     }
1274     if (rgkn->root_off != 0x20) {
1275         ERR("rgkn->root_off not 0x20, please report !\n");
1276         goto error;
1277     }
1278     if (rgkn->last_dke > rgkn->size)
1279     {
1280       ERR("registry file corrupt! last_dke > size!\n");
1281       goto error;
1282     }
1283     /* verify last dke */
1284     dke = (_w95dke*)((char*)rgkn + rgkn->last_dke);
1285     if (dke->x1 != 0x80000000)
1286     { /* wrong magic */
1287       ERR("last dke invalid !\n");
1288       goto error;
1289     }
1290     if (rgkn->size > creg->rgdb_off)
1291     {
1292       ERR("registry file corrupt! rgkn size > rgdb_off !\n");
1293       goto error;
1294     }
1295     root_dke = (_w95dke*)((char*)rgkn + rgkn->root_off);
1296     if ( (root_dke->prevlvl != 0xffffffff) || (root_dke->next != 0xffffffff) )
1297     {
1298         ERR("registry file corrupt! invalid root dke !\n");
1299         goto error;
1300     }
1301
1302     if ( (ret = _get_tmp_fn(&f)) == NULL) goto error;
1303     fprintf(f,"WINE REGISTRY Version 2");
1304     _w95_dump_dke("",creg,rgkn,root_dke,f,level);
1305     fclose(f);
1306
1307 error:
1308     if(ret == NULL) {
1309         ERR("Unable to load native win95 registry file %s.\n",fn);
1310         ERR("Please report to a.mohr@mailto.de.\n");
1311         ERR("Make a backup of the file, run a good reg cleaner program and try again!\n");
1312     }
1313
1314     munmap(base, st.st_size);
1315 error1:
1316     close(fd);
1317     return ret;
1318 }
1319
1320 /* convert winnt native registry file to wine format [Internal] */
1321 static LPSTR _convert_winnt_registry_to_wine_format(LPCSTR fn,int level)
1322 {
1323     int fd;
1324     FILE *f;
1325     DOS_FULL_NAME full_name;
1326     void *base;
1327     LPSTR ret = NULL;
1328     struct stat st;
1329
1330     nt_regf *regf;
1331     nt_hbin *hbin;
1332     nt_hbin_sub *hbin_sub;
1333     nt_nk *nk;
1334
1335     if (!DOSFS_GetFullName( fn, 0, &full_name )) return NULL;
1336
1337     /* map the registry into the memory */
1338     if ((fd = open(full_name.long_name, O_RDONLY | O_NONBLOCK)) == -1) return NULL;
1339     if ((fstat(fd, &st) == -1)) goto error1;
1340     if (!st.st_size) goto error1;
1341     if ((base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto error1;
1342
1343     /* control signature */
1344     if (*(LPDWORD)base != NT_REG_HEADER_BLOCK_ID) {
1345         ERR("unable to load native winnt registry file %s: unknown signature.\n",fn);
1346         goto error;
1347     }
1348
1349     /* start block */
1350     regf = base;
1351
1352     /* hbin block */
1353     hbin = (nt_hbin*)((char*) base + 0x1000);
1354     if (hbin->id != NT_REG_POOL_BLOCK_ID) {
1355       ERR( "hbin block invalid\n");
1356       goto error;
1357     }
1358
1359     /* hbin_sub block */
1360     hbin_sub = (nt_hbin_sub*)&(hbin->hbin_sub);
1361     if ((hbin_sub->data[0] != 'n') || (hbin_sub->data[1] != 'k')) {
1362       ERR( "hbin_sub block invalid\n");
1363       goto error;
1364     }
1365
1366     /* nk block */
1367     nk = (nt_nk*)&(hbin_sub->data[0]);
1368     if (nk->Type != NT_REG_ROOT_KEY_BLOCK_TYPE) {
1369       ERR( "special nk block not found\n");
1370       goto error;
1371     }
1372
1373     if ( (ret = _get_tmp_fn(&f)) == NULL) goto error;
1374     fprintf(f,"WINE REGISTRY Version 2");
1375     _nt_dump_nk("",(char*)base+0x1000,nk,f,level);
1376     fclose(f);
1377
1378 error:
1379     munmap(base,st.st_size);
1380 error1:
1381     close(fd);
1382     return ret;
1383 }
1384
1385 /* convert native native registry to wine format and load it via server call [Internal] */
1386 static void _convert_and_load_native_registry(LPCSTR fn,HKEY hkey,int reg_type,int level)
1387 {
1388     LPSTR tmp = NULL;
1389
1390     switch (reg_type) {
1391         case REG_WINNT:
1392             /* FIXME: following function doesn't really convert yet */
1393             tmp = _convert_winnt_registry_to_wine_format(fn,level);
1394             break;
1395         case REG_WIN95:
1396             tmp = _convert_win95_registry_to_wine_format(fn,level);
1397             break;
1398         case REG_WIN31:
1399             ERR("Don't know how to convert native 3.1 registry yet.\n");
1400             break;
1401         default:
1402             ERR("Unknown registry format parameter (%d)\n",reg_type);
1403             break;
1404     }
1405
1406     if (tmp != NULL) {
1407         load_wine_registry(hkey,tmp);
1408         TRACE("File %s successfuly converted to %s and loaded to registry.\n",fn,tmp);
1409         unlink(tmp);
1410     }
1411     else WARN("Unable to convert %s (not exist?)\n",fn);
1412     free(tmp);
1413 }
1414
1415 /* load all native windows registry files [Internal] */
1416 static void _load_windows_registry( HKEY hkey_users_default )
1417 {
1418     int reg_type;
1419     char windir[MAX_PATHNAME_LEN];
1420     char path[MAX_PATHNAME_LEN];
1421
1422     GetWindowsDirectoryA(windir,MAX_PATHNAME_LEN);
1423
1424     reg_type = _get_reg_type();
1425     switch (reg_type) {
1426         case REG_WINNT: {
1427             HKEY hkey;
1428
1429             /* user specific ntuser.dat */
1430             if (PROFILE_GetWineIniString( "Wine", "Profile", "", path, MAX_PATHNAME_LEN)) {
1431                 strcat(path,"\\ntuser.dat");
1432                 _convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WINNT,1);
1433             }
1434
1435             /* default user.dat */
1436             if (hkey_users_default) {
1437                 strcpy(path,windir);
1438                 strcat(path,"\\system32\\config\\default");
1439                 _convert_and_load_native_registry(path,hkey_users_default,REG_WINNT,1);
1440             }
1441
1442             /*
1443             * FIXME
1444             *  map HLM\System\ControlSet001 to HLM\System\CurrentControlSet
1445             */
1446
1447             if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SYSTEM", &hkey)) {
1448               strcpy(path,windir);
1449               strcat(path,"\\system32\\config\\system");
1450               _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
1451               RegCloseKey(hkey);
1452             }
1453
1454             if (!RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE", &hkey)) {
1455                 strcpy(path,windir);
1456                 strcat(path,"\\system32\\config\\software");
1457                 _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
1458                 RegCloseKey(hkey);
1459             }
1460
1461             strcpy(path,windir);
1462             strcat(path,"\\system32\\config\\sam");
1463             _convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WINNT,0);
1464
1465             strcpy(path,windir);
1466             strcat(path,"\\system32\\config\\security");
1467             _convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WINNT,0);
1468
1469             /* this key is generated when the nt-core booted successfully */
1470             if (!RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\Clone",&hkey)) RegCloseKey(hkey);
1471             break;
1472         }
1473
1474         case REG_WIN95:
1475             _convert_and_load_native_registry("c:\\system.1st",HKEY_LOCAL_MACHINE,REG_WIN95,0);
1476
1477             strcpy(path,windir);
1478             strcat(path,"\\system.dat");
1479             _convert_and_load_native_registry(path,HKEY_LOCAL_MACHINE,REG_WIN95,0);
1480
1481             if (PROFILE_GetWineIniString("Wine","Profile","",path,MAX_PATHNAME_LEN)) {
1482                 /* user specific user.dat */
1483                 strncat(path, "\\user.dat", MAX_PATHNAME_LEN - strlen(path) - 1);
1484                 _convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1);
1485
1486                 /* default user.dat */
1487                 if (hkey_users_default) {
1488                     strcpy(path,windir);
1489                     strcat(path,"\\user.dat");
1490                     _convert_and_load_native_registry(path,hkey_users_default,REG_WIN95,1);
1491                 }
1492             } else {
1493                 strcpy(path,windir);
1494                 strcat(path,"\\user.dat");
1495                 _convert_and_load_native_registry(path,HKEY_CURRENT_USER,REG_WIN95,1);
1496             }
1497             break;
1498
1499         case REG_WIN31:
1500             /* FIXME: here we should convert to *.reg file supported by server and call REQ_LOAD_REGISTRY, see REG_WIN95 case */
1501             _w31_loadreg();
1502             break;
1503
1504         case REG_DONTLOAD:
1505             TRACE("REG_DONTLOAD\n");
1506             break;
1507
1508         default:
1509             ERR("switch: no match (%d)\n",reg_type);
1510             break;
1511
1512     }
1513 }
1514
1515 /* load global registry files (stored in /etc/wine) [Internal] */
1516 static void _load_global_registry(void)
1517 {
1518     TRACE("(void)\n");
1519
1520     /* Load the global HKU hive directly from sysconfdir */
1521     load_wine_registry( HKEY_USERS, SAVE_GLOBAL_REGBRANCH_USER_DEFAULT );
1522
1523     /* Load the global machine defaults directly from sysconfdir */
1524     load_wine_registry( HKEY_LOCAL_MACHINE, SAVE_GLOBAL_REGBRANCH_LOCAL_MACHINE );
1525 }
1526
1527 /* load home registry files (stored in ~/.wine) [Internal] */
1528 static void _load_home_registry( HKEY hkey_users_default )
1529 {
1530     LPCSTR confdir = get_config_dir();
1531     LPSTR tmp = _xmalloc(strlen(confdir)+20);
1532
1533     strcpy(tmp,confdir);
1534     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
1535     load_wine_registry(hkey_users_default,tmp);
1536
1537     strcpy(tmp,confdir);
1538     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER);
1539     load_wine_registry(HKEY_CURRENT_USER,tmp);
1540
1541     strcpy(tmp,confdir);
1542     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
1543     load_wine_registry(HKEY_LOCAL_MACHINE,tmp);
1544
1545     free(tmp);
1546 }
1547
1548 /* load all registry (native and global and home) */
1549 void SHELL_LoadRegistry( void )
1550 {
1551     HKEY hkey_users_default;
1552
1553     TRACE("(void)\n");
1554
1555     if (!CLIENT_IsBootThread()) return;  /* already loaded */
1556
1557     if (!RegCreateKeyA(HKEY_USERS,".Default",&hkey_users_default)) hkey_users_default = 0;
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.143]
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.172]
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.164]
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.163]
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.161]
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 }