4 * Copyright 1996 Marcus Meissner
14 #include <sys/types.h>
15 #include <sys/fcntl.h>
28 #define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y))
30 /* FIXME: following defines should be configured global ... */
32 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
33 #define WINE_PREFIX "/.wine"
34 #define SAVE_USERS_DEFAULT "/usr/local/etc/wine.userreg"
35 #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
37 /* relative in ~user/.wine/ : */
38 #define SAVE_CURRENT_USER "user.reg"
39 #define SAVE_LOCAL_MACHINE "system.reg"
41 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
42 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
44 static KEYSTRUCT
*key_classes_root
=NULL
; /* windows 3.1 global values */
45 static KEYSTRUCT
*key_current_user
=NULL
; /* user specific values */
46 static KEYSTRUCT
*key_local_machine
=NULL
;/* machine specific values */
47 static KEYSTRUCT
*key_users
=NULL
; /* all users? */
49 /* dynamic, not saved */
50 static KEYSTRUCT
*key_performance_data
=NULL
;
51 static KEYSTRUCT
*key_current_config
=NULL
;
52 static KEYSTRUCT
*key_dyn_data
=NULL
;
54 /* what valuetypes do we need to convert? */
55 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
57 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
58 #define strdupW2A(x) STRING32_DupUniToAnsi(x)
59 #define strdupW(x) STRING32_strdupW(x)
60 #define strcmpW(a,b) STRING32_lstrcmpW(a,b)
61 #define strcmpniW(a,b) STRING32_lstrcmpniW(a,b)
62 #define strchrW(a,c) STRING32_lstrchrW(a,c)
63 #define strlenW(a) STRING32_UniLen(a)
64 #define strcpyWA(a,b) STRING32_UniToAnsi(a,b)
66 static struct openhandle
{
71 static int nrofopenhandles
=0;
72 static int currenthandle
=1;
75 add_handle(HKEY hkey
,LPKEYSTRUCT lpkey
,REGSAM accessmask
) {
78 for (i
=0;i
<nrofopenhandles
;i
++) {
79 if (openhandles
[i
].lpkey
==lpkey
) {
80 dprintf_reg(stddeb
,"add_handle:Tried to add %p twice!\n",lpkey
);
82 if (openhandles
[i
].hkey
==hkey
) {
83 dprintf_reg(stddeb
,"add_handle:Tried to add %lx twice!\n",(LONG
)hkey
);
86 openhandles
=xrealloc( openhandles
,
87 sizeof(struct openhandle
)*(nrofopenhandles
+1)
89 openhandles
[i
].lpkey
= lpkey
;
90 openhandles
[i
].hkey
= hkey
;
91 openhandles
[i
].accessmask
= accessmask
;
96 get_handle(HKEY hkey
) {
99 for (i
=0;i
<nrofopenhandles
;i
++)
100 if (openhandles
[i
].hkey
==hkey
)
101 return openhandles
[i
].lpkey
;
102 dprintf_reg(stddeb
,"get_handle:Didn't find handle %lx?\n",(LONG
)hkey
);
107 remove_handle(HKEY hkey
) {
110 for (i
=0;i
<nrofopenhandles
;i
++)
111 if (openhandles
[i
].hkey
==hkey
)
113 if (i
==nrofopenhandles
) {
114 dprintf_reg(stddeb
,"remove_handle:Didn't find handle %08x?\n",hkey
);
117 memcpy( openhandles
+i
,
119 sizeof(struct openhandle
)*(nrofopenhandles
-i
-1)
121 openhandles
=xrealloc(openhandles
,sizeof(struct openhandle
)*(nrofopenhandles
-1));
127 /* debug function, converts a unicode into a static memory area
128 * (sub for using two static strings, in case we need them in a single call)
131 W2C(LPCWSTR x
,int sub
) {
132 static LPSTR unicodedebug
[2]={NULL
,NULL
};
135 if (sub
!=0 && sub
!=1)
136 return "<W2C:bad sub>";
137 if (unicodedebug
[sub
]) free(unicodedebug
[sub
]);
138 unicodedebug
[sub
] = strdupW2A(x
);
139 return unicodedebug
[sub
];
143 lookup_hkey(HKEY hkey
) {
147 case HKEY_CLASSES_ROOT
:
148 return key_classes_root
;
149 case HKEY_CURRENT_USER
:
150 return key_current_user
;
151 case HKEY_LOCAL_MACHINE
:
152 return key_local_machine
;
155 case HKEY_PERFORMANCE_DATA
:
156 return key_performance_data
;
159 case HKEY_CURRENT_CONFIG
:
160 return key_current_config
;
162 dprintf_reg(stddeb
,"lookup_hkey(%lx), special key!\n",
165 return get_handle(hkey
);
171 * splits the unicode string 'wp' into an array of strings.
172 * the array is allocated by this function.
173 * the number of components will be stored in 'wpc'
174 * Free the array using FREE_KEY_PATH
177 split_keypath(LPCWSTR wp
,LPWSTR
**wpv
,int *wpc
) {
183 for (i
=0;ws
[i
];i
++) {
190 *wpv
= (LPWSTR
*)xmalloc(sizeof(LPWSTR
)*(*wpc
+2));
198 #define FREE_KEY_PATH free(wps[0]);free(wps);
201 * Shell initialisation, allocates keys.
207 HKEY cl_r_hkey
,c_u_hkey
;
208 #define ADD_ROOT_KEY(xx) \
209 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
210 memset(xx,'\0',sizeof(KEYSTRUCT));\
211 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
213 ADD_ROOT_KEY(key_local_machine
);
214 if (RegCreateKey16(HKEY_LOCAL_MACHINE
,"\\SOFTWARE\\Classes",&cl_r_hkey
)!=ERROR_SUCCESS
) {
215 fprintf(stderr
,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
218 key_classes_root
= lookup_hkey(cl_r_hkey
);
220 ADD_ROOT_KEY(key_users
);
223 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
224 * (later, when a win32 registry editing tool becomes avail.)
226 while (pwd
=getpwent()) {
227 if (pwd
->pw_name
== NULL
)
229 RegCreateKey16(HKEY_USERS
,pwd
->pw_name
,&c_u_hkey
);
230 RegCloseKey(c_u_hkey
);
233 pwd
=getpwuid(getuid());
234 if (pwd
&& pwd
->pw_name
) {
235 RegCreateKey16(HKEY_USERS
,pwd
->pw_name
,&c_u_hkey
);
236 key_current_user
= lookup_hkey(c_u_hkey
);
238 ADD_ROOT_KEY(key_current_user
);
240 ADD_ROOT_KEY(key_performance_data
);
241 ADD_ROOT_KEY(key_current_config
);
242 ADD_ROOT_KEY(key_dyn_data
);
246 /************************ SAVE Registry Function ****************************/
248 #define REGISTRY_SAVE_VERSION 0x00000001
250 /* Registry saveformat:
251 * If you change it, increase above number by 1, which will flush
252 * old registry database files.
255 * "WINE REGISTRY Version %d"
259 * valuename=lastmodified,type,data
263 * keyname,valuename,stringdata:
264 * the usual ascii characters from 0x00-0xff (well, not 0x00)
265 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
266 * ( "=\\\t" escaped in \uXXXX form.)
270 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
272 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
273 * SaveOnlyUpdatedKeys=yes
276 _save_check_tainted(LPKEYSTRUCT lpkey
) {
281 if (lpkey
->flags
& REG_OPTION_TAINTED
)
286 if (_save_check_tainted(lpkey
->nextsub
)) {
287 lpkey
->flags
|= REG_OPTION_TAINTED
;
296 _save_USTRING(FILE *F
,LPWSTR wstr
,int escapeeq
) {
309 if (escapeeq
&& *s
=='=')
312 fputc(*s
,F
); /* if \\ than put it twice. */
314 fprintf(F
,"\\u%04x",*((unsigned short*)s
));
322 _savesubkey(FILE *F
,LPKEYSTRUCT lpkey
,int level
,int all
) {
328 if ( !(lpxkey
->flags
& REG_OPTION_VOLATILE
) &&
329 (all
|| (lpxkey
->flags
& REG_OPTION_TAINTED
))
331 for (tabs
=level
;tabs
--;)
333 _save_USTRING(F
,lpxkey
->keyname
,1);
335 for (i
=0;i
<lpxkey
->nrofvalues
;i
++) {
336 LPKEYVALUE val
=lpxkey
->values
+i
;
338 for (tabs
=level
+1;tabs
--;)
340 _save_USTRING(F
,val
->name
,0);
342 fprintf(F
,"%ld,%ld,",val
->type
,val
->lastmodified
);
343 if ((1<<val
->type
) & UNICONVMASK
)
344 _save_USTRING(F
,(LPWSTR
)val
->data
,0);
346 for (j
=0;j
<val
->len
;j
++)
347 fprintf(F
,"%02x",*((unsigned char*)val
->data
+j
));
350 /* descend recursively */
351 if (!_savesubkey(F
,lpxkey
->nextsub
,level
+1,all
))
360 _savesubreg(FILE *F
,LPKEYSTRUCT lpkey
,int all
) {
361 fprintf(F
,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION
);
362 _save_check_tainted(lpkey
->nextsub
);
363 return _savesubkey(F
,lpkey
->nextsub
,0,all
);
367 _savereg(LPKEYSTRUCT lpkey
,char *fn
,int all
) {
372 fprintf(stddeb
,__FILE__
":_savereg:Couldn't open %s for writing: %s\n",
377 if (!_savesubreg(F
,lpkey
,all
)) {
380 fprintf(stddeb
,__FILE__
":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn
);
387 SHELL_SaveRegistry() {
395 if (RegOpenKey16(HKEY_CURRENT_USER
,KEY_REGISTRY
,&hkey
)!=ERROR_SUCCESS
) {
401 if ( (ERROR_SUCCESS
!=RegQueryValueEx32A(
413 if (strcasecmp(buf
,"yes"))
415 pwd
=getpwuid(getuid());
416 if (pwd
!=NULL
&& pwd
->pw_dir
!=NULL
) {
417 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_USERS_DEFAULT
)+2);
418 strcpy(fn
,pwd
->pw_dir
);
419 strcat(fn
,WINE_PREFIX
);
420 /* create the directory. don't care about errorcodes. */
421 mkdir(fn
,0755); /* drwxr-xr-x */
422 strcat(fn
,"/"SAVE_CURRENT_USER
);
423 _savereg(key_current_user
,fn
,all
);
425 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_LOCAL_MACHINE
)+2);
426 strcpy(fn
,pwd
->pw_dir
);
427 strcat(fn
,WINE_PREFIX
"/"SAVE_LOCAL_MACHINE
);
428 _savereg(key_local_machine
,fn
,all
);
431 fprintf(stderr
,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
434 /************************ LOAD Registry Function ****************************/
437 _find_or_add_key(LPKEYSTRUCT lpkey
,LPWSTR keyname
) {
438 LPKEYSTRUCT lpxkey
,*lplpkey
;
440 lplpkey
= &(lpkey
->nextsub
);
443 if (!strcmpW(lpxkey
->keyname
,keyname
))
445 lplpkey
= &(lpxkey
->next
);
449 *lplpkey
= (LPKEYSTRUCT
)xmalloc(sizeof(KEYSTRUCT
));
451 memset(lpxkey
,'\0',sizeof(KEYSTRUCT
));
452 lpxkey
->keyname
= keyname
;
460 LPKEYSTRUCT lpkey
,LPWSTR name
,DWORD type
,LPBYTE data
,DWORD len
,
466 for (i
=0;i
<lpkey
->nrofvalues
;i
++) {
472 if ( val
->name
!=NULL
&&
473 !strcmpW(val
->name
,name
)
478 if (i
==lpkey
->nrofvalues
) {
479 lpkey
->values
= xrealloc(
481 (++lpkey
->nrofvalues
)*sizeof(KEYVALUE
)
484 memset(val
,'\0',sizeof(KEYVALUE
));
490 if (val
->lastmodified
<lastmodified
) {
491 val
->lastmodified
=lastmodified
;
502 /* reads a line including dynamically enlarging the readbuffer and throwing
506 _wine_read_line(FILE *F
,char **buf
,int *len
) {
515 s
=fgets(curread
,mylen
,F
);
518 if (NULL
==(s
=strchr(curread
,'\n'))) {
519 /* buffer wasn't large enough */
520 curoff
= strlen(*buf
);
521 *buf
= xrealloc(*buf
,*len
*2);
522 curread
= *buf
+ curoff
;
523 mylen
= *len
; /* we filled up the buffer and
524 * got new '*len' bytes to fill
532 /* throw away comments */
533 if (**buf
=='#' || **buf
==';') {
538 if (s
) /* got end of line */
544 /* converts a char* into a UNICODE string (up to a special char)
545 * and returns the position exactly after that string
548 _wine_read_USTRING(char *buf
,LPWSTR
*str
) {
552 /* read up to "=" or "\0" or "\n" */
555 /* empty string is the win3.1 default value(NULL)*/
559 *str
= (LPWSTR
)xmalloc(2*strlen(buf
)+2);
561 while (*s
&& (*s
!='\n') && (*s
!='=')) {
563 *ws
++=*((unsigned char*)s
++);
572 fprintf(stderr
,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s
,buf
);
580 memcpy(xbuf
,s
,4);xbuf
[4]='\0';
581 if (!sscanf(xbuf
,"%x",&wc
))
582 fprintf(stderr
,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf
,buf
);
584 *ws
++ =(unsigned short)wc
;
590 *str
= strdupW(*str
);
597 FILE *F
,LPKEYSTRUCT lpkey
,int level
,char **buf
,int *buflen
,int optflag
604 lpkey
->flags
|= optflag
;
606 /* good. we already got a line here ... so parse it */
616 fprintf(stderr
,"_load_subkey:Got a subhierarchy without resp. key?\n");
619 _wine_loadsubkey(F
,lpxkey
,level
+1,buf
,buflen
,optflag
);
622 /* let the caller handle this line */
623 if (i
<level
|| **buf
=='\0')
626 /* it can be: a value or a keyname. Parse the name first */
627 s
=_wine_read_USTRING(s
,&name
);
629 /* switch() default: hack to avoid gotos */
633 lpxkey
=_find_or_add_key(lpkey
,name
);
636 int len
,lastmodified
,type
;
639 fprintf(stderr
,"_wine_load_subkey:unexpected character: %c\n",*s
);
643 if (2!=sscanf(s
,"%d,%d,",&type
,&lastmodified
)) {
644 fprintf(stderr
,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf
);
650 if ((1<<type
) & UNICONVMASK
) {
651 s
=_wine_read_USTRING(s
,(LPWSTR
*)&data
);
653 len
= strlenW((LPWSTR
)data
)*2+2;
658 data
= (LPBYTE
)xmalloc(len
+1);
659 for (i
=0;i
<len
;i
++) {
661 if (*s
>='0' && *s
<='9')
663 if (*s
>='a' && *s
<='f')
665 if (*s
>='A' && *s
<='F')
668 if (*s
>='0' && *s
<='9')
670 if (*s
>='a' && *s
<='f')
672 if (*s
>='A' && *s
<='F')
677 _find_or_add_value(lpkey
,name
,type
,data
,len
,lastmodified
);
680 /* read the next line */
681 if (!_wine_read_line(F
,buf
,buflen
))
688 _wine_loadsubreg(FILE *F
,LPKEYSTRUCT lpkey
,int optflag
) {
693 buf
=xmalloc(10);buflen
=10;
694 if (!_wine_read_line(F
,&buf
,&buflen
)) {
698 if (!sscanf(buf
,"WINE REGISTRY Version %d",&ver
)) {
702 if (ver
!=REGISTRY_SAVE_VERSION
) {
703 dprintf_reg(stddeb
,__FILE__
":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver
,buf
);
707 if (!_wine_read_line(F
,&buf
,&buflen
)) {
711 if (!_wine_loadsubkey(F
,lpkey
,0,&buf
,&buflen
,optflag
)) {
720 _wine_loadreg(LPKEYSTRUCT lpkey
,char *fn
,int optflag
) {
725 dprintf_reg(stddeb
,__FILE__
":Couldn't open %s for reading: %s\n",
730 if (!_wine_loadsubreg(F
,lpkey
,optflag
)) {
739 _copy_registry(LPKEYSTRUCT from
,LPKEYSTRUCT to
) {
746 lpxkey
= _find_or_add_key(to
,strdupW(from
->keyname
));
748 for (j
=0;j
<from
->nrofvalues
;j
++) {
752 valfrom
= from
->values
+j
;
754 if (name
) name
=strdupW(name
);
755 data
=(LPBYTE
)malloc(valfrom
->len
);
756 memcpy(data
,valfrom
->data
,valfrom
->len
);
764 valfrom
->lastmodified
767 _copy_registry(from
,lpxkey
);
772 /* WINDOWS 95 REGISTRY LOADER */
774 * Structure of a win95 registry database.
778 * 8 : DWORD offset_of_RGDB_part
779 * 0C..1F: ? (someone fill in please)
784 * 4..0x1B: ? (fill in)
785 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
787 * Disk Key Entry Structure:
788 * 00: DWORD - unknown
789 * 04: DWORD - unknown
790 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
791 * 0C: DWORD - disk address of PreviousLevel Key.
792 * 10: DWORD - disk address of Next Sublevel Key.
793 * 14: DWORD - disk address of Next Key (on same level).
794 * DKEP>18: WORD - Nr, Low Significant part.
795 * 1A: WORD - Nr, High Significant part.
797 * The disk address always points to the nr part of the previous key entry
798 * of the referenced key. Don't ask me why, or even if I got this correct
799 * from staring at 1kg of hexdumps. (DKEP)
801 * The number of the entry is the low byte of the Low Significant Part ored
802 * with 0x100 * (low byte of the High Significant part)
803 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
805 * There are two minor corrections to the position of that structure.
806 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
807 * the DKE reread from there.
808 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
809 * (FIXME: slightly better explanation needed here)
813 * 04: DWORD offset to next RGDB section (perhaps WORD)
818 * 00: DWORD nextkeyoffset - offset to the next disk key structure
819 * 08: WORD nrLS - low significant part of NR
820 * 0A: WORD nrHS - high significant part of NR
821 * 0C: DWORD bytesused - bytes used in this structure.
822 * 10: WORD name_len - length of name in bytes. without \0
823 * 12: WORD nr_of_values - number of values.
824 * 14: char name[name_len] - name string. No \0.
825 * 14+name_len: disk values
826 * nextkeyoffset: ... next disk key
829 * 00: DWORD type - value type (hmm, could be WORD too)
830 * 04: DWORD - unknown, usually 0
831 * 08: WORD namelen - length of Name. 0 means name=NULL
832 * 0C: WORD datalen - length of Data.
833 * 10: char name[namelen] - name, no \0
834 * 10+namelen: BYTE data[datalen] - data, without \0 if string
835 * 10+namelen+datalen: next values or disk key
837 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
838 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
839 * structure) and reading another RGDB_section.
840 * repeat until end of file.
842 * FIXME: this description needs some serious help, yes.
845 struct _w95keyvalue
{
847 unsigned short datalen
;
857 struct _w95keyvalue
*values
;
858 unsigned long dkeaddr
;
863 struct _w95key
*prevlvl
;
864 struct _w95key
*nextsub
;
865 struct _w95key
*next
;
868 /* fast lookup table dkeaddr->nr */
870 unsigned long dkeaddr
;
876 _w95_walk_tree(LPKEYSTRUCT lpkey
,struct _w95key
*key
) {
882 if (key
->name
== NULL
) {
883 fprintf(stderr
,"key with dkeaddr %lx not loaded, skipping hierarchy\n",
889 lpxkey
=_find_or_add_key(lpkey
,strdupA2W(key
->name
));
891 if (key
->nrofvals
<0) {
892 /* shouldn't happen */
893 fprintf(stderr
,"key %s already processed!\n",key
->name
);
897 for (i
=0;i
<key
->nrofvals
;i
++) {
901 name
= strdupA2W(key
->values
[i
].name
);
902 if (!*name
) name
= NULL
;
903 free(key
->values
[i
].name
);
905 len
= key
->values
[i
].datalen
;
906 data
= key
->values
[i
].data
;
907 if ((1<<key
->values
[i
].type
) & UNICONVMASK
) {
908 data
= (BYTE
*)strdupA2W(data
);
909 len
= strlenW((LPWSTR
)data
)*2+2;
910 free(key
->values
[i
].data
);
918 key
->values
[i
].lastmodified
925 key
->nrofvals
=-key
->nrofvals
-1;
926 _w95_walk_tree(lpxkey
,key
->nextsub
);
931 /* small helper function to adjust address offset (dkeaddrs) */
933 _w95_adj_da(unsigned long dkeaddr
) {
934 if ((dkeaddr
&0xFFF)<0x018) {
937 diff
=0x1C-(dkeaddr
&0xFFF);
940 if (((dkeaddr
+0x1C)&0xFFF)<0x1C) {
941 /* readjust to 0x000,
942 * but ONLY if we are >0x1000 already
944 if (dkeaddr
& ~0xFFF)
945 return dkeaddr
& ~0xFFF;
951 _w95dkecomp(struct _w95nr2da
*a
,struct _w95nr2da
*b
){return a
->dkeaddr
-b
->dkeaddr
;}
953 static struct _w95key
*
954 _w95dkelookup(unsigned long dkeaddr
,int n
,struct _w95nr2da
*nr2da
,struct _w95key
*keys
) {
957 if (dkeaddr
== 0xFFFFFFFF)
961 dkeaddr
=_w95_adj_da(dkeaddr
+0x1c);
962 off
= (dkeaddr
-0x3c)/0x1c;
964 if (nr2da
[(i
+off
)%n
].dkeaddr
== dkeaddr
)
965 return keys
+nr2da
[(i
+off
)%n
].nr
;
966 fprintf(stderr
,"search didn't found dkeaddr %lx?\n",dkeaddr
);
971 _w95_loadreg(char* fn
,LPKEYSTRUCT lpkey
) {
972 /* Disk Key Entry structure (RGKN part) */
976 unsigned long x3
;/*usually 0xFFFFFFFF */
977 unsigned long prevlvl
;
978 unsigned long nextsub
;
983 /* Disk Key Header structure (RGDB part) */
985 unsigned long nextkeyoff
;
988 unsigned long bytesused
;
989 unsigned short keynamelen
;
990 unsigned short values
;
993 /* disk key values or nothing */
995 /* Disk Key Value structure */
999 unsigned short valnamelen
;
1000 unsigned short valdatalen
;
1001 /* valname, valdata */
1003 struct _w95nr2da
*nr2da
;
1006 int fd
,lastmodified
;
1008 unsigned long nr
,pos
,i
,where
,version
,rgdbsection
,end
,off_next_rgdb
;
1009 struct _w95key
*keys
;
1011 unsigned char *data
,*curdata
,*nextrgdb
;
1015 dprintf_reg(stddeb
,"Loading Win95 registry database '%s'\n",fn
);
1016 hfd
=OpenFile(fn
,&ofs
,OF_READ
);
1017 if (hfd
==HFILE_ERROR
)
1019 fd
= FILE_GetUnixHandle(hfd
);
1021 if (4!=read(fd
,magic
,4))
1023 if (strcmp(magic
,"CREG")) {
1024 fprintf(stddeb
,"%s is not a w95 registry.\n",fn
);
1027 if (4!=read(fd
,&version
,4))
1029 if (4!=read(fd
,&rgdbsection
,4))
1031 if (-1==lseek(fd
,0x20,SEEK_SET
))
1033 if (4!=read(fd
,magic
,4))
1035 if (strcmp(magic
,"RGKN")) {
1036 dprintf_reg(stddeb
,"second IFF header not RGKN, but %s\n",magic
);
1040 /* STEP 1: Keylink structures */
1041 if (-1==lseek(fd
,0x40,SEEK_SET
))
1046 nrofdkes
= (end
-where
)/sizeof(struct dke
);
1047 data
= (char*)xmalloc(end
-where
);
1048 if ((end
-where
)!=read(fd
,data
,end
-where
))
1052 keys
= (struct _w95key
*)xmalloc(nrofdkes
* sizeof(struct _w95key
));
1053 memset(keys
,'\0',nrofdkes
*sizeof(struct _w95key
));
1054 nr2da
= (struct _w95nr2da
*)xmalloc(nrofdkes
* sizeof(struct _w95nr2da
));
1056 for (i
=0;i
<nrofdkes
;i
++) {
1058 unsigned long dkeaddr
;
1060 pos
=curdata
-data
+0x40;
1061 memcpy(&dke
,curdata
,sizeof(dke
));
1062 curdata
+=sizeof(dke
);
1063 nr
= dke
.nrLS
+ (dke
.nrMS
<<8);
1065 if ((dkeaddr
&0xFFF)<0x018) {
1068 diff
=0x1C-(dkeaddr
&0xFFF);
1070 curdata
+=diff
-sizeof(dke
);
1071 memcpy(&dke
,curdata
,sizeof(dke
));
1072 nr
= dke
.nrLS
+ (dke
.nrMS
<<8);
1073 curdata
+=sizeof(dke
);
1075 if (((dkeaddr
+0x1C)&0xFFF)<0x1C) {
1076 /* readjust to 0x000,
1077 * but ONLY if we are >0x1000 already
1079 if (dkeaddr
& ~0xFFF)
1080 dkeaddr
= dkeaddr
& ~0xFFF;
1083 dprintf_reg(stddeb
,"nr %ld exceeds nrofdkes %d, skipping.\n",nr
,nrofdkes
);
1086 if (keys
[nr
].dkeaddr
) {
1089 for (x
=sizeof(dke
);x
--;)
1090 if (((char*)&dke
)[x
])
1093 break; /* finished reading if we got only 0 */
1095 dprintf_reg(stddeb
,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr
,keys
[nr
].dkeaddr
,dkeaddr
);
1099 nr2da
[i
].dkeaddr
= dkeaddr
;
1101 keys
[nr
].dkeaddr
= dkeaddr
;
1102 keys
[nr
].x1
= dke
.x1
;
1103 keys
[nr
].x2
= dke
.x2
;
1104 keys
[nr
].x3
= dke
.x3
;
1105 keys
[nr
].prevlvl
= (struct _w95key
*)dke
.prevlvl
;
1106 keys
[nr
].nextsub
= (struct _w95key
*)dke
.nextsub
;
1107 keys
[nr
].next
= (struct _w95key
*)dke
.next
;
1111 qsort(nr2da
,nrofdkes
,sizeof(nr2da
[0]),_w95dkecomp
);
1113 /* STEP 2: keydata & values */
1114 if (-1==fstat(fd
,&stbuf
))
1116 end
= stbuf
.st_size
;
1117 lastmodified
= stbuf
.st_mtime
;
1119 if (-1==lseek(fd
,rgdbsection
,SEEK_SET
))
1121 data
= (char*)xmalloc(end
-rgdbsection
);
1122 if ((end
-rgdbsection
)!=read(fd
,data
,end
-rgdbsection
))
1126 memcpy(magic
,curdata
,4);
1127 memcpy(&off_next_rgdb
,curdata
+4,4);
1128 nextrgdb
= curdata
+off_next_rgdb
;
1129 if (strcmp(magic
,"RGDB")) {
1130 dprintf_reg(stddeb
,"third IFF header not RGDB, but %s\n",magic
);
1137 struct _w95key
*key
,xkey
;
1140 if (curdata
>=nextrgdb
) {
1142 if (!strncmp(curdata
,"RGDB",4)) {
1143 memcpy(&off_next_rgdb
,curdata
+4,4);
1144 nextrgdb
= curdata
+off_next_rgdb
;
1147 dprintf_reg(stddeb
,"at end of RGDB section, but no next header. Breaking.\n");
1151 #define XREAD(whereto,len) \
1152 if ((curdata-data+len)<end) {\
1153 memcpy(whereto,curdata,len);\
1158 XREAD(&dkh
,sizeof(dkh
));
1159 nr
= dkh
.nrLS
+ (dkh
.nrMS
<<8);
1161 if (dkh
.nrLS
== 0xFFFF) {
1162 curdata
+= dkh
.nextkeyoff
- bytesread
;
1164 if (strcmp(magic
,"RGDB")) {
1165 if ((curdata
-data
)<end
)
1166 dprintf_reg(stddeb
,"while skipping to next RGDB block found magic %s\n",magic
);
1172 if (dkh
.nrLS
== 0xFFFE) {
1173 dprintf_reg(stddeb
,"0xFFFE at %x\n",curdata
-data
);
1176 dprintf_reg(stddeb
,"haven't found nr %ld.\n",nr
);
1178 memset(key
,'\0',sizeof(xkey
));
1182 dprintf_reg(stddeb
,"key with nr=%ld has no dkeaddr?\n",nr
);
1184 key
->nrofvals
= dkh
.values
;
1185 key
->name
= (char*)xmalloc(dkh
.keynamelen
+1);
1187 XREAD(key
->name
,dkh
.keynamelen
);
1188 key
->name
[dkh
.keynamelen
]=0;
1189 if (key
->nrofvals
) {
1190 key
->values
= (struct _w95keyvalue
*)xmalloc(
1191 sizeof(struct _w95keyvalue
)*key
->nrofvals
1193 for (i
=0;i
<key
->nrofvals
;i
++) {
1196 XREAD(&dkv
,sizeof(dkv
));
1197 key
->values
[i
].type
= dkv
.type
;
1198 key
->values
[i
].name
= (char*)xmalloc(
1201 key
->values
[i
].datalen
= dkv
.valdatalen
;
1202 key
->values
[i
].data
= (unsigned char*)xmalloc(
1205 key
->values
[i
].x1
= dkv
.x1
;
1206 XREAD(key
->values
[i
].name
,dkv
.valnamelen
);
1207 XREAD(key
->values
[i
].data
,dkv
.valdatalen
);
1208 key
->values
[i
].data
[dkv
.valdatalen
]=0;
1209 key
->values
[i
].name
[dkv
.valnamelen
]=0;
1210 key
->values
[i
].lastmodified
=lastmodified
;
1213 if (bytesread
!= dkh
.nextkeyoff
) {
1214 if (dkh
.bytesused
!= bytesread
)
1216 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread
,dkh
.nextkeyoff
,
1219 curdata
+= dkh
.nextkeyoff
-bytesread
;
1221 key
->prevlvl
= _w95dkelookup((long)key
->prevlvl
,nrofdkes
,nr2da
,keys
);
1222 key
->nextsub
= _w95dkelookup((long)key
->nextsub
,nrofdkes
,nr2da
,keys
);
1223 key
->next
= _w95dkelookup((long)key
->next
,nrofdkes
,nr2da
,keys
);
1228 _w95_walk_tree(lpkey
,keys
);
1233 SHELL_LoadRegistry() {
1240 if (key_classes_root
==NULL
)
1243 /* Load windows 95 entries */
1244 _w95_loadreg("C:\\system.1st", key_local_machine
);
1245 _w95_loadreg("system.dat", key_local_machine
);
1246 _w95_loadreg("user.dat", key_users
);
1248 /* FIXME: win3.1 reg.dat loader still missing */
1250 /* the global user default is loaded under HKEY_USERS\\.Default */
1251 RegCreateKey16(HKEY_USERS
,".Default",&hkey
);
1252 lpkey
= lookup_hkey(hkey
);
1253 _wine_loadreg(lpkey
,SAVE_USERS_DEFAULT
,0);
1255 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1256 _copy_registry(lpkey
,key_current_user
);
1259 /* the global machine defaults */
1260 _wine_loadreg(key_local_machine
,SAVE_LOCAL_MACHINE_DEFAULT
,0);
1262 /* load the user saved registries */
1264 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1266 pwd
=getpwuid(getuid());
1267 if (pwd
!=NULL
&& pwd
->pw_dir
!=NULL
) {
1268 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_CURRENT_USER
)+2);
1269 strcpy(fn
,pwd
->pw_dir
);
1270 strcat(fn
,WINE_PREFIX
"/"SAVE_CURRENT_USER
);
1271 _wine_loadreg(key_current_user
,fn
,REG_OPTION_TAINTED
);
1273 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_LOCAL_MACHINE
)+2);
1274 strcpy(fn
,pwd
->pw_dir
);
1275 strcat(fn
,WINE_PREFIX
"/"SAVE_LOCAL_MACHINE
);
1276 _wine_loadreg(key_local_machine
,fn
,REG_OPTION_TAINTED
);
1279 fprintf(stderr
,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1280 if (ERROR_SUCCESS
==RegCreateKey16(HKEY_CURRENT_USER
,KEY_REGISTRY
,&hkey
)) {
1281 DWORD junk
,type
,len
;
1285 if (( RegQueryValueEx32A(
1292 )!=ERROR_SUCCESS
) ||
1295 RegSetValueEx32A(hkey
,VAL_SAVEUPDATED
,0,REG_SZ
,"yes",4);
1301 /********************* API FUNCTIONS ***************************************/
1305 * All functions are stubs to RegOpenKeyEx32W where all the
1308 * FIXME: security,options,desiredaccess,...
1311 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1312 * RegOpenKey32W -> RegOpenKeyEx32W
1315 /* RegOpenKeyExW [ADVAPI32.150] */
1316 DWORD
RegOpenKeyEx32W(
1323 LPKEYSTRUCT lpNextKey
,lpxkey
;
1326 dprintf_reg(stddeb
,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1327 (LONG
)hkey
,W2C(lpszSubKey
,0),dwReserved
,samDesired
,retkey
1330 lpNextKey
= lookup_hkey(hkey
);
1332 return SHELL_ERROR_BADKEY
;
1333 if (!lpszSubKey
|| !*lpszSubKey
) {
1334 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1335 *retkey
=currenthandle
;
1336 return SHELL_ERROR_SUCCESS
;
1338 split_keypath(lpszSubKey
,&wps
,&wpc
);
1340 while ((i
<wpc
) && (wps
[i
][0]=='\0')) i
++;
1343 lpxkey
=lpNextKey
->nextsub
;
1345 if (!strcmpW(wps
[i
],lpxkey
->keyname
))
1347 lpxkey
=lpxkey
->next
;
1351 return SHELL_ERROR_BADKEY
;
1356 add_handle(++currenthandle
,lpxkey
,samDesired
);
1357 *retkey
= currenthandle
;
1359 return SHELL_ERROR_SUCCESS
;
1362 /* RegOpenKeyW [ADVAPI32.151] */
1363 DWORD
RegOpenKey32W(
1368 dprintf_reg(stddeb
,"RegOpenKey32W(%lx,%s,%p)\n",
1369 (LONG
)hkey
,W2C(lpszSubKey
,0),retkey
1371 return RegOpenKeyEx32W(hkey
,lpszSubKey
,0,KEY_ALL_ACCESS
,retkey
);
1375 /* RegOpenKeyExA [ADVAPI32.149] */
1376 DWORD
RegOpenKeyEx32A(
1386 dprintf_reg(stddeb
,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1387 (LONG
)hkey
,lpszSubKey
,dwReserved
,samDesired
,retkey
1390 lpszSubKeyW
=strdupA2W(lpszSubKey
);
1393 ret
=RegOpenKeyEx32W(hkey
,lpszSubKeyW
,dwReserved
,samDesired
,retkey
);
1399 /* RegOpenKeyA [ADVAPI32.148] */
1400 DWORD
RegOpenKey32A(
1405 dprintf_reg(stddeb
,"RegOpenKey32A(%lx,%s,%p)\n",
1406 (LONG
)hkey
,lpszSubKey
,retkey
1408 return RegOpenKeyEx32A(hkey
,lpszSubKey
,0,KEY_ALL_ACCESS
,retkey
);
1411 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1417 dprintf_reg(stddeb
,"RegOpenKey16(%lx,%s,%p)\n",
1418 (LONG
)hkey
,lpszSubKey
,retkey
1420 return RegOpenKey32A(hkey
,lpszSubKey
,retkey
);
1426 * All those functions convert their respective
1427 * arguments and call RegCreateKeyExW at the end.
1429 * FIXME: no security,no access attrib,no optionhandling yet.
1432 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1433 * RegCreateKey32W -> RegCreateKeyEx32W
1436 /* RegCreateKeyExW [ADVAPI32.131] */
1437 DWORD
RegCreateKeyEx32W(
1444 LPSECURITY_ATTRIBUTES lpSecAttribs
,
1448 LPKEYSTRUCT
*lplpPrevKey
,lpNextKey
,lpxkey
;
1452 /*FIXME: handle security/access/whatever */
1453 dprintf_reg(stddeb
,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1465 lpNextKey
= lookup_hkey(hkey
);
1467 return SHELL_ERROR_BADKEY
;
1468 if (!lpszSubKey
|| !*lpszSubKey
) {
1469 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1470 *retkey
=currenthandle
;
1471 return SHELL_ERROR_SUCCESS
;
1473 split_keypath(lpszSubKey
,&wps
,&wpc
);
1475 while ((i
<wpc
) && (wps
[i
][0]=='\0')) i
++;
1478 lpxkey
=lpNextKey
->nextsub
;
1480 if (!strcmpW(wps
[i
],lpxkey
->keyname
))
1482 lpxkey
=lpxkey
->next
;
1490 add_handle(++currenthandle
,lpxkey
,samDesired
);
1491 *retkey
= currenthandle
;
1492 *lpDispos
= REG_OPENED_EXISTING_KEY
;
1494 return SHELL_ERROR_SUCCESS
;
1496 /* good. now the hard part */
1498 lplpPrevKey
= &(lpNextKey
->nextsub
);
1499 lpxkey
= *lplpPrevKey
;
1501 lplpPrevKey
= &(lpxkey
->next
);
1502 lpxkey
= *lplpPrevKey
;
1504 *lplpPrevKey
=malloc(sizeof(KEYSTRUCT
));
1505 if (!*lplpPrevKey
) {
1507 return SHELL_ERROR_OUTOFMEMORY
;
1509 memset(*lplpPrevKey
,'\0',sizeof(KEYSTRUCT
));
1510 (*lplpPrevKey
)->keyname
= strdupW(wps
[i
]);
1511 (*lplpPrevKey
)->next
= NULL
;
1512 (*lplpPrevKey
)->nextsub
= NULL
;
1513 (*lplpPrevKey
)->values
= NULL
;
1514 (*lplpPrevKey
)->nrofvalues
= 0;
1516 (*lplpPrevKey
)->class = strdupW(lpszClass
);
1518 (*lplpPrevKey
)->class = NULL
;
1519 lpNextKey
= *lplpPrevKey
;
1522 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1524 /*FIXME: flag handling correct? */
1525 lpNextKey
->flags
= fdwOptions
;
1527 lpNextKey
->class = strdupW(lpszClass
);
1529 lpNextKey
->class = NULL
;
1530 lpNextKey
->flags
|=REG_OPTION_TAINTED
;
1531 *retkey
= currenthandle
;
1532 *lpDispos
= REG_CREATED_NEW_KEY
;
1534 return SHELL_ERROR_SUCCESS
;
1537 /* RegCreateKeyW [ADVAPI32.132] */
1538 DWORD
RegCreateKey32W(
1545 dprintf_reg(stddeb
,"RegCreateKey32W(%lx,%s,%p)\n",
1546 (LONG
)hkey
,W2C(lpszSubKey
,0),retkey
1548 ret
=RegCreateKeyEx32W(
1549 hkey
, /* key handle */
1550 lpszSubKey
, /* subkey name */
1551 0, /* reserved = 0 */
1552 NULL
, /* lpszClass? FIXME: ? */
1553 REG_OPTION_NON_VOLATILE
, /* options */
1554 KEY_ALL_ACCESS
, /* desired access attribs */
1555 NULL
, /* lpsecurity attributes */
1556 retkey
, /* lpretkey */
1557 &junk
/* disposition value */
1562 /* RegCreateKeyExA [ADVAPI32.130] */
1563 DWORD
RegCreateKeyEx32A(
1570 LPSECURITY_ATTRIBUTES lpSecAttribs
,
1574 LPWSTR lpszSubKeyW
,lpszClassW
;
1577 dprintf_reg(stddeb
,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1589 lpszSubKeyW
=strdupA2W(lpszSubKey
);
1593 lpszClassW
=strdupA2W(lpszClass
);
1596 ret
=RegCreateKeyEx32W(
1614 /* RegCreateKeyA [ADVAPI32.129] */
1615 DWORD
RegCreateKey32A(
1622 dprintf_reg(stddeb
,"RegCreateKey32A(%lx,%s,%p)\n",
1623 (LONG
)hkey
,lpszSubKey
,retkey
1625 return RegCreateKeyEx32A(
1626 hkey
, /* key handle */
1627 lpszSubKey
, /* subkey name */
1628 0, /* reserved = 0 */
1629 NULL
, /* lpszClass? FIXME: ? */
1630 REG_OPTION_NON_VOLATILE
,/* options */
1631 KEY_ALL_ACCESS
, /* desired access attribs */
1632 NULL
, /* lpsecurity attributes */
1633 retkey
, /* lpretkey */
1634 &junk
/* disposition value */
1638 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1639 DWORD
RegCreateKey16(
1644 dprintf_reg(stddeb
,"RegCreateKey16(%lx,%s,%p)\n",
1645 (LONG
)hkey
,lpszSubKey
,retkey
1647 return RegCreateKey32A(hkey
,lpszSubKey
,retkey
);
1651 * Query Value Functions
1652 * Win32 differs between keynames and valuenames.
1653 * multiple values may belong to one key, the special value
1654 * with name NULL is the default value used by the win31
1658 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1659 * RegQueryValue32W -> RegQueryValueEx32W
1662 /* RegQueryValueExW [ADVAPI32.158] */
1663 DWORD
RegQueryValueEx32W(
1665 LPWSTR lpszValueName
,
1666 LPDWORD lpdwReserved
,
1674 dprintf_reg(stddeb
,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%p)\n",
1675 hkey
,W2C(lpszValueName
,0),lpdwReserved
,lpdwType
,lpbData
,lpcbData
1678 lpkey
= lookup_hkey(hkey
);
1680 return SHELL_ERROR_BADKEY
;
1681 if (lpszValueName
==NULL
) {
1682 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
1683 if (lpkey
->values
[i
].name
==NULL
)
1686 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
1687 if (!strcmpW(lpszValueName
,lpkey
->values
[i
].name
))
1690 if (i
==lpkey
->nrofvalues
) {
1691 if (lpszValueName
==NULL
) {
1692 *(WCHAR
*)lpbData
= 0;
1695 return SHELL_ERROR_SUCCESS
;
1697 return SHELL_ERROR_BADKEY
;/*FIXME: correct return? */
1700 *lpdwType
= lpkey
->values
[i
].type
;
1701 if (lpbData
==NULL
) {
1703 return SHELL_ERROR_SUCCESS
;
1704 *lpcbData
= lpkey
->values
[i
].len
;
1705 return SHELL_ERROR_SUCCESS
;
1707 if (*lpcbData
<lpkey
->values
[i
].len
) {
1710 *lpcbData
= lpkey
->values
[i
].len
;
1711 return ERROR_MORE_DATA
;
1713 memcpy(lpbData
,lpkey
->values
[i
].data
,lpkey
->values
[i
].len
);
1714 *lpcbData
= lpkey
->values
[i
].len
;
1715 return SHELL_ERROR_SUCCESS
;
1718 /* RegQueryValueW [ADVAPI32.159] */
1719 DWORD
RegQueryValue32W(
1728 dprintf_reg(stddeb
,"RegQueryValue32W(%x,%s,%p,%p)\n->",
1729 hkey
,W2C(lpszSubKey
,0),lpszData
,lpcbData
1732 /* only open subkey, if we really do descend */
1733 if (lpszSubKey
&& *lpszSubKey
) {
1734 ret
= RegOpenKey32W(hkey
,lpszSubKey
,&xhkey
);
1735 if (ret
!=ERROR_SUCCESS
)
1741 ret
= RegQueryValueEx32W(
1743 NULL
, /* varname NULL -> compat */
1744 NULL
, /* lpdwReserved, must be NULL */
1754 /* RegQueryValueExA [ADVAPI32.157] */
1755 DWORD
RegQueryValueEx32A(
1757 LPSTR lpszValueName
,
1758 LPDWORD lpdwReserved
,
1763 LPWSTR lpszValueNameW
;
1768 dprintf_reg(stddeb
,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%p)\n->",
1769 hkey
,lpszValueName
,lpdwReserved
,lpdwType
,lpbData
,lpcbData
1773 buf
= (LPBYTE
)xmalloc((*lpcbData
)*2);
1774 myxlen
= *lpcbData
*2;
1779 myxlen
= *lpcbData
*2;
1785 lpszValueNameW
=strdupA2W(lpszValueName
);
1787 lpszValueNameW
=NULL
;
1789 ret
=RegQueryValueEx32W(
1798 if (ret
==ERROR_SUCCESS
) {
1800 if (UNICONVMASK
& (1<<(*lpdwType
))) {
1801 /* convert UNICODE to ASCII */
1802 strcpyWA(lpbData
,(LPWSTR
)buf
);
1803 *lpcbData
= myxlen
/2;
1805 if (myxlen
>*lpcbData
)
1806 ret
= ERROR_MORE_DATA
;
1808 memcpy(lpbData
,buf
,myxlen
);
1813 if ((UNICONVMASK
& (1<<(*lpdwType
))) && lpcbData
)
1814 *lpcbData
= myxlen
/2;
1817 if ((UNICONVMASK
& (1<<(*lpdwType
))) && lpcbData
)
1818 *lpcbData
= myxlen
/2;
1825 /* RegQueryValueEx [KERNEL.225] */
1826 DWORD
RegQueryValueEx16(
1828 LPSTR lpszValueName
,
1829 LPDWORD lpdwReserved
,
1834 dprintf_reg(stddeb
,"RegQueryValueEx16(%x,%s,%p,%p,%p,%p)\n",
1835 hkey
,lpszValueName
,lpdwReserved
,lpdwType
,lpbData
,lpcbData
1837 return RegQueryValueEx32A(
1847 /* RegQueryValueA [ADVAPI32.156] */
1848 DWORD
RegQueryValue32A(
1857 dprintf_reg(stddeb
,"RegQueryValue32A(%x,%s,%p,%p)\n",
1858 hkey
,lpszSubKey
,lpszData
,lpcbData
1861 /* only open subkey, if we really do descend */
1862 if (lpszSubKey
&& *lpszSubKey
) {
1863 ret
= RegOpenKey16(hkey
,lpszSubKey
,&xhkey
);
1864 if (ret
!=ERROR_SUCCESS
)
1870 ret
= RegQueryValueEx32A(
1872 NULL
, /* lpszValueName NULL -> compat */
1873 NULL
, /* lpdwReserved, must be NULL */
1883 /* RegQueryValue [SHELL.6] [KERNEL.224] */
1884 DWORD
RegQueryValue16(
1890 dprintf_reg(stddeb
,"RegQueryValue16(%x,%s,%p,%p)\n",
1891 hkey
,lpszSubKey
,lpszData
,lpcbData
1893 return RegQueryValue32A(hkey
,lpszSubKey
,lpszData
,lpcbData
);
1897 * Setting values of Registry keys
1900 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
1901 * RegSetValue32W -> RegSetValueEx32W
1904 /* RegSetValueExW [ADVAPI32.170] */
1905 DWORD
RegSetValueEx32W(
1907 LPWSTR lpszValueName
,
1916 dprintf_reg(stddeb
,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
1917 hkey
,W2C(lpszValueName
,0),dwReserved
,dwType
,lpbData
,cbData
1919 /* we no longer care about the lpbData type here... */
1920 lpkey
= lookup_hkey(hkey
);
1922 return SHELL_ERROR_BADKEY
;
1924 lpkey
->flags
|= REG_OPTION_TAINTED
;
1926 if (lpszValueName
==NULL
) {
1927 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
1928 if (lpkey
->values
[i
].name
==NULL
)
1931 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
1932 if (!strcmpW(lpszValueName
,lpkey
->values
[i
].name
))
1935 if (i
==lpkey
->nrofvalues
) {
1936 lpkey
->values
= (LPKEYVALUE
)xrealloc(
1938 (lpkey
->nrofvalues
+1)*sizeof(KEYVALUE
)
1940 lpkey
->nrofvalues
++;
1941 memset(lpkey
->values
+i
,'\0',sizeof(KEYVALUE
));
1943 if (lpkey
->values
[i
].name
==NULL
)
1945 lpkey
->values
[i
].name
= strdupW(lpszValueName
);
1947 lpkey
->values
[i
].name
= NULL
;
1948 lpkey
->values
[i
].len
= cbData
;
1949 lpkey
->values
[i
].type
= dwType
;
1950 if (lpkey
->values
[i
].data
!=NULL
)
1951 free(lpkey
->values
[i
].data
);
1952 lpkey
->values
[i
].data
= (LPBYTE
)xmalloc(cbData
);
1953 lpkey
->values
[i
].lastmodified
= time(NULL
);
1954 memcpy(lpkey
->values
[i
].data
,lpbData
,cbData
);
1955 return SHELL_ERROR_SUCCESS
;
1958 /* RegSetValueExA [ADVAPI32.169] */
1959 DWORD
RegSetValueEx32A(
1961 LPSTR lpszValueName
,
1968 LPWSTR lpszValueNameW
;
1971 dprintf_reg(stddeb
,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
1972 hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
1974 if ((1<<dwType
) & UNICONVMASK
) {
1975 buf
=(LPBYTE
)strdupA2W(lpbData
);
1976 cbData
=2*strlen(lpbData
)+2;
1980 lpszValueNameW
= strdupA2W(lpszValueName
);
1982 lpszValueNameW
= NULL
;
1983 ret
=RegSetValueEx32W(hkey
,lpszValueNameW
,dwReserved
,dwType
,buf
,cbData
);
1985 free(lpszValueNameW
);
1991 /* RegSetValueEx [KERNEL.226] */
1992 DWORD
RegSetValueEx16(
1994 LPSTR lpszValueName
,
2000 dprintf_reg(stddeb
,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2001 hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
2003 return RegSetValueEx32A(hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
);
2006 /* RegSetValueW [ADVAPI32.171] */
2007 DWORD
RegSetValue32W(
2017 dprintf_reg(stddeb
,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2018 hkey
,W2C(lpszSubKey
,0),dwType
,W2C(lpszData
,0),cbData
2020 if (lpszSubKey
&& *lpszSubKey
) {
2021 ret
=RegCreateKey32W(hkey
,lpszSubKey
,&xhkey
);
2022 if (ret
!=ERROR_SUCCESS
)
2026 if (dwType
!=REG_SZ
) {
2027 fprintf(stddeb
,"RegSetValueX called with dwType=%ld!\n",dwType
);
2030 if (cbData
!=2*strlenW(lpszData
)+2) {
2031 dprintf_reg(stddeb
,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2032 cbData
,W2C(lpszData
,0),2*strlenW(lpszData
)+2
2034 cbData
=2*strlenW(lpszData
)+2;
2036 ret
=RegSetValueEx32W(xhkey
,NULL
,0,dwType
,(LPBYTE
)lpszData
,cbData
);
2042 /* RegSetValueA [ADVAPI32.168] */
2043 DWORD
RegSetValue32A(
2053 dprintf_reg(stddeb
,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2054 hkey
,lpszSubKey
,dwType
,lpszData
,cbData
2056 if (lpszSubKey
&& *lpszSubKey
) {
2057 ret
=RegCreateKey16(hkey
,lpszSubKey
,&xhkey
);
2058 if (ret
!=ERROR_SUCCESS
)
2063 if (dwType
!=REG_SZ
) {
2064 dprintf_reg(stddeb
,"RegSetValueA called with dwType=%ld!\n",dwType
);
2067 if (cbData
!=strlen(lpszData
)+1)
2068 cbData
=strlen(lpszData
)+1;
2069 ret
=RegSetValueEx32A(xhkey
,NULL
,0,dwType
,(LPBYTE
)lpszData
,cbData
);
2075 /* RegSetValue [KERNEL.221] [SHELL.5] */
2076 DWORD
RegSetValue16(
2084 dprintf_reg(stddeb
,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2085 hkey
,lpszSubKey
,dwType
,lpszData
,cbData
2087 ret
=RegSetValue32A(hkey
,lpszSubKey
,dwType
,lpszData
,cbData
);
2095 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2096 * RegEnumKey32W -> RegEnumKeyEx32W
2099 /* RegEnumKeyExW [ADVAPI32.139] */
2100 DWORD
RegEnumKeyEx32W(
2105 LPDWORD lpdwReserved
,
2110 LPKEYSTRUCT lpkey
,lpxkey
;
2112 dprintf_reg(stddeb
,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2113 hkey
,iSubkey
,lpszName
,*lpcchName
,lpdwReserved
,lpszClass
,lpcchClass
,ft
2115 lpkey
=lookup_hkey(hkey
);
2117 return SHELL_ERROR_BADKEY
;
2118 if (!lpkey
->nextsub
)
2119 return ERROR_NO_MORE_ITEMS
;
2120 lpxkey
=lpkey
->nextsub
;
2121 while (iSubkey
&& lpxkey
) {
2123 lpxkey
=lpxkey
->next
;
2125 if (iSubkey
|| !lpxkey
)
2126 return ERROR_NO_MORE_ITEMS
;
2127 if (2*strlenW(lpxkey
->keyname
)+2>*lpcchName
)
2128 return ERROR_MORE_DATA
;
2129 memcpy(lpszName
,lpxkey
->keyname
,strlenW(lpxkey
->keyname
)*2+2);
2131 /* what should we write into it? */
2135 return ERROR_SUCCESS
;
2139 /* RegEnumKeyW [ADVAPI32.140] */
2140 DWORD
RegEnumKey32W(
2148 dprintf_reg(stddeb
,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2149 hkey
,iSubkey
,lpszName
,lpcchName
2151 return RegEnumKeyEx32W(hkey
,iSubkey
,lpszName
,&lpcchName
,NULL
,NULL
,NULL
,&ft
);
2153 /* RegEnumKeyExA [ADVAPI32.138] */
2154 DWORD
RegEnumKeyEx32A(
2159 LPDWORD lpdwReserved
,
2164 DWORD ret
,lpcchNameW
,lpcchClassW
;
2165 LPWSTR lpszNameW
,lpszClassW
;
2168 dprintf_reg(stddeb
,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2169 hkey
,iSubkey
,lpszName
,*lpcchName
,lpdwReserved
,lpszClass
,lpcchClass
,ft
2172 lpszNameW
= (LPWSTR
)xmalloc(*lpcchName
*2);
2173 lpcchNameW
= *lpcchName
*2;
2179 lpszClassW
= (LPWSTR
)xmalloc(*lpcchClass
*2);
2180 lpcchClassW
= *lpcchClass
*2;
2185 ret
=RegEnumKeyEx32W(
2195 if (ret
==ERROR_SUCCESS
) {
2196 strcpyWA(lpszName
,lpszNameW
);
2197 *lpcchName
=strlen(lpszName
);
2199 strcpyWA(lpszClass
,lpszClassW
);
2200 *lpcchClass
=strlen(lpszClass
);
2210 /* RegEnumKeyA [ADVAPI32.137] */
2211 DWORD
RegEnumKey32A(
2219 dprintf_reg(stddeb
,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2220 hkey
,iSubkey
,lpszName
,lpcchName
2222 return RegEnumKeyEx32A(
2234 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2241 dprintf_reg(stddeb
,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2242 hkey
,iSubkey
,lpszName
,lpcchName
2244 return RegEnumKey32A(hkey
,iSubkey
,lpszName
,lpcchName
);
2248 * Enumerate Registry Values
2251 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2254 /* RegEnumValueW [ADVAPI32.142] */
2255 DWORD
RegEnumValue32W(
2260 LPDWORD lpdReserved
,
2268 dprintf_reg(stddeb
,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2269 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2271 lpkey
= lookup_hkey(hkey
);
2273 return SHELL_ERROR_BADKEY
;
2274 if (lpkey
->nrofvalues
<=iValue
)
2275 return ERROR_NO_MORE_ITEMS
;
2276 val
= lpkey
->values
+iValue
;
2279 if (strlenW(val
->name
)*2+2>*lpcchValue
) {
2280 *lpcchValue
= strlenW(val
->name
)*2+2;
2281 return ERROR_MORE_DATA
;
2283 memcpy(lpszValue
,val
->name
,2*strlenW(val
->name
)+2);
2284 *lpcchValue
=strlenW(val
->name
)*2+2;
2286 /* how to handle NULL value? */
2290 *lpdwType
=val
->type
;
2292 if (val
->len
>*lpcbData
)
2293 return ERROR_MORE_DATA
;
2294 memcpy(lpbData
,val
->data
,val
->len
);
2295 *lpcbData
= val
->len
;
2297 return SHELL_ERROR_SUCCESS
;
2300 /* RegEnumValueA [ADVAPI32.141] */
2301 DWORD
RegEnumValue32A(
2306 LPDWORD lpdReserved
,
2313 DWORD ret
,lpcbDataW
;
2315 dprintf_reg(stddeb
,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2316 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2319 lpszValueW
= (LPWSTR
)xmalloc(*lpcchValue
*2);
2321 lpbDataW
= (LPBYTE
)xmalloc(*lpcbData
*2);
2322 lpcbDataW
= *lpcbData
*2;
2325 ret
=RegEnumValue32W(
2336 if (ret
==ERROR_SUCCESS
) {
2337 strcpyWA(lpszValue
,lpszValueW
);
2339 if ((1<<*lpdwType
) & UNICONVMASK
) {
2340 strcpyWA(lpbData
,(LPWSTR
)lpbDataW
);
2342 if (lpcbDataW
> *lpcbData
)
2343 ret
= ERROR_MORE_DATA
;
2345 memcpy(lpbData
,lpbDataW
,lpcbDataW
);
2347 *lpcbData
= lpcbDataW
;
2357 /* RegEnumValue [KERNEL.223] */
2358 DWORD
RegEnumValue16(
2363 LPDWORD lpdReserved
,
2368 dprintf_reg(stddeb
,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2369 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2371 return RegEnumValue32A(
2384 * Close registry key
2386 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2387 DWORD
RegCloseKey(HKEY hkey
) {
2388 dprintf_reg(stddeb
,"RegCloseKey(%x)\n",hkey
);
2389 remove_handle(hkey
);
2390 return ERROR_SUCCESS
;
2393 * Delete registry key
2396 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2398 /* RegDeleteKeyW [ADVAPI32.134] */
2399 DWORD
RegDeleteKey32W(HKEY hkey
,LPWSTR lpszSubKey
) {
2400 LPKEYSTRUCT
*lplpPrevKey
,lpNextKey
,lpxkey
;
2404 dprintf_reg(stddeb
,"RegDeleteKey32W(%x,%s)\n",
2405 hkey
,W2C(lpszSubKey
,0)
2407 lpNextKey
= lookup_hkey(hkey
);
2409 return SHELL_ERROR_BADKEY
;
2410 /* we need to know the previous key in the hier. */
2411 if (!lpszSubKey
|| !*lpszSubKey
)
2412 return SHELL_ERROR_BADKEY
;
2413 split_keypath(lpszSubKey
,&wps
,&wpc
);
2417 lpxkey
=lpNextKey
->nextsub
;
2419 if (!strcmpW(wps
[i
],lpxkey
->keyname
))
2421 lpxkey
=lpxkey
->next
;
2425 /* not found is success */
2426 return SHELL_ERROR_SUCCESS
;
2431 lpxkey
= lpNextKey
->nextsub
;
2432 lplpPrevKey
= &(lpNextKey
->nextsub
);
2434 if (!strcmpW(wps
[i
],lpxkey
->keyname
))
2436 lplpPrevKey
= &(lpxkey
->next
);
2437 lpxkey
= lpxkey
->next
;
2440 return SHELL_ERROR_SUCCESS
;
2441 if (lpxkey
->nextsub
)
2442 return SHELL_ERROR_CANTWRITE
;
2443 *lplpPrevKey
= lpxkey
->next
;
2444 free(lpxkey
->keyname
);
2446 free(lpxkey
->class);
2448 free(lpxkey
->values
);
2451 return SHELL_ERROR_SUCCESS
;
2454 /* RegDeleteKeyA [ADVAPI32.133] */
2455 DWORD
RegDeleteKey32A(HKEY hkey
,LPCSTR lpszSubKey
) {
2459 dprintf_reg(stddeb
,"RegDeleteKey32A(%x,%s)\n",
2462 lpszSubKeyW
=strdupA2W(lpszSubKey
);
2463 ret
=RegDeleteKey32W(hkey
,lpszSubKeyW
);
2468 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2469 DWORD
RegDeleteKey16(HKEY hkey
,LPCSTR lpszSubKey
) {
2470 dprintf_reg(stddeb
,"RegDeleteKey16(%x,%s)\n",
2473 return RegDeleteKey32A(hkey
,lpszSubKey
);
2477 * Delete registry value
2480 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2482 /* RegDeleteValueW [ADVAPI32.136] */
2483 DWORD
RegDeleteValue32W(HKEY hkey
,LPWSTR lpszValue
) {
2488 dprintf_reg(stddeb
,"RegDeleteValue32W(%x,%s)\n",
2489 hkey
,W2C(lpszValue
,0)
2491 lpkey
=lookup_hkey(hkey
);
2493 return SHELL_ERROR_BADKEY
;
2495 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2496 if (!strcmpW(lpkey
->values
[i
].name
,lpszValue
))
2499 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2500 if (lpkey
->values
[i
].name
==NULL
)
2503 if (i
==lpkey
->nrofvalues
)
2504 return SHELL_ERROR_BADKEY
;/*FIXME: correct errorcode? */
2505 val
= lpkey
->values
+i
;
2506 if (val
->name
) free(val
->name
);
2507 if (val
->data
) free(val
->data
);
2511 sizeof(KEYVALUE
)*(lpkey
->nrofvalues
-i
-1)
2513 lpkey
->values
= (LPKEYVALUE
)xrealloc(
2515 (lpkey
->nrofvalues
-1)*sizeof(KEYVALUE
)
2517 lpkey
->nrofvalues
--;
2518 return SHELL_ERROR_SUCCESS
;
2521 /* RegDeleteValueA [ADVAPI32.135] */
2522 DWORD
RegDeleteValue32A(HKEY hkey
,LPSTR lpszValue
) {
2526 dprintf_reg( stddeb
, "RegDeleteValue32A(%x,%s)\n", hkey
,lpszValue
);
2528 lpszValueW
=strdupA2W(lpszValue
);
2531 ret
=RegDeleteValue32W(hkey
,lpszValueW
);
2537 /* RegDeleteValue [KERNEL.222] */
2538 DWORD
RegDeleteValue16(HKEY hkey
,LPSTR lpszValue
) {
2539 dprintf_reg( stddeb
,"RegDeleteValue16(%x,%s)\n", hkey
,lpszValue
);
2540 return RegDeleteValue32A(hkey
,lpszValue
);
2543 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2544 DWORD
RegFlushKey(HKEY hkey
) {
2545 dprintf_reg(stddeb
,"RegFlushKey(%x), STUB.\n",hkey
);
2546 return SHELL_ERROR_SUCCESS
;
2549 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2551 /* RegQueryInfoKeyW [ADVAPI32.153] */
2552 DWORD
RegQueryInfoKey32W(
2556 LPDWORD lpdwReserved
,
2558 LPDWORD lpcchMaxSubkey
,
2559 LPDWORD lpcchMaxClass
,
2561 LPDWORD lpcchMaxValueName
,
2562 LPDWORD lpccbMaxValueData
,
2563 LPDWORD lpcbSecurityDescriptor
,
2566 LPKEYSTRUCT lpkey
,lpxkey
;
2567 int nrofkeys
,maxsubkey
,maxclass
,maxvalues
,maxvname
,maxvdata
;
2570 dprintf_reg(stddeb
,"RegQueryInfoKey32W(%x,......)\n",hkey
);
2571 lpkey
=lookup_hkey(hkey
);
2573 return SHELL_ERROR_BADKEY
;
2576 if (strlenW(lpkey
->class)*2+2>*lpcchClass
) {
2577 *lpcchClass
=strlenW(lpkey
->class)*2;
2578 return ERROR_MORE_DATA
;
2580 *lpcchClass
=strlenW(lpkey
->class)*2;
2581 memcpy(lpszClass
,lpkey
->class,strlenW(lpkey
->class));
2588 *lpcchClass
= strlenW(lpkey
->class)*2;
2590 lpxkey
=lpkey
->nextsub
;
2591 nrofkeys
=maxsubkey
=maxclass
=maxvalues
=maxvname
=maxvdata
=0;
2594 if (strlenW(lpxkey
->keyname
)>maxsubkey
)
2595 maxsubkey
=strlenW(lpxkey
->keyname
);
2596 if (lpxkey
->class && strlenW(lpxkey
->class)>maxclass
)
2597 maxclass
=strlenW(lpxkey
->class);
2598 if (lpxkey
->nrofvalues
>maxvalues
)
2599 maxvalues
=lpxkey
->nrofvalues
;
2600 for (i
=0;i
<lpxkey
->nrofvalues
;i
++) {
2601 LPKEYVALUE val
=lpxkey
->values
+i
;
2603 if (val
->name
&& strlenW(val
->name
)>maxvname
)
2604 maxvname
=strlenW(val
->name
);
2605 if (val
->len
>maxvdata
)
2608 lpxkey
=lpxkey
->next
;
2610 if (!maxclass
) maxclass
= 1;
2611 if (!maxvname
) maxvname
= 1;
2613 *lpcSubKeys
= nrofkeys
;
2615 *lpcchMaxSubkey
= maxsubkey
*2;
2617 *lpcchMaxClass
= maxclass
*2;
2619 *lpcValues
= maxvalues
;
2620 if (lpcchMaxValueName
)
2621 *lpcchMaxValueName
= maxvname
;
2622 if (lpccbMaxValueData
)
2623 *lpccbMaxValueData
= maxvdata
;
2624 return SHELL_ERROR_SUCCESS
;
2627 /* RegQueryInfoKeyA [ADVAPI32.152] */
2628 DWORD
RegQueryInfoKey32A(
2632 LPDWORD lpdwReserved
,
2634 LPDWORD lpcchMaxSubkey
,
2635 LPDWORD lpcchMaxClass
,
2637 LPDWORD lpcchMaxValueName
,
2638 LPDWORD lpccbMaxValueData
,
2639 LPDWORD lpcbSecurityDescriptor
,
2645 dprintf_reg(stddeb
,"RegQueryInfoKey32A(%x,......)\n",hkey
);
2648 lpszClassW
= (LPWSTR
)xmalloc(*lpcchClass
);
2652 ret
=RegQueryInfoKey32W(
2663 lpcbSecurityDescriptor
,
2666 if (ret
==ERROR_SUCCESS
)
2667 strcpyWA(lpszClass
,lpszClassW
);
2674 if (lpcchMaxValueName
)
2675 *lpcchMaxValueName
/=2;