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