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