4 * Copyright 1996 Marcus Meissner
5 * Copyright 1998 Matthew Becker
6 * Copyright 1999 Sylvain St-Germain
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.
13 * When changing this file, please re-run the regtest program to ensure
14 * the conditions are handled properly.
19 * Time for RegEnumKey*, RegQueryInfoKey*
29 #ifdef HAVE_SYS_ERRNO_H
30 #include <sys/errno.h>
32 #include <sys/types.h>
33 #include <sys/fcntl.h>
39 #include "wine/winbase16.h"
40 #include "wine/winestring.h"
44 #include "debugtools.h"
51 DEFAULT_DEBUG_CHANNEL(reg)
53 static void REGISTRY_Init(void);
54 /* FIXME: following defines should be configured global ... */
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"
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"
66 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
67 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
70 /* what valuetypes do we need to convert? */
71 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
77 * Are these doing the same as HEAP_strdupAtoW and HEAP_strdupWtoA?
78 * If so, can we remove them?
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
84 static LPWSTR strdupA2W(LPCSTR src)
87 LPWSTR dest=xmalloc(2*strlen(src)+2);
88 lstrcpyAtoW(dest,src);
94 LPWSTR strcvtA2W(LPCSTR src, int nchars)
97 LPWSTR dest = xmalloc (2 * nchars + 2);
99 lstrcpynAtoW(dest,src,nchars+1);
106 /******************************************************************************
107 * REGISTRY_Init [Internal]
108 * Registry initialisation, allocates some default keys.
110 static void REGISTRY_Init(void) {
116 RegCreateKeyA(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
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"));
125 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
129 * string RegisteredOwner
130 * string RegisteredOrganization
133 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
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);
146 /************************ SAVE Registry Function ****************************/
148 #define REGISTRY_SAVE_VERSION 0x00000001
150 /* Registry saveformat:
151 * If you change it, increase above number by 1, which will flush
152 * old registry database files.
155 * "WINE REGISTRY Version %d"
159 * valuename=lastmodified,type,data
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.)
170 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
172 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
173 * SaveOnlyUpdatedKeys=yes
176 /* Same as RegSaveKey but with Unix pathnames */
177 static void save_key( HKEY hkey, const char *filename )
179 struct save_registry_request *req = get_req_buffer();
184 char *name = HeapAlloc( GetProcessHeap(), 0, strlen(filename) + 20 );
187 strcpy( name, filename );
188 if ((p = strrchr( name, '/' ))) p++;
193 sprintf( p, "reg%04x.tmp", count++ );
194 handle = FILE_CreateFile( name, GENERIC_WRITE, 0, NULL,
195 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
196 if (handle != INVALID_HANDLE_VALUE) break;
197 if ((ret = GetLastError()) != ERROR_FILE_EXISTS) break;
200 if (handle != INVALID_HANDLE_VALUE)
204 ret = server_call_noerr( REQ_SAVE_REGISTRY );
205 CloseHandle( handle );
206 if (ret) unlink( name );
207 else if (rename( name, filename ) == -1)
209 ERR( "Failed to move %s to %s: ", name, filename );
214 HeapFree( GetProcessHeap(), 0, name );
218 /******************************************************************************
219 * SHELL_SaveRegistryBranch [Internal]
221 * Saves main registry branch specified by hkey.
223 static void SHELL_SaveRegistryBranch(HKEY hkey)
227 /* Find out what to save to, get from config file */
228 BOOL writeToHome = PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1);
229 BOOL writeToAlt = PROFILE_GetWineIniBool("registry","WritetoAltRegistries",1);
231 /* FIXME: does this check apply to all keys written below ? */
232 if (!(home = getenv( "HOME" )))
233 ERR("Failed to get homedirectory of UID %ld.\n",(long) getuid());
235 /* HKEY_LOCAL_MACHINE contains the HKEY_CLASSES_ROOT branch */
236 if (hkey == HKEY_CLASSES_ROOT) hkey = HKEY_LOCAL_MACHINE;
240 case HKEY_CURRENT_USER:
241 fn = xmalloc( MAX_PATHNAME_LEN );
242 if (writeToAlt && PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "",
243 fn, MAX_PATHNAME_LEN - 1))
244 save_key( HKEY_CURRENT_USER, fn );
247 if (home && writeToHome)
249 fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) +
250 strlen(SAVE_CURRENT_USER) + 2 );
252 strcat(fn,WINE_PREFIX);
254 /* create the directory. don't care about errorcodes. */
255 mkdir(fn,0755); /* drwxr-xr-x */
256 strcat(fn,"/"SAVE_CURRENT_USER);
257 save_key( HKEY_CURRENT_USER, fn );
261 case HKEY_LOCAL_MACHINE:
262 /* Try first saving according to the defined location in .winerc */
263 fn = xmalloc ( MAX_PATHNAME_LEN);
264 if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltLocalMachineFile", "",
265 fn, MAX_PATHNAME_LEN - 1))
266 save_key( HKEY_LOCAL_MACHINE, fn );
269 if (home && writeToHome)
271 fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) +
272 strlen(SAVE_LOCAL_MACHINE) + 2);
274 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
275 save_key( HKEY_LOCAL_MACHINE, fn );
280 fn = xmalloc( MAX_PATHNAME_LEN );
281 if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltUserFile", "",
282 fn, MAX_PATHNAME_LEN - 1))
283 save_key( HKEY_USERS, fn );
286 if (home && writeToHome)
288 fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) +
289 strlen(SAVE_LOCAL_USERS_DEFAULT) + 2);
291 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
292 save_key( HKEY_USERS, fn );
297 ERR("unknown/invalid key handle !\n");
303 /******************************************************************************
304 * SHELL_SaveRegistry [Internal]
306 void SHELL_SaveRegistry( void )
308 struct set_registry_levels_request *req = get_req_buffer();
316 if (RegOpenKeyA(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS)
325 if ((ERROR_SUCCESS!=RegQueryValueExA( hkey,
330 &len)) || (type!=REG_SZ))
337 if (lstrcmpiA(buf,"yes")) all = 1;
339 /* set saving level (0 for saving everything, 1 for saving only modified keys) */
342 req->version = PROFILE_GetWineIniBool( "registry", "UseNewFormat", 0 ) ? 2 : 1;
343 server_call( REQ_SET_REGISTRY_LEVELS );
345 SHELL_SaveRegistryBranch(HKEY_CURRENT_USER);
346 SHELL_SaveRegistryBranch(HKEY_LOCAL_MACHINE);
347 SHELL_SaveRegistryBranch(HKEY_USERS);
350 /* Periodic save callback */
351 static void CALLBACK periodic_save( ULONG_PTR dummy )
353 SHELL_SaveRegistry();
356 /************************ LOAD Registry Function ****************************/
360 /******************************************************************************
361 * _find_or_add_key [Internal]
363 static inline HKEY _find_or_add_key( HKEY hkey, LPWSTR keyname )
366 if (RegCreateKeyW( hkey, keyname, &subkey ) != ERROR_SUCCESS) subkey = 0;
367 if (keyname) free( keyname );
371 /******************************************************************************
372 * _find_or_add_value [Internal]
374 static void _find_or_add_value( HKEY hkey, LPWSTR name, DWORD type, LPBYTE data, DWORD len )
376 RegSetValueExW( hkey, name, 0, type, data, len );
377 if (name) free( name );
378 if (data) free( data );
382 /******************************************************************************
383 * _wine_read_line [Internal]
385 * reads a line including dynamically enlarging the readbuffer and throwing
388 static int _wine_read_line( FILE *F, char **buf, int *len )
398 s=fgets(curread,mylen,F);
401 if (NULL==(s=strchr(curread,'\n'))) {
402 /* buffer wasn't large enough */
403 curoff = strlen(*buf);
404 *buf = xrealloc(*buf,*len*2);
405 curread = *buf + curoff;
406 mylen = *len; /* we filled up the buffer and
407 * got new '*len' bytes to fill
415 /* throw away comments */
416 if (**buf=='#' || **buf==';') {
421 if (s) /* got end of line */
428 /******************************************************************************
429 * _wine_read_USTRING [Internal]
431 * converts a char* into a UNICODE string (up to a special char)
432 * and returns the position exactly after that string
434 static char* _wine_read_USTRING( char *buf, LPWSTR *str )
439 /* read up to "=" or "\0" or "\n" */
441 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
443 while (*s && (*s!='\n') && (*s!='=')) {
445 *ws++=*((unsigned char*)s++);
449 /* Dangling \ ... may only happen if a registry
450 * write was short. FIXME: What do to?
460 WARN("Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
468 memcpy(xbuf,s,4);xbuf[4]='\0';
469 if (!sscanf(xbuf,"%x",&wc))
470 WARN("Strange escape sequence %s found in |%s|\n",xbuf,buf);
472 *ws++ =(unsigned short)wc;
481 /******************************************************************************
482 * _wine_loadsubkey [Internal]
485 * It seems like this is returning a boolean. Should it?
491 static int _wine_loadsubkey( FILE *F, HKEY hkey, int level, char **buf, int *buflen )
498 TRACE("(%p,%x,%d,%s,%d)\n", F, hkey, level, debugstr_a(*buf), *buflen);
500 /* Good. We already got a line here ... so parse it */
510 WARN("Got a subhierarchy without resp. key?\n");
513 if (!_wine_loadsubkey(F,subkey,level+1,buf,buflen))
514 if (!_wine_read_line(F,buf,buflen))
519 /* let the caller handle this line */
520 if (i<level || **buf=='\0')
523 /* it can be: a value or a keyname. Parse the name first */
524 s=_wine_read_USTRING(s,&name);
526 /* switch() default: hack to avoid gotos */
530 if (subkey) RegCloseKey( subkey );
531 subkey=_find_or_add_key(hkey,name);
534 int len,lastmodified,type;
537 WARN("Unexpected character: %c\n",*s);
541 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
542 WARN("Haven't understood possible value in |%s|, skipping.\n",*buf);
549 WARN("Haven't understood possible value in |%s|, skipping.\n",*buf);
552 if (type == REG_SZ || type == REG_EXPAND_SZ) {
553 s=_wine_read_USTRING(s,(LPWSTR*)&data);
554 len = lstrlenW((LPWSTR)data)*2+2;
557 data = (LPBYTE)xmalloc(len+1);
558 for (i=0;i<len;i++) {
560 if (*s>='0' && *s<='9')
562 if (*s>='a' && *s<='f')
563 data[i]=(*s-'a'+'\xa')<<4;
564 if (*s>='A' && *s<='F')
565 data[i]=(*s-'A'+'\xa')<<4;
567 if (*s>='0' && *s<='9')
569 if (*s>='a' && *s<='f')
570 data[i]|=*s-'a'+'\xa';
571 if (*s>='A' && *s<='F')
572 data[i]|=*s-'A'+'\xa';
576 _find_or_add_value(hkey,name,type,data,len);
579 /* read the next line */
580 if (!_wine_read_line(F,buf,buflen))
584 if (subkey) RegCloseKey( subkey );
589 /******************************************************************************
590 * _wine_loadsubreg [Internal]
592 static int _wine_loadsubreg( FILE *F, HKEY hkey, const char *fn )
598 buf=xmalloc(10);buflen=10;
599 if (!_wine_read_line(F,&buf,&buflen)) {
603 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
607 if (ver!=REGISTRY_SAVE_VERSION) {
608 if (ver == 2) /* new version */
611 if ((file = FILE_CreateFile( fn, GENERIC_READ, 0, NULL, OPEN_EXISTING,
612 FILE_ATTRIBUTE_NORMAL, -1 )) != INVALID_HANDLE_VALUE)
614 struct load_registry_request *req = get_req_buffer();
618 server_call( REQ_LOAD_REGISTRY );
626 TRACE("Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
631 if (!_wine_read_line(F,&buf,&buflen)) {
635 if (!_wine_loadsubkey(F,hkey,0,&buf,&buflen)) {
644 /******************************************************************************
645 * _wine_loadreg [Internal]
647 static void _wine_loadreg( HKEY hkey, char *fn )
651 TRACE("(%x,%s)\n",hkey,debugstr_a(fn));
655 WARN("Couldn't open %s for reading: %s\n",fn,strerror(errno) );
658 _wine_loadsubreg(F,hkey,fn);
662 /******************************************************************************
663 * _flush_registry [Internal]
665 * This function allow to flush section of the internal registry. It is mainly
666 * implements to fix a problem with the global HKU and the local HKU.
667 * Those two files are read to build the HKU\.Default branch to finaly copy
668 * this branch onto HKCU hive, once this is done, if we keep the HKU hive as is,
669 * all the global HKU are saved onto the user's personal version of HKU hive.
673 static void _flush_registry( HKEY hkey )
675 WCHAR name[MAX_PATH];
680 /* FIXME: we assume that deleting a key will move the other ones up, */
681 /* so that we can always use index 0 until there are no more keys */
682 if (RegEnumKeyW( hkey, 0, name, sizeof(name) ) != ERROR_SUCCESS) break;
683 if (RegOpenKeyW( hkey, name, &subkey ) != ERROR_SUCCESS) break;
684 _flush_registry( subkey );
685 if (RegDeleteKeyW( subkey, NULL ) != ERROR_SUCCESS) break;
686 RegCloseKey( subkey );
691 /******************************************************************************
692 * _copy_registry [Internal]
694 static void _copy_registry( HKEY from, HKEY to )
699 DWORD type, name_len, len;
700 static WCHAR name[MAX_PATH];
701 static BYTE data[2048];
708 name_len = sizeof(name);
709 if (RegEnumValueW( from, index++, name, &name_len,
710 NULL, &type, data, &len ) != ERROR_SUCCESS) break;
711 RegSetValueExW( to, name, 0, type, data, len );
718 name_len = sizeof(name);
719 if (RegEnumKeyExW( from, index++, name, &name_len,
720 NULL, NULL, 0, &ft ) != ERROR_SUCCESS)
722 if (RegOpenKeyW( from, name, &subkey ) == ERROR_SUCCESS)
725 if (RegCreateKeyW( to, name, &newsub ) == ERROR_SUCCESS)
727 _copy_registry( subkey, newsub );
728 RegCloseKey( newsub );
730 RegCloseKey( subkey );
734 /* NT REGISTRY LOADER */
735 #include <sys/mman.h>
738 #define MAP_FAILED ((LPVOID)-1)
743 #define REG_BLOCK_SIZE 0x1000
745 #define REG_HEADER_BLOCK_ID 0x66676572 /* regf */
746 #define REG_POOL_BLOCK_ID 0x6E696268 /* hbin */
747 #define REG_KEY_BLOCK_ID 0x6b6e
748 #define REG_VALUE_BLOCK_ID 0x6b76
749 #define REG_HASH_BLOCK_ID 0x666c
750 #define REG_NOHASH_BLOCK_ID 0x696c
751 #define REG_KEY_BLOCK_TYPE 0x20
752 #define REG_ROOT_KEY_BLOCK_TYPE 0x2c
756 DWORD id; /* 0x66676572 'regf'*/
757 DWORD uk1; /* 0x04 */
758 DWORD uk2; /* 0x08 */
759 FILETIME DateModified; /* 0x0c */
760 DWORD uk3; /* 0x14 */
761 DWORD uk4; /* 0x18 */
762 DWORD uk5; /* 0x1c */
763 DWORD uk6; /* 0x20 */
764 DWORD RootKeyBlock; /* 0x24 */
765 DWORD BlockSize; /* 0x28 */
767 DWORD Checksum; /* at offset 0x1FC */
778 DWORD id; /* 0x6E696268 'hbin' */
782 DWORD uk2; /* 0x10 */
783 DWORD uk3; /* 0x14 */
784 DWORD uk4; /* 0x18 */
785 DWORD size; /* 0x1C */
786 nt_hbin_sub hbin_sub; /* 0x20 */
790 * the value_list consists of offsets to the values (vk)
794 WORD SubBlockId; /* 0x00 0x6B6E */
795 WORD Type; /* 0x02 for the root-key: 0x2C, otherwise 0x20*/
796 FILETIME writetime; /* 0x04 */
797 DWORD uk1; /* 0x0C */
798 DWORD parent_off; /* 0x10 Offset of Owner/Parent key */
799 DWORD nr_subkeys; /* 0x14 number of sub-Keys */
800 DWORD uk8; /* 0x18 */
801 DWORD lf_off; /* 0x1C Offset of the sub-key lf-Records */
802 DWORD uk2; /* 0x20 */
803 DWORD nr_values; /* 0x24 number of values */
804 DWORD valuelist_off; /* 0x28 Offset of the Value-List */
805 DWORD off_sk; /* 0x2c Offset of the sk-Record */
806 DWORD off_class; /* 0x30 Offset of the Class-Name */
807 DWORD uk3; /* 0x34 */
808 DWORD uk4; /* 0x38 */
809 DWORD uk5; /* 0x3c */
810 DWORD uk6; /* 0x40 */
811 DWORD uk7; /* 0x44 */
812 WORD name_len; /* 0x48 name-length */
813 WORD class_len; /* 0x4a class-name length */
814 char name[1]; /* 0x4c key-name */
819 DWORD off_nk; /* 0x00 */
820 DWORD name; /* 0x04 */
825 WORD id; /* 0x00 0x666c */
826 WORD nr_keys; /* 0x06 */
827 hash_rec hash_rec[1];
832 WORD id; /* 0x00 0x696c */
839 WORD id; /* 0x00 'vk' */
850 #define vk_expsz 0x0002
851 #define vk_bin 0x0003
852 #define vk_dword 0x0004
853 #define vk_multisz 0x0007
857 LPSTR _strdupnA( LPCSTR str, int len )
861 if (!str) return NULL;
862 ret = malloc( len + 1 );
863 lstrcpynA( ret, str, len );
868 int _nt_parse_nk(HKEY hkey, char * base, nt_nk * nk, int level);
869 int _nt_parse_vk(HKEY hkey, char * base, nt_vk * vk, int level);
870 int _nt_parse_lf(HKEY hkey, char * base, nt_lf * lf, int level);
877 * 0 value is a default value
878 * 1 the value has a name
881 * len of the whole data block
883 * bytes including the terminating \0 = 2*(number_of_chars+1)
884 * - reg_dword, reg_binary:
885 * if highest bit of data_len is set data_off contains the value
887 int _nt_parse_vk(HKEY hkey, char * base, nt_vk * vk, int level)
890 BYTE * pdata = (BYTE *)(base+vk->data_off+4); /* start of data */
892 if(vk->id != REG_VALUE_BLOCK_ID) goto error;
894 lstrcpynAtoW(name, vk->name, vk->nam_len+1);
896 if (RegSetValueExW( hkey, (vk->flag & 0x00000001) ? name : NULL, 0, vk->type,
897 (vk->data_len & 0x80000000) ? (LPBYTE)&(vk->data_off): pdata,
898 (vk->data_len & 0x7fffffff) )) goto error;
901 ERR_(reg)("vk block invalid\n");
908 * this structure contains the hash of a keyname and points to all
911 * exception: if the id is 'il' there are no hash values and every
914 int _nt_parse_lf(HKEY hkey, char * base, nt_lf * lf, int level)
918 if (lf->id == REG_HASH_BLOCK_ID)
920 for (i=0; i<lf->nr_keys; i++)
922 if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+lf->hash_rec[i].off_nk+4), level)) goto error;
926 else if (lf->id == REG_NOHASH_BLOCK_ID)
928 for (i=0; i<lf->nr_keys; i++)
930 if (!_nt_parse_nk(hkey, base, (nt_nk*)(base+((nt_il*)lf)->off_nk[i]+4), level)) goto error;
935 error: ERR_(reg)("error reading lf block\n");
939 int _nt_parse_nk(HKEY hkey, char * base, nt_nk * nk, int level)
946 if(nk->SubBlockId != REG_KEY_BLOCK_ID) goto error;
947 if((nk->Type!=REG_ROOT_KEY_BLOCK_TYPE) &&
948 (((nt_nk*)(base+nk->parent_off+4))->SubBlockId != REG_KEY_BLOCK_ID)) goto error;
950 /* create the new key */
951 name = _strdupnA( nk->name, nk->name_len+1);
952 if(RegCreateKeyA( hkey, name, &subkey )) { free(name); goto error; }
955 /* loop through the subkeys */
958 nt_lf * lf = (nt_lf*)(base+nk->lf_off+4);
959 if (nk->nr_subkeys != lf->nr_keys) goto error1;
960 if (!_nt_parse_lf(subkey, base, lf, level+1)) goto error1;
963 /* loop trough the value list */
964 vl = (DWORD *)(base+nk->valuelist_off+4);
965 for (i=0; i<nk->nr_values; i++)
967 nt_vk * vk = (nt_vk*)(base+vl[i]+4);
968 if (!_nt_parse_vk(subkey, base, vk, level+1 )) goto error1;
974 error1: RegCloseKey(subkey);
975 error: ERR_(reg)("error reading nk block\n");
980 * this function intentionally uses unix file functions to make it possible
981 * to move it to a seperate registry helper programm
983 static int _nt_loadreg( HKEY hkey, char* fn )
990 nt_hbin_sub * hbin_sub;
992 DOS_FULL_NAME full_name;
994 if (!DOSFS_GetFullName( fn, 0, &full_name ));
996 TRACE_(reg)("Loading NT registry database '%s' '%s'\n",fn, full_name.long_name);
998 if ((fd = open(full_name.long_name, O_RDONLY | O_NONBLOCK)) == -1) return FALSE;
999 if (fstat(fd, &st ) == -1) goto error1;
1001 if ((base=mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto error1;
1005 if(regf->id != REG_HEADER_BLOCK_ID) /* 'regf' */
1007 ERR( "%s is not a nt-registry\n", fn);
1010 TRACE_(reg)( "%p [regf] offset=%lx size=%lx\n", regf, regf->RootKeyBlock, regf->BlockSize);
1013 hbin = base + 0x1000;
1014 if (hbin->id != REG_POOL_BLOCK_ID)
1016 ERR_(reg)( "%s hbin block invalid\n", fn);
1019 TRACE_(reg)( "%p [hbin] prev=%lx next=%lx size=%lx\n", hbin, hbin->off_prev, hbin->off_next, hbin->size);
1021 /* hbin_sub block */
1022 hbin_sub = (nt_hbin_sub*)&(hbin->hbin_sub);
1023 if ((hbin_sub->data[0] != 'n') || (hbin_sub->data[1] != 'k'))
1025 ERR_(reg)( "%s hbin_sub block invalid\n", fn);
1028 TRACE_(reg)( "%p [hbin sub] size=%lx\n", hbin_sub, hbin_sub->blocksize);
1031 nk = (nt_nk*)&(hbin_sub->data[0]);
1032 if (nk->Type != REG_ROOT_KEY_BLOCK_TYPE)
1034 ERR_(reg)( "%s special nk block not found\n", fn);
1038 _nt_parse_nk (hkey, base+0x1000, nk, 0);
1044 error: munmap(base, len);
1046 ERR_(reg)("error reading registry file\n");
1051 /* WINDOWS 95 REGISTRY LOADER */
1053 * Structure of a win95 registry database.
1055 * 0 : "CREG" - magic
1057 * 8 : DWORD offset_of_RGDB_part
1058 * 0C..0F: ? (someone fill in please)
1059 * 10: WORD number of RGDB blocks
1061 * 14: WORD always 0000?
1062 * 16: WORD always 0001?
1063 * 18..1F: ? (someone fill in please)
1067 * 0 : "RGKN" - magic
1068 * 4 : DWORD offset to first RGDB section
1069 * 8 : DWORD offset to the root record
1070 * C..0x1B: ? (fill in)
1071 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
1073 * Disk Key Entry Structure:
1074 * 00: DWORD - Free entry indicator(?)
1075 * 04: DWORD - Hash = sum of bytes of keyname
1076 * 08: DWORD - Root key indicator? unknown, but usually 0xFFFFFFFF on win95 systems
1077 * 0C: DWORD - disk address of PreviousLevel Key.
1078 * 10: DWORD - disk address of Next Sublevel Key.
1079 * 14: DWORD - disk address of Next Key (on same level).
1080 * DKEP>18: WORD - Nr, Low Significant part.
1081 * 1A: WORD - Nr, High Significant part.
1083 * The disk address always points to the nr part of the previous key entry
1084 * of the referenced key. Don't ask me why, or even if I got this correct
1085 * from staring at 1kg of hexdumps. (DKEP)
1087 * The High significant part of the structure seems to equal the number
1088 * of the RGDB section. The low significant part is a unique ID within
1091 * There are two minor corrections to the position of that structure.
1092 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
1093 * the DKE reread from there.
1094 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
1095 * CPS - I have not experienced the above phenomenon in my registry files
1098 * 00: "RGDB" - magic
1099 * 04: DWORD offset to next RGDB section
1101 * 0C: WORD always 000d?
1102 * 0E: WORD RGDB block number
1103 * 10: DWORD ? (equals value at offset 4 - value at offset 8)
1105 * 20.....: disk keys
1108 * 00: DWORD nextkeyoffset - offset to the next disk key structure
1109 * 08: WORD nrLS - low significant part of NR
1110 * 0A: WORD nrHS - high significant part of NR
1111 * 0C: DWORD bytesused - bytes used in this structure.
1112 * 10: WORD name_len - length of name in bytes. without \0
1113 * 12: WORD nr_of_values - number of values.
1114 * 14: char name[name_len] - name string. No \0.
1115 * 14+name_len: disk values
1116 * nextkeyoffset: ... next disk key
1119 * 00: DWORD type - value type (hmm, could be WORD too)
1120 * 04: DWORD - unknown, usually 0
1121 * 08: WORD namelen - length of Name. 0 means name=NULL
1122 * 0C: WORD datalen - length of Data.
1123 * 10: char name[namelen] - name, no \0
1124 * 10+namelen: BYTE data[datalen] - data, without \0 if string
1125 * 10+namelen+datalen: next values or disk key
1127 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
1128 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
1129 * structure) and reading another RGDB_section.
1130 * repeat until end of file.
1132 * An interesting relationship exists in RGDB_section. The value at offset
1133 * 10 equals the value at offset 4 minus the value at offset 8. I have no
1134 * idea at the moment what this means. (Kevin Cozens)
1136 * FIXME: this description needs some serious help, yes.
1139 struct _w95keyvalue {
1141 unsigned short datalen;
1143 unsigned char *data;
1151 struct _w95keyvalue *values;
1152 struct _w95key *prevlvl;
1153 struct _w95key *nextsub;
1154 struct _w95key *next;
1168 /******************************************************************************
1169 * _w95_processKey [Internal]
1171 static HKEY _w95_processKey ( HKEY hkey, int nrLS, int nrMS, struct _w95_info *info )
1174 /* Disk Key Header structure (RGDB part) */
1176 unsigned long nextkeyoff;
1177 unsigned short nrLS;
1178 unsigned short nrMS;
1179 unsigned long bytesused;
1180 unsigned short keynamelen;
1181 unsigned short values;
1184 /* disk key values or nothing */
1186 /* Disk Key Value structure */
1190 unsigned short valnamelen;
1191 unsigned short valdatalen;
1192 /* valname, valdata */
1198 char *rgdbdata = info->rgdbbuffer;
1199 int nbytes = info->rgdbsize;
1200 char *curdata = rgdbdata;
1201 char *end = rgdbdata + nbytes;
1203 char *next = rgdbdata;
1209 if (strncmp(curdata, "RGDB", 4)) return 0;
1211 memcpy(&off_next_rgdb,curdata+4,4);
1212 next = curdata + off_next_rgdb;
1213 nrgdb = (int) *((short *)curdata + 7);
1215 } while (nrgdb != nrMS && (next < end));
1217 /* curdata now points to the start of the right RGDB section */
1220 #define XREAD(whereto,len) \
1221 if ((curdata + len) <= end) {\
1222 memcpy(whereto,curdata,len);\
1227 while (curdata < next) {
1228 struct dkh *xdkh = (struct dkh*)curdata;
1230 bytesread += sizeof(dkh); /* FIXME... nextkeyoff? */
1231 if (xdkh->nrLS == nrLS) {
1232 memcpy(&dkh,xdkh,sizeof(dkh));
1233 curdata += sizeof(dkh);
1236 curdata += xdkh->nextkeyoff;
1239 if (dkh.nrLS != nrLS) return 0;
1241 if (nrgdb != dkh.nrMS)
1244 assert((dkh.keynamelen<2) || curdata[0]);
1245 subkey=_find_or_add_key(hkey,strcvtA2W(curdata, dkh.keynamelen));
1246 curdata += dkh.keynamelen;
1248 for (i=0;i< dkh.values; i++) {
1254 XREAD(&dkv,sizeof(dkv));
1256 name = strcvtA2W(curdata, dkv.valnamelen);
1257 curdata += dkv.valnamelen;
1259 if ((1 << dkv.type) & UNICONVMASK) {
1260 data = (LPBYTE) strcvtA2W(curdata, dkv.valdatalen);
1261 len = 2*(dkv.valdatalen + 1);
1263 /* I don't think we want to NULL terminate all data */
1264 data = xmalloc(dkv.valdatalen);
1265 memcpy (data, curdata, dkv.valdatalen);
1266 len = dkv.valdatalen;
1269 curdata += dkv.valdatalen;
1271 _find_or_add_value( subkey, name, dkv.type, data, len );
1276 /******************************************************************************
1277 * _w95_walkrgkn [Internal]
1279 static void _w95_walkrgkn( HKEY prevkey, char *off,
1280 struct _w95_info *info )
1283 /* Disk Key Entry structure (RGKN part) */
1287 unsigned long x3;/*usually 0xFFFFFFFF */
1288 unsigned long prevlvl;
1289 unsigned long nextsub;
1291 unsigned short nrLS;
1292 unsigned short nrMS;
1293 } *dke = (struct dke *)off;
1297 dke = (struct dke *) ((char *)info->rgknbuffer);
1300 subkey = _w95_processKey(prevkey, dke->nrLS, dke->nrMS, info);
1302 if (dke->nextsub != -1 &&
1303 ((dke->nextsub - 0x20) < info->rgknsize)
1304 && (dke->nextsub > 0x20)) {
1306 _w95_walkrgkn(subkey ? subkey : prevkey, /* XXX <-- This is a hack*/
1307 info->rgknbuffer + dke->nextsub - 0x20,
1310 if (subkey) RegCloseKey( subkey );
1312 if (dke->next != -1 &&
1313 ((dke->next - 0x20) < info->rgknsize) &&
1314 (dke->next > 0x20)) {
1315 _w95_walkrgkn(prevkey,
1316 info->rgknbuffer + dke->next - 0x20,
1322 /******************************************************************************
1323 * _w95_loadreg [Internal]
1325 static void _w95_loadreg( char* fn, HKEY hkey )
1329 unsigned long where,version,rgdbsection,end;
1330 struct _w95_info info;
1332 BY_HANDLE_FILE_INFORMATION hfdinfo;
1334 TRACE("Loading Win95 registry database '%s'\n",fn);
1335 hfd=OpenFile(fn,&ofs,OF_READ);
1336 if (hfd==HFILE_ERROR)
1339 if (4!=_lread(hfd,magic,4))
1341 if (strcmp(magic,"CREG")) {
1342 WARN("%s is not a w95 registry.\n",fn);
1345 if (4!=_lread(hfd,&version,4))
1347 if (4!=_lread(hfd,&rgdbsection,4))
1349 if (-1==_llseek(hfd,0x20,SEEK_SET))
1351 if (4!=_lread(hfd,magic,4))
1353 if (strcmp(magic,"RGKN")) {
1354 WARN("second IFF header not RGKN, but %s\n", magic);
1358 /* STEP 1: Keylink structures */
1359 if (-1==_llseek(hfd,0x40,SEEK_SET))
1364 info.rgknsize = end - where;
1365 info.rgknbuffer = (char*)xmalloc(info.rgknsize);
1366 if (info.rgknsize != _lread(hfd,info.rgknbuffer,info.rgknsize))
1369 if (!GetFileInformationByHandle(hfd,&hfdinfo))
1372 end = hfdinfo.nFileSizeLow;
1373 info.lastmodified = DOSFS_FileTimeToUnixTime(&hfdinfo.ftLastWriteTime,NULL);
1375 if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
1378 info.rgdbbuffer = (char*)xmalloc(end-rgdbsection);
1379 info.rgdbsize = end - rgdbsection;
1381 if (info.rgdbsize !=_lread(hfd,info.rgdbbuffer,info.rgdbsize))
1385 _w95_walkrgkn(hkey, NULL, &info);
1387 free (info.rgdbbuffer);
1388 free (info.rgknbuffer);
1392 /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1395 reghack - windows 3.11 registry data format demo program.
1397 The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1398 a combined hash table and tree description, and finally a text table.
1400 The header is obvious from the struct header. The taboff1 and taboff2
1401 fields are always 0x20, and their usage is unknown.
1403 The 8-byte entry table has various entry types.
1405 tabent[0] is a root index. The second word has the index of the root of
1407 tabent[1..hashsize] is a hash table. The first word in the hash entry is
1408 the index of the key/value that has that hash. Data with the same
1409 hash value are on a circular list. The other three words in the
1410 hash entry are always zero.
1411 tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1412 entry: dirent and keyent/valent. They are identified by context.
1413 tabent[freeidx] is the first free entry. The first word in a free entry
1414 is the index of the next free entry. The last has 0 as a link.
1415 The other three words in the free list are probably irrelevant.
1417 Entries in text table are preceeded by a word at offset-2. This word
1418 has the value (2*index)+1, where index is the referring keyent/valent
1419 entry in the table. I have no suggestion for the 2* and the +1.
1420 Following the word, there are N bytes of data, as per the keyent/valent
1421 entry length. The offset of the keyent/valent entry is from the start
1422 of the text table to the first data byte.
1424 This information is not available from Microsoft. The data format is
1425 deduced from the reg.dat file by me. Mistakes may
1426 have been made. I claim no rights and give no guarantees for this program.
1428 Tor Sjøwall, tor@sn.no
1431 /* reg.dat header format */
1432 struct _w31_header {
1433 char cookie[8]; /* 'SHCC3.10' */
1434 unsigned long taboff1; /* offset of hash table (??) = 0x20 */
1435 unsigned long taboff2; /* offset of index table (??) = 0x20 */
1436 unsigned long tabcnt; /* number of entries in index table */
1437 unsigned long textoff; /* offset of text part */
1438 unsigned long textsize; /* byte size of text part */
1439 unsigned short hashsize; /* hash size */
1440 unsigned short freeidx; /* free index */
1443 /* generic format of table entries */
1444 struct _w31_tabent {
1445 unsigned short w0, w1, w2, w3;
1448 /* directory tabent: */
1449 struct _w31_dirent {
1450 unsigned short sibling_idx; /* table index of sibling dirent */
1451 unsigned short child_idx; /* table index of child dirent */
1452 unsigned short key_idx; /* table index of key keyent */
1453 unsigned short value_idx; /* table index of value valent */
1457 struct _w31_keyent {
1458 unsigned short hash_idx; /* hash chain index for string */
1459 unsigned short refcnt; /* reference count */
1460 unsigned short length; /* length of string */
1461 unsigned short string_off; /* offset of string in text table */
1465 struct _w31_valent {
1466 unsigned short hash_idx; /* hash chain index for string */
1467 unsigned short refcnt; /* reference count */
1468 unsigned short length; /* length of string */
1469 unsigned short string_off; /* offset of string in text table */
1472 /* recursive helper function to display a directory tree */
1474 __w31_dumptree( unsigned short idx,
1476 struct _w31_tabent *tab,
1477 struct _w31_header *head,
1479 time_t lastmodified,
1482 struct _w31_dirent *dir;
1483 struct _w31_keyent *key;
1484 struct _w31_valent *val;
1486 static char tail[400];
1489 dir=(struct _w31_dirent*)&tab[idx];
1492 key = (struct _w31_keyent*)&tab[dir->key_idx];
1494 memcpy(tail,&txt[key->string_off],key->length);
1495 tail[key->length]='\0';
1496 /* all toplevel entries AND the entries in the
1497 * toplevel subdirectory belong to \SOFTWARE\Classes
1499 if (!level && !lstrcmpA(tail,".classes")) {
1500 __w31_dumptree(dir->child_idx,txt,tab,head,hkey,lastmodified,level+1);
1501 idx=dir->sibling_idx;
1504 if (subkey) RegCloseKey( subkey );
1505 if (RegCreateKeyA( hkey, tail, &subkey ) != ERROR_SUCCESS) subkey = 0;
1506 /* only add if leaf node or valued node */
1507 if (dir->value_idx!=0||dir->child_idx==0) {
1508 if (dir->value_idx) {
1509 val=(struct _w31_valent*)&tab[dir->value_idx];
1510 memcpy(tail,&txt[val->string_off],val->length);
1511 tail[val->length]='\0';
1512 RegSetValueA( subkey, NULL, REG_SZ, tail, 0 );
1516 TRACE("strange: no directory key name, idx=%04x\n", idx);
1518 __w31_dumptree(dir->child_idx,txt,tab,head,subkey,lastmodified,level+1);
1519 idx=dir->sibling_idx;
1521 if (subkey) RegCloseKey( subkey );
1525 /******************************************************************************
1526 * _w31_loadreg [Internal]
1528 void _w31_loadreg(void) {
1530 struct _w31_header head;
1531 struct _w31_tabent *tab;
1535 BY_HANDLE_FILE_INFORMATION hfinfo;
1536 time_t lastmodified;
1540 hf = OpenFile("reg.dat",&ofs,OF_READ);
1541 if (hf==HFILE_ERROR)
1544 /* read & dump header */
1545 if (sizeof(head)!=_lread(hf,&head,sizeof(head))) {
1546 ERR("reg.dat is too short.\n");
1550 if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
1551 ERR("reg.dat has bad signature.\n");
1556 len = head.tabcnt * sizeof(struct _w31_tabent);
1557 /* read and dump index table */
1559 if (len!=_lread(hf,tab,len)) {
1560 ERR("couldn't read %d bytes.\n",len);
1567 txt = xmalloc(head.textsize);
1568 if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
1569 ERR("couldn't seek to textblock.\n");
1575 if (head.textsize!=_lread(hf,txt,head.textsize)) {
1576 ERR("textblock too short (%d instead of %ld).\n",len,head.textsize);
1583 if (!GetFileInformationByHandle(hf,&hfinfo)) {
1584 ERR("GetFileInformationByHandle failed?.\n");
1590 lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
1591 __w31_dumptree(tab[0].w1,txt,tab,&head,HKEY_CLASSES_ROOT,lastmodified,0);
1599 /**********************************************************************************
1600 * SHELL_LoadRegistry [Internal]
1602 void SHELL_LoadRegistry( void )
1604 struct set_registry_levels_request *req = get_req_buffer();
1613 /* set level to 0 for loading system files */
1617 server_call( REQ_SET_REGISTRY_LEVELS );
1619 if (PROFILE_GetWineIniBool ("registry", "LoadWin311RegistryFiles", 1))
1621 /* Load windows 3.1 entries */
1624 if (PROFILE_GetWineIniBool ("registry", "LoadWin95RegistryFiles", 1))
1626 /* Load windows 95 entries */
1627 _w95_loadreg("C:\\system.1st", HKEY_LOCAL_MACHINE);
1628 _w95_loadreg("system.dat", HKEY_LOCAL_MACHINE);
1629 _w95_loadreg("user.dat", HKEY_USERS);
1631 if (PROFILE_GetWineIniBool ("registry", "LoadWinNTRegistryFiles", 1))
1633 fn = xmalloc( MAX_PATHNAME_LEN );
1634 home = xmalloc ( MAX_PATHNAME_LEN );
1635 if ( PROFILE_GetWineIniString( "registry", "NTUser", "", home, MAX_PATHNAME_LEN - 1))
1637 GetWindowsDirectoryA( fn, MAX_PATHNAME_LEN );
1638 strncat(fn, "\\Profiles\\", MAX_PATHNAME_LEN - strlen(fn) - 1);
1639 strncat(fn, home, MAX_PATHNAME_LEN - strlen(fn) - 1);
1640 strncat(fn, "\\ntuser.dat", MAX_PATHNAME_LEN - strlen(fn) - 1);
1641 _nt_loadreg( HKEY_USERS, fn );
1645 * map HLM\System\ControlSet001 to HLM\System\CurrentControlSet
1647 GetSystemDirectoryA( fn, MAX_PATHNAME_LEN );
1650 strncat(home, "\\config\\system", MAX_PATHNAME_LEN - strlen(home) - 1);
1651 _nt_loadreg(HKEY_LOCAL_MACHINE, home);
1654 strncat(home, "\\config\\software", MAX_PATHNAME_LEN - strlen(home) - 1);
1655 _nt_loadreg(HKEY_LOCAL_MACHINE, home);
1658 strncat(home, "\\config\\sam", MAX_PATHNAME_LEN - strlen(home) - 1);
1659 _nt_loadreg(HKEY_LOCAL_MACHINE, home);
1662 strncat(home, "\\config\\security", MAX_PATHNAME_LEN - strlen(home) - 1);
1663 _nt_loadreg(HKEY_LOCAL_MACHINE, home);
1669 if (PROFILE_GetWineIniBool ("registry","LoadGlobalRegistryFiles", 1))
1672 * Load the global HKU hive directly from sysconfdir
1674 _wine_loadreg( HKEY_USERS, SAVE_USERS_DEFAULT );
1677 * Load the global machine defaults directly form sysconfdir
1679 _wine_loadreg( HKEY_LOCAL_MACHINE, SAVE_LOCAL_MACHINE_DEFAULT );
1682 /* set level to 1 for loading user files */
1686 server_call( REQ_SET_REGISTRY_LEVELS );
1689 * Load the user saved registries
1691 if (!(home = getenv( "HOME" )))
1692 WARN("Failed to get homedirectory of UID %ld.\n",(long) getuid());
1693 else if (PROFILE_GetWineIniBool("registry", "LoadHomeRegistryFiles", 1))
1696 * Load user's personal versions of global HKU/.Default keys
1698 fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX) +
1699 strlen(SAVE_LOCAL_USERS_DEFAULT)+2);
1701 strcat(fn, WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
1702 _wine_loadreg( HKEY_USERS, fn );
1705 fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) + strlen(SAVE_CURRENT_USER)+2);
1707 strcat(fn, WINE_PREFIX"/"SAVE_CURRENT_USER);
1708 _wine_loadreg( HKEY_CURRENT_USER, fn );
1712 * Load HKLM, attempt to get the registry location from the config
1713 * file first, if exist, load and keep going.
1715 fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX)+ strlen(SAVE_LOCAL_MACHINE)+2);
1717 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1718 _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
1723 * Load HKCU, get the registry location from the config
1724 * file, if exist, load and keep going.
1726 if (PROFILE_GetWineIniBool ( "registry", "LoadAltRegistryFiles", 1))
1728 fn = xmalloc( MAX_PATHNAME_LEN );
1729 if ( PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "",
1730 fn, MAX_PATHNAME_LEN - 1))
1732 _wine_loadreg( HKEY_CURRENT_USER, fn );
1736 * Load HKU, get the registry location from the config
1737 * file, if exist, load and keep going.
1739 fn = xmalloc ( MAX_PATHNAME_LEN );
1740 if ( PROFILE_GetWineIniString ( "registry", "AltUserFile", "",
1741 fn, MAX_PATHNAME_LEN - 1))
1743 _wine_loadreg( HKEY_USERS, fn );
1747 * Load HKLM, get the registry location from the config
1748 * file, if exist, load and keep going.
1750 fn = xmalloc ( MAX_PATHNAME_LEN );
1751 if (PROFILE_GetWineIniString ( "registry", "AltLocalMachineFile", "",
1752 fn, MAX_PATHNAME_LEN - 1))
1754 _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
1760 * Obtain the handle of the HKU\.Default key.
1761 * in order to copy HKU\.Default\* onto HKEY_CURRENT_USER
1763 if (RegCreateKeyA(HKEY_USERS,".Default",&hkey) != ERROR_SUCCESS)
1764 WARN("Could not create global user default key\n");
1766 _copy_registry( hkey, HKEY_CURRENT_USER );
1770 * Since HKU is built from the global HKU and the local user HKU file we must
1771 * flush the HKU tree we have built at this point otherwise the part brought
1772 * in from the global HKU is saved into the local HKU. To avoid this
1773 * useless dupplication of HKU keys we reread the local HKU key.
1776 /* Allways flush the HKU hive and reload it only with user's personal HKU */
1777 _flush_registry( HKEY_USERS );
1779 /* Reload user's local HKU hive */
1780 if (home && PROFILE_GetWineIniBool ("registry","LoadHomeRegistryFiles",1))
1782 fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX)
1783 + strlen(SAVE_LOCAL_USERS_DEFAULT) + 2);
1786 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
1788 _wine_loadreg( HKEY_USERS, fn );
1794 * Make sure the update mode is there
1796 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey))
1798 DWORD junk,type,len;
1802 if (( RegQueryValueExA(
1808 &len) != ERROR_SUCCESS) || (type != REG_SZ))
1810 RegSetValueExA(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1816 if ((save_timeout = PROFILE_GetWineIniInt( "registry", "PeriodicSave", 0 )))
1818 SERVICE_AddTimer( save_timeout * 1000000, periodic_save, 0 );
1823 /********************* API FUNCTIONS ***************************************/
1828 /******************************************************************************
1829 * RegFlushKey [KERNEL.227] [ADVAPI32.143]
1830 * Immediately writes key to registry.
1831 * Only returns after data has been written to disk.
1833 * FIXME: does it really wait until data is written ?
1836 * hkey [I] Handle of key to write
1839 * Success: ERROR_SUCCESS
1840 * Failure: Error code
1842 DWORD WINAPI RegFlushKey( HKEY hkey )
1844 FIXME( "(%x): stub\n", hkey );
1845 return ERROR_SUCCESS;
1848 /******************************************************************************
1849 * RegConnectRegistry32W [ADVAPI32.128]
1852 * lpMachineName [I] Address of name of remote computer
1853 * hHey [I] Predefined registry handle
1854 * phkResult [I] Address of buffer for remote registry handle
1856 LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey,
1859 TRACE("(%s,%x,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
1861 if (!lpMachineName || !*lpMachineName) {
1862 /* Use the local machine name */
1863 return RegOpenKey16( hKey, "", phkResult );
1866 FIXME("Cannot connect to %s\n",debugstr_w(lpMachineName));
1867 return ERROR_BAD_NETPATH;
1871 /******************************************************************************
1872 * RegConnectRegistry32A [ADVAPI32.127]
1874 LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, LPHKEY reskey )
1877 LPWSTR machineW = strdupA2W(machine);
1878 ret = RegConnectRegistryW( machineW, hkey, reskey );
1884 /******************************************************************************
1885 * RegGetKeySecurity [ADVAPI32.144]
1886 * Retrieves a copy of security descriptor protecting the registry key
1889 * hkey [I] Open handle of key to set
1890 * SecurityInformation [I] Descriptor contents
1891 * pSecurityDescriptor [O] Address of descriptor for key
1892 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
1895 * Success: ERROR_SUCCESS
1896 * Failure: Error code
1898 LONG WINAPI RegGetKeySecurity( HKEY hkey,
1899 SECURITY_INFORMATION SecurityInformation,
1900 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1901 LPDWORD lpcbSecurityDescriptor )
1903 TRACE("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
1904 lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1906 /* FIXME: Check for valid SecurityInformation values */
1908 if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
1909 return ERROR_INSUFFICIENT_BUFFER;
1911 FIXME("(%x,%ld,%p,%ld): stub\n",hkey,SecurityInformation,
1912 pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1914 return ERROR_SUCCESS;
1918 /******************************************************************************
1919 * RegNotifyChangeKeyValue [ADVAPI32.???]
1922 * hkey [I] Handle of key to watch
1923 * fWatchSubTree [I] Flag for subkey notification
1924 * fdwNotifyFilter [I] Changes to be reported
1925 * hEvent [I] Handle of signaled event
1926 * fAsync [I] Flag for asynchronous reporting
1928 LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
1929 DWORD fdwNotifyFilter, HANDLE hEvent,
1932 FIXME("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter,
1934 return ERROR_SUCCESS;
1938 /******************************************************************************
1939 * RegUnLoadKey32W [ADVAPI32.173]
1942 * hkey [I] Handle of open key
1943 * lpSubKey [I] Address of name of subkey to unload
1945 LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey )
1947 FIXME("(%x,%s): stub\n",hkey, debugstr_w(lpSubKey));
1948 return ERROR_SUCCESS;
1952 /******************************************************************************
1953 * RegUnLoadKey32A [ADVAPI32.172]
1955 LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
1958 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
1959 ret = RegUnLoadKeyW( hkey, lpSubKeyW );
1960 if(lpSubKeyW) free(lpSubKeyW);
1965 /******************************************************************************
1966 * RegSetKeySecurity [ADVAPI32.167]
1969 * hkey [I] Open handle of key to set
1970 * SecurityInfo [I] Descriptor contents
1971 * pSecurityDesc [I] Address of descriptor for key
1973 LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
1974 PSECURITY_DESCRIPTOR pSecurityDesc )
1976 TRACE("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
1978 /* It seems to perform this check before the hkey check */
1979 if ((SecurityInfo & OWNER_SECURITY_INFORMATION) ||
1980 (SecurityInfo & GROUP_SECURITY_INFORMATION) ||
1981 (SecurityInfo & DACL_SECURITY_INFORMATION) ||
1982 (SecurityInfo & SACL_SECURITY_INFORMATION)) {
1985 return ERROR_INVALID_PARAMETER;
1988 return ERROR_INVALID_PARAMETER;
1990 FIXME(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
1992 return ERROR_SUCCESS;
1996 /******************************************************************************
1997 * RegRestoreKey32W [ADVAPI32.164]
2000 * hkey [I] Handle of key where restore begins
2001 * lpFile [I] Address of filename containing saved tree
2002 * dwFlags [I] Optional flags
2004 LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
2006 TRACE("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
2008 /* It seems to do this check before the hkey check */
2009 if (!lpFile || !*lpFile)
2010 return ERROR_INVALID_PARAMETER;
2012 FIXME("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
2014 /* Check for file existence */
2016 return ERROR_SUCCESS;
2020 /******************************************************************************
2021 * RegRestoreKey32A [ADVAPI32.163]
2023 LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
2026 LPWSTR lpFileW = strdupA2W(lpFile);
2027 ret = RegRestoreKeyW( hkey, lpFileW, dwFlags );
2028 if(lpFileW) free(lpFileW);
2033 /******************************************************************************
2034 * RegReplaceKey32W [ADVAPI32.162]
2037 * hkey [I] Handle of open key
2038 * lpSubKey [I] Address of name of subkey
2039 * lpNewFile [I] Address of filename for file with new data
2040 * lpOldFile [I] Address of filename for backup file
2042 LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
2045 FIXME("(%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey),
2046 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
2047 return ERROR_SUCCESS;
2051 /******************************************************************************
2052 * RegReplaceKey32A [ADVAPI32.161]
2054 LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
2058 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
2059 LPWSTR lpNewFileW = strdupA2W(lpNewFile);
2060 LPWSTR lpOldFileW = strdupA2W(lpOldFile);
2061 ret = RegReplaceKeyW( hkey, lpSubKeyW, lpNewFileW, lpOldFileW );
2073 /* 16-bit functions */
2075 /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
2076 * some programs. Do not remove those cases. -MM
2078 static inline void fix_win16_hkey( HKEY *hkey )
2080 if (*hkey == 0 || *hkey == 1) *hkey = HKEY_CLASSES_ROOT;
2083 /******************************************************************************
2084 * RegEnumKey16 [KERNEL.216] [SHELL.7]
2086 DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
2088 fix_win16_hkey( &hkey );
2089 return RegEnumKeyA( hkey, index, name, name_len );
2092 /******************************************************************************
2093 * RegOpenKey16 [KERNEL.217] [SHELL.1]
2095 DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
2097 fix_win16_hkey( &hkey );
2098 return RegOpenKeyA( hkey, name, retkey );
2101 /******************************************************************************
2102 * RegCreateKey16 [KERNEL.218] [SHELL.2]
2104 DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
2106 fix_win16_hkey( &hkey );
2107 return RegCreateKeyA( hkey, name, retkey );
2110 /******************************************************************************
2111 * RegDeleteKey16 [KERNEL.219] [SHELL.4]
2113 DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name )
2115 fix_win16_hkey( &hkey );
2116 return RegDeleteKeyA( hkey, name );
2119 /******************************************************************************
2120 * RegCloseKey16 [KERNEL.220] [SHELL.3]
2122 DWORD WINAPI RegCloseKey16( HKEY hkey )
2124 fix_win16_hkey( &hkey );
2125 return RegCloseKey( hkey );
2128 /******************************************************************************
2129 * RegSetValue16 [KERNEL.221] [SHELL.5]
2131 DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
2133 fix_win16_hkey( &hkey );
2134 return RegSetValueA( hkey, name, type, data, count );
2137 /******************************************************************************
2138 * RegDeleteValue16 [KERNEL.222]
2140 DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR name )
2142 fix_win16_hkey( &hkey );
2143 return RegDeleteValueA( hkey, name );
2146 /******************************************************************************
2147 * RegEnumValue16 [KERNEL.223]
2149 DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
2150 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
2152 fix_win16_hkey( &hkey );
2153 return RegEnumValueA( hkey, index, value, val_count, reserved, type, data, count );
2156 /******************************************************************************
2157 * RegQueryValue16 [KERNEL.224] [SHELL.6]
2160 * Is this HACK still applicable?
2163 * The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
2164 * mask out the high 16 bit. This (not so much incidently) hopefully fixes
2167 DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count )
2169 fix_win16_hkey( &hkey );
2170 if (count) *count &= 0xffff;
2171 return RegQueryValueA( hkey, name, data, count );
2174 /******************************************************************************
2175 * RegQueryValueEx16 [KERNEL.225]
2177 DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
2178 LPBYTE data, LPDWORD count )
2180 fix_win16_hkey( &hkey );
2181 return RegQueryValueExA( hkey, name, reserved, type, data, count );
2184 /******************************************************************************
2185 * RegSetValueEx16 [KERNEL.226]
2187 DWORD WINAPI RegSetValueEx16( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
2188 CONST BYTE *data, DWORD count )
2190 fix_win16_hkey( &hkey );
2191 return RegSetValueExA( hkey, name, reserved, type, data, count );