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