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