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