4 * Copyright 1996 Marcus Meissner
14 #include <sys/types.h>
15 #include <sys/fcntl.h>
30 #define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y))
32 /* FIXME: following defines should be configured global ... */
34 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
35 #define WINE_PREFIX "/.wine"
36 #define SAVE_USERS_DEFAULT "/usr/local/etc/wine.userreg"
37 #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
39 /* relative in ~user/.wine/ : */
40 #define SAVE_CURRENT_USER "user.reg"
41 #define SAVE_LOCAL_MACHINE "system.reg"
43 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
44 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
46 /* one value of a key */
47 typedef struct tagKEYVALUE
49 LPWSTR name
; /* name of value (UNICODE) or NULL for win31 */
50 DWORD type
; /* type of value */
51 DWORD len
; /* length of data */
52 DWORD lastmodified
; /* time of seconds since 1.1.1970 */
53 LPBYTE data
; /* content, may be strings, binaries, etc. */
54 } KEYVALUE
,*LPKEYVALUE
;
57 typedef struct tagKEYSTRUCT
59 LPWSTR keyname
; /* name of THIS key (UNICODE) */
60 DWORD flags
; /* flags. */
63 DWORD nrofvalues
; /* nr of values in THIS key */
64 LPKEYVALUE values
; /* values in THIS key */
65 /* key management pointers */
66 struct tagKEYSTRUCT
*next
; /* next key on same hierarchy */
67 struct tagKEYSTRUCT
*nextsub
; /* keys that hang below THIS key */
68 } KEYSTRUCT
, *LPKEYSTRUCT
;
71 static KEYSTRUCT
*key_classes_root
=NULL
; /* windows 3.1 global values */
72 static KEYSTRUCT
*key_current_user
=NULL
; /* user specific values */
73 static KEYSTRUCT
*key_local_machine
=NULL
;/* machine specific values */
74 static KEYSTRUCT
*key_users
=NULL
; /* all users? */
76 /* dynamic, not saved */
77 static KEYSTRUCT
*key_performance_data
=NULL
;
78 static KEYSTRUCT
*key_current_config
=NULL
;
79 static KEYSTRUCT
*key_dyn_data
=NULL
;
81 /* what valuetypes do we need to convert? */
82 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
84 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
85 #define strdupW2A(x) STRING32_DupUniToAnsi(x)
86 #define strdupW(x) STRING32_strdupW(x)
87 #define strcmpniW(a,b) STRING32_lstrcmpniW(a,b)
88 #define strchrW(a,c) STRING32_lstrchrW(a,c)
89 #define strcpyWA(a,b) STRING32_UniToAnsi(a,b)
91 static struct openhandle
{
96 static int nrofopenhandles
=0;
97 static int currenthandle
=1;
100 add_handle(HKEY hkey
,LPKEYSTRUCT lpkey
,REGSAM accessmask
) {
103 for (i
=0;i
<nrofopenhandles
;i
++) {
104 if (openhandles
[i
].lpkey
==lpkey
) {
105 dprintf_reg(stddeb
,"add_handle:Tried to add %p twice!\n",lpkey
);
107 if (openhandles
[i
].hkey
==hkey
) {
108 dprintf_reg(stddeb
,"add_handle:Tried to add %lx twice!\n",(LONG
)hkey
);
111 openhandles
=xrealloc( openhandles
,
112 sizeof(struct openhandle
)*(nrofopenhandles
+1)
114 openhandles
[i
].lpkey
= lpkey
;
115 openhandles
[i
].hkey
= hkey
;
116 openhandles
[i
].accessmask
= accessmask
;
121 get_handle(HKEY hkey
) {
124 for (i
=0;i
<nrofopenhandles
;i
++)
125 if (openhandles
[i
].hkey
==hkey
)
126 return openhandles
[i
].lpkey
;
127 dprintf_reg(stddeb
,"get_handle:Didn't find handle %lx?\n",(LONG
)hkey
);
132 remove_handle(HKEY hkey
) {
135 for (i
=0;i
<nrofopenhandles
;i
++)
136 if (openhandles
[i
].hkey
==hkey
)
138 if (i
==nrofopenhandles
) {
139 dprintf_reg(stddeb
,"remove_handle:Didn't find handle %08x?\n",hkey
);
142 memcpy( openhandles
+i
,
144 sizeof(struct openhandle
)*(nrofopenhandles
-i
-1)
146 openhandles
=xrealloc(openhandles
,sizeof(struct openhandle
)*(nrofopenhandles
-1));
152 /* debug function, converts a unicode into a static memory area
153 * (sub for using two static strings, in case we need them in a single call)
156 W2C(LPCWSTR x
,int sub
) {
157 static LPSTR unicodedebug
[2]={NULL
,NULL
};
160 if (sub
!=0 && sub
!=1)
161 return "<W2C:bad sub>";
162 if (unicodedebug
[sub
]) free(unicodedebug
[sub
]);
163 unicodedebug
[sub
] = strdupW2A(x
);
164 return unicodedebug
[sub
];
168 lookup_hkey(HKEY hkey
) {
172 case HKEY_CLASSES_ROOT
:
173 return key_classes_root
;
174 case HKEY_CURRENT_USER
:
175 return key_current_user
;
176 case HKEY_LOCAL_MACHINE
:
177 return key_local_machine
;
180 case HKEY_PERFORMANCE_DATA
:
181 return key_performance_data
;
184 case HKEY_CURRENT_CONFIG
:
185 return key_current_config
;
187 dprintf_reg(stddeb
,"lookup_hkey(%lx), special key!\n",
190 return get_handle(hkey
);
196 * splits the unicode string 'wp' into an array of strings.
197 * the array is allocated by this function.
198 * the number of components will be stored in 'wpc'
199 * Free the array using FREE_KEY_PATH
202 split_keypath(LPCWSTR wp
,LPWSTR
**wpv
,int *wpc
) {
208 for (i
=0;ws
[i
];i
++) {
215 *wpv
= (LPWSTR
*)xmalloc(sizeof(LPWSTR
)*(*wpc
+2));
223 #define FREE_KEY_PATH free(wps[0]);free(wps);
226 * Shell initialisation, allocates keys.
228 void SHELL_StartupRegistry();
233 HKEY cl_r_hkey
,c_u_hkey
;
234 #define ADD_ROOT_KEY(xx) \
235 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
236 memset(xx,'\0',sizeof(KEYSTRUCT));\
237 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
239 ADD_ROOT_KEY(key_local_machine
);
240 if (RegCreateKey16(HKEY_LOCAL_MACHINE
,"\\SOFTWARE\\Classes",&cl_r_hkey
)!=ERROR_SUCCESS
) {
241 fprintf(stderr
,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
244 key_classes_root
= lookup_hkey(cl_r_hkey
);
246 ADD_ROOT_KEY(key_users
);
249 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
250 * (later, when a win32 registry editing tool becomes avail.)
252 while (pwd
=getpwent()) {
253 if (pwd
->pw_name
== NULL
)
255 RegCreateKey16(HKEY_USERS
,pwd
->pw_name
,&c_u_hkey
);
256 RegCloseKey(c_u_hkey
);
259 pwd
=getpwuid(getuid());
260 if (pwd
&& pwd
->pw_name
) {
261 RegCreateKey16(HKEY_USERS
,pwd
->pw_name
,&c_u_hkey
);
262 key_current_user
= lookup_hkey(c_u_hkey
);
264 ADD_ROOT_KEY(key_current_user
);
266 ADD_ROOT_KEY(key_performance_data
);
267 ADD_ROOT_KEY(key_current_config
);
268 ADD_ROOT_KEY(key_dyn_data
);
270 SHELL_StartupRegistry();
275 SHELL_StartupRegistry() {
278 char buf
[200],cpubuf
[200];
280 RegCreateKey16(HKEY_DYN_DATA
,"\\PerfStats\\StatData",&xhkey
);
282 RegCreateKey16(HKEY_LOCAL_MACHINE
,"\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey
);
284 F
=fopen("/proc/cpuinfo","r");
287 while (NULL
!=fgets(buf
,200,F
)) {
288 if (sscanf(buf
,"processor\t: %d",&x
)) {
293 RegCreateKey16(hkey
,buf
,&xhkey
);
295 if (sscanf(buf
,"cpu\t\t: %s",cpubuf
)) {
296 sprintf(buf
,"CPU %s",cpubuf
);
298 RegSetValueEx32A(xhkey
,"Identifier",0,REG_SZ
,buf
,strlen(buf
));
308 RegCreateKey16(hkey
,"0",&xhkey
);
309 RegSetValueEx32A(xhkey
,"Identifier",0,REG_SZ
,"CPU 386",strlen("CPU 386"));
311 RegOpenKey16(HKEY_LOCAL_MACHINE
,"\\HARDWARE\\DESCRIPTION\\System",&hkey
);
312 RegSetValueEx32A(hkey
,"Identifier",0,REG_SZ
,"SystemType WINE",strlen("SystemType WINE"));
314 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
318 * string RegisteredOwner
319 * string RegisteredOrganization
322 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
327 if (-1!=gethostname(buf
,200)) {
328 RegCreateKey16(HKEY_LOCAL_MACHINE
,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&xhkey
);
329 RegSetValueEx16(xhkey
,"ComputerName",0,REG_SZ
,buf
,strlen(buf
)+1);
333 /************************ SAVE Registry Function ****************************/
335 #define REGISTRY_SAVE_VERSION 0x00000001
337 /* Registry saveformat:
338 * If you change it, increase above number by 1, which will flush
339 * old registry database files.
342 * "WINE REGISTRY Version %d"
346 * valuename=lastmodified,type,data
350 * keyname,valuename,stringdata:
351 * the usual ascii characters from 0x00-0xff (well, not 0x00)
352 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
353 * ( "=\\\t" escaped in \uXXXX form.)
357 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
359 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
360 * SaveOnlyUpdatedKeys=yes
363 _save_check_tainted(LPKEYSTRUCT lpkey
) {
368 if (lpkey
->flags
& REG_OPTION_TAINTED
)
373 if (_save_check_tainted(lpkey
->nextsub
)) {
374 lpkey
->flags
|= REG_OPTION_TAINTED
;
383 _save_USTRING(FILE *F
,LPWSTR wstr
,int escapeeq
) {
396 if (escapeeq
&& *s
=='=')
399 fputc(*s
,F
); /* if \\ than put it twice. */
401 fprintf(F
,"\\u%04x",*((unsigned short*)s
));
409 _savesubkey(FILE *F
,LPKEYSTRUCT lpkey
,int level
,int all
) {
415 if ( !(lpxkey
->flags
& REG_OPTION_VOLATILE
) &&
416 (all
|| (lpxkey
->flags
& REG_OPTION_TAINTED
))
418 for (tabs
=level
;tabs
--;)
420 _save_USTRING(F
,lpxkey
->keyname
,1);
422 for (i
=0;i
<lpxkey
->nrofvalues
;i
++) {
423 LPKEYVALUE val
=lpxkey
->values
+i
;
425 for (tabs
=level
+1;tabs
--;)
427 _save_USTRING(F
,val
->name
,0);
429 fprintf(F
,"%ld,%ld,",val
->type
,val
->lastmodified
);
430 if ((1<<val
->type
) & UNICONVMASK
)
431 _save_USTRING(F
,(LPWSTR
)val
->data
,0);
433 for (j
=0;j
<val
->len
;j
++)
434 fprintf(F
,"%02x",*((unsigned char*)val
->data
+j
));
437 /* descend recursively */
438 if (!_savesubkey(F
,lpxkey
->nextsub
,level
+1,all
))
447 _savesubreg(FILE *F
,LPKEYSTRUCT lpkey
,int all
) {
448 fprintf(F
,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION
);
449 _save_check_tainted(lpkey
->nextsub
);
450 return _savesubkey(F
,lpkey
->nextsub
,0,all
);
454 _savereg(LPKEYSTRUCT lpkey
,char *fn
,int all
) {
459 fprintf(stddeb
,__FILE__
":_savereg:Couldn't open %s for writing: %s\n",
464 if (!_savesubreg(F
,lpkey
,all
)) {
467 fprintf(stddeb
,__FILE__
":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn
);
475 SHELL_SaveRegistry() {
483 if (RegOpenKey16(HKEY_CURRENT_USER
,KEY_REGISTRY
,&hkey
)!=ERROR_SUCCESS
) {
489 if ( (ERROR_SUCCESS
!=RegQueryValueEx32A(
501 if (lstrcmpi32A(buf
,"yes"))
503 pwd
=getpwuid(getuid());
504 if (pwd
!=NULL
&& pwd
->pw_dir
!=NULL
)
508 fn
=(char*)xmalloc( strlen(pwd
->pw_dir
) + strlen(WINE_PREFIX
) +
509 strlen(SAVE_CURRENT_USER
) + 2 );
510 strcpy(fn
,pwd
->pw_dir
);
511 strcat(fn
,WINE_PREFIX
);
512 /* create the directory. don't care about errorcodes. */
513 mkdir(fn
,0755); /* drwxr-xr-x */
514 strcat(fn
,"/"SAVE_CURRENT_USER
);
515 tmp
= (char*)xmalloc(strlen(fn
)+strlen(".tmp")+1);
516 strcpy(tmp
,fn
);strcat(tmp
,".tmp");
517 if (_savereg(key_current_user
,tmp
,all
)) {
518 if (-1==rename(tmp
,fn
)) {
519 perror("rename tmp registry");
525 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_LOCAL_MACHINE
)+2);
526 strcpy(fn
,pwd
->pw_dir
);
527 strcat(fn
,WINE_PREFIX
"/"SAVE_LOCAL_MACHINE
);
528 tmp
= (char*)xmalloc(strlen(fn
)+strlen(".tmp")+1);
529 strcpy(tmp
,fn
);strcat(tmp
,".tmp");
530 if (_savereg(key_local_machine
,tmp
,all
)) {
531 if (-1==rename(tmp
,fn
)) {
532 perror("rename tmp registry");
539 fprintf(stderr
,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
542 /************************ LOAD Registry Function ****************************/
545 _find_or_add_key(LPKEYSTRUCT lpkey
,LPWSTR keyname
) {
546 LPKEYSTRUCT lpxkey
,*lplpkey
;
548 lplpkey
= &(lpkey
->nextsub
);
551 if (!lstrcmp32W(lpxkey
->keyname
,keyname
))
553 lplpkey
= &(lpxkey
->next
);
557 *lplpkey
= (LPKEYSTRUCT
)xmalloc(sizeof(KEYSTRUCT
));
559 memset(lpxkey
,'\0',sizeof(KEYSTRUCT
));
560 lpxkey
->keyname
= keyname
;
568 LPKEYSTRUCT lpkey
,LPWSTR name
,DWORD type
,LPBYTE data
,DWORD len
,
574 for (i
=0;i
<lpkey
->nrofvalues
;i
++) {
580 if ( val
->name
!=NULL
&&
581 !lstrcmp32W(val
->name
,name
)
586 if (i
==lpkey
->nrofvalues
) {
587 lpkey
->values
= xrealloc(
589 (++lpkey
->nrofvalues
)*sizeof(KEYVALUE
)
592 memset(val
,'\0',sizeof(KEYVALUE
));
598 if (val
->lastmodified
<lastmodified
) {
599 val
->lastmodified
=lastmodified
;
610 /* reads a line including dynamically enlarging the readbuffer and throwing
614 _wine_read_line(FILE *F
,char **buf
,int *len
) {
623 s
=fgets(curread
,mylen
,F
);
626 if (NULL
==(s
=strchr(curread
,'\n'))) {
627 /* buffer wasn't large enough */
628 curoff
= strlen(*buf
);
629 *buf
= xrealloc(*buf
,*len
*2);
630 curread
= *buf
+ curoff
;
631 mylen
= *len
; /* we filled up the buffer and
632 * got new '*len' bytes to fill
640 /* throw away comments */
641 if (**buf
=='#' || **buf
==';') {
646 if (s
) /* got end of line */
652 /* converts a char* into a UNICODE string (up to a special char)
653 * and returns the position exactly after that string
656 _wine_read_USTRING(char *buf
,LPWSTR
*str
) {
660 /* read up to "=" or "\0" or "\n" */
663 /* empty string is the win3.1 default value(NULL)*/
667 *str
= (LPWSTR
)xmalloc(2*strlen(buf
)+2);
669 while (*s
&& (*s
!='\n') && (*s
!='=')) {
671 *ws
++=*((unsigned char*)s
++);
680 fprintf(stderr
,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s
,buf
);
688 memcpy(xbuf
,s
,4);xbuf
[4]='\0';
689 if (!sscanf(xbuf
,"%x",&wc
))
690 fprintf(stderr
,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf
,buf
);
692 *ws
++ =(unsigned short)wc
;
698 *str
= strdupW(*str
);
705 FILE *F
,LPKEYSTRUCT lpkey
,int level
,char **buf
,int *buflen
,int optflag
712 lpkey
->flags
|= optflag
;
714 /* good. we already got a line here ... so parse it */
724 fprintf(stderr
,"_load_subkey:Got a subhierarchy without resp. key?\n");
727 _wine_loadsubkey(F
,lpxkey
,level
+1,buf
,buflen
,optflag
);
730 /* let the caller handle this line */
731 if (i
<level
|| **buf
=='\0')
734 /* it can be: a value or a keyname. Parse the name first */
735 s
=_wine_read_USTRING(s
,&name
);
737 /* switch() default: hack to avoid gotos */
741 lpxkey
=_find_or_add_key(lpkey
,name
);
744 int len
,lastmodified
,type
;
747 fprintf(stderr
,"_wine_load_subkey:unexpected character: %c\n",*s
);
751 if (2!=sscanf(s
,"%d,%d,",&type
,&lastmodified
)) {
752 fprintf(stderr
,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf
);
758 if ((1<<type
) & UNICONVMASK
) {
759 s
=_wine_read_USTRING(s
,(LPWSTR
*)&data
);
761 len
= lstrlen32W((LPWSTR
)data
)*2+2;
766 data
= (LPBYTE
)xmalloc(len
+1);
767 for (i
=0;i
<len
;i
++) {
769 if (*s
>='0' && *s
<='9')
771 if (*s
>='a' && *s
<='f')
773 if (*s
>='A' && *s
<='F')
776 if (*s
>='0' && *s
<='9')
778 if (*s
>='a' && *s
<='f')
780 if (*s
>='A' && *s
<='F')
785 _find_or_add_value(lpkey
,name
,type
,data
,len
,lastmodified
);
788 /* read the next line */
789 if (!_wine_read_line(F
,buf
,buflen
))
796 _wine_loadsubreg(FILE *F
,LPKEYSTRUCT lpkey
,int optflag
) {
801 buf
=xmalloc(10);buflen
=10;
802 if (!_wine_read_line(F
,&buf
,&buflen
)) {
806 if (!sscanf(buf
,"WINE REGISTRY Version %d",&ver
)) {
810 if (ver
!=REGISTRY_SAVE_VERSION
) {
811 dprintf_reg(stddeb
,__FILE__
":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver
,buf
);
815 if (!_wine_read_line(F
,&buf
,&buflen
)) {
819 if (!_wine_loadsubkey(F
,lpkey
,0,&buf
,&buflen
,optflag
)) {
828 _wine_loadreg(LPKEYSTRUCT lpkey
,char *fn
,int optflag
) {
833 dprintf_reg(stddeb
,__FILE__
":Couldn't open %s for reading: %s\n",
838 if (!_wine_loadsubreg(F
,lpkey
,optflag
)) {
847 _copy_registry(LPKEYSTRUCT from
,LPKEYSTRUCT to
) {
854 lpxkey
= _find_or_add_key(to
,strdupW(from
->keyname
));
856 for (j
=0;j
<from
->nrofvalues
;j
++) {
860 valfrom
= from
->values
+j
;
862 if (name
) name
=strdupW(name
);
863 data
=(LPBYTE
)malloc(valfrom
->len
);
864 memcpy(data
,valfrom
->data
,valfrom
->len
);
872 valfrom
->lastmodified
875 _copy_registry(from
,lpxkey
);
880 /* WINDOWS 95 REGISTRY LOADER */
882 * Structure of a win95 registry database.
886 * 8 : DWORD offset_of_RGDB_part
887 * 0C..1F: ? (someone fill in please)
892 * 4..0x1B: ? (fill in)
893 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
895 * Disk Key Entry Structure:
896 * 00: DWORD - unknown
897 * 04: DWORD - unknown
898 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
899 * 0C: DWORD - disk address of PreviousLevel Key.
900 * 10: DWORD - disk address of Next Sublevel Key.
901 * 14: DWORD - disk address of Next Key (on same level).
902 * DKEP>18: WORD - Nr, Low Significant part.
903 * 1A: WORD - Nr, High Significant part.
905 * The disk address always points to the nr part of the previous key entry
906 * of the referenced key. Don't ask me why, or even if I got this correct
907 * from staring at 1kg of hexdumps. (DKEP)
909 * The number of the entry is the low byte of the Low Significant Part ored
910 * with 0x100 * (low byte of the High Significant part)
911 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
913 * There are two minor corrections to the position of that structure.
914 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
915 * the DKE reread from there.
916 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
917 * (FIXME: slightly better explanation needed here)
921 * 04: DWORD offset to next RGDB section (perhaps WORD)
926 * 00: DWORD nextkeyoffset - offset to the next disk key structure
927 * 08: WORD nrLS - low significant part of NR
928 * 0A: WORD nrHS - high significant part of NR
929 * 0C: DWORD bytesused - bytes used in this structure.
930 * 10: WORD name_len - length of name in bytes. without \0
931 * 12: WORD nr_of_values - number of values.
932 * 14: char name[name_len] - name string. No \0.
933 * 14+name_len: disk values
934 * nextkeyoffset: ... next disk key
937 * 00: DWORD type - value type (hmm, could be WORD too)
938 * 04: DWORD - unknown, usually 0
939 * 08: WORD namelen - length of Name. 0 means name=NULL
940 * 0C: WORD datalen - length of Data.
941 * 10: char name[namelen] - name, no \0
942 * 10+namelen: BYTE data[datalen] - data, without \0 if string
943 * 10+namelen+datalen: next values or disk key
945 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
946 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
947 * structure) and reading another RGDB_section.
948 * repeat until end of file.
950 * FIXME: this description needs some serious help, yes.
953 struct _w95keyvalue
{
955 unsigned short datalen
;
965 struct _w95keyvalue
*values
;
966 unsigned long dkeaddr
;
971 struct _w95key
*prevlvl
;
972 struct _w95key
*nextsub
;
973 struct _w95key
*next
;
976 /* fast lookup table dkeaddr->nr */
978 unsigned long dkeaddr
;
984 _w95_walk_tree(LPKEYSTRUCT lpkey
,struct _w95key
*key
) {
990 if (key
->name
== NULL
) {
991 fprintf(stderr
,"_w95_walk_tree:Please report: key with dkeaddr %lx not loaded, skipping hierarchy\n",
996 lpxkey
=_find_or_add_key(lpkey
,strdupA2W(key
->name
));
998 if (key
->nrofvals
<0) {
999 /* shouldn't happen */
1000 fprintf(stderr
,"key %s already processed!\n",key
->name
);
1004 for (i
=0;i
<key
->nrofvals
;i
++) {
1008 name
= strdupA2W(key
->values
[i
].name
);
1009 if (!*name
) name
= NULL
;
1010 free(key
->values
[i
].name
);
1012 len
= key
->values
[i
].datalen
;
1013 data
= key
->values
[i
].data
;
1014 if ((1<<key
->values
[i
].type
) & UNICONVMASK
) {
1015 data
= (BYTE
*)strdupA2W(data
);
1016 len
= lstrlen32W((LPWSTR
)data
)*2+2;
1017 free(key
->values
[i
].data
);
1022 key
->values
[i
].type
,
1025 key
->values
[i
].lastmodified
1032 key
->nrofvals
=-key
->nrofvals
-1;
1033 _w95_walk_tree(lpxkey
,key
->nextsub
);
1038 /* small helper function to adjust address offset (dkeaddrs) */
1039 static unsigned long
1040 _w95_adj_da(unsigned long dkeaddr
) {
1041 if ((dkeaddr
&0xFFF)<0x018) {
1044 diff
=0x1C-(dkeaddr
&0xFFF);
1045 return dkeaddr
+diff
;
1047 if (((dkeaddr
+0x1C)&0xFFF)<0x1C) {
1048 /* readjust to 0x000,
1049 * but ONLY if we are >0x1000 already
1051 if (dkeaddr
& ~0xFFF)
1052 return dkeaddr
& ~0xFFF;
1058 _w95dkecomp(struct _w95nr2da
*a
,struct _w95nr2da
*b
){return a
->dkeaddr
-b
->dkeaddr
;}
1060 static struct _w95key
*
1061 _w95dkelookup(unsigned long dkeaddr
,int n
,struct _w95nr2da
*nr2da
,struct _w95key
*keys
) {
1064 if (dkeaddr
== 0xFFFFFFFF)
1068 dkeaddr
=_w95_adj_da(dkeaddr
+0x1c);
1069 off
= (dkeaddr
-0x3c)/0x1c;
1071 if (nr2da
[(i
+off
)%n
].dkeaddr
== dkeaddr
)
1072 return keys
+nr2da
[(i
+off
)%n
].nr
;
1073 /* 0x3C happens often, just report unusual values */
1075 dprintf_reg(stddeb
,"search hasn't found dkeaddr %lx?\n",dkeaddr
);
1080 _w95_loadreg(char* fn
,LPKEYSTRUCT lpkey
) {
1081 /* Disk Key Entry structure (RGKN part) */
1085 unsigned long x3
;/*usually 0xFFFFFFFF */
1086 unsigned long prevlvl
;
1087 unsigned long nextsub
;
1089 unsigned short nrLS
;
1090 unsigned short nrMS
;
1092 /* Disk Key Header structure (RGDB part) */
1094 unsigned long nextkeyoff
;
1095 unsigned short nrLS
;
1096 unsigned short nrMS
;
1097 unsigned long bytesused
;
1098 unsigned short keynamelen
;
1099 unsigned short values
;
1102 /* disk key values or nothing */
1104 /* Disk Key Value structure */
1108 unsigned short valnamelen
;
1109 unsigned short valdatalen
;
1110 /* valname, valdata */
1112 struct _w95nr2da
*nr2da
;
1117 unsigned long nr
,pos
,i
,where
,version
,rgdbsection
,end
,off_next_rgdb
;
1118 struct _w95key
*keys
;
1120 unsigned char *data
,*curdata
,*nextrgdb
;
1122 BY_HANDLE_FILE_INFORMATION hfdinfo
;
1124 dprintf_reg(stddeb
,"Loading Win95 registry database '%s'\n",fn
);
1125 hfd
=OpenFile(fn
,&ofs
,OF_READ
);
1126 if (hfd
==HFILE_ERROR
)
1129 if (4!=_lread32(hfd
,magic
,4))
1131 if (strcmp(magic
,"CREG")) {
1132 fprintf(stddeb
,"%s is not a w95 registry.\n",fn
);
1135 if (4!=_lread32(hfd
,&version
,4))
1137 if (4!=_lread32(hfd
,&rgdbsection
,4))
1139 if (-1==_llseek(hfd
,0x20,SEEK_SET
))
1141 if (4!=_lread32(hfd
,magic
,4))
1143 if (strcmp(magic
,"RGKN")) {
1144 dprintf_reg(stddeb
,"second IFF header not RGKN, but %s\n",magic
);
1148 /* STEP 1: Keylink structures */
1149 if (-1==_llseek(hfd
,0x40,SEEK_SET
))
1154 nrofdkes
= (end
-where
)/sizeof(struct dke
)+100;
1155 data
= (char*)xmalloc(end
-where
);
1156 if ((end
-where
)!=_lread32(hfd
,data
,end
-where
))
1160 keys
= (struct _w95key
*)xmalloc(nrofdkes
* sizeof(struct _w95key
));
1161 memset(keys
,'\0',nrofdkes
*sizeof(struct _w95key
));
1162 nr2da
= (struct _w95nr2da
*)xmalloc(nrofdkes
* sizeof(struct _w95nr2da
));
1163 memset(nr2da
,'\0',nrofdkes
*sizeof(struct _w95nr2da
));
1165 for (i
=0;i
<nrofdkes
;i
++) {
1167 unsigned long dkeaddr
;
1169 pos
=curdata
-data
+0x40;
1170 memcpy(&dke
,curdata
,sizeof(dke
));
1171 curdata
+=sizeof(dke
);
1172 nr
= dke
.nrLS
+ (dke
.nrMS
<<8);
1174 if ((dkeaddr
&0xFFF)<0x018) {
1177 diff
=0x1C-(dkeaddr
&0xFFF);
1179 curdata
+=diff
-sizeof(dke
);
1180 memcpy(&dke
,curdata
,sizeof(dke
));
1181 nr
= dke
.nrLS
+ (dke
.nrMS
<<8);
1182 curdata
+=sizeof(dke
);
1184 if (((dkeaddr
+0x1C)&0xFFF)<0x1C) {
1185 /* readjust to 0x000,
1186 * but ONLY if we are >0x1000 already
1188 if (dkeaddr
& ~0xFFF)
1189 dkeaddr
= dkeaddr
& ~0xFFF;
1192 /* 0xFFFFFFFF happens often, just report unusual values */
1194 dprintf_reg(stddeb
,"nr %ld exceeds nrofdkes %d, skipping.\n",nr
,nrofdkes
);
1197 if (keys
[nr
].dkeaddr
) {
1200 for (x
=sizeof(dke
);x
--;)
1201 if (((char*)&dke
)[x
])
1204 break; /* finished reading if we got only 0 */
1206 if ( (dke
.next
!=(long)keys
[nr
].next
) ||
1207 (dke
.nextsub
!=(long)keys
[nr
].nextsub
) ||
1208 (dke
.prevlvl
!=(long)keys
[nr
].prevlvl
)
1210 dprintf_reg(stddeb
,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr
,keys
[nr
].dkeaddr
,dkeaddr
);
1215 nr2da
[i
].dkeaddr
= dkeaddr
;
1217 keys
[nr
].dkeaddr
= dkeaddr
;
1218 keys
[nr
].x1
= dke
.x1
;
1219 keys
[nr
].x2
= dke
.x2
;
1220 keys
[nr
].x3
= dke
.x3
;
1221 keys
[nr
].prevlvl
= (struct _w95key
*)dke
.prevlvl
;
1222 keys
[nr
].nextsub
= (struct _w95key
*)dke
.nextsub
;
1223 keys
[nr
].next
= (struct _w95key
*)dke
.next
;
1227 qsort(nr2da
,nrofdkes
,sizeof(nr2da
[0]),
1228 (int(*)(const void *,const void*))_w95dkecomp
);
1230 /* STEP 2: keydata & values */
1231 if (!GetFileInformationByHandle(hfd
,&hfdinfo
))
1233 end
= hfdinfo
.nFileSizeLow
;
1234 lastmodified
= DOSFS_FileTimeToUnixTime(&(hfdinfo
.ftLastWriteTime
));
1236 if (-1==_llseek(hfd
,rgdbsection
,SEEK_SET
))
1238 data
= (char*)xmalloc(end
-rgdbsection
);
1239 if ((end
-rgdbsection
)!=_lread32(hfd
,data
,end
-rgdbsection
))
1243 memcpy(magic
,curdata
,4);
1244 memcpy(&off_next_rgdb
,curdata
+4,4);
1245 nextrgdb
= curdata
+off_next_rgdb
;
1246 if (strcmp(magic
,"RGDB")) {
1247 dprintf_reg(stddeb
,"third IFF header not RGDB, but %s\n",magic
);
1254 struct _w95key
*key
,xkey
;
1257 if (curdata
>=nextrgdb
) {
1259 if (!strncmp(curdata
,"RGDB",4)) {
1260 memcpy(&off_next_rgdb
,curdata
+4,4);
1261 nextrgdb
= curdata
+off_next_rgdb
;
1264 dprintf_reg(stddeb
,"at end of RGDB section, but no next header (%x of %lx). Breaking.\n",curdata
-data
,end
-rgdbsection
);
1268 #define XREAD(whereto,len) \
1269 if ((curdata-data+len)<end) {\
1270 memcpy(whereto,curdata,len);\
1275 XREAD(&dkh
,sizeof(dkh
));
1276 nr
= dkh
.nrLS
+ (dkh
.nrMS
<<8);
1277 if ((nr
>nrofdkes
) || (dkh
.nrLS
== 0xFFFF)) {
1278 if (dkh
.nrLS
== 0xFFFF) {
1279 /* skip over key using nextkeyoff */
1280 curdata
+=dkh
.nextkeyoff
-sizeof(struct dkh
);
1283 dprintf_reg(stddeb
,"haven't found nr %ld.\n",nr
);
1285 memset(key
,'\0',sizeof(xkey
));
1289 dprintf_reg(stddeb
,"key with nr=%ld has no dkeaddr?\n",nr
);
1291 key
->nrofvals
= dkh
.values
;
1292 key
->name
= (char*)xmalloc(dkh
.keynamelen
+1);
1294 XREAD(key
->name
,dkh
.keynamelen
);
1295 key
->name
[dkh
.keynamelen
]=0;
1296 if (key
->nrofvals
) {
1297 key
->values
= (struct _w95keyvalue
*)xmalloc(
1298 sizeof(struct _w95keyvalue
)*key
->nrofvals
1300 for (i
=0;i
<key
->nrofvals
;i
++) {
1303 XREAD(&dkv
,sizeof(dkv
));
1304 key
->values
[i
].type
= dkv
.type
;
1305 key
->values
[i
].name
= (char*)xmalloc(
1308 key
->values
[i
].datalen
= dkv
.valdatalen
;
1309 key
->values
[i
].data
= (unsigned char*)xmalloc(
1312 key
->values
[i
].x1
= dkv
.x1
;
1313 XREAD(key
->values
[i
].name
,dkv
.valnamelen
);
1314 XREAD(key
->values
[i
].data
,dkv
.valdatalen
);
1315 key
->values
[i
].data
[dkv
.valdatalen
]=0;
1316 key
->values
[i
].name
[dkv
.valnamelen
]=0;
1317 key
->values
[i
].lastmodified
=lastmodified
;
1320 if (bytesread
!= dkh
.nextkeyoff
) {
1321 if (dkh
.bytesused
!= bytesread
)
1323 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread
,dkh
.nextkeyoff
,
1326 curdata
+= dkh
.nextkeyoff
-bytesread
;
1328 key
->prevlvl
= _w95dkelookup((long)key
->prevlvl
,nrofdkes
,nr2da
,keys
);
1329 key
->nextsub
= _w95dkelookup((long)key
->nextsub
,nrofdkes
,nr2da
,keys
);
1330 key
->next
= _w95dkelookup((long)key
->next
,nrofdkes
,nr2da
,keys
);
1335 _w95_walk_tree(lpkey
,keys
);
1339 /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1342 reghack - windows 3.11 registry data format demo program.
1344 The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1345 a combined hash table and tree description, and finally a text table.
1347 The header is obvious from the struct header. The taboff1 and taboff2
1348 fields are always 0x20, and their usage is unknown.
1350 The 8-byte entry table has various entry types.
1352 tabent[0] is a root index. The second word has the index of the root of
1354 tabent[1..hashsize] is a hash table. The first word in the hash entry is
1355 the index of the key/value that has that hash. Data with the same
1356 hash value are on a circular list. The other three words in the
1357 hash entry are always zero.
1358 tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1359 entry: dirent and keyent/valent. They are identified by context.
1360 tabent[freeidx] is the first free entry. The first word in a free entry
1361 is the index of the next free entry. The last has 0 as a link.
1362 The other three words in the free list are probably irrelevant.
1364 Entries in text table are preceeded by a word at offset-2. This word
1365 has the value (2*index)+1, where index is the referring keyent/valent
1366 entry in the table. I have no suggestion for the 2* and the +1.
1367 Following the word, there are N bytes of data, as per the keyent/valent
1368 entry length. The offset of the keyent/valent entry is from the start
1369 of the text table to the first data byte.
1371 This information is not available from Microsoft. The data format is
1372 deduced from the reg.dat file by me. Mistakes may
1373 have been made. I claim no rights and give no guarantees for this program.
1375 Tor Sjøwall, tor@sn.no
1378 /* reg.dat header format */
1379 struct _w31_header
{
1380 char cookie
[8]; /* 'SHCC3.10' */
1381 unsigned long taboff1
; /* offset of hash table (??) = 0x20 */
1382 unsigned long taboff2
; /* offset of index table (??) = 0x20 */
1383 unsigned long tabcnt
; /* number of entries in index table */
1384 unsigned long textoff
; /* offset of text part */
1385 unsigned long textsize
; /* byte size of text part */
1386 unsigned short hashsize
; /* hash size */
1387 unsigned short freeidx
; /* free index */
1390 /* generic format of table entries */
1391 struct _w31_tabent
{
1392 unsigned short w0
, w1
, w2
, w3
;
1395 /* directory tabent: */
1396 struct _w31_dirent
{
1397 unsigned short sibling_idx
; /* table index of sibling dirent */
1398 unsigned short child_idx
; /* table index of child dirent */
1399 unsigned short key_idx
; /* table index of key keyent */
1400 unsigned short value_idx
; /* table index of value valent */
1404 struct _w31_keyent
{
1405 unsigned short hash_idx
; /* hash chain index for string */
1406 unsigned short refcnt
; /* reference count */
1407 unsigned short length
; /* length of string */
1408 unsigned short string_off
; /* offset of string in text table */
1412 struct _w31_valent
{
1413 unsigned short hash_idx
; /* hash chain index for string */
1414 unsigned short refcnt
; /* reference count */
1415 unsigned short length
; /* length of string */
1416 unsigned short string_off
; /* offset of string in text table */
1419 /* recursive helper function to display a directory tree */
1421 __w31_dumptree( unsigned short idx
,
1423 struct _w31_tabent
*tab
,
1424 struct _w31_header
*head
,
1426 time_t lastmodified
,
1429 struct _w31_dirent
*dir
;
1430 struct _w31_keyent
*key
;
1431 struct _w31_valent
*val
;
1434 static char tail
[400];
1437 dir
=(struct _w31_dirent
*)&tab
[idx
];
1440 key
= (struct _w31_keyent
*)&tab
[dir
->key_idx
];
1442 memcpy(tail
,&txt
[key
->string_off
],key
->length
);
1443 tail
[key
->length
]='\0';
1444 /* all toplevel entries AND the entries in the
1445 * toplevel subdirectory belong to \SOFTWARE\Classes
1447 if (!level
&& !lstrcmp32A(tail
,".classes")) {
1448 __w31_dumptree(dir
->child_idx
,txt
,tab
,head
,lpkey
,lastmodified
,level
+1);
1449 idx
=dir
->sibling_idx
;
1452 name
=STRING32_DupAnsiToUni(tail
);
1454 xlpkey
=_find_or_add_key(lpkey
,name
);
1456 /* only add if leaf node or valued node */
1457 if (dir
->value_idx
!=0||dir
->child_idx
==0) {
1458 if (dir
->value_idx
) {
1459 val
=(struct _w31_valent
*)&tab
[dir
->value_idx
];
1460 memcpy(tail
,&txt
[val
->string_off
],val
->length
);
1461 tail
[val
->length
]='\0';
1462 value
=STRING32_DupAnsiToUni(tail
);
1463 _find_or_add_value(xlpkey
,NULL
,REG_SZ
,(LPBYTE
)value
,lstrlen32W(value
)*2+2,lastmodified
);
1467 dprintf_reg(stddeb
,"__w31_dumptree:strange: no directory key name, idx=%04x\n", idx
);
1469 __w31_dumptree(dir
->child_idx
,txt
,tab
,head
,xlpkey
,lastmodified
,level
+1);
1470 idx
=dir
->sibling_idx
;
1477 struct _w31_header head
;
1478 struct _w31_tabent
*tab
;
1482 BY_HANDLE_FILE_INFORMATION hfinfo
;
1483 time_t lastmodified
;
1487 hf
= OpenFile("reg.dat",&ofs
,OF_READ
);
1488 if (hf
==HFILE_ERROR
)
1491 /* read & dump header */
1492 if (sizeof(head
)!=_lread32(hf
,&head
,sizeof(head
))) {
1493 dprintf_reg(stddeb
,"_w31_loadreg:reg.dat is too short.\n");
1497 if (memcmp(head
.cookie
, "SHCC3.10", sizeof(head
.cookie
))!=0) {
1498 dprintf_reg(stddeb
,"_w31_loadreg:reg.dat has bad signature.\n");
1503 len
= head
.tabcnt
* sizeof(struct _w31_tabent
);
1504 /* read and dump index table */
1506 if (len
!=_lread32(hf
,tab
,len
)) {
1507 dprintf_reg(stderr
,"_w31_loadreg:couldn't read %d bytes.\n",len
);
1514 txt
= xmalloc(head
.textsize
);
1515 if (-1==_llseek(hf
,head
.textoff
,SEEK_SET
)) {
1516 dprintf_reg(stderr
,"_w31_loadreg:couldn't seek to textblock.\n");
1522 if (head
.textsize
!=_lread32(hf
,txt
,head
.textsize
)) {
1523 dprintf_reg(stderr
,"_w31_loadreg:textblock too short (%d instead of %ld).\n",len
,head
.textsize
);
1530 if (!GetFileInformationByHandle(hf
,&hfinfo
)) {
1531 dprintf_reg(stderr
,"_w31_loadreg:GetFileInformationByHandle failed?.\n");
1537 lastmodified
= DOSFS_FileTimeToUnixTime(&(hfinfo
.ftLastWriteTime
));
1539 if (RegCreateKey16(HKEY_LOCAL_MACHINE
,"\\SOFTWARE\\Classes",&hkey
)!=ERROR_SUCCESS
)
1541 lpkey
= lookup_hkey(hkey
);
1542 __w31_dumptree(tab
[0].w1
,txt
,tab
,&head
,lpkey
,lastmodified
,0);
1550 SHELL_LoadRegistry() {
1557 if (key_classes_root
==NULL
)
1560 /* Load windows 3.1 entries */
1562 /* Load windows 95 entries */
1563 _w95_loadreg("C:\\system.1st", key_local_machine
);
1564 _w95_loadreg("system.dat", key_local_machine
);
1565 _w95_loadreg("user.dat", key_users
);
1567 /* the global user default is loaded under HKEY_USERS\\.Default */
1568 RegCreateKey16(HKEY_USERS
,".Default",&hkey
);
1569 lpkey
= lookup_hkey(hkey
);
1570 _wine_loadreg(lpkey
,SAVE_USERS_DEFAULT
,0);
1572 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1573 _copy_registry(lpkey
,key_current_user
);
1576 /* the global machine defaults */
1577 _wine_loadreg(key_local_machine
,SAVE_LOCAL_MACHINE_DEFAULT
,0);
1579 /* load the user saved registries */
1581 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1583 pwd
=getpwuid(getuid());
1584 if (pwd
!=NULL
&& pwd
->pw_dir
!=NULL
) {
1585 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_CURRENT_USER
)+2);
1586 strcpy(fn
,pwd
->pw_dir
);
1587 strcat(fn
,WINE_PREFIX
"/"SAVE_CURRENT_USER
);
1588 _wine_loadreg(key_current_user
,fn
,REG_OPTION_TAINTED
);
1590 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_LOCAL_MACHINE
)+2);
1591 strcpy(fn
,pwd
->pw_dir
);
1592 strcat(fn
,WINE_PREFIX
"/"SAVE_LOCAL_MACHINE
);
1593 _wine_loadreg(key_local_machine
,fn
,REG_OPTION_TAINTED
);
1596 fprintf(stderr
,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1597 if (ERROR_SUCCESS
==RegCreateKey16(HKEY_CURRENT_USER
,KEY_REGISTRY
,&hkey
)) {
1598 DWORD junk
,type
,len
;
1602 if (( RegQueryValueEx32A(
1609 )!=ERROR_SUCCESS
) ||
1612 RegSetValueEx32A(hkey
,VAL_SAVEUPDATED
,0,REG_SZ
,"yes",4);
1618 /********************* API FUNCTIONS ***************************************/
1622 * All functions are stubs to RegOpenKeyEx32W where all the
1625 * FIXME: security,options,desiredaccess,...
1628 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1629 * RegOpenKey32W -> RegOpenKeyEx32W
1632 /* RegOpenKeyExW [ADVAPI32.150] */
1633 DWORD
RegOpenKeyEx32W(
1640 LPKEYSTRUCT lpNextKey
,lpxkey
;
1643 dprintf_reg(stddeb
,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1644 (LONG
)hkey
,W2C(lpszSubKey
,0),dwReserved
,samDesired
,retkey
1647 lpNextKey
= lookup_hkey(hkey
);
1649 return SHELL_ERROR_BADKEY
;
1650 if (!lpszSubKey
|| !*lpszSubKey
) {
1651 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1652 *retkey
=currenthandle
;
1653 return SHELL_ERROR_SUCCESS
;
1655 split_keypath(lpszSubKey
,&wps
,&wpc
);
1657 while ((i
<wpc
) && (wps
[i
][0]=='\0')) i
++;
1660 lpxkey
=lpNextKey
->nextsub
;
1662 if (!lstrcmp32W(wps
[i
],lpxkey
->keyname
))
1664 lpxkey
=lpxkey
->next
;
1668 return SHELL_ERROR_BADKEY
;
1673 add_handle(++currenthandle
,lpxkey
,samDesired
);
1674 *retkey
= currenthandle
;
1676 return SHELL_ERROR_SUCCESS
;
1679 /* RegOpenKeyW [ADVAPI32.151] */
1680 DWORD
RegOpenKey32W(
1685 dprintf_reg(stddeb
,"RegOpenKey32W(%lx,%s,%p)\n",
1686 (LONG
)hkey
,W2C(lpszSubKey
,0),retkey
1688 return RegOpenKeyEx32W(hkey
,lpszSubKey
,0,KEY_ALL_ACCESS
,retkey
);
1692 /* RegOpenKeyExA [ADVAPI32.149] */
1693 DWORD
RegOpenKeyEx32A(
1703 dprintf_reg(stddeb
,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1704 (LONG
)hkey
,lpszSubKey
,dwReserved
,samDesired
,retkey
1707 lpszSubKeyW
=strdupA2W(lpszSubKey
);
1710 ret
=RegOpenKeyEx32W(hkey
,lpszSubKeyW
,dwReserved
,samDesired
,retkey
);
1716 /* RegOpenKeyA [ADVAPI32.148] */
1717 DWORD
RegOpenKey32A(
1722 dprintf_reg(stddeb
,"RegOpenKey32A(%lx,%s,%p)\n",
1723 (LONG
)hkey
,lpszSubKey
,retkey
1725 return RegOpenKeyEx32A(hkey
,lpszSubKey
,0,KEY_ALL_ACCESS
,retkey
);
1728 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1734 dprintf_reg(stddeb
,"RegOpenKey16(%lx,%s,%p)\n",
1735 (LONG
)hkey
,lpszSubKey
,retkey
1737 return RegOpenKey32A(hkey
,lpszSubKey
,retkey
);
1743 * All those functions convert their respective
1744 * arguments and call RegCreateKeyExW at the end.
1746 * FIXME: no security,no access attrib,no optionhandling yet.
1749 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1750 * RegCreateKey32W -> RegCreateKeyEx32W
1753 /* RegCreateKeyExW [ADVAPI32.131] */
1754 DWORD
RegCreateKeyEx32W(
1761 LPSECURITY_ATTRIBUTES lpSecAttribs
,
1765 LPKEYSTRUCT
*lplpPrevKey
,lpNextKey
,lpxkey
;
1769 /*FIXME: handle security/access/whatever */
1770 dprintf_reg(stddeb
,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1782 lpNextKey
= lookup_hkey(hkey
);
1784 return SHELL_ERROR_BADKEY
;
1785 if (!lpszSubKey
|| !*lpszSubKey
) {
1786 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1787 *retkey
=currenthandle
;
1788 lpNextKey
->flags
|=REG_OPTION_TAINTED
;
1789 return SHELL_ERROR_SUCCESS
;
1791 split_keypath(lpszSubKey
,&wps
,&wpc
);
1793 while ((i
<wpc
) && (wps
[i
][0]=='\0')) i
++;
1796 lpxkey
=lpNextKey
->nextsub
;
1798 if (!lstrcmp32W(wps
[i
],lpxkey
->keyname
))
1800 lpxkey
=lpxkey
->next
;
1808 add_handle(++currenthandle
,lpxkey
,samDesired
);
1809 lpxkey
->flags
|= REG_OPTION_TAINTED
;
1810 *retkey
= currenthandle
;
1812 *lpDispos
= REG_OPENED_EXISTING_KEY
;
1814 return SHELL_ERROR_SUCCESS
;
1816 /* good. now the hard part */
1818 lplpPrevKey
= &(lpNextKey
->nextsub
);
1819 lpxkey
= *lplpPrevKey
;
1821 lplpPrevKey
= &(lpxkey
->next
);
1822 lpxkey
= *lplpPrevKey
;
1824 *lplpPrevKey
=malloc(sizeof(KEYSTRUCT
));
1825 if (!*lplpPrevKey
) {
1827 return SHELL_ERROR_OUTOFMEMORY
;
1829 memset(*lplpPrevKey
,'\0',sizeof(KEYSTRUCT
));
1830 (*lplpPrevKey
)->keyname
= strdupW(wps
[i
]);
1831 (*lplpPrevKey
)->next
= NULL
;
1832 (*lplpPrevKey
)->nextsub
= NULL
;
1833 (*lplpPrevKey
)->values
= NULL
;
1834 (*lplpPrevKey
)->nrofvalues
= 0;
1835 (*lplpPrevKey
)->flags
= REG_OPTION_TAINTED
;
1837 (*lplpPrevKey
)->class = strdupW(lpszClass
);
1839 (*lplpPrevKey
)->class = NULL
;
1840 lpNextKey
= *lplpPrevKey
;
1843 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1845 /*FIXME: flag handling correct? */
1846 lpNextKey
->flags
= fdwOptions
|REG_OPTION_TAINTED
;
1848 lpNextKey
->class = strdupW(lpszClass
);
1850 lpNextKey
->class = NULL
;
1851 *retkey
= currenthandle
;
1853 *lpDispos
= REG_CREATED_NEW_KEY
;
1855 return SHELL_ERROR_SUCCESS
;
1858 /* RegCreateKeyW [ADVAPI32.132] */
1859 DWORD
RegCreateKey32W(
1866 dprintf_reg(stddeb
,"RegCreateKey32W(%lx,%s,%p)\n",
1867 (LONG
)hkey
,W2C(lpszSubKey
,0),retkey
1869 ret
=RegCreateKeyEx32W(
1870 hkey
, /* key handle */
1871 lpszSubKey
, /* subkey name */
1872 0, /* reserved = 0 */
1873 NULL
, /* lpszClass? FIXME: ? */
1874 REG_OPTION_NON_VOLATILE
, /* options */
1875 KEY_ALL_ACCESS
, /* desired access attribs */
1876 NULL
, /* lpsecurity attributes */
1877 retkey
, /* lpretkey */
1878 &junk
/* disposition value */
1883 /* RegCreateKeyExA [ADVAPI32.130] */
1884 DWORD
RegCreateKeyEx32A(
1891 LPSECURITY_ATTRIBUTES lpSecAttribs
,
1895 LPWSTR lpszSubKeyW
,lpszClassW
;
1898 dprintf_reg(stddeb
,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1910 lpszSubKeyW
=strdupA2W(lpszSubKey
);
1914 lpszClassW
=strdupA2W(lpszClass
);
1917 ret
=RegCreateKeyEx32W(
1935 /* RegCreateKeyA [ADVAPI32.129] */
1936 DWORD
RegCreateKey32A(
1943 dprintf_reg(stddeb
,"RegCreateKey32A(%lx,%s,%p)\n",
1944 (LONG
)hkey
,lpszSubKey
,retkey
1946 return RegCreateKeyEx32A(
1947 hkey
, /* key handle */
1948 lpszSubKey
, /* subkey name */
1949 0, /* reserved = 0 */
1950 NULL
, /* lpszClass? FIXME: ? */
1951 REG_OPTION_NON_VOLATILE
,/* options */
1952 KEY_ALL_ACCESS
, /* desired access attribs */
1953 NULL
, /* lpsecurity attributes */
1954 retkey
, /* lpretkey */
1955 &junk
/* disposition value */
1959 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1960 DWORD
RegCreateKey16(
1965 dprintf_reg(stddeb
,"RegCreateKey16(%lx,%s,%p)\n",
1966 (LONG
)hkey
,lpszSubKey
,retkey
1968 return RegCreateKey32A(hkey
,lpszSubKey
,retkey
);
1972 * Query Value Functions
1973 * Win32 differs between keynames and valuenames.
1974 * multiple values may belong to one key, the special value
1975 * with name NULL is the default value used by the win31
1979 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1980 * RegQueryValue32W -> RegQueryValueEx32W
1983 /* RegQueryValueExW [ADVAPI32.158] */
1984 DWORD
RegQueryValueEx32W(
1986 LPWSTR lpszValueName
,
1987 LPDWORD lpdwReserved
,
1995 dprintf_reg(stddeb
,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%ld)\n",
1996 hkey
,W2C(lpszValueName
,0),lpdwReserved
,lpdwType
,lpbData
,
1997 lpcbData
?*lpcbData
:0
2000 lpkey
= lookup_hkey(hkey
);
2002 return SHELL_ERROR_BADKEY
;
2003 if (lpszValueName
==NULL
) {
2004 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2005 if (lpkey
->values
[i
].name
==NULL
)
2008 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2009 if ( lpkey
->values
[i
].name
&&
2010 !lstrcmp32W(lpszValueName
,lpkey
->values
[i
].name
)
2014 if (i
==lpkey
->nrofvalues
) {
2015 if (lpszValueName
==NULL
) {
2017 *(WCHAR
*)lpbData
= 0;
2022 return SHELL_ERROR_SUCCESS
;
2024 return SHELL_ERROR_BADKEY
;/*FIXME: correct return? */
2027 *lpdwType
= lpkey
->values
[i
].type
;
2028 if (lpbData
==NULL
) {
2030 return SHELL_ERROR_SUCCESS
;
2031 *lpcbData
= lpkey
->values
[i
].len
;
2032 return SHELL_ERROR_SUCCESS
;
2034 if (*lpcbData
<lpkey
->values
[i
].len
) {
2037 *lpcbData
= lpkey
->values
[i
].len
;
2038 return ERROR_MORE_DATA
;
2040 memcpy(lpbData
,lpkey
->values
[i
].data
,lpkey
->values
[i
].len
);
2041 *lpcbData
= lpkey
->values
[i
].len
;
2042 return SHELL_ERROR_SUCCESS
;
2045 /* RegQueryValueW [ADVAPI32.159] */
2046 DWORD
RegQueryValue32W(
2055 dprintf_reg(stddeb
,"RegQueryValue32W(%x,%s,%p,%ld)\n->",
2056 hkey
,W2C(lpszSubKey
,0),lpszData
,
2057 lpcbData
?*lpcbData
:0
2060 /* only open subkey, if we really do descend */
2061 if (lpszSubKey
&& *lpszSubKey
) {
2062 ret
= RegOpenKey32W(hkey
,lpszSubKey
,&xhkey
);
2063 if (ret
!=ERROR_SUCCESS
)
2069 ret
= RegQueryValueEx32W(
2071 NULL
, /* varname NULL -> compat */
2072 NULL
, /* lpdwReserved, must be NULL */
2082 /* RegQueryValueExA [ADVAPI32.157] */
2083 DWORD
RegQueryValueEx32A(
2085 LPSTR lpszValueName
,
2086 LPDWORD lpdwReserved
,
2091 LPWSTR lpszValueNameW
;
2097 dprintf_reg(stddeb
,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%ld)\n->",
2098 hkey
,lpszValueName
,lpdwReserved
,lpdwType
,lpbData
,
2099 lpcbData
?*lpcbData
:0
2103 buf
= (LPBYTE
)xmalloc((*lpcbData
)*2);
2104 myxlen
= *lpcbData
*2;
2109 myxlen
= *lpcbData
*2;
2115 lpszValueNameW
=strdupA2W(lpszValueName
);
2117 lpszValueNameW
=NULL
;
2121 ret
=RegQueryValueEx32W(
2131 if (ret
==ERROR_SUCCESS
) {
2133 if (UNICONVMASK
& (1<<(type
))) {
2134 /* convert UNICODE to ASCII */
2135 strcpyWA(lpbData
,(LPWSTR
)buf
);
2136 *lpcbData
= myxlen
/2;
2138 if (myxlen
>*lpcbData
)
2139 ret
= ERROR_MORE_DATA
;
2141 memcpy(lpbData
,buf
,myxlen
);
2146 if ((UNICONVMASK
& (1<<(type
))) && lpcbData
)
2147 *lpcbData
= myxlen
/2;
2150 if ((UNICONVMASK
& (1<<(type
))) && lpcbData
)
2151 *lpcbData
= myxlen
/2;
2158 /* RegQueryValueEx [KERNEL.225] */
2159 DWORD
RegQueryValueEx16(
2161 LPSTR lpszValueName
,
2162 LPDWORD lpdwReserved
,
2167 dprintf_reg(stddeb
,"RegQueryValueEx16(%x,%s,%p,%p,%p,%ld)\n",
2168 hkey
,lpszValueName
,lpdwReserved
,lpdwType
,lpbData
,
2169 lpcbData
?*lpcbData
:0
2171 return RegQueryValueEx32A(
2181 /* RegQueryValueA [ADVAPI32.156] */
2182 DWORD
RegQueryValue32A(
2191 dprintf_reg(stddeb
,"RegQueryValue32A(%x,%s,%p,%ld)\n",
2192 hkey
,lpszSubKey
,lpszData
,
2193 lpcbData
?*lpcbData
:0
2196 /* only open subkey, if we really do descend */
2197 if (lpszSubKey
&& *lpszSubKey
) {
2198 ret
= RegOpenKey16(hkey
,lpszSubKey
,&xhkey
);
2199 if (ret
!=ERROR_SUCCESS
)
2205 ret
= RegQueryValueEx32A(
2207 NULL
, /* lpszValueName NULL -> compat */
2208 NULL
, /* lpdwReserved, must be NULL */
2218 /* RegQueryValue [SHELL.6] [KERNEL.224] */
2219 DWORD
RegQueryValue16(
2225 dprintf_reg(stddeb
,"RegQueryValue16(%x,%s,%p,%ld)\n",
2226 hkey
,lpszSubKey
,lpszData
,lpcbData
?*lpcbData
:0
2228 /* HACK: the 16bit RegQueryValue doesn't handle selectorblocks
2229 * anyway, so we just mask out the high 16 bit.
2230 * (this (not so much incidently;) hopefully fixes Aldus FH4)
2233 *lpcbData
&= 0xFFFF;
2234 return RegQueryValue32A(hkey
,lpszSubKey
,lpszData
,lpcbData
);
2238 * Setting values of Registry keys
2241 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
2242 * RegSetValue32W -> RegSetValueEx32W
2245 /* RegSetValueExW [ADVAPI32.170] */
2246 DWORD
RegSetValueEx32W(
2248 LPWSTR lpszValueName
,
2257 dprintf_reg(stddeb
,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
2258 hkey
,W2C(lpszValueName
,0),dwReserved
,dwType
,lpbData
,cbData
2260 /* we no longer care about the lpbData type here... */
2261 lpkey
= lookup_hkey(hkey
);
2263 return SHELL_ERROR_BADKEY
;
2265 lpkey
->flags
|= REG_OPTION_TAINTED
;
2267 if (lpszValueName
==NULL
) {
2268 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2269 if (lpkey
->values
[i
].name
==NULL
)
2272 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2273 if ( lpkey
->values
[i
].name
&&
2274 !lstrcmp32W(lpszValueName
,lpkey
->values
[i
].name
)
2278 if (i
==lpkey
->nrofvalues
) {
2279 lpkey
->values
= (LPKEYVALUE
)xrealloc(
2281 (lpkey
->nrofvalues
+1)*sizeof(KEYVALUE
)
2283 lpkey
->nrofvalues
++;
2284 memset(lpkey
->values
+i
,'\0',sizeof(KEYVALUE
));
2286 if (lpkey
->values
[i
].name
==NULL
)
2288 lpkey
->values
[i
].name
= strdupW(lpszValueName
);
2290 lpkey
->values
[i
].name
= NULL
;
2291 lpkey
->values
[i
].len
= cbData
;
2292 lpkey
->values
[i
].type
= dwType
;
2293 if (lpkey
->values
[i
].data
!=NULL
)
2294 free(lpkey
->values
[i
].data
);
2295 lpkey
->values
[i
].data
= (LPBYTE
)xmalloc(cbData
);
2296 lpkey
->values
[i
].lastmodified
= time(NULL
);
2297 memcpy(lpkey
->values
[i
].data
,lpbData
,cbData
);
2298 return SHELL_ERROR_SUCCESS
;
2301 /* RegSetValueExA [ADVAPI32.169] */
2302 DWORD
RegSetValueEx32A(
2304 LPSTR lpszValueName
,
2311 LPWSTR lpszValueNameW
;
2314 dprintf_reg(stddeb
,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
2315 hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
2317 if ((1<<dwType
) & UNICONVMASK
) {
2318 buf
=(LPBYTE
)strdupA2W(lpbData
);
2319 cbData
=2*strlen(lpbData
)+2;
2323 lpszValueNameW
= strdupA2W(lpszValueName
);
2325 lpszValueNameW
= NULL
;
2326 ret
=RegSetValueEx32W(hkey
,lpszValueNameW
,dwReserved
,dwType
,buf
,cbData
);
2328 free(lpszValueNameW
);
2334 /* RegSetValueEx [KERNEL.226] */
2335 DWORD
RegSetValueEx16(
2337 LPSTR lpszValueName
,
2343 dprintf_reg(stddeb
,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2344 hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
2346 return RegSetValueEx32A(hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
);
2349 /* RegSetValueW [ADVAPI32.171] */
2350 DWORD
RegSetValue32W(
2360 dprintf_reg(stddeb
,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2361 hkey
,W2C(lpszSubKey
,0),dwType
,W2C(lpszData
,0),cbData
2363 if (lpszSubKey
&& *lpszSubKey
) {
2364 ret
=RegCreateKey32W(hkey
,lpszSubKey
,&xhkey
);
2365 if (ret
!=ERROR_SUCCESS
)
2369 if (dwType
!=REG_SZ
) {
2370 fprintf(stddeb
,"RegSetValueX called with dwType=%ld!\n",dwType
);
2373 if (cbData
!=2*lstrlen32W(lpszData
)+2) {
2374 dprintf_reg(stddeb
,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2375 cbData
,W2C(lpszData
,0),2*lstrlen32W(lpszData
)+2
2377 cbData
=2*lstrlen32W(lpszData
)+2;
2379 ret
=RegSetValueEx32W(xhkey
,NULL
,0,dwType
,(LPBYTE
)lpszData
,cbData
);
2385 /* RegSetValueA [ADVAPI32.168] */
2386 DWORD
RegSetValue32A(
2396 dprintf_reg(stddeb
,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2397 hkey
,lpszSubKey
,dwType
,lpszData
,cbData
2399 if (lpszSubKey
&& *lpszSubKey
) {
2400 ret
=RegCreateKey16(hkey
,lpszSubKey
,&xhkey
);
2401 if (ret
!=ERROR_SUCCESS
)
2406 if (dwType
!=REG_SZ
) {
2407 dprintf_reg(stddeb
,"RegSetValueA called with dwType=%ld!\n",dwType
);
2410 if (cbData
!=strlen(lpszData
)+1)
2411 cbData
=strlen(lpszData
)+1;
2412 ret
=RegSetValueEx32A(xhkey
,NULL
,0,dwType
,(LPBYTE
)lpszData
,cbData
);
2418 /* RegSetValue [KERNEL.221] [SHELL.5] */
2419 DWORD
RegSetValue16(
2427 dprintf_reg(stddeb
,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2428 hkey
,lpszSubKey
,dwType
,lpszData
,cbData
2430 ret
=RegSetValue32A(hkey
,lpszSubKey
,dwType
,lpszData
,cbData
);
2438 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2439 * RegEnumKey32W -> RegEnumKeyEx32W
2442 /* RegEnumKeyExW [ADVAPI32.139] */
2443 DWORD
RegEnumKeyEx32W(
2448 LPDWORD lpdwReserved
,
2453 LPKEYSTRUCT lpkey
,lpxkey
;
2455 dprintf_reg(stddeb
,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2456 hkey
,iSubkey
,lpszName
,*lpcchName
,lpdwReserved
,lpszClass
,lpcchClass
,ft
2458 lpkey
=lookup_hkey(hkey
);
2460 return SHELL_ERROR_BADKEY
;
2461 if (!lpkey
->nextsub
)
2462 return ERROR_NO_MORE_ITEMS
;
2463 lpxkey
=lpkey
->nextsub
;
2464 while (iSubkey
&& lpxkey
) {
2466 lpxkey
=lpxkey
->next
;
2468 if (iSubkey
|| !lpxkey
)
2469 return ERROR_NO_MORE_ITEMS
;
2470 if (2*lstrlen32W(lpxkey
->keyname
)+2>*lpcchName
)
2471 return ERROR_MORE_DATA
;
2472 memcpy(lpszName
,lpxkey
->keyname
,lstrlen32W(lpxkey
->keyname
)*2+2);
2474 /* what should we write into it? */
2478 return ERROR_SUCCESS
;
2482 /* RegEnumKeyW [ADVAPI32.140] */
2483 DWORD
RegEnumKey32W(
2491 dprintf_reg(stddeb
,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2492 hkey
,iSubkey
,lpszName
,lpcchName
2494 return RegEnumKeyEx32W(hkey
,iSubkey
,lpszName
,&lpcchName
,NULL
,NULL
,NULL
,&ft
);
2496 /* RegEnumKeyExA [ADVAPI32.138] */
2497 DWORD
RegEnumKeyEx32A(
2502 LPDWORD lpdwReserved
,
2507 DWORD ret
,lpcchNameW
,lpcchClassW
;
2508 LPWSTR lpszNameW
,lpszClassW
;
2511 dprintf_reg(stddeb
,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2512 hkey
,iSubkey
,lpszName
,*lpcchName
,lpdwReserved
,lpszClass
,lpcchClass
,ft
2515 lpszNameW
= (LPWSTR
)xmalloc(*lpcchName
*2);
2516 lpcchNameW
= *lpcchName
*2;
2522 lpszClassW
= (LPWSTR
)xmalloc(*lpcchClass
*2);
2523 lpcchClassW
= *lpcchClass
*2;
2528 ret
=RegEnumKeyEx32W(
2538 if (ret
==ERROR_SUCCESS
) {
2539 strcpyWA(lpszName
,lpszNameW
);
2540 *lpcchName
=strlen(lpszName
);
2542 strcpyWA(lpszClass
,lpszClassW
);
2543 *lpcchClass
=strlen(lpszClass
);
2553 /* RegEnumKeyA [ADVAPI32.137] */
2554 DWORD
RegEnumKey32A(
2562 dprintf_reg(stddeb
,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2563 hkey
,iSubkey
,lpszName
,lpcchName
2565 return RegEnumKeyEx32A(
2577 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2584 dprintf_reg(stddeb
,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2585 hkey
,iSubkey
,lpszName
,lpcchName
2587 return RegEnumKey32A(hkey
,iSubkey
,lpszName
,lpcchName
);
2591 * Enumerate Registry Values
2594 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2597 /* RegEnumValueW [ADVAPI32.142] */
2598 DWORD
RegEnumValue32W(
2603 LPDWORD lpdReserved
,
2611 dprintf_reg(stddeb
,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2612 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2614 lpkey
= lookup_hkey(hkey
);
2616 return SHELL_ERROR_BADKEY
;
2617 if (lpkey
->nrofvalues
<=iValue
)
2618 return ERROR_NO_MORE_ITEMS
;
2619 val
= lpkey
->values
+iValue
;
2622 if (lstrlen32W(val
->name
)*2+2>*lpcchValue
) {
2623 *lpcchValue
= lstrlen32W(val
->name
)*2+2;
2624 return ERROR_MORE_DATA
;
2626 memcpy(lpszValue
,val
->name
,2*lstrlen32W(val
->name
)+2);
2627 *lpcchValue
=lstrlen32W(val
->name
)*2+2;
2629 /* how to handle NULL value? */
2633 *lpdwType
=val
->type
;
2635 if (val
->len
>*lpcbData
)
2636 return ERROR_MORE_DATA
;
2637 memcpy(lpbData
,val
->data
,val
->len
);
2638 *lpcbData
= val
->len
;
2640 return SHELL_ERROR_SUCCESS
;
2643 /* RegEnumValueA [ADVAPI32.141] */
2644 DWORD
RegEnumValue32A(
2649 LPDWORD lpdReserved
,
2656 DWORD ret
,lpcbDataW
;
2658 dprintf_reg(stddeb
,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2659 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2662 lpszValueW
= (LPWSTR
)xmalloc(*lpcchValue
*2);
2664 lpbDataW
= (LPBYTE
)xmalloc(*lpcbData
*2);
2665 lpcbDataW
= *lpcbData
*2;
2668 ret
=RegEnumValue32W(
2679 if (ret
==ERROR_SUCCESS
) {
2680 strcpyWA(lpszValue
,lpszValueW
);
2682 if ((1<<*lpdwType
) & UNICONVMASK
) {
2683 strcpyWA(lpbData
,(LPWSTR
)lpbDataW
);
2685 if (lpcbDataW
> *lpcbData
)
2686 ret
= ERROR_MORE_DATA
;
2688 memcpy(lpbData
,lpbDataW
,lpcbDataW
);
2690 *lpcbData
= lpcbDataW
;
2700 /* RegEnumValue [KERNEL.223] */
2701 DWORD
RegEnumValue16(
2706 LPDWORD lpdReserved
,
2711 dprintf_reg(stddeb
,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2712 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2714 return RegEnumValue32A(
2727 * Close registry key
2729 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2730 DWORD
RegCloseKey(HKEY hkey
) {
2731 dprintf_reg(stddeb
,"RegCloseKey(%x)\n",hkey
);
2732 remove_handle(hkey
);
2733 return ERROR_SUCCESS
;
2736 * Delete registry key
2739 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2741 /* RegDeleteKeyW [ADVAPI32.134] */
2742 DWORD
RegDeleteKey32W(HKEY hkey
,LPWSTR lpszSubKey
) {
2743 LPKEYSTRUCT
*lplpPrevKey
,lpNextKey
,lpxkey
;
2747 dprintf_reg(stddeb
,"RegDeleteKey32W(%x,%s)\n",
2748 hkey
,W2C(lpszSubKey
,0)
2750 lpNextKey
= lookup_hkey(hkey
);
2752 return SHELL_ERROR_BADKEY
;
2753 /* we need to know the previous key in the hier. */
2754 if (!lpszSubKey
|| !*lpszSubKey
)
2755 return SHELL_ERROR_BADKEY
;
2756 split_keypath(lpszSubKey
,&wps
,&wpc
);
2760 lpxkey
=lpNextKey
->nextsub
;
2762 if (!lstrcmp32W(wps
[i
],lpxkey
->keyname
))
2764 lpxkey
=lpxkey
->next
;
2768 /* not found is success */
2769 return SHELL_ERROR_SUCCESS
;
2774 lpxkey
= lpNextKey
->nextsub
;
2775 lplpPrevKey
= &(lpNextKey
->nextsub
);
2777 if (!lstrcmp32W(wps
[i
],lpxkey
->keyname
))
2779 lplpPrevKey
= &(lpxkey
->next
);
2780 lpxkey
= lpxkey
->next
;
2783 return SHELL_ERROR_SUCCESS
;
2784 if (lpxkey
->nextsub
)
2785 return SHELL_ERROR_CANTWRITE
;
2786 *lplpPrevKey
= lpxkey
->next
;
2787 free(lpxkey
->keyname
);
2789 free(lpxkey
->class);
2791 free(lpxkey
->values
);
2794 return SHELL_ERROR_SUCCESS
;
2797 /* RegDeleteKeyA [ADVAPI32.133] */
2798 DWORD
RegDeleteKey32A(HKEY hkey
,LPCSTR lpszSubKey
) {
2802 dprintf_reg(stddeb
,"RegDeleteKey32A(%x,%s)\n",
2805 lpszSubKeyW
=strdupA2W(lpszSubKey
);
2806 ret
=RegDeleteKey32W(hkey
,lpszSubKeyW
);
2811 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2812 DWORD
RegDeleteKey16(HKEY hkey
,LPCSTR lpszSubKey
) {
2813 dprintf_reg(stddeb
,"RegDeleteKey16(%x,%s)\n",
2816 return RegDeleteKey32A(hkey
,lpszSubKey
);
2820 * Delete registry value
2823 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2825 /* RegDeleteValueW [ADVAPI32.136] */
2826 DWORD
RegDeleteValue32W(HKEY hkey
,LPWSTR lpszValue
) {
2831 dprintf_reg(stddeb
,"RegDeleteValue32W(%x,%s)\n",
2832 hkey
,W2C(lpszValue
,0)
2834 lpkey
=lookup_hkey(hkey
);
2836 return SHELL_ERROR_BADKEY
;
2838 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2839 if ( lpkey
->values
[i
].name
&&
2840 !lstrcmp32W(lpkey
->values
[i
].name
,lpszValue
)
2844 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2845 if (lpkey
->values
[i
].name
==NULL
)
2848 if (i
==lpkey
->nrofvalues
)
2849 return SHELL_ERROR_BADKEY
;/*FIXME: correct errorcode? */
2850 val
= lpkey
->values
+i
;
2851 if (val
->name
) free(val
->name
);
2852 if (val
->data
) free(val
->data
);
2856 sizeof(KEYVALUE
)*(lpkey
->nrofvalues
-i
-1)
2858 lpkey
->values
= (LPKEYVALUE
)xrealloc(
2860 (lpkey
->nrofvalues
-1)*sizeof(KEYVALUE
)
2862 lpkey
->nrofvalues
--;
2863 return SHELL_ERROR_SUCCESS
;
2866 /* RegDeleteValueA [ADVAPI32.135] */
2867 DWORD
RegDeleteValue32A(HKEY hkey
,LPSTR lpszValue
) {
2871 dprintf_reg( stddeb
, "RegDeleteValue32A(%x,%s)\n", hkey
,lpszValue
);
2873 lpszValueW
=strdupA2W(lpszValue
);
2876 ret
=RegDeleteValue32W(hkey
,lpszValueW
);
2882 /* RegDeleteValue [KERNEL.222] */
2883 DWORD
RegDeleteValue16(HKEY hkey
,LPSTR lpszValue
) {
2884 dprintf_reg( stddeb
,"RegDeleteValue16(%x,%s)\n", hkey
,lpszValue
);
2885 return RegDeleteValue32A(hkey
,lpszValue
);
2888 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2889 DWORD
RegFlushKey(HKEY hkey
) {
2890 dprintf_reg(stddeb
,"RegFlushKey(%x), STUB.\n",hkey
);
2891 return SHELL_ERROR_SUCCESS
;
2894 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2896 /* RegQueryInfoKeyW [ADVAPI32.153] */
2897 DWORD
RegQueryInfoKey32W(
2901 LPDWORD lpdwReserved
,
2903 LPDWORD lpcchMaxSubkey
,
2904 LPDWORD lpcchMaxClass
,
2906 LPDWORD lpcchMaxValueName
,
2907 LPDWORD lpccbMaxValueData
,
2908 LPDWORD lpcbSecurityDescriptor
,
2911 LPKEYSTRUCT lpkey
,lpxkey
;
2912 int nrofkeys
,maxsubkey
,maxclass
,maxvalues
,maxvname
,maxvdata
;
2915 dprintf_reg(stddeb
,"RegQueryInfoKey32W(%x,......)\n",hkey
);
2916 lpkey
=lookup_hkey(hkey
);
2918 return SHELL_ERROR_BADKEY
;
2921 if (lstrlen32W(lpkey
->class)*2+2>*lpcchClass
) {
2922 *lpcchClass
=lstrlen32W(lpkey
->class)*2;
2923 return ERROR_MORE_DATA
;
2925 *lpcchClass
=lstrlen32W(lpkey
->class)*2;
2926 memcpy(lpszClass
,lpkey
->class,lstrlen32W(lpkey
->class));
2933 *lpcchClass
= lstrlen32W(lpkey
->class)*2;
2935 lpxkey
=lpkey
->nextsub
;
2936 nrofkeys
=maxsubkey
=maxclass
=maxvalues
=maxvname
=maxvdata
=0;
2939 if (lstrlen32W(lpxkey
->keyname
)>maxsubkey
)
2940 maxsubkey
=lstrlen32W(lpxkey
->keyname
);
2941 if (lpxkey
->class && lstrlen32W(lpxkey
->class)>maxclass
)
2942 maxclass
=lstrlen32W(lpxkey
->class);
2943 if (lpxkey
->nrofvalues
>maxvalues
)
2944 maxvalues
=lpxkey
->nrofvalues
;
2945 for (i
=0;i
<lpxkey
->nrofvalues
;i
++) {
2946 LPKEYVALUE val
=lpxkey
->values
+i
;
2948 if (val
->name
&& lstrlen32W(val
->name
)>maxvname
)
2949 maxvname
=lstrlen32W(val
->name
);
2950 if (val
->len
>maxvdata
)
2953 lpxkey
=lpxkey
->next
;
2955 if (!maxclass
) maxclass
= 1;
2956 if (!maxvname
) maxvname
= 1;
2958 *lpcSubKeys
= nrofkeys
;
2960 *lpcchMaxSubkey
= maxsubkey
*2;
2962 *lpcchMaxClass
= maxclass
*2;
2964 *lpcValues
= maxvalues
;
2965 if (lpcchMaxValueName
)
2966 *lpcchMaxValueName
= maxvname
;
2967 if (lpccbMaxValueData
)
2968 *lpccbMaxValueData
= maxvdata
;
2969 return SHELL_ERROR_SUCCESS
;
2972 /* RegQueryInfoKeyA [ADVAPI32.152] */
2973 DWORD
RegQueryInfoKey32A(
2977 LPDWORD lpdwReserved
,
2979 LPDWORD lpcchMaxSubkey
,
2980 LPDWORD lpcchMaxClass
,
2982 LPDWORD lpcchMaxValueName
,
2983 LPDWORD lpccbMaxValueData
,
2984 LPDWORD lpcbSecurityDescriptor
,
2990 dprintf_reg(stddeb
,"RegQueryInfoKey32A(%x,......)\n",hkey
);
2993 lpszClassW
= (LPWSTR
)xmalloc(*lpcchClass
);
2997 ret
=RegQueryInfoKey32W(
3008 lpcbSecurityDescriptor
,
3011 if (ret
==ERROR_SUCCESS
)
3012 strcpyWA(lpszClass
,lpszClassW
);
3019 if (lpcchMaxValueName
)
3020 *lpcchMaxValueName
/=2;