Don't reapply all the texture states if the texture we are replacing
[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     OBJECT_ATTRIBUTES attr;
1344     LARGE_INTEGER lg_int;
1345     NTSTATUS nts;
1346     SIZE_T len;
1347
1348     nt_regf *regf;
1349     nt_hbin *hbin;
1350     nt_hbin_sub *hbin_sub;
1351     nt_nk *nk;
1352
1353     TRACE("%s\n", debugstr_w(fn));
1354
1355     hFile = CreateFileW( fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1356     if ( hFile == INVALID_HANDLE_VALUE ) return NULL;
1357     attr.Length                   = sizeof(attr);
1358     attr.RootDirectory            = 0;
1359     attr.ObjectName               = NULL;
1360     attr.Attributes               = 0;
1361     attr.SecurityDescriptor       = NULL;
1362     attr.SecurityQualityOfService = NULL;
1363
1364     lg_int.QuadPart = 0;
1365     nts = NtCreateSection( &hMapping, 
1366                            STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|SECTION_MAP_READ,
1367                            &attr, &lg_int, PAGE_READONLY, SEC_COMMIT, hFile );
1368     if (nts != STATUS_SUCCESS) goto error1;
1369
1370     base = NULL; len = 0;
1371     nts = NtMapViewOfSection( hMapping, GetCurrentProcess(),
1372                               &base, 0, 0, &lg_int, &len, ViewShare, 0, 
1373                               PAGE_READONLY);
1374     NtClose( hMapping );
1375     if (nts != STATUS_SUCCESS) goto error1;
1376
1377     /* control signature */
1378     if (*(LPDWORD)base != NT_REG_HEADER_BLOCK_ID) {
1379         ERR("unable to load native winnt registry file %s: unknown signature.\n",
1380             debugstr_w(fn));
1381         goto error;
1382     }
1383
1384     /* start block */
1385     regf = base;
1386
1387     /* hbin block */
1388     hbin = (nt_hbin*)((char*) base + 0x1000);
1389     if (hbin->id != NT_REG_POOL_BLOCK_ID) {
1390       ERR( "hbin block invalid\n");
1391       goto error;
1392     }
1393
1394     /* hbin_sub block */
1395     hbin_sub = (nt_hbin_sub*)&(hbin->hbin_sub);
1396     if ((hbin_sub->data[0] != 'n') || (hbin_sub->data[1] != 'k')) {
1397       ERR( "hbin_sub block invalid\n");
1398       goto error;
1399     }
1400
1401     /* nk block */
1402     nk = (nt_nk*)&(hbin_sub->data[0]);
1403     if (nk->Type != NT_REG_ROOT_KEY_BLOCK_TYPE) {
1404       ERR( "special nk block not found\n");
1405       goto error;
1406     }
1407
1408     if ( (ret = _get_tmp_fn(&f)) == NULL) goto error;
1409     fprintf(f,"WINE REGISTRY Version 2");
1410     _nt_dump_nk("",(char*)base+0x1000,nk,f,level);
1411     fclose(f);
1412
1413 error:
1414     NtUnmapViewOfSection( GetCurrentProcess(), base );
1415 error1:
1416     NtClose(hFile);
1417     return ret;
1418 }
1419
1420 /* convert native registry to wine format and load it via server call [Internal] */
1421 static void _convert_and_load_native_registry(LPCWSTR fn, HKEY hkey, int reg_type, int level)
1422 {
1423     LPSTR tmp = NULL;
1424
1425     switch (reg_type) {
1426         case REG_WINNT:
1427             /* FIXME: following function doesn't really convert yet */
1428             tmp = _convert_winnt_registry_to_wine_format(fn,level);
1429             break;
1430         case REG_WIN95:
1431             tmp = _convert_win95_registry_to_wine_format(fn,level);
1432             break;
1433         case REG_WIN31:
1434             ERR("Don't know how to convert native 3.1 registry yet.\n");
1435             break;
1436         default:
1437             ERR("Unknown registry format parameter (%d)\n",reg_type);
1438             break;
1439     }
1440
1441     if (tmp != NULL) {
1442         load_wine_registry(hkey,tmp);
1443         TRACE("File %s successfully converted to %s and loaded to registry.\n",
1444               debugstr_w(fn), tmp);
1445         unlink(tmp);
1446     }
1447     else WARN("Unable to convert %s (doesn't exist?)\n", debugstr_w(fn));
1448     free(tmp);
1449 }
1450
1451 /* load all native windows registry files [Internal] */
1452 static void _load_windows_registry( HKEY hkey_local_machine, HKEY hkey_current_user,
1453                                     HKEY hkey_users_default )
1454 {
1455     int reg_type;
1456     WCHAR windir[MAX_PATHNAME_LEN];
1457     WCHAR path[MAX_PATHNAME_LEN];
1458     OBJECT_ATTRIBUTES attr;
1459     UNICODE_STRING nameW;
1460     HKEY hkey;
1461
1462     static const WCHAR WineW[] = {'W','i','n','e',0};
1463     static const WCHAR ProfileW[] = {'P','r','o','f','i','l','e',0};
1464     static const WCHAR empty_strW[] = { 0 };
1465     static const WCHAR System[] = {'M','a','c','h','i','n','e','\\','S','y','s','t','e','m',0};
1466     static const WCHAR Software[] = {'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e',0};
1467     static const WCHAR Clone[] = {'M','a','c','h','i','n','e','\\',
1468                                   'S','y','s','t','e','m','\\',
1469                                   'C','l','o','n','e',0};
1470
1471     attr.Length = sizeof(attr);
1472     attr.RootDirectory = 0;
1473     attr.ObjectName = &nameW;
1474     attr.Attributes = 0;
1475     attr.SecurityDescriptor = NULL;
1476     attr.SecurityQualityOfService = NULL;
1477
1478     GetWindowsDirectoryW(windir, MAX_PATHNAME_LEN);
1479
1480     reg_type = _get_reg_type();
1481     switch (reg_type) {
1482         case REG_WINNT: {
1483             HKEY hkey;
1484             static const WCHAR ntuser_datW[] = {'\\','n','t','u','s','e','r','.','d','a','t',0};
1485             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};
1486             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};
1487             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};
1488             static const WCHAR samW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','s','a','m',0};
1489             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};
1490
1491             /* user specific ntuser.dat */
1492             if (PROFILE_GetWineIniString( WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN )) {
1493                 strcatW(path, ntuser_datW);
1494                 _convert_and_load_native_registry(path,hkey_current_user,REG_WINNT,1);
1495             }
1496             else
1497             {
1498                 MESSAGE("When you are running with a native NT directory specify\n");
1499                 MESSAGE("'Profile=<profiledirectory>' or disable loading of Windows\n");
1500                 MESSAGE("registry (LoadWindowsRegistryFiles=N)\n");
1501                 break;
1502             }
1503
1504             /* default user.dat */
1505             if (hkey_users_default) {
1506                 strcpyW(path, windir);
1507                 strcatW(path, defaultW);
1508                 _convert_and_load_native_registry(path,hkey_users_default,REG_WINNT,1);
1509             }
1510
1511             /*
1512             * FIXME
1513             *  map HLM\System\ControlSet001 to HLM\System\CurrentControlSet
1514             */
1515             RtlInitUnicodeString( &nameW, System );
1516             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1517             {
1518                 strcpyW(path, windir);
1519                 strcatW(path, systemW);
1520                 _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
1521                 NtClose( hkey );
1522             }
1523             RtlInitUnicodeString( &nameW, Software );
1524             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1525             {
1526                 strcpyW(path, windir);
1527                 strcatW(path, softwareW);
1528                 _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
1529                 NtClose( hkey );
1530             }
1531
1532             strcpyW(path, windir);
1533             strcatW(path, samW);
1534             _convert_and_load_native_registry(path,hkey_local_machine,REG_WINNT,0);
1535
1536             strcpyW(path,windir);
1537             strcatW(path, securityW);
1538             _convert_and_load_native_registry(path,hkey_local_machine,REG_WINNT,0);
1539
1540             /* this key is generated when the nt-core booted successfully */
1541             RtlInitUnicodeString( &nameW, Clone );
1542             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) NtClose( hkey );
1543             break;
1544         }
1545
1546         case REG_WIN95:
1547         {
1548             static const WCHAR system_1stW[] = {'c',':','\\','s','y','s','t','e','m','.','1','s','t',0};
1549             static const WCHAR system_datW[] = {'\\','s','y','s','t','e','m','.','d','a','t',0};
1550             static const WCHAR classes_datW[] = {'\\','c','l','a','s','s','e','s','.','d','a','t',0};
1551             static const WCHAR user_datW[] = {'\\','u','s','e','r','.','d','a','t',0};
1552
1553             _convert_and_load_native_registry(system_1stW,hkey_local_machine,REG_WIN95,0);
1554
1555             strcpyW(path, windir);
1556             strcatW(path, system_datW);
1557             _convert_and_load_native_registry(path,hkey_local_machine,REG_WIN95,0);
1558
1559             RtlInitUnicodeString( &nameW, ClassesRootW );
1560             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1561             {
1562                 strcpyW(path, windir);
1563                 strcatW(path, classes_datW);
1564                 _convert_and_load_native_registry(path,hkey,REG_WIN95,0);
1565                 NtClose( hkey );
1566             }
1567
1568             if (PROFILE_GetWineIniString(WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN)) {
1569                 /* user specific user.dat */
1570                 strcatW(path, user_datW);
1571                 _convert_and_load_native_registry(path,hkey_current_user,REG_WIN95,1);
1572
1573                 /* default user.dat */
1574                 if (hkey_users_default) {
1575                     strcpyW(path, windir);
1576                     strcatW(path, user_datW);
1577                     _convert_and_load_native_registry(path,hkey_users_default,REG_WIN95,1);
1578                 }
1579             } else {
1580                 strcpyW(path, windir);
1581                 strcatW(path, user_datW);
1582                 _convert_and_load_native_registry(path,hkey_current_user,REG_WIN95,1);
1583             }
1584             break;
1585         }
1586
1587         case REG_WIN31:
1588             /* FIXME: here we should convert to *.reg file supported by server and call REQ_LOAD_REGISTRY, see REG_WIN95 case */
1589             _w31_loadreg();
1590             break;
1591
1592         case REG_DONTLOAD:
1593             TRACE("REG_DONTLOAD\n");
1594             break;
1595
1596         default:
1597             ERR("switch: no match (%d)\n",reg_type);
1598             break;
1599
1600     }
1601 }
1602
1603 /* load home registry files (stored in ~/.wine) [Internal] */
1604 static void _load_home_registry( HKEY hkey_local_machine, HKEY hkey_current_user,
1605                                  HKEY hkey_users_default )
1606 {
1607     LPCSTR confdir = wine_get_config_dir();
1608     LPSTR tmp = _xmalloc(strlen(confdir)+20);
1609
1610     strcpy(tmp,confdir);
1611     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
1612     load_wine_registry(hkey_users_default,tmp);
1613
1614     strcpy(tmp,confdir);
1615     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER);
1616     load_wine_registry(hkey_current_user,tmp);
1617
1618     strcpy(tmp,confdir);
1619     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
1620     load_wine_registry(hkey_local_machine,tmp);
1621
1622     free(tmp);
1623 }
1624
1625
1626 /* load all registry (native and global and home) */
1627 void SHELL_LoadRegistry( void )
1628 {
1629     HKEY hkey_local_machine, hkey_users, hkey_users_default, hkey_current_user, hkey_config;
1630     OBJECT_ATTRIBUTES attr;
1631     UNICODE_STRING nameW;
1632     DWORD count;
1633     BOOL res;
1634     int all, period;
1635     char tmp[1024];
1636
1637     static const WCHAR MachineW[] = {'M','a','c','h','i','n','e',0};
1638     static const WCHAR UserW[] = {'U','s','e','r',0};
1639     static const WCHAR DefaultW[] = {'.','D','e','f','a','u','l','t',0};
1640     static const WCHAR RegistryW[] = {'M','a','c','h','i','n','e','\\',
1641                                       'S','o','f','t','w','a','r','e','\\',
1642                                       'W','i','n','e','\\',
1643                                       'W','i','n','e','\\',
1644                                       'C','o','n','f','i','g','\\',
1645                                       'R','e','g','i','s','t','r','y',0};
1646     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};
1647     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};
1648     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};
1649     static const WCHAR SaveOnlyUpdatedKeysW[] = {'S','a','v','e','O','n','l','y','U','p','d','a','t','e','d','K','e','y','s',0};
1650     static const WCHAR PeriodicSaveW[] = {'P','e','r','i','o','d','i','c','S','a','v','e',0};
1651     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};
1652     static const WCHAR GlobalRegistryDirW[] = {'G','l','o','b','a','l','R','e','g','i','s','t','r','y','D','i','r',0};
1653
1654     TRACE("(void)\n");
1655
1656     if (!CLIENT_IsBootThread()) return;  /* already loaded */
1657
1658     attr.Length = sizeof(attr);
1659     attr.RootDirectory = 0;
1660     attr.ObjectName = &nameW;
1661     attr.Attributes = 0;
1662     attr.SecurityDescriptor = NULL;
1663     attr.SecurityQualityOfService = NULL;
1664
1665     RtlInitUnicodeString( &nameW, MachineW );
1666     NtCreateKey( &hkey_local_machine, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
1667     RtlInitUnicodeString( &nameW, UserW );
1668     NtCreateKey( &hkey_users, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
1669
1670     attr.RootDirectory = hkey_users;
1671     RtlInitUnicodeString( &nameW, DefaultW );
1672     if (NtCreateKey( &hkey_users_default, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1673     {
1674         ERR("Cannot create HKEY_USERS/.Default\n" );
1675         ExitProcess(1);
1676     }
1677     RtlOpenCurrentUser( KEY_ALL_ACCESS, &hkey_current_user );
1678
1679     _set_registry_levels(0,0,0);
1680     _allocate_default_keys();
1681
1682     attr.RootDirectory = 0;
1683     RtlInitUnicodeString( &nameW, RegistryW );
1684     if (NtOpenKey( &hkey_config, KEY_ALL_ACCESS, &attr )) hkey_config = 0;
1685
1686     /* load windows registry if required */
1687
1688     res = TRUE;
1689     attr.RootDirectory = hkey_config;
1690     RtlInitUnicodeString( &nameW, load_win_reg_filesW );
1691     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1692     {
1693         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1694         res = !IS_OPTION_FALSE(str[0]);
1695     }
1696     if (res) _load_windows_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
1697
1698     /* load global registry if required */
1699
1700     res = TRUE;
1701     RtlInitUnicodeString( &nameW, load_global_reg_filesW );
1702     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1703     {
1704         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1705         res = !IS_OPTION_FALSE(str[0]);
1706     }
1707     if (res)
1708     {
1709         /* load global registry files (stored in /etc/wine) */
1710         char *p, configfile[MAX_PATHNAME_LEN];
1711
1712         /* Override ETCDIR? */
1713         configfile[0] = 0;
1714         RtlInitUnicodeString( &nameW, GlobalRegistryDirW );
1715         if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1716         {
1717             WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1718             WideCharToMultiByte(CP_ACP, 0, str, -1, configfile, sizeof(configfile), NULL, NULL);
1719         }
1720         if (configfile[0] != '/') strcpy(configfile, ETCDIR);
1721
1722         TRACE("GlobalRegistryDir is '%s'.\n", configfile);
1723
1724         /* Load the global HKU hive directly from sysconfdir */
1725         p = configfile + strlen(configfile);
1726         strcpy(p, SAVE_GLOBAL_REGBRANCH_USER_DEFAULT);
1727         load_wine_registry( hkey_users, configfile );
1728
1729         /* Load the global machine defaults directly from sysconfdir */
1730         strcpy(p, SAVE_GLOBAL_REGBRANCH_LOCAL_MACHINE);
1731         load_wine_registry( hkey_local_machine, configfile );
1732     }
1733
1734     _set_registry_levels(1,0,0);
1735
1736     /* load home registry if required */
1737
1738     res = TRUE;
1739     RtlInitUnicodeString( &nameW, load_home_reg_filesW );
1740     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1741     {
1742         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1743         res = !IS_OPTION_FALSE(str[0]);
1744     }
1745     if (res) _load_home_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
1746
1747     /* setup registry saving */
1748
1749     all = FALSE;
1750     RtlInitUnicodeString( &nameW, SaveOnlyUpdatedKeysW );
1751     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1752     {
1753         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1754         all = IS_OPTION_FALSE(str[0]);
1755     }
1756
1757     period = 0;
1758     RtlInitUnicodeString( &nameW, PeriodicSaveW );
1759     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1760     {
1761         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1762         period = (int)strtolW(str, NULL, 10);
1763     }
1764
1765     /* set saving level (0 for saving everything, 1 for saving only modified keys) */
1766     _set_registry_levels(1,!all,period*1000);
1767
1768     /* setup keys to save */
1769
1770     res = TRUE;
1771     RtlInitUnicodeString( &nameW, WritetoHomeRegistryFilesW );
1772     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1773     {
1774         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1775         res = !IS_OPTION_FALSE(str[0]);
1776     }
1777     if (res)
1778     {
1779         _save_at_exit(hkey_current_user,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER );
1780         _save_at_exit(hkey_local_machine,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
1781         _save_at_exit(hkey_users_default,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
1782     }
1783
1784     NtClose(hkey_users_default);
1785     NtClose(hkey_current_user);
1786     NtClose(hkey_users);
1787     NtClose(hkey_local_machine);
1788     NtClose(hkey_config);
1789 }