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