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