Changed to use new server-side registry support.
[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  * NOTES
13  *    When changing this file, please re-run the regtest program to ensure
14  *    the conditions are handled properly.
15  *
16  * TODO
17  *    Security access
18  *    Option handling
19  *    Time for RegEnumKey*, RegQueryInfoKey*
20  */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #ifdef HAVE_SYS_ERRNO_H
30 #include <sys/errno.h>
31 #endif
32 #include <sys/types.h>
33 #include <sys/fcntl.h>
34 #include <sys/stat.h>
35 #include <assert.h>
36 #include <time.h>
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wine/winbase16.h"
40 #include "wine/winestring.h"
41 #include "winerror.h"
42 #include "file.h"
43 #include "heap.h"
44 #include "debugtools.h"
45 #include "xmalloc.h"
46 #include "options.h"
47 #include "winreg.h"
48 #include "winversion.h"
49 #include "server.h"
50
51 DEFAULT_DEBUG_CHANNEL(reg)
52
53 static void REGISTRY_Init(void);
54 /* FIXME: following defines should be configured global ... */
55
56 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
57 #define WINE_PREFIX                 "/.wine"
58 #define SAVE_USERS_DEFAULT          ETCDIR"/wine.userreg"
59 #define SAVE_LOCAL_MACHINE_DEFAULT  ETCDIR"/wine.systemreg"
60
61 /* relative in ~user/.wine/ : */
62 #define SAVE_CURRENT_USER           "user.reg"
63 #define SAVE_LOCAL_USERS_DEFAULT    "wine.userreg"
64 #define SAVE_LOCAL_MACHINE          "system.reg"
65
66 #define KEY_REGISTRY                "Software\\The WINE team\\WINE\\Registry"
67 #define VAL_SAVEUPDATED             "SaveOnlyUpdatedKeys"
68
69
70 /* what valuetypes do we need to convert? */
71 #define UNICONVMASK     ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
72
73
74
75 /*
76  * QUESTION
77  *   Are these doing the same as HEAP_strdupAtoW and HEAP_strdupWtoA?
78  *   If so, can we remove them?
79  * ANSWER
80  *   No, the memory handling functions are called very often in here, 
81  *   just replacing them by HeapAlloc(SystemHeap,...) makes registry
82  *   loading 100 times slower. -MM
83  */
84 static LPWSTR strdupA2W(LPCSTR src)
85 {
86     if(src) {
87         LPWSTR dest=xmalloc(2*strlen(src)+2);
88         lstrcpyAtoW(dest,src);
89         return dest;
90     }
91     return NULL;
92 }
93
94 LPWSTR strcvtA2W(LPCSTR src, int nchars)
95
96 {
97    LPWSTR dest = xmalloc (2 * nchars + 2);
98
99    lstrcpynAtoW(dest,src,nchars+1);
100    dest[nchars] = 0;
101    return dest;
102 }
103
104
105
106 /******************************************************************************
107  * REGISTRY_Init [Internal]
108  * Registry initialisation, allocates some default keys. 
109  */
110 static void REGISTRY_Init(void) {
111         HKEY    hkey;
112         char    buf[200];
113
114         TRACE_(reg)("(void)\n");
115
116         RegCreateKeyA(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
117         RegCloseKey(hkey);
118
119         /* This was an Open, but since it is called before the real registries
120            are loaded, it was changed to a Create - MTB 980507*/
121         RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
122         RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
123         RegCloseKey(hkey);
124
125         /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
126          *                                              CurrentVersion
127          *                                              CurrentBuildNumber
128          *                                              CurrentType
129          *                                      string  RegisteredOwner
130          *                                      string  RegisteredOrganization
131          *
132          */
133         /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
134          *                                      string  SysContact
135          *                                      string  SysLocation
136          *                                              SysServices
137          */
138         if (-1!=gethostname(buf,200)) {
139                 RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
140                 RegSetValueExA(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
141                 RegCloseKey(hkey);
142         }
143 }
144
145
146 /************************ SAVE Registry Function ****************************/
147
148 #define REGISTRY_SAVE_VERSION   0x00000001
149
150 /* Registry saveformat:
151  * If you change it, increase above number by 1, which will flush
152  * old registry database files.
153  * 
154  * Global:
155  *      "WINE REGISTRY Version %d"
156  *      subkeys....
157  * Subkeys:
158  *      keyname
159  *              valuename=lastmodified,type,data
160  *              ...
161  *              subkeys
162  *      ...
163  * keyname,valuename,stringdata:
164  *      the usual ascii characters from 0x00-0xff (well, not 0x00)
165  *      and \uXXXX as UNICODE value XXXX with XXXX>0xff
166  *      ( "=\\\t" escaped in \uXXXX form.)
167  * type,lastmodified: 
168  *      int
169  * 
170  * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
171  *
172  * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
173  * SaveOnlyUpdatedKeys=yes
174  */
175
176
177
178 /******************************************************************************
179  * SHELL_SaveRegistryBranch [Internal]
180  *
181  * Saves main registry branch specified by hkey.
182  */
183 static void SHELL_SaveRegistryBranch(HKEY hkey)
184 {
185     char   *fn, *home;
186
187     /* Find out what to save to, get from config file */
188     BOOL writeToHome = PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1);
189     BOOL writeToAlt = PROFILE_GetWineIniBool("registry","WritetoAltRegistries",1);
190
191     /* FIXME: does this check apply to all keys written below ? */
192     if (!(home = getenv( "HOME" )))
193         ERR_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid());
194
195     /* HKEY_LOCAL_MACHINE contains the HKEY_CLASSES_ROOT branch */
196     if (hkey == HKEY_CLASSES_ROOT) hkey = HKEY_LOCAL_MACHINE;
197
198     switch (hkey)
199     {
200     case HKEY_CURRENT_USER:
201         fn = xmalloc( MAX_PATHNAME_LEN ); 
202         if (writeToAlt && PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "",
203                                                     fn, MAX_PATHNAME_LEN - 1))
204             RegSaveKeyA( HKEY_CURRENT_USER, fn, NULL );
205         free (fn);
206
207         if (home && writeToHome)
208         {
209             fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) +
210                                strlen(SAVE_CURRENT_USER) + 2 );
211             strcpy(fn,home);
212             strcat(fn,WINE_PREFIX);
213   
214             /* create the directory. don't care about errorcodes. */
215             mkdir(fn,0755); /* drwxr-xr-x */
216             strcat(fn,"/"SAVE_CURRENT_USER);
217             RegSaveKeyA( HKEY_CURRENT_USER, fn, NULL );
218             free(fn);
219         }
220         break;
221     case HKEY_LOCAL_MACHINE:
222         /* Try first saving according to the defined location in .winerc */
223         fn = xmalloc ( MAX_PATHNAME_LEN);
224         if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltLocalMachineFile", "", 
225                                                     fn, MAX_PATHNAME_LEN - 1))
226             RegSaveKeyA( HKEY_LOCAL_MACHINE, fn, NULL );
227         free (fn);
228
229         if (home && writeToHome)
230         {
231             fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) +
232                                strlen(SAVE_LOCAL_MACHINE) + 2);
233             strcpy(fn,home);
234             strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
235             RegSaveKeyA( HKEY_LOCAL_MACHINE, fn, NULL );
236             free(fn);
237         }
238         break;
239     case HKEY_USERS:
240         fn = xmalloc( MAX_PATHNAME_LEN );
241         if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltUserFile", "", 
242                                                     fn, MAX_PATHNAME_LEN - 1))
243             RegSaveKeyA( HKEY_USERS, fn, NULL );
244         free (fn);
245
246         if (home && writeToHome)
247         {
248             fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) +
249                                strlen(SAVE_LOCAL_USERS_DEFAULT) + 2);
250             strcpy(fn,home);
251             strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
252             RegSaveKeyA( HKEY_USERS, fn, NULL );
253             free(fn);
254         }
255         break;
256     default:
257         ERR_(reg)("unknown/invalid key handle !\n");
258         break;
259     }
260 }
261
262
263 /******************************************************************************
264  * SHELL_SaveRegistry [Internal]
265  */
266 void SHELL_SaveRegistry( void )
267 {
268     struct set_registry_levels_request *req = get_req_buffer();
269     char   buf[4];
270     HKEY   hkey;
271     int    all;
272
273     TRACE_(reg)("(void)\n");
274
275     all=0;
276     if (RegOpenKeyA(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) 
277     {
278         strcpy(buf,"yes");
279     } 
280     else 
281     {
282         DWORD len,junk,type;
283
284         len=4;
285         if ((ERROR_SUCCESS!=RegQueryValueExA( hkey,
286                                               VAL_SAVEUPDATED,
287                                               &junk,
288                                               &type,
289                                               buf,
290                                               &len)) || (type!=REG_SZ))
291         {
292             strcpy(buf,"yes");
293         }
294         RegCloseKey(hkey);
295     }
296
297     if (lstrcmpiA(buf,"yes")) all = 1;
298
299     /* set saving level (0 for saving everything, 1 for saving only modified keys) */
300     req->current = 1;
301     req->saving  = !all;
302     server_call( REQ_SET_REGISTRY_LEVELS );
303
304     SHELL_SaveRegistryBranch(HKEY_CURRENT_USER);
305     SHELL_SaveRegistryBranch(HKEY_LOCAL_MACHINE);
306     SHELL_SaveRegistryBranch(HKEY_USERS);
307 }
308
309
310 /************************ LOAD Registry Function ****************************/
311
312
313
314 /******************************************************************************
315  * _find_or_add_key [Internal]
316  */
317 static inline HKEY _find_or_add_key( HKEY hkey, LPWSTR keyname )
318 {
319     HKEY subkey;
320     if (RegCreateKeyW( hkey, keyname, &subkey ) != ERROR_SUCCESS) subkey = 0;
321     if (keyname) free( keyname );
322     return subkey;
323 }
324
325 /******************************************************************************
326  * _find_or_add_value [Internal]
327  */
328 static void _find_or_add_value( HKEY hkey, LPWSTR name, DWORD type, LPBYTE data, DWORD len )
329 {
330     RegSetValueExW( hkey, name, 0, type, data, len );
331     if (name) free( name );
332     if (data) free( data );
333 }
334
335
336 /******************************************************************************
337  * _wine_read_line [Internal]
338  *
339  * reads a line including dynamically enlarging the readbuffer and throwing
340  * away comments
341  */
342 static int _wine_read_line( FILE *F, char **buf, int *len )
343 {
344         char    *s,*curread;
345         int     mylen,curoff;
346
347         curread = *buf;
348         mylen   = *len;
349         **buf   = '\0';
350         while (1) {
351                 while (1) {
352                         s=fgets(curread,mylen,F);
353                         if (s==NULL)
354                                 return 0; /* EOF */
355                         if (NULL==(s=strchr(curread,'\n'))) {
356                                 /* buffer wasn't large enough */
357                                 curoff  = strlen(*buf);
358                                 *buf    = xrealloc(*buf,*len*2);
359                                 curread = *buf + curoff;
360                                 mylen   = *len; /* we filled up the buffer and 
361                                                  * got new '*len' bytes to fill
362                                                  */
363                                 *len    = *len * 2;
364                         } else {
365                                 *s='\0';
366                                 break;
367                         }
368                 }
369                 /* throw away comments */
370                 if (**buf=='#' || **buf==';') {
371                         curread = *buf;
372                         mylen   = *len;
373                         continue;
374                 }
375                 if (s)  /* got end of line */
376                         break;
377         }
378         return 1;
379 }
380
381
382 /******************************************************************************
383  * _wine_read_USTRING [Internal]
384  *
385  * converts a char* into a UNICODE string (up to a special char)
386  * and returns the position exactly after that string
387  */
388 static char* _wine_read_USTRING( char *buf, LPWSTR *str )
389 {
390         char    *s;
391         LPWSTR  ws;
392
393         /* read up to "=" or "\0" or "\n" */
394         s       = buf;
395         *str    = (LPWSTR)xmalloc(2*strlen(buf)+2);
396         ws      = *str;
397         while (*s && (*s!='\n') && (*s!='=')) {
398                 if (*s!='\\')
399                         *ws++=*((unsigned char*)s++);
400                 else {
401                         s++;
402                         if (!*s) {
403                                 /* Dangling \ ... may only happen if a registry
404                                  * write was short. FIXME: What do to?
405                                  */
406                                  break;
407                         }
408                         if (*s=='\\') {
409                                 *ws++='\\';
410                                 s++;
411                                 continue;
412                         }
413                         if (*s!='u') {
414                                 WARN_(reg)("Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
415                                 *ws++='\\';
416                                 *ws++=*s++;
417                         } else {
418                                 char    xbuf[5];
419                                 int     wc;
420
421                                 s++;
422                                 memcpy(xbuf,s,4);xbuf[4]='\0';
423                                 if (!sscanf(xbuf,"%x",&wc))
424                                         WARN_(reg)("Strange escape sequence %s found in |%s|\n",xbuf,buf);
425                                 s+=4;
426                                 *ws++   =(unsigned short)wc;
427                         }
428                 }
429         }
430         *ws     = 0;
431         return s;
432 }
433
434
435 /******************************************************************************
436  * _wine_loadsubkey [Internal]
437  *
438  * NOTES
439  *    It seems like this is returning a boolean.  Should it?
440  *
441  * RETURNS
442  *    Success: 1
443  *    Failure: 0
444  */
445 static int _wine_loadsubkey( FILE *F, HKEY hkey, int level, char **buf, int *buflen )
446 {
447         HKEY subkey;
448         int             i;
449         char            *s;
450         LPWSTR          name;
451
452     TRACE_(reg)("(%p,%x,%d,%s,%d)\n", F, hkey, level, debugstr_a(*buf), *buflen);
453
454     /* Good.  We already got a line here ... so parse it */
455     subkey = 0;
456     while (1) {
457         i=0;s=*buf;
458         while (*s=='\t') {
459             s++;
460             i++;
461         }
462         if (i>level) {
463             if (!subkey) {
464                 WARN_(reg)("Got a subhierarchy without resp. key?\n");
465                 return 0;
466             }
467             if (!_wine_loadsubkey(F,subkey,level+1,buf,buflen))
468                if (!_wine_read_line(F,buf,buflen))
469                   return 1;
470             continue;
471         }
472
473                 /* let the caller handle this line */
474                 if (i<level || **buf=='\0')
475                         return 1;
476
477                 /* it can be: a value or a keyname. Parse the name first */
478                 s=_wine_read_USTRING(s,&name);
479
480                 /* switch() default: hack to avoid gotos */
481                 switch (0) {
482                 default:
483                         if (*s=='\0') {
484                                 subkey=_find_or_add_key(hkey,name);
485                         } else {
486                                 LPBYTE          data;
487                                 int             len,lastmodified,type;
488
489                                 if (*s!='=') {
490                                         WARN_(reg)("Unexpected character: %c\n",*s);
491                                         break;
492                                 }
493                                 s++;
494                                 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
495                                         WARN_(reg)("Haven't understood possible value in |%s|, skipping.\n",*buf);
496                                         break;
497                                 }
498                                 /* skip the 2 , */
499                                 s=strchr(s,',');s++;
500                                 s=strchr(s,',');
501                                 if (!s++) {
502                                         WARN_(reg)("Haven't understood possible value in |%s|, skipping.\n",*buf);
503                                         break;
504                                 }
505                                 if (type == REG_SZ || type == REG_EXPAND_SZ) {
506                                         s=_wine_read_USTRING(s,(LPWSTR*)&data);
507                                         len = lstrlenW((LPWSTR)data)*2+2;
508                                 } else {
509                                         len=strlen(s)/2;
510                                         data = (LPBYTE)xmalloc(len+1);
511                                         for (i=0;i<len;i++) {
512                                                 data[i]=0;
513                                                 if (*s>='0' && *s<='9')
514                                                         data[i]=(*s-'0')<<4;
515                                                 if (*s>='a' && *s<='f')
516                                                         data[i]=(*s-'a'+'\xa')<<4;
517                                                 if (*s>='A' && *s<='F')
518                                                         data[i]=(*s-'A'+'\xa')<<4;
519                                                 s++;
520                                                 if (*s>='0' && *s<='9')
521                                                         data[i]|=*s-'0';
522                                                 if (*s>='a' && *s<='f')
523                                                         data[i]|=*s-'a'+'\xa';
524                                                 if (*s>='A' && *s<='F')
525                                                         data[i]|=*s-'A'+'\xa';
526                                                 s++;
527                                         }
528                                 }
529                                 _find_or_add_value(hkey,name,type,data,len);
530                         }
531                 }
532                 /* read the next line */
533                 if (!_wine_read_line(F,buf,buflen))
534                         return 1;
535     }
536     return 1;
537 }
538
539
540 /******************************************************************************
541  * _wine_loadsubreg [Internal]
542  */
543 static int _wine_loadsubreg( FILE *F, HKEY hkey, const char *fn )
544 {
545         int     ver;
546         char    *buf;
547         int     buflen;
548
549         buf=xmalloc(10);buflen=10;
550         if (!_wine_read_line(F,&buf,&buflen)) {
551                 free(buf);
552                 return 0;
553         }
554         if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
555                 free(buf);
556                 return 0;
557         }
558         if (ver!=REGISTRY_SAVE_VERSION) {
559                 TRACE_(reg)("Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
560                 free(buf);
561                 return 0;
562         }
563         if (!_wine_read_line(F,&buf,&buflen)) {
564                 free(buf);
565                 return 0;
566         }
567         if (!_wine_loadsubkey(F,hkey,0,&buf,&buflen)) {
568                 free(buf);
569                 return 0;
570         }
571         free(buf);
572         return 1;
573 }
574
575
576 /******************************************************************************
577  * _wine_loadreg [Internal]
578  */
579 static void _wine_loadreg( HKEY hkey, char *fn )
580 {
581     FILE *F;
582
583     TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(fn));
584
585     F = fopen(fn,"rb");
586     if (F==NULL) {
587         WARN_(reg)("Couldn't open %s for reading: %s\n",fn,strerror(errno) );
588         return;
589     }
590     _wine_loadsubreg(F,hkey,fn);
591     fclose(F);
592 }
593
594 /******************************************************************************
595  * _flush_registry [Internal]
596  * 
597  * This function allow to flush section of the internal registry.  It is mainly
598  * implements to fix a problem with the global HKU and the local HKU.
599  * Those two files are read to build the HKU\.Default branch to finaly copy
600  * this branch onto HKCU hive, once this is done, if we keep the HKU hive as is, 
601  * all the global HKU are saved onto the user's personal version of HKU hive.
602  * which is bad...
603  */
604
605 static void _flush_registry( HKEY hkey )
606 {
607     WCHAR name[MAX_PATH];
608
609     for (;;)
610     {
611         HKEY subkey;
612         /* FIXME: we assume that deleting a key will move the other ones up, */
613         /* so that we can always use index 0 until there are no more keys    */
614         if (RegEnumKeyW( hkey, 0, name, sizeof(name) ) != ERROR_SUCCESS) break;
615         if (RegOpenKeyW( hkey, name, &subkey ) != ERROR_SUCCESS) break;
616         _flush_registry( subkey );
617         if (RegDeleteKeyW( subkey, NULL ) != ERROR_SUCCESS) break;
618         RegCloseKey( subkey );
619     }
620 }
621
622
623 /******************************************************************************
624  * _copy_registry [Internal]
625  */
626 static void _copy_registry( HKEY from, HKEY to )
627 {
628     int index;
629     HKEY subkey;
630     FILETIME ft;
631     DWORD type, name_len, len;
632     static WCHAR name[MAX_PATH];
633     static BYTE data[2048];
634
635     /* copy values */
636     index = 0;
637     for (;;)
638     {
639         len = sizeof(data);
640         name_len = sizeof(name);
641         if (RegEnumValueW( from, index++, name, &name_len,
642                            NULL, &type, data, &len ) != ERROR_SUCCESS) break;
643         RegSetValueW( to, name, type, (LPCWSTR)data, len );
644     }
645
646     /* copy subkeys */
647     index = 0;
648     for (;;)
649     {
650         name_len = sizeof(name);
651         if (RegEnumKeyExW( from, index++, name, &name_len,
652                            NULL, NULL, 0, &ft ) != ERROR_SUCCESS)
653             break;
654         if (RegOpenKeyW( from, name, &subkey ) == ERROR_SUCCESS)
655         {
656             HKEY newsub;
657             if (RegCreateKeyW( to, name, &newsub ) == ERROR_SUCCESS)
658             {
659                 _copy_registry( subkey, newsub );
660                 RegCloseKey( newsub );
661             }
662             RegCloseKey( subkey );
663         }
664     }
665 }
666
667
668 /* WINDOWS 95 REGISTRY LOADER */
669 /* 
670  * Structure of a win95 registry database.
671  * main header:
672  * 0 :  "CREG"  - magic
673  * 4 :  DWORD version
674  * 8 :  DWORD offset_of_RGDB_part
675  * 0C..0F:      ? (someone fill in please)
676  * 10:  WORD    number of RGDB blocks
677  * 12:  WORD    ?
678  * 14:  WORD    always 0000?
679  * 16:  WORD    always 0001?
680  * 18..1F:      ? (someone fill in please)
681  *
682  * 20: RGKN_section:
683  *   header:
684  *      0 :             "RGKN"  - magic
685  *      4 : DWORD       offset to first RGDB section
686  *      8 : DWORD       offset to the root record
687  *      C..0x1B:        ? (fill in)
688  *      0x20 ... offset_of_RGDB_part: Disk Key Entry structures
689  *
690  *   Disk Key Entry Structure:
691  *      00: DWORD       - Free entry indicator(?)
692  *      04: DWORD       - Hash = sum of bytes of keyname
693  *      08: DWORD       - Root key indicator? unknown, but usually 0xFFFFFFFF on win95 systems
694  *      0C: DWORD       - disk address of PreviousLevel Key.
695  *      10: DWORD       - disk address of Next Sublevel Key.
696  *      14: DWORD       - disk address of Next Key (on same level).
697  * DKEP>18: WORD        - Nr, Low Significant part.
698  *      1A: WORD        - Nr, High Significant part.
699  *
700  * The disk address always points to the nr part of the previous key entry 
701  * of the referenced key. Don't ask me why, or even if I got this correct
702  * from staring at 1kg of hexdumps. (DKEP)
703  *
704  * The High significant part of the structure seems to equal the number
705  * of the RGDB section. The low significant part is a unique ID within
706  * that RGDB section
707  *
708  * There are two minor corrections to the position of that structure.
709  * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND 
710  *    the DKE reread from there.
711  * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
712  * CPS - I have not experienced the above phenomenon in my registry files
713  *
714  * RGDB_section:
715  *      00:             "RGDB"  - magic
716  *      04: DWORD       offset to next RGDB section
717  *      08: DWORD       ?
718  *      0C: WORD        always 000d?
719  *      0E: WORD        RGDB block number
720  *      10:     DWORD   ? (equals value at offset 4 - value at offset 8)
721  *      14..1F:         ?
722  *      20.....:        disk keys
723  *
724  * disk key:
725  *      00:     DWORD   nextkeyoffset   - offset to the next disk key structure
726  *      08:     WORD    nrLS            - low significant part of NR
727  *      0A:     WORD    nrHS            - high significant part of NR
728  *      0C:     DWORD   bytesused       - bytes used in this structure.
729  *      10:     WORD    name_len        - length of name in bytes. without \0
730  *      12:     WORD    nr_of_values    - number of values.
731  *      14:     char    name[name_len]  - name string. No \0.
732  *      14+name_len: disk values
733  *      nextkeyoffset: ... next disk key
734  *
735  * disk value:
736  *      00:     DWORD   type            - value type (hmm, could be WORD too)
737  *      04:     DWORD                   - unknown, usually 0
738  *      08:     WORD    namelen         - length of Name. 0 means name=NULL
739  *      0C:     WORD    datalen         - length of Data.
740  *      10:     char    name[namelen]   - name, no \0
741  *      10+namelen: BYTE        data[datalen] - data, without \0 if string
742  *      10+namelen+datalen: next values or disk key
743  *
744  * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
745  * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
746  * structure) and reading another RGDB_section.
747  * repeat until end of file.
748  *
749  * An interesting relationship exists in RGDB_section. The value at offset
750  * 10 equals the value at offset 4 minus the value at offset 8. I have no
751  * idea at the moment what this means.  (Kevin Cozens)
752  *
753  * FIXME: this description needs some serious help, yes.
754  */
755
756 struct  _w95keyvalue {
757         unsigned long           type;
758         unsigned short          datalen;
759         char                    *name;
760         unsigned char           *data;
761         unsigned long           x1;
762         int                     lastmodified;
763 };
764
765 struct  _w95key {
766         char                    *name;
767         int                     nrofvals;
768         struct  _w95keyvalue    *values;
769         struct _w95key          *prevlvl;
770         struct _w95key          *nextsub;
771         struct _w95key          *next;
772 };
773
774
775 struct _w95_info {
776   char *rgknbuffer;
777   int  rgknsize;
778   char *rgdbbuffer;
779   int  rgdbsize;
780   int  depth;
781   int  lastmodified;
782 };
783
784
785 /******************************************************************************
786  * _w95_processKey [Internal]
787  */
788 static HKEY _w95_processKey ( HKEY hkey, int nrLS, int nrMS, struct _w95_info *info )
789
790 {
791   /* Disk Key Header structure (RGDB part) */
792         struct  dkh {
793                 unsigned long           nextkeyoff; 
794                 unsigned short          nrLS;
795                 unsigned short          nrMS;
796                 unsigned long           bytesused;
797                 unsigned short          keynamelen;
798                 unsigned short          values;
799                 unsigned long           xx1;
800                 /* keyname */
801                 /* disk key values or nothing */
802         };
803         /* Disk Key Value structure */
804         struct  dkv {
805                 unsigned long           type;
806                 unsigned long           x1;
807                 unsigned short          valnamelen;
808                 unsigned short          valdatalen;
809                 /* valname, valdata */
810         };
811
812         
813         struct  dkh dkh;
814         int     bytesread = 0;
815         char    *rgdbdata = info->rgdbbuffer;
816         int     nbytes = info->rgdbsize;
817         char    *curdata = rgdbdata;
818         char    *end = rgdbdata + nbytes;
819         int     off_next_rgdb;
820         char    *next = rgdbdata;
821         int     nrgdb, i;
822         HKEY subkey;
823         
824         do {
825           curdata = next;
826           if (strncmp(curdata, "RGDB", 4)) return 0;
827             
828           memcpy(&off_next_rgdb,curdata+4,4);
829           next = curdata + off_next_rgdb;
830           nrgdb = (int) *((short *)curdata + 7);
831
832         } while (nrgdb != nrMS && (next < end));
833
834         /* curdata now points to the start of the right RGDB section */
835         curdata += 0x20;
836
837 #define XREAD(whereto,len) \
838         if ((curdata + len) <= end) {\
839                 memcpy(whereto,curdata,len);\
840                 curdata+=len;\
841                 bytesread+=len;\
842         }
843
844         while (curdata < next) {
845           struct        dkh *xdkh = (struct dkh*)curdata;
846
847           bytesread += sizeof(dkh); /* FIXME... nextkeyoff? */
848           if (xdkh->nrLS == nrLS) {
849                 memcpy(&dkh,xdkh,sizeof(dkh));
850                 curdata += sizeof(dkh);
851                 break;
852           }
853           curdata += xdkh->nextkeyoff;
854         };
855
856         if (dkh.nrLS != nrLS) return 0;
857
858         if (nrgdb != dkh.nrMS)
859           return 0;
860
861         assert((dkh.keynamelen<2) || curdata[0]);
862         subkey=_find_or_add_key(hkey,strcvtA2W(curdata, dkh.keynamelen));
863         curdata += dkh.keynamelen;
864
865         for (i=0;i< dkh.values; i++) {
866           struct dkv dkv;
867           LPBYTE data;
868           int len;
869           LPWSTR name;
870
871           XREAD(&dkv,sizeof(dkv));
872
873           name = strcvtA2W(curdata, dkv.valnamelen);
874           curdata += dkv.valnamelen;
875
876           if ((1 << dkv.type) & UNICONVMASK) {
877             data = (LPBYTE) strcvtA2W(curdata, dkv.valdatalen);
878             len = 2*(dkv.valdatalen + 1);
879           } else {
880             /* I don't think we want to NULL terminate all data */
881             data = xmalloc(dkv.valdatalen);
882             memcpy (data, curdata, dkv.valdatalen);
883             len = dkv.valdatalen;
884           }
885
886           curdata += dkv.valdatalen;
887           
888           _find_or_add_value( subkey, name, dkv.type, data, len );
889         }
890         return subkey;
891 }
892
893 /******************************************************************************
894  * _w95_walkrgkn [Internal]
895  */
896 static void _w95_walkrgkn( HKEY prevkey, char *off, 
897                            struct _w95_info *info )
898
899 {
900   /* Disk Key Entry structure (RGKN part) */
901   struct        dke {
902     unsigned long               x1;
903     unsigned long               x2;
904     unsigned long               x3;/*usually 0xFFFFFFFF */
905     unsigned long               prevlvl;
906     unsigned long               nextsub;
907     unsigned long               next;
908     unsigned short              nrLS;
909     unsigned short              nrMS;
910   } *dke = (struct dke *)off;
911   HKEY subkey;
912
913   if (dke == NULL) {
914     dke = (struct dke *) ((char *)info->rgknbuffer);
915   }
916
917   subkey = _w95_processKey(prevkey, dke->nrLS, dke->nrMS, info);
918   /* XXX <-- This is a hack*/
919   if (!subkey) subkey = prevkey;
920
921   if (dke->nextsub != -1 && 
922       ((dke->nextsub - 0x20) < info->rgknsize) 
923       && (dke->nextsub > 0x20)) {
924     
925     _w95_walkrgkn(subkey, 
926                   info->rgknbuffer + dke->nextsub - 0x20, 
927                   info);
928   }
929   
930   if (dke->next != -1 && 
931       ((dke->next - 0x20) < info->rgknsize) && 
932       (dke->next > 0x20)) {
933     _w95_walkrgkn(prevkey,  
934                   info->rgknbuffer + dke->next - 0x20,
935                   info);
936   }
937 }
938
939
940 /******************************************************************************
941  * _w95_loadreg [Internal]
942  */
943 static void _w95_loadreg( char* fn, HKEY hkey )
944 {
945         HFILE           hfd;
946         char            magic[5];
947         unsigned long   where,version,rgdbsection,end;
948         struct          _w95_info info;
949         OFSTRUCT        ofs;
950         BY_HANDLE_FILE_INFORMATION hfdinfo;
951
952         TRACE_(reg)("Loading Win95 registry database '%s'\n",fn);
953         hfd=OpenFile(fn,&ofs,OF_READ);
954         if (hfd==HFILE_ERROR)
955                 return;
956         magic[4]=0;
957         if (4!=_lread(hfd,magic,4))
958                 return;
959         if (strcmp(magic,"CREG")) {
960                 WARN_(reg)("%s is not a w95 registry.\n",fn);
961                 return;
962         }
963         if (4!=_lread(hfd,&version,4))
964                 return;
965         if (4!=_lread(hfd,&rgdbsection,4))
966                 return;
967         if (-1==_llseek(hfd,0x20,SEEK_SET))
968                 return;
969         if (4!=_lread(hfd,magic,4))
970                 return;
971         if (strcmp(magic,"RGKN")) {
972                 WARN_(reg)("second IFF header not RGKN, but %s\n", magic);
973                 return;
974         }
975
976         /* STEP 1: Keylink structures */
977         if (-1==_llseek(hfd,0x40,SEEK_SET))
978                 return;
979         where   = 0x40;
980         end     = rgdbsection;
981
982         info.rgknsize = end - where;
983         info.rgknbuffer = (char*)xmalloc(info.rgknsize);
984         if (info.rgknsize != _lread(hfd,info.rgknbuffer,info.rgknsize))
985                 return;
986
987         if (!GetFileInformationByHandle(hfd,&hfdinfo))
988                 return;
989
990         end = hfdinfo.nFileSizeLow;
991         info.lastmodified = DOSFS_FileTimeToUnixTime(&hfdinfo.ftLastWriteTime,NULL);
992
993         if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
994                 return;
995
996         info.rgdbbuffer = (char*)xmalloc(end-rgdbsection);
997         info.rgdbsize = end - rgdbsection;
998
999         if (info.rgdbsize !=_lread(hfd,info.rgdbbuffer,info.rgdbsize))
1000                 return;
1001         _lclose(hfd);
1002
1003         _w95_walkrgkn(hkey, NULL, &info);
1004
1005         free (info.rgdbbuffer);
1006         free (info.rgknbuffer);
1007 }
1008
1009
1010 /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1011
1012 /*
1013     reghack - windows 3.11 registry data format demo program.
1014
1015     The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1016     a combined hash table and tree description, and finally a text table.
1017
1018     The header is obvious from the struct header. The taboff1 and taboff2
1019     fields are always 0x20, and their usage is unknown.
1020
1021     The 8-byte entry table has various entry types.
1022
1023     tabent[0] is a root index. The second word has the index of the root of
1024             the directory.
1025     tabent[1..hashsize] is a hash table. The first word in the hash entry is
1026             the index of the key/value that has that hash. Data with the same
1027             hash value are on a circular list. The other three words in the
1028             hash entry are always zero.
1029     tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1030             entry: dirent and keyent/valent. They are identified by context.
1031     tabent[freeidx] is the first free entry. The first word in a free entry
1032             is the index of the next free entry. The last has 0 as a link.
1033             The other three words in the free list are probably irrelevant.
1034
1035     Entries in text table are preceeded by a word at offset-2. This word
1036     has the value (2*index)+1, where index is the referring keyent/valent
1037     entry in the table. I have no suggestion for the 2* and the +1.
1038     Following the word, there are N bytes of data, as per the keyent/valent
1039     entry length. The offset of the keyent/valent entry is from the start
1040     of the text table to the first data byte.
1041
1042     This information is not available from Microsoft. The data format is
1043     deduced from the reg.dat file by me. Mistakes may
1044     have been made. I claim no rights and give no guarantees for this program.
1045
1046     Tor Sjøwall, tor@sn.no
1047 */
1048
1049 /* reg.dat header format */
1050 struct _w31_header {
1051         char            cookie[8];      /* 'SHCC3.10' */
1052         unsigned long   taboff1;        /* offset of hash table (??) = 0x20 */
1053         unsigned long   taboff2;        /* offset of index table (??) = 0x20 */
1054         unsigned long   tabcnt;         /* number of entries in index table */
1055         unsigned long   textoff;        /* offset of text part */
1056         unsigned long   textsize;       /* byte size of text part */
1057         unsigned short  hashsize;       /* hash size */
1058         unsigned short  freeidx;        /* free index */
1059 };
1060
1061 /* generic format of table entries */
1062 struct _w31_tabent {
1063         unsigned short w0, w1, w2, w3;
1064 };
1065
1066 /* directory tabent: */
1067 struct _w31_dirent {
1068         unsigned short  sibling_idx;    /* table index of sibling dirent */
1069         unsigned short  child_idx;      /* table index of child dirent */
1070         unsigned short  key_idx;        /* table index of key keyent */
1071         unsigned short  value_idx;      /* table index of value valent */
1072 };
1073
1074 /* key tabent: */
1075 struct _w31_keyent {
1076         unsigned short  hash_idx;       /* hash chain index for string */
1077         unsigned short  refcnt;         /* reference count */
1078         unsigned short  length;         /* length of string */
1079         unsigned short  string_off;     /* offset of string in text table */
1080 };
1081
1082 /* value tabent: */
1083 struct _w31_valent {
1084         unsigned short  hash_idx;       /* hash chain index for string */
1085         unsigned short  refcnt;         /* reference count */
1086         unsigned short  length;         /* length of string */
1087         unsigned short  string_off;     /* offset of string in text table */
1088 };
1089
1090 /* recursive helper function to display a directory tree */
1091 void
1092 __w31_dumptree( unsigned short idx,
1093                 unsigned char *txt,
1094                 struct _w31_tabent *tab,
1095                 struct _w31_header *head,
1096                 HKEY hkey,
1097                 time_t          lastmodified,
1098                 int             level
1099 ) {
1100         struct _w31_dirent      *dir;
1101         struct _w31_keyent      *key;
1102         struct _w31_valent      *val;
1103         HKEY subkey = 0;
1104         static char             tail[400];
1105
1106         while (idx!=0) {
1107                 dir=(struct _w31_dirent*)&tab[idx];
1108
1109                 if (dir->key_idx) {
1110                         key = (struct _w31_keyent*)&tab[dir->key_idx];
1111
1112                         memcpy(tail,&txt[key->string_off],key->length);
1113                         tail[key->length]='\0';
1114                         /* all toplevel entries AND the entries in the 
1115                          * toplevel subdirectory belong to \SOFTWARE\Classes
1116                          */
1117                         if (!level && !lstrcmpA(tail,".classes")) {
1118                                 __w31_dumptree(dir->child_idx,txt,tab,head,hkey,lastmodified,level+1);
1119                                 idx=dir->sibling_idx;
1120                                 continue;
1121                         }
1122                         if (RegCreateKeyA( hkey, tail, &subkey ) != ERROR_SUCCESS) subkey = 0;
1123                         /* only add if leaf node or valued node */
1124                         if (dir->value_idx!=0||dir->child_idx==0) {
1125                                 if (dir->value_idx) {
1126                                         val=(struct _w31_valent*)&tab[dir->value_idx];
1127                                         memcpy(tail,&txt[val->string_off],val->length);
1128                                         tail[val->length]='\0';
1129                                         RegSetValueA( hkey, NULL, REG_SZ, tail, 0 );
1130                                 }
1131                         }
1132                 } else {
1133                         TRACE_(reg)("strange: no directory key name, idx=%04x\n", idx);
1134                 }
1135                 __w31_dumptree(dir->child_idx,txt,tab,head,subkey,lastmodified,level+1);
1136                 idx=dir->sibling_idx;
1137         }
1138 }
1139
1140
1141 /******************************************************************************
1142  * _w31_loadreg [Internal]
1143  */
1144 void _w31_loadreg(void) {
1145         HFILE                   hf;
1146         struct _w31_header      head;
1147         struct _w31_tabent      *tab;
1148         unsigned char           *txt;
1149         int                     len;
1150         OFSTRUCT                ofs;
1151         BY_HANDLE_FILE_INFORMATION hfinfo;
1152         time_t                  lastmodified;
1153
1154         TRACE_(reg)("(void)\n");
1155
1156         hf = OpenFile("reg.dat",&ofs,OF_READ);
1157         if (hf==HFILE_ERROR)
1158                 return;
1159
1160         /* read & dump header */
1161         if (sizeof(head)!=_lread(hf,&head,sizeof(head))) {
1162                 ERR_(reg)("reg.dat is too short.\n");
1163                 _lclose(hf);
1164                 return;
1165         }
1166         if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
1167                 ERR_(reg)("reg.dat has bad signature.\n");
1168                 _lclose(hf);
1169                 return;
1170         }
1171
1172         len = head.tabcnt * sizeof(struct _w31_tabent);
1173         /* read and dump index table */
1174         tab = xmalloc(len);
1175         if (len!=_lread(hf,tab,len)) {
1176                 ERR_(reg)("couldn't read %d bytes.\n",len); 
1177                 free(tab);
1178                 _lclose(hf);
1179                 return;
1180         }
1181
1182         /* read text */
1183         txt = xmalloc(head.textsize);
1184         if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
1185                 ERR_(reg)("couldn't seek to textblock.\n"); 
1186                 free(tab);
1187                 free(txt);
1188                 _lclose(hf);
1189                 return;
1190         }
1191         if (head.textsize!=_lread(hf,txt,head.textsize)) {
1192                 ERR_(reg)("textblock too short (%d instead of %ld).\n",len,head.textsize); 
1193                 free(tab);
1194                 free(txt);
1195                 _lclose(hf);
1196                 return;
1197         }
1198
1199         if (!GetFileInformationByHandle(hf,&hfinfo)) {
1200                 ERR_(reg)("GetFileInformationByHandle failed?.\n"); 
1201                 free(tab);
1202                 free(txt);
1203                 _lclose(hf);
1204                 return;
1205         }
1206         lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
1207         __w31_dumptree(tab[0].w1,txt,tab,&head,HKEY_CLASSES_ROOT,lastmodified,0);
1208         free(tab);
1209         free(txt);
1210         _lclose(hf);
1211         return;
1212 }
1213
1214
1215 /**********************************************************************************
1216  * SHELL_LoadRegistry [Internal]
1217  */
1218 void SHELL_LoadRegistry( void )
1219 {
1220   struct set_registry_levels_request *req = get_req_buffer();
1221   char        *fn, *home;
1222   HKEY              hkey;
1223
1224   TRACE_(reg)("(void)\n");
1225
1226   REGISTRY_Init();
1227
1228   /* set level to 0 for loading system files */
1229   req->current = 0;
1230   req->saving  = 0;
1231   server_call( REQ_SET_REGISTRY_LEVELS );
1232
1233   if (PROFILE_GetWineIniBool ("registry", "LoadWindowsRegistryFiles", 1)) 
1234   { 
1235       /* Load windows 3.1 entries */
1236       _w31_loadreg();
1237       /* Load windows 95 entries */
1238       _w95_loadreg("C:\\system.1st", HKEY_LOCAL_MACHINE);
1239       _w95_loadreg("system.dat", HKEY_LOCAL_MACHINE);
1240       _w95_loadreg("user.dat", HKEY_USERS);
1241   }
1242
1243   if (PROFILE_GetWineIniBool ("registry","LoadGlobalRegistryFiles", 1))
1244   {
1245       /* 
1246        * Load the global HKU hive directly from sysconfdir
1247        */ 
1248       _wine_loadreg( HKEY_USERS, SAVE_USERS_DEFAULT );
1249
1250       /* 
1251        * Load the global machine defaults directly form sysconfdir
1252        */
1253       _wine_loadreg( HKEY_LOCAL_MACHINE, SAVE_LOCAL_MACHINE_DEFAULT );
1254   }
1255
1256   /* set level to 1 for loading user files */
1257   req->current = 1;
1258   req->saving  = 0;
1259   server_call( REQ_SET_REGISTRY_LEVELS );
1260
1261   /*
1262    * Load the user saved registries 
1263    */
1264   if (!(home = getenv( "HOME" )))
1265       WARN_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid());
1266   else if (PROFILE_GetWineIniBool("registry", "LoadHomeRegistryFiles", 1))
1267   {
1268       /* 
1269        * Load user's personal versions of global HKU/.Default keys
1270        */
1271       fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX) +
1272                          strlen(SAVE_LOCAL_USERS_DEFAULT)+2);
1273       strcpy(fn, home);
1274       strcat(fn, WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
1275       _wine_loadreg( HKEY_USERS, fn ); 
1276       free(fn);
1277
1278       fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) + strlen(SAVE_CURRENT_USER)+2);
1279       strcpy(fn, home);
1280       strcat(fn, WINE_PREFIX"/"SAVE_CURRENT_USER);
1281       _wine_loadreg( HKEY_CURRENT_USER, fn );
1282       free(fn);
1283
1284       /* 
1285        * Load HKLM, attempt to get the registry location from the config 
1286        * file first, if exist, load and keep going.
1287        */
1288       fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX)+ strlen(SAVE_LOCAL_MACHINE)+2);
1289       strcpy(fn,home);
1290       strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1291       _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
1292       free(fn);
1293   }
1294   
1295   /* 
1296    * Load HKCU, get the registry location from the config 
1297    * file, if exist, load and keep going.
1298    */      
1299   if (PROFILE_GetWineIniBool ( "registry", "LoadAltRegistryFiles", 1))
1300   {
1301       fn = xmalloc( MAX_PATHNAME_LEN ); 
1302       if ( PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "", 
1303                                      fn, MAX_PATHNAME_LEN - 1)) 
1304        {
1305          _wine_loadreg( HKEY_CURRENT_USER, fn );
1306        }
1307       free (fn);
1308       /*
1309        * Load HKU, get the registry location from the config
1310        * file, if exist, load and keep going.
1311        */
1312       fn = xmalloc ( MAX_PATHNAME_LEN );
1313       if ( PROFILE_GetWineIniString ( "registry", "AltUserFile", "",
1314                                       fn, MAX_PATHNAME_LEN - 1))
1315        {
1316          _wine_loadreg( HKEY_USERS, fn );
1317        }
1318       free (fn);
1319       /*
1320        * Load HKLM, get the registry location from the config
1321        * file, if exist, load and keep going.
1322        */
1323       fn = xmalloc ( MAX_PATHNAME_LEN );
1324       if (PROFILE_GetWineIniString ( "registry", "AltLocalMachineFile", "",
1325                                      fn, MAX_PATHNAME_LEN - 1))
1326        {
1327          _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
1328        }
1329       free (fn);
1330     }
1331   
1332   /* 
1333    * Obtain the handle of the HKU\.Default key.
1334    * in order to copy HKU\.Default\* onto HKEY_CURRENT_USER 
1335    */
1336   if (RegCreateKeyA(HKEY_USERS,".Default",&hkey) != ERROR_SUCCESS)
1337       WARN_(reg)("Could not create global user default key\n");
1338   else
1339     _copy_registry( hkey, HKEY_CURRENT_USER );
1340   RegCloseKey(hkey);
1341
1342   /* 
1343    * Since HKU is built from the global HKU and the local user HKU file we must
1344    * flush the HKU tree we have built at this point otherwise the part brought
1345    * in from the global HKU is saved into the local HKU.  To avoid this 
1346    * useless dupplication of HKU keys we reread the local HKU key.
1347    */
1348
1349   /* Allways flush the HKU hive and reload it only with user's personal HKU */
1350   _flush_registry( HKEY_USERS ); 
1351
1352   /* Reload user's local HKU hive */
1353   if (home && PROFILE_GetWineIniBool ("registry","LoadHomeRegistryFiles",1))
1354   {
1355       fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX)
1356                          + strlen(SAVE_LOCAL_USERS_DEFAULT) + 2);
1357       
1358       strcpy(fn,home);
1359       strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
1360
1361       _wine_loadreg( HKEY_USERS, fn );
1362
1363       free(fn);
1364   }
1365
1366   /* 
1367    * Make sure the update mode is there
1368    */
1369   if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) 
1370   {
1371     DWORD       junk,type,len;
1372     char        data[5];
1373
1374     len=4;
1375     if ((       RegQueryValueExA(
1376             hkey,
1377             VAL_SAVEUPDATED,
1378             &junk,
1379             &type,
1380             data,
1381             &len) != ERROR_SUCCESS) || (type != REG_SZ))
1382     {
1383       RegSetValueExA(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1384     }
1385
1386     RegCloseKey(hkey);
1387   }
1388 }
1389
1390
1391 /********************* API FUNCTIONS ***************************************/
1392
1393
1394
1395
1396 /******************************************************************************
1397  * RegFlushKey [KERNEL.227] [ADVAPI32.143]
1398  * Immediately writes key to registry.
1399  * Only returns after data has been written to disk.
1400  *
1401  * FIXME: does it really wait until data is written ?
1402  *
1403  * PARAMS
1404  *    hkey [I] Handle of key to write
1405  *
1406  * RETURNS
1407  *    Success: ERROR_SUCCESS
1408  *    Failure: Error code
1409  */
1410 DWORD WINAPI RegFlushKey( HKEY hkey )
1411 {
1412     FIXME( "(%x): stub\n", hkey );
1413     return ERROR_SUCCESS;
1414 }
1415
1416 /******************************************************************************
1417  * RegConnectRegistry32W [ADVAPI32.128]
1418  *
1419  * PARAMS
1420  *    lpMachineName [I] Address of name of remote computer
1421  *    hHey          [I] Predefined registry handle
1422  *    phkResult     [I] Address of buffer for remote registry handle
1423  */
1424 LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey, 
1425                                    LPHKEY phkResult )
1426 {
1427     TRACE_(reg)("(%s,%x,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
1428
1429     if (!lpMachineName || !*lpMachineName) {
1430         /* Use the local machine name */
1431         return RegOpenKey16( hKey, "", phkResult );
1432     }
1433
1434     FIXME_(reg)("Cannot connect to %s\n",debugstr_w(lpMachineName));
1435     return ERROR_BAD_NETPATH;
1436 }
1437
1438
1439 /******************************************************************************
1440  * RegConnectRegistry32A [ADVAPI32.127]
1441  */
1442 LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, LPHKEY reskey )
1443 {
1444     DWORD ret;
1445     LPWSTR machineW = strdupA2W(machine);
1446     ret = RegConnectRegistryW( machineW, hkey, reskey );
1447     free(machineW);
1448     return ret;
1449 }
1450
1451
1452 /******************************************************************************
1453  * RegGetKeySecurity [ADVAPI32.144]
1454  * Retrieves a copy of security descriptor protecting the registry key
1455  *
1456  * PARAMS
1457  *    hkey                   [I]   Open handle of key to set
1458  *    SecurityInformation    [I]   Descriptor contents
1459  *    pSecurityDescriptor    [O]   Address of descriptor for key
1460  *    lpcbSecurityDescriptor [I/O] Address of size of buffer and description
1461  *
1462  * RETURNS
1463  *    Success: ERROR_SUCCESS
1464  *    Failure: Error code
1465  */
1466 LONG WINAPI RegGetKeySecurity( HKEY hkey, 
1467                                SECURITY_INFORMATION SecurityInformation,
1468                                PSECURITY_DESCRIPTOR pSecurityDescriptor,
1469                                LPDWORD lpcbSecurityDescriptor )
1470 {
1471     TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
1472           lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1473
1474     /* FIXME: Check for valid SecurityInformation values */
1475
1476     if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
1477         return ERROR_INSUFFICIENT_BUFFER;
1478
1479     FIXME_(reg)("(%x,%ld,%p,%ld): stub\n",hkey,SecurityInformation,
1480           pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1481
1482     return ERROR_SUCCESS;
1483 }
1484
1485
1486 /******************************************************************************
1487  * RegNotifyChangeKeyValue [ADVAPI32.???]
1488  *
1489  * PARAMS
1490  *    hkey            [I] Handle of key to watch
1491  *    fWatchSubTree   [I] Flag for subkey notification
1492  *    fdwNotifyFilter [I] Changes to be reported
1493  *    hEvent          [I] Handle of signaled event
1494  *    fAsync          [I] Flag for asynchronous reporting
1495  */
1496 LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree, 
1497                                      DWORD fdwNotifyFilter, HANDLE hEvent,
1498                                      BOOL fAsync )
1499 {
1500     FIXME_(reg)("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter,
1501           hEvent,fAsync);
1502     return ERROR_SUCCESS;
1503 }
1504
1505
1506 /******************************************************************************
1507  * RegUnLoadKey32W [ADVAPI32.173]
1508  *
1509  * PARAMS
1510  *    hkey     [I] Handle of open key
1511  *    lpSubKey [I] Address of name of subkey to unload
1512  */
1513 LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey )
1514 {
1515     FIXME_(reg)("(%x,%s): stub\n",hkey, debugstr_w(lpSubKey));
1516     return ERROR_SUCCESS;
1517 }
1518
1519
1520 /******************************************************************************
1521  * RegUnLoadKey32A [ADVAPI32.172]
1522  */
1523 LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
1524 {
1525     LONG ret;
1526     LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
1527     ret = RegUnLoadKeyW( hkey, lpSubKeyW );
1528     if(lpSubKeyW) free(lpSubKeyW);
1529     return ret;
1530 }
1531
1532
1533 /******************************************************************************
1534  * RegSetKeySecurity [ADVAPI32.167]
1535  *
1536  * PARAMS
1537  *    hkey          [I] Open handle of key to set
1538  *    SecurityInfo  [I] Descriptor contents
1539  *    pSecurityDesc [I] Address of descriptor for key
1540  */
1541 LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
1542                                PSECURITY_DESCRIPTOR pSecurityDesc )
1543 {
1544     TRACE_(reg)("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
1545
1546     /* It seems to perform this check before the hkey check */
1547     if ((SecurityInfo & OWNER_SECURITY_INFORMATION) ||
1548         (SecurityInfo & GROUP_SECURITY_INFORMATION) ||
1549         (SecurityInfo & DACL_SECURITY_INFORMATION) ||
1550         (SecurityInfo & SACL_SECURITY_INFORMATION)) {
1551         /* Param OK */
1552     } else
1553         return ERROR_INVALID_PARAMETER;
1554
1555     if (!pSecurityDesc)
1556         return ERROR_INVALID_PARAMETER;
1557
1558     FIXME_(reg)(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
1559
1560     return ERROR_SUCCESS;
1561 }
1562
1563
1564 /******************************************************************************
1565  * RegRestoreKey32W [ADVAPI32.164]
1566  *
1567  * PARAMS
1568  *    hkey    [I] Handle of key where restore begins
1569  *    lpFile  [I] Address of filename containing saved tree
1570  *    dwFlags [I] Optional flags
1571  */
1572 LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
1573 {
1574     TRACE_(reg)("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
1575
1576     /* It seems to do this check before the hkey check */
1577     if (!lpFile || !*lpFile)
1578         return ERROR_INVALID_PARAMETER;
1579
1580     FIXME_(reg)("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
1581
1582     /* Check for file existence */
1583
1584     return ERROR_SUCCESS;
1585 }
1586
1587
1588 /******************************************************************************
1589  * RegRestoreKey32A [ADVAPI32.163]
1590  */
1591 LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
1592 {
1593     LONG ret;
1594     LPWSTR lpFileW = strdupA2W(lpFile);
1595     ret = RegRestoreKeyW( hkey, lpFileW, dwFlags );
1596     if(lpFileW) free(lpFileW);
1597     return ret;
1598 }
1599
1600
1601 /******************************************************************************
1602  * RegReplaceKey32W [ADVAPI32.162]
1603  *
1604  * PARAMS
1605  *    hkey      [I] Handle of open key
1606  *    lpSubKey  [I] Address of name of subkey
1607  *    lpNewFile [I] Address of filename for file with new data
1608  *    lpOldFile [I] Address of filename for backup file
1609  */
1610 LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
1611                               LPCWSTR lpOldFile )
1612 {
1613     FIXME_(reg)("(%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey), 
1614           debugstr_w(lpNewFile),debugstr_w(lpOldFile));
1615     return ERROR_SUCCESS;
1616 }
1617
1618
1619 /******************************************************************************
1620  * RegReplaceKey32A [ADVAPI32.161]
1621  */
1622 LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
1623                               LPCSTR lpOldFile )
1624 {
1625     LONG ret;
1626     LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
1627     LPWSTR lpNewFileW = strdupA2W(lpNewFile);
1628     LPWSTR lpOldFileW = strdupA2W(lpOldFile);
1629     ret = RegReplaceKeyW( hkey, lpSubKeyW, lpNewFileW, lpOldFileW );
1630     free(lpOldFileW);
1631     free(lpNewFileW);
1632     free(lpSubKeyW);
1633     return ret;
1634 }
1635
1636
1637
1638
1639
1640
1641 /* 16-bit functions */
1642
1643 /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
1644  * some programs. Do not remove those cases. -MM
1645  */
1646 static inline void fix_win16_hkey( HKEY *hkey )
1647 {
1648     if (*hkey == 0 || *hkey == 1) *hkey = HKEY_CLASSES_ROOT;
1649 }
1650
1651 /******************************************************************************
1652  *           RegEnumKey16   [KERNEL.216] [SHELL.7]
1653  */
1654 DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
1655 {
1656     fix_win16_hkey( &hkey );
1657     return RegEnumKeyA( hkey, index, name, name_len );
1658 }
1659
1660 /******************************************************************************
1661  *           RegOpenKey16   [KERNEL.217] [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  *           RegCreateKey16   [KERNEL.218] [SHELL.2]
1671  */
1672 DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
1673 {
1674     fix_win16_hkey( &hkey );
1675     return RegCreateKeyA( hkey, name, retkey );
1676 }
1677
1678 /******************************************************************************
1679  *           RegDeleteKey16   [KERNEL.219] [SHELL.4]
1680  */
1681 DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name )
1682 {
1683     fix_win16_hkey( &hkey );
1684     return RegDeleteKeyA( hkey, name );
1685 }
1686
1687 /******************************************************************************
1688  *           RegCloseKey16   [KERNEL.220] [SHELL.3]
1689  */
1690 DWORD WINAPI RegCloseKey16( HKEY hkey )
1691 {
1692     fix_win16_hkey( &hkey );
1693     return RegCloseKey( hkey );
1694 }
1695
1696 /******************************************************************************
1697  *           RegSetValue16   [KERNEL.221] [SHELL.5]
1698  */
1699 DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
1700 {
1701     fix_win16_hkey( &hkey );
1702     return RegSetValueA( hkey, name, type, data, count );
1703 }
1704
1705 /******************************************************************************
1706  *           RegDeleteValue16  [KERNEL.222]
1707  */
1708 DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR name )
1709 {
1710     fix_win16_hkey( &hkey );
1711     return RegDeleteValueA( hkey, name );
1712 }
1713
1714 /******************************************************************************
1715  *           RegEnumValue16   [KERNEL.223]
1716  */
1717 DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1718                              LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
1719 {
1720     fix_win16_hkey( &hkey );
1721     return RegEnumValueA( hkey, index, value, val_count, reserved, type, data, count );
1722 }
1723
1724 /******************************************************************************
1725  *           RegQueryValue16   [KERNEL.224] [SHELL.6]
1726  *
1727  * NOTES
1728  *    Is this HACK still applicable?
1729  *
1730  * HACK
1731  *    The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
1732  *    mask out the high 16 bit.  This (not so much incidently) hopefully fixes
1733  *    Aldus FH4)
1734  */
1735 DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count )
1736 {
1737     fix_win16_hkey( &hkey );
1738     if (count) *count &= 0xffff;
1739     return RegQueryValueA( hkey, name, data, count );
1740 }
1741
1742 /******************************************************************************
1743  *           RegQueryValueEx16   [KERNEL.225]
1744  */
1745 DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
1746                                 LPBYTE data, LPDWORD count )
1747 {
1748     fix_win16_hkey( &hkey );
1749     return RegQueryValueExA( hkey, name, reserved, type, data, count );
1750 }
1751
1752 /******************************************************************************
1753  *           RegSetValueEx16   [KERNEL.226]
1754  */
1755 DWORD WINAPI RegSetValueEx16( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
1756                               CONST BYTE *data, DWORD count )
1757 {
1758     fix_win16_hkey( &hkey );
1759     return RegSetValueExA( hkey, name, reserved, type, data, count );
1760 }