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