Fixed a possible memory corruption.
[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 /* load the registry file in wine format [Internal] */
1150 static void load_wine_registry(HKEY hkey,LPCSTR fn)
1151 {
1152     HANDLE file;
1153     if ((file = FILE_CreateFile( fn, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1154                                  FILE_ATTRIBUTE_NORMAL, 0, TRUE, DRIVE_UNKNOWN )))
1155     {
1156         SERVER_START_REQ( load_registry )
1157         {
1158             req->hkey    = hkey;
1159             req->file    = file;
1160             wine_server_call( req );
1161         }
1162         SERVER_END_REQ;
1163         CloseHandle( file );
1164     }
1165 }
1166
1167 /* generate and return the name of the tmp file and associated stream [Internal] */
1168 static LPSTR _get_tmp_fn(FILE **f)
1169 {
1170     LPSTR ret;
1171     int tmp_fd,count;
1172
1173     ret = _xmalloc(50);
1174     for (count = 0;;) {
1175         sprintf(ret,"/tmp/reg%lx%04x.tmp",(long)getpid(),count++);
1176         if ((tmp_fd = open(ret,O_CREAT | O_EXCL | O_WRONLY,0666)) != -1) break;
1177         if (errno != EEXIST) {
1178             ERR("Unexpected error while open() call: %s\n",strerror(errno));
1179             free(ret);
1180             *f = NULL;
1181             return NULL;
1182         }
1183     }
1184
1185     if ((*f = fdopen(tmp_fd,"w")) == NULL) {
1186         ERR("Unexpected error while fdopen() call: %s\n",strerror(errno));
1187         close(tmp_fd);
1188         free(ret);
1189         return NULL;
1190     }
1191
1192     return ret;
1193 }
1194
1195 /* convert win95 native registry file to wine format [Internal] */
1196 static LPSTR _convert_win95_registry_to_wine_format(LPCWSTR fn, int level)
1197 {
1198     int fd;
1199     FILE *f;
1200     DOS_FULL_NAME full_name;
1201     void *base;
1202     LPSTR ret = NULL;
1203     struct stat st;
1204
1205     _w95creg *creg;
1206     _w95rgkn *rgkn;
1207     _w95dke *dke, *root_dke;
1208
1209     if (!DOSFS_GetFullName( fn, 0, &full_name )) return NULL;
1210
1211     /* map the registry into the memory */
1212     if ((fd = open(full_name.long_name, O_RDONLY | O_NONBLOCK)) == -1) return NULL;
1213     if ((fstat(fd, &st) == -1)) goto error1;
1214     if (!st.st_size) goto error1;
1215     if ((base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto error1;
1216
1217     /* control signature */
1218     if (*(LPDWORD)base != W95_REG_CREG_ID) {
1219         ERR("unable to load native win95 registry file %s: unknown signature.\n",
1220             debugstr_w(fn));
1221         goto error;
1222     }
1223
1224     creg = base;
1225     /* load the header (rgkn) */
1226     rgkn = (_w95rgkn*)(creg + 1);
1227     if (rgkn->id != W95_REG_RGKN_ID) {
1228         ERR("second IFF header not RGKN, but %lx\n", rgkn->id);
1229         goto error;
1230     }
1231     if (rgkn->root_off != 0x20) {
1232         ERR("rgkn->root_off not 0x20, please report !\n");
1233         goto error;
1234     }
1235     if (rgkn->last_dke > rgkn->size)
1236     {
1237       ERR("registry file corrupt! last_dke > size!\n");
1238       goto error;
1239     }
1240     /* verify last dke */
1241     dke = (_w95dke*)((char*)rgkn + rgkn->last_dke);
1242     if (dke->x1 != 0x80000000)
1243     { /* wrong magic */
1244       ERR("last dke invalid !\n");
1245       goto error;
1246     }
1247     if (rgkn->size > creg->rgdb_off)
1248     {
1249       ERR("registry file corrupt! rgkn size > rgdb_off !\n");
1250       goto error;
1251     }
1252     root_dke = (_w95dke*)((char*)rgkn + rgkn->root_off);
1253     if ( (root_dke->prevlvl != 0xffffffff) || (root_dke->next != 0xffffffff) )
1254     {
1255         ERR("registry file corrupt! invalid root dke !\n");
1256         goto error;
1257     }
1258
1259     if ( (ret = _get_tmp_fn(&f)) == NULL) goto error;
1260     fprintf(f,"WINE REGISTRY Version 2");
1261     _w95_dump_dke("",creg,rgkn,root_dke,f,level);
1262     fclose(f);
1263
1264 error:
1265     if(ret == NULL) {
1266         ERR("Unable to load native win95 registry file %s.\n", debugstr_w(fn));
1267         ERR("Please report this.\n");
1268         ERR("Make a backup of the file, run a good reg cleaner program and try again!\n");
1269     }
1270
1271     munmap(base, st.st_size);
1272 error1:
1273     close(fd);
1274     return ret;
1275 }
1276
1277 /* convert winnt native registry file to wine format [Internal] */
1278 static LPSTR _convert_winnt_registry_to_wine_format(LPCWSTR fn, int level)
1279 {
1280     FILE *f;
1281     void *base;
1282     LPSTR ret = NULL;
1283     HANDLE hFile;
1284     HANDLE hMapping;
1285     OBJECT_ATTRIBUTES attr;
1286     LARGE_INTEGER lg_int;
1287     NTSTATUS nts;
1288     SIZE_T len;
1289
1290     nt_regf *regf;
1291     nt_hbin *hbin;
1292     nt_hbin_sub *hbin_sub;
1293     nt_nk *nk;
1294
1295     TRACE("%s\n", debugstr_w(fn));
1296
1297     hFile = CreateFileW( fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1298     if ( hFile == INVALID_HANDLE_VALUE ) return NULL;
1299     attr.Length                   = sizeof(attr);
1300     attr.RootDirectory            = 0;
1301     attr.ObjectName               = NULL;
1302     attr.Attributes               = 0;
1303     attr.SecurityDescriptor       = NULL;
1304     attr.SecurityQualityOfService = NULL;
1305
1306     lg_int.QuadPart = 0;
1307     nts = NtCreateSection( &hMapping, 
1308                            STANDARD_RIGHTS_REQUIRED|SECTION_QUERY|SECTION_MAP_READ,
1309                            &attr, &lg_int, PAGE_READONLY, SEC_COMMIT, hFile );
1310     if (nts != STATUS_SUCCESS) goto error1;
1311
1312     base = NULL; len = 0;
1313     nts = NtMapViewOfSection( hMapping, GetCurrentProcess(),
1314                               &base, 0, 0, &lg_int, &len, ViewShare, 0, 
1315                               PAGE_READONLY);
1316     NtClose( hMapping );
1317     if (nts != STATUS_SUCCESS) goto error1;
1318
1319     /* control signature */
1320     if (*(LPDWORD)base != NT_REG_HEADER_BLOCK_ID) {
1321         ERR("unable to load native winnt registry file %s: unknown signature.\n",
1322             debugstr_w(fn));
1323         goto error;
1324     }
1325
1326     /* start block */
1327     regf = base;
1328
1329     /* hbin block */
1330     hbin = (nt_hbin*)((char*) base + 0x1000);
1331     if (hbin->id != NT_REG_POOL_BLOCK_ID) {
1332       ERR( "hbin block invalid\n");
1333       goto error;
1334     }
1335
1336     /* hbin_sub block */
1337     hbin_sub = (nt_hbin_sub*)&(hbin->hbin_sub);
1338     if ((hbin_sub->data[0] != 'n') || (hbin_sub->data[1] != 'k')) {
1339       ERR( "hbin_sub block invalid\n");
1340       goto error;
1341     }
1342
1343     /* nk block */
1344     nk = (nt_nk*)&(hbin_sub->data[0]);
1345     if (nk->Type != NT_REG_ROOT_KEY_BLOCK_TYPE) {
1346       ERR( "special nk block not found\n");
1347       goto error;
1348     }
1349
1350     if ( (ret = _get_tmp_fn(&f)) == NULL) goto error;
1351     fprintf(f,"WINE REGISTRY Version 2");
1352     _nt_dump_nk("",(char*)base+0x1000,nk,f,level);
1353     fclose(f);
1354
1355 error:
1356     NtUnmapViewOfSection( GetCurrentProcess(), base );
1357 error1:
1358     NtClose(hFile);
1359     return ret;
1360 }
1361
1362 /* convert native registry to wine format and load it via server call [Internal] */
1363 static void _convert_and_load_native_registry(LPCWSTR fn, HKEY hkey, int reg_type, int level)
1364 {
1365     LPSTR tmp = NULL;
1366
1367     switch (reg_type) {
1368         case REG_WINNT:
1369             /* FIXME: following function doesn't really convert yet */
1370             tmp = _convert_winnt_registry_to_wine_format(fn,level);
1371             break;
1372         case REG_WIN95:
1373             tmp = _convert_win95_registry_to_wine_format(fn,level);
1374             break;
1375         case REG_WIN31:
1376             ERR("Don't know how to convert native 3.1 registry yet.\n");
1377             break;
1378         default:
1379             ERR("Unknown registry format parameter (%d)\n",reg_type);
1380             break;
1381     }
1382
1383     if (tmp != NULL) {
1384         load_wine_registry(hkey,tmp);
1385         TRACE("File %s successfully converted to %s and loaded to registry.\n",
1386               debugstr_w(fn), tmp);
1387         unlink(tmp);
1388     }
1389     else WARN("Unable to convert %s (doesn't exist?)\n", debugstr_w(fn));
1390     free(tmp);
1391 }
1392
1393 /* load all native windows registry files [Internal] */
1394 static void _load_windows_registry( HKEY hkey_local_machine, HKEY hkey_current_user,
1395                                     HKEY hkey_users_default )
1396 {
1397     int reg_type;
1398     WCHAR windir[MAX_PATHNAME_LEN];
1399     WCHAR path[MAX_PATHNAME_LEN];
1400     OBJECT_ATTRIBUTES attr;
1401     UNICODE_STRING nameW;
1402     HKEY hkey;
1403
1404     static const WCHAR WineW[] = {'W','i','n','e',0};
1405     static const WCHAR ProfileW[] = {'P','r','o','f','i','l','e',0};
1406     static const WCHAR empty_strW[] = { 0 };
1407     static const WCHAR System[] = {'M','a','c','h','i','n','e','\\','S','y','s','t','e','m',0};
1408     static const WCHAR Software[] = {'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e',0};
1409     static const WCHAR Clone[] = {'M','a','c','h','i','n','e','\\',
1410                                   'S','y','s','t','e','m','\\',
1411                                   'C','l','o','n','e',0};
1412
1413     attr.Length = sizeof(attr);
1414     attr.RootDirectory = 0;
1415     attr.ObjectName = &nameW;
1416     attr.Attributes = 0;
1417     attr.SecurityDescriptor = NULL;
1418     attr.SecurityQualityOfService = NULL;
1419
1420     GetWindowsDirectoryW(windir, MAX_PATHNAME_LEN);
1421
1422     reg_type = _get_reg_type();
1423     switch (reg_type) {
1424         case REG_WINNT: {
1425             HKEY hkey;
1426             static const WCHAR ntuser_datW[] = {'\\','n','t','u','s','e','r','.','d','a','t',0};
1427             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};
1428             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};
1429             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};
1430             static const WCHAR samW[] = {'\\','s','y','s','t','e','m','3','2','\\','c','o','n','f','i','g','\\','s','a','m',0};
1431             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};
1432
1433             /* user specific ntuser.dat */
1434             if (PROFILE_GetWineIniString( WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN )) {
1435                 strcatW(path, ntuser_datW);
1436                 _convert_and_load_native_registry(path,hkey_current_user,REG_WINNT,1);
1437             }
1438             else
1439             {
1440                 MESSAGE("When you are running with a native NT directory specify\n");
1441                 MESSAGE("'Profile=<profiledirectory>' or disable loading of Windows\n");
1442                 MESSAGE("registry (LoadWindowsRegistryFiles=N)\n");
1443                 break;
1444             }
1445
1446             /* default user.dat */
1447             if (hkey_users_default) {
1448                 strcpyW(path, windir);
1449                 strcatW(path, defaultW);
1450                 _convert_and_load_native_registry(path,hkey_users_default,REG_WINNT,1);
1451             }
1452
1453             /*
1454             * FIXME
1455             *  map HLM\System\ControlSet001 to HLM\System\CurrentControlSet
1456             */
1457             RtlInitUnicodeString( &nameW, System );
1458             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1459             {
1460                 strcpyW(path, windir);
1461                 strcatW(path, systemW);
1462                 _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
1463                 NtClose( hkey );
1464             }
1465             RtlInitUnicodeString( &nameW, Software );
1466             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1467             {
1468                 strcpyW(path, windir);
1469                 strcatW(path, softwareW);
1470                 _convert_and_load_native_registry(path,hkey,REG_WINNT,1);
1471                 NtClose( hkey );
1472             }
1473
1474             strcpyW(path, windir);
1475             strcatW(path, samW);
1476             _convert_and_load_native_registry(path,hkey_local_machine,REG_WINNT,0);
1477
1478             strcpyW(path,windir);
1479             strcatW(path, securityW);
1480             _convert_and_load_native_registry(path,hkey_local_machine,REG_WINNT,0);
1481
1482             /* this key is generated when the nt-core booted successfully */
1483             RtlInitUnicodeString( &nameW, Clone );
1484             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL )) NtClose( hkey );
1485             break;
1486         }
1487
1488         case REG_WIN95:
1489         {
1490             static const WCHAR system_1stW[] = {'c',':','\\','s','y','s','t','e','m','.','1','s','t',0};
1491             static const WCHAR system_datW[] = {'\\','s','y','s','t','e','m','.','d','a','t',0};
1492             static const WCHAR classes_datW[] = {'\\','c','l','a','s','s','e','s','.','d','a','t',0};
1493             static const WCHAR user_datW[] = {'\\','u','s','e','r','.','d','a','t',0};
1494
1495             _convert_and_load_native_registry(system_1stW,hkey_local_machine,REG_WIN95,0);
1496
1497             strcpyW(path, windir);
1498             strcatW(path, system_datW);
1499             _convert_and_load_native_registry(path,hkey_local_machine,REG_WIN95,0);
1500
1501             RtlInitUnicodeString( &nameW, ClassesRootW );
1502             if (!NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1503             {
1504                 strcpyW(path, windir);
1505                 strcatW(path, classes_datW);
1506                 _convert_and_load_native_registry(path,hkey,REG_WIN95,0);
1507                 NtClose( hkey );
1508             }
1509
1510             if (PROFILE_GetWineIniString(WineW, ProfileW, empty_strW, path, MAX_PATHNAME_LEN)) {
1511                 /* user specific user.dat */
1512                 strcatW(path, user_datW);
1513                 _convert_and_load_native_registry(path,hkey_current_user,REG_WIN95,1);
1514
1515                 /* default user.dat */
1516                 if (hkey_users_default) {
1517                     strcpyW(path, windir);
1518                     strcatW(path, user_datW);
1519                     _convert_and_load_native_registry(path,hkey_users_default,REG_WIN95,1);
1520                 }
1521             } else {
1522                 strcpyW(path, windir);
1523                 strcatW(path, user_datW);
1524                 _convert_and_load_native_registry(path,hkey_current_user,REG_WIN95,1);
1525             }
1526             break;
1527         }
1528
1529         case REG_WIN31:
1530             /* FIXME: here we should convert to *.reg file supported by server and call REQ_LOAD_REGISTRY, see REG_WIN95 case */
1531             _w31_loadreg();
1532             break;
1533
1534         case REG_DONTLOAD:
1535             TRACE("REG_DONTLOAD\n");
1536             break;
1537
1538         default:
1539             ERR("switch: no match (%d)\n",reg_type);
1540             break;
1541
1542     }
1543 }
1544
1545 /* load home registry files (stored in ~/.wine) [Internal] */
1546 static void _load_home_registry( HKEY hkey_local_machine, HKEY hkey_current_user,
1547                                  HKEY hkey_users_default )
1548 {
1549     LPCSTR confdir = wine_get_config_dir();
1550     LPSTR tmp = _xmalloc(strlen(confdir)+20);
1551
1552     strcpy(tmp,confdir);
1553     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
1554     load_wine_registry(hkey_users_default,tmp);
1555
1556     strcpy(tmp,confdir);
1557     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER);
1558     load_wine_registry(hkey_current_user,tmp);
1559
1560     strcpy(tmp,confdir);
1561     strcat(tmp,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
1562     load_wine_registry(hkey_local_machine,tmp);
1563
1564     free(tmp);
1565 }
1566
1567
1568 /* load all registry (native and global and home) */
1569 void SHELL_LoadRegistry( void )
1570 {
1571     HKEY hkey_local_machine, hkey_users, hkey_users_default, hkey_current_user, hkey_config;
1572     OBJECT_ATTRIBUTES attr;
1573     UNICODE_STRING nameW;
1574     DWORD count;
1575     BOOL res;
1576     int all, period;
1577     char tmp[1024];
1578
1579     static const WCHAR MachineW[] = {'M','a','c','h','i','n','e',0};
1580     static const WCHAR UserW[] = {'U','s','e','r',0};
1581     static const WCHAR DefaultW[] = {'.','D','e','f','a','u','l','t',0};
1582     static const WCHAR RegistryW[] = {'M','a','c','h','i','n','e','\\',
1583                                       'S','o','f','t','w','a','r','e','\\',
1584                                       'W','i','n','e','\\',
1585                                       'W','i','n','e','\\',
1586                                       'C','o','n','f','i','g','\\',
1587                                       'R','e','g','i','s','t','r','y',0};
1588     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};
1589     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};
1590     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};
1591     static const WCHAR SaveOnlyUpdatedKeysW[] = {'S','a','v','e','O','n','l','y','U','p','d','a','t','e','d','K','e','y','s',0};
1592     static const WCHAR PeriodicSaveW[] = {'P','e','r','i','o','d','i','c','S','a','v','e',0};
1593     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};
1594     static const WCHAR GlobalRegistryDirW[] = {'G','l','o','b','a','l','R','e','g','i','s','t','r','y','D','i','r',0};
1595
1596     TRACE("(void)\n");
1597
1598     if (!CLIENT_IsBootThread()) return;  /* already loaded */
1599
1600     attr.Length = sizeof(attr);
1601     attr.RootDirectory = 0;
1602     attr.ObjectName = &nameW;
1603     attr.Attributes = 0;
1604     attr.SecurityDescriptor = NULL;
1605     attr.SecurityQualityOfService = NULL;
1606
1607     RtlInitUnicodeString( &nameW, MachineW );
1608     NtCreateKey( &hkey_local_machine, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
1609     RtlInitUnicodeString( &nameW, UserW );
1610     NtCreateKey( &hkey_users, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL );
1611
1612     attr.RootDirectory = hkey_users;
1613     RtlInitUnicodeString( &nameW, DefaultW );
1614     if (NtCreateKey( &hkey_users_default, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ))
1615     {
1616         ERR("Cannot create HKEY_USERS/.Default\n" );
1617         ExitProcess(1);
1618     }
1619     RtlOpenCurrentUser( KEY_ALL_ACCESS, &hkey_current_user );
1620
1621     _set_registry_levels(0,0,0);
1622     _allocate_default_keys();
1623
1624     attr.RootDirectory = 0;
1625     RtlInitUnicodeString( &nameW, RegistryW );
1626     if (NtOpenKey( &hkey_config, KEY_ALL_ACCESS, &attr )) hkey_config = 0;
1627
1628     /* load windows registry if required */
1629
1630     res = TRUE;
1631     attr.RootDirectory = hkey_config;
1632     RtlInitUnicodeString( &nameW, load_win_reg_filesW );
1633     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1634     {
1635         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1636         res = !IS_OPTION_FALSE(str[0]);
1637     }
1638     if (res) _load_windows_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
1639
1640     /* load global registry if required */
1641
1642     res = TRUE;
1643     RtlInitUnicodeString( &nameW, load_global_reg_filesW );
1644     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1645     {
1646         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1647         res = !IS_OPTION_FALSE(str[0]);
1648     }
1649     if (res)
1650     {
1651         /* load global registry files (stored in /etc/wine) */
1652         char *p, configfile[MAX_PATHNAME_LEN];
1653
1654         /* Override ETCDIR? */
1655         configfile[0] = 0;
1656         RtlInitUnicodeString( &nameW, GlobalRegistryDirW );
1657         if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1658         {
1659             WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1660             WideCharToMultiByte(CP_ACP, 0, str, -1, configfile, sizeof(configfile), NULL, NULL);
1661         }
1662         if (configfile[0] != '/') strcpy(configfile, ETCDIR);
1663
1664         TRACE("GlobalRegistryDir is '%s'.\n", configfile);
1665
1666         /* Load the global HKU hive directly from sysconfdir */
1667         p = configfile + strlen(configfile);
1668         strcpy(p, SAVE_GLOBAL_REGBRANCH_USER_DEFAULT);
1669         load_wine_registry( hkey_users, configfile );
1670
1671         /* Load the global machine defaults directly from sysconfdir */
1672         strcpy(p, SAVE_GLOBAL_REGBRANCH_LOCAL_MACHINE);
1673         load_wine_registry( hkey_local_machine, configfile );
1674     }
1675
1676     _set_registry_levels(1,0,0);
1677
1678     /* load home registry if required */
1679
1680     res = TRUE;
1681     RtlInitUnicodeString( &nameW, load_home_reg_filesW );
1682     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1683     {
1684         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1685         res = !IS_OPTION_FALSE(str[0]);
1686     }
1687     if (res) _load_home_registry( hkey_local_machine, hkey_current_user, hkey_users_default );
1688
1689     /* setup registry saving */
1690
1691     all = FALSE;
1692     RtlInitUnicodeString( &nameW, SaveOnlyUpdatedKeysW );
1693     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1694     {
1695         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1696         all = IS_OPTION_FALSE(str[0]);
1697     }
1698
1699     period = 0;
1700     RtlInitUnicodeString( &nameW, PeriodicSaveW );
1701     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1702     {
1703         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1704         period = (int)strtolW(str, NULL, 10);
1705     }
1706
1707     /* set saving level (0 for saving everything, 1 for saving only modified keys) */
1708     _set_registry_levels(1,!all,period*1000);
1709
1710     /* setup keys to save */
1711
1712     res = TRUE;
1713     RtlInitUnicodeString( &nameW, WritetoHomeRegistryFilesW );
1714     if (!NtQueryValueKey( hkey_config, &nameW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
1715     {
1716         WCHAR *str = (WCHAR *)((KEY_VALUE_PARTIAL_INFORMATION *)tmp)->Data;
1717         res = !IS_OPTION_FALSE(str[0]);
1718     }
1719     if (res)
1720     {
1721         _save_at_exit(hkey_current_user,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER );
1722         _save_at_exit(hkey_local_machine,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
1723         _save_at_exit(hkey_users_default,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
1724     }
1725
1726     NtClose(hkey_users_default);
1727     NtClose(hkey_current_user);
1728     NtClose(hkey_users);
1729     NtClose(hkey_local_machine);
1730     NtClose(hkey_config);
1731 }