4 * Copyright 1996 Marcus Meissner
13 #include <sys/types.h>
14 #include <sys/fcntl.h>
29 /* FIXME: following defines should be configured global ... */
31 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
32 #define WINE_PREFIX "/.wine"
33 #define SAVE_USERS_DEFAULT "/usr/local/etc/wine.userreg"
34 #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
36 /* relative in ~user/.wine/ : */
37 #define SAVE_CURRENT_USER "user.reg"
38 #define SAVE_LOCAL_MACHINE "system.reg"
40 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
41 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
43 /* one value of a key */
44 typedef struct tagKEYVALUE
46 LPWSTR name
; /* name of value (UNICODE) or NULL for win31 */
47 DWORD type
; /* type of value */
48 DWORD len
; /* length of data */
49 DWORD lastmodified
; /* time of seconds since 1.1.1970 */
50 LPBYTE data
; /* content, may be strings, binaries, etc. */
51 } KEYVALUE
,*LPKEYVALUE
;
54 typedef struct tagKEYSTRUCT
56 LPWSTR keyname
; /* name of THIS key (UNICODE) */
57 DWORD flags
; /* flags. */
60 DWORD nrofvalues
; /* nr of values in THIS key */
61 LPKEYVALUE values
; /* values in THIS key */
62 /* key management pointers */
63 struct tagKEYSTRUCT
*next
; /* next key on same hierarchy */
64 struct tagKEYSTRUCT
*nextsub
; /* keys that hang below THIS key */
65 } KEYSTRUCT
, *LPKEYSTRUCT
;
68 static KEYSTRUCT
*key_classes_root
=NULL
; /* windows 3.1 global values */
69 static KEYSTRUCT
*key_current_user
=NULL
; /* user specific values */
70 static KEYSTRUCT
*key_local_machine
=NULL
;/* machine specific values */
71 static KEYSTRUCT
*key_users
=NULL
; /* all users? */
73 /* dynamic, not saved */
74 static KEYSTRUCT
*key_performance_data
=NULL
;
75 static KEYSTRUCT
*key_current_config
=NULL
;
76 static KEYSTRUCT
*key_dyn_data
=NULL
;
78 /* what valuetypes do we need to convert? */
79 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
81 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
82 #define strdupW(x) STRING32_strdupW(x)
83 #define strchrW(a,c) STRING32_lstrchrW(a,c)
85 static struct openhandle
{
90 static int nrofopenhandles
=0;
91 static int currenthandle
=1;
94 add_handle(HKEY hkey
,LPKEYSTRUCT lpkey
,REGSAM accessmask
) {
97 for (i
=0;i
<nrofopenhandles
;i
++) {
98 if (openhandles
[i
].lpkey
==lpkey
) {
99 dprintf_reg(stddeb
,"add_handle:Tried to add %p twice!\n",lpkey
);
101 if (openhandles
[i
].hkey
==hkey
) {
102 dprintf_reg(stddeb
,"add_handle:Tried to add %lx twice!\n",(LONG
)hkey
);
105 openhandles
=xrealloc( openhandles
,
106 sizeof(struct openhandle
)*(nrofopenhandles
+1)
108 openhandles
[i
].lpkey
= lpkey
;
109 openhandles
[i
].hkey
= hkey
;
110 openhandles
[i
].accessmask
= accessmask
;
115 get_handle(HKEY hkey
) {
118 for (i
=0;i
<nrofopenhandles
;i
++)
119 if (openhandles
[i
].hkey
==hkey
)
120 return openhandles
[i
].lpkey
;
121 dprintf_reg(stddeb
,"get_handle:Didn't find handle %lx?\n",(LONG
)hkey
);
126 remove_handle(HKEY hkey
) {
129 for (i
=0;i
<nrofopenhandles
;i
++)
130 if (openhandles
[i
].hkey
==hkey
)
132 if (i
==nrofopenhandles
) {
133 dprintf_reg(stddeb
,"remove_handle:Didn't find handle %08x?\n",hkey
);
136 memcpy( openhandles
+i
,
138 sizeof(struct openhandle
)*(nrofopenhandles
-i
-1)
140 openhandles
=xrealloc(openhandles
,sizeof(struct openhandle
)*(nrofopenhandles
-1));
146 /* debug function, converts a unicode into a static memory area
147 * (sub for using two static strings, in case we need them in a single call)
150 W2C(LPCWSTR x
,int sub
) {
151 static LPSTR unicodedebug
[2]={NULL
,NULL
};
154 if (sub
!=0 && sub
!=1)
155 return "<W2C:bad sub>";
156 if (unicodedebug
[sub
]) HeapFree( SystemHeap
, 0, unicodedebug
[sub
] );
157 unicodedebug
[sub
] = HEAP_strdupWtoA( SystemHeap
, 0, x
);
158 return unicodedebug
[sub
];
162 lookup_hkey(HKEY hkey
) {
166 case HKEY_CLASSES_ROOT
:
167 return key_classes_root
;
168 case HKEY_CURRENT_USER
:
169 return key_current_user
;
170 case HKEY_LOCAL_MACHINE
:
171 return key_local_machine
;
174 case HKEY_PERFORMANCE_DATA
:
175 return key_performance_data
;
178 case HKEY_CURRENT_CONFIG
:
179 return key_current_config
;
181 dprintf_reg(stddeb
,"lookup_hkey(%lx), special key!\n",
184 return get_handle(hkey
);
190 * splits the unicode string 'wp' into an array of strings.
191 * the array is allocated by this function.
192 * the number of components will be stored in 'wpc'
193 * Free the array using FREE_KEY_PATH
196 split_keypath(LPCWSTR wp
,LPWSTR
**wpv
,int *wpc
) {
200 ws
= HEAP_strdupW( SystemHeap
, 0, wp
);
202 for (i
=0;ws
[i
];i
++) {
209 *wpv
= (LPWSTR
*)HeapAlloc( SystemHeap
, 0, sizeof(LPWSTR
)*(*wpc
+2));
217 #define FREE_KEY_PATH HeapFree(SystemHeap,0,wps[0]);HeapFree(SystemHeap,0,wps);
220 * Shell initialisation, allocates keys.
222 void SHELL_StartupRegistry();
227 HKEY cl_r_hkey
,c_u_hkey
;
228 #define ADD_ROOT_KEY(xx) \
229 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
230 memset(xx,'\0',sizeof(KEYSTRUCT));\
231 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
233 ADD_ROOT_KEY(key_local_machine
);
234 if (RegCreateKey16(HKEY_LOCAL_MACHINE
,"\\SOFTWARE\\Classes",&cl_r_hkey
)!=ERROR_SUCCESS
) {
235 fprintf(stderr
,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
238 key_classes_root
= lookup_hkey(cl_r_hkey
);
240 ADD_ROOT_KEY(key_users
);
243 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
244 * (later, when a win32 registry editing tool becomes avail.)
246 while (pwd
=getpwent()) {
247 if (pwd
->pw_name
== NULL
)
249 RegCreateKey16(HKEY_USERS
,pwd
->pw_name
,&c_u_hkey
);
250 RegCloseKey(c_u_hkey
);
253 pwd
=getpwuid(getuid());
254 if (pwd
&& pwd
->pw_name
) {
255 RegCreateKey16(HKEY_USERS
,pwd
->pw_name
,&c_u_hkey
);
256 key_current_user
= lookup_hkey(c_u_hkey
);
258 ADD_ROOT_KEY(key_current_user
);
260 ADD_ROOT_KEY(key_performance_data
);
261 ADD_ROOT_KEY(key_current_config
);
262 ADD_ROOT_KEY(key_dyn_data
);
264 SHELL_StartupRegistry();
269 SHELL_StartupRegistry() {
272 char buf
[200],cpubuf
[200];
274 RegCreateKey16(HKEY_DYN_DATA
,"\\PerfStats\\StatData",&xhkey
);
277 RegCreateKey16(HKEY_LOCAL_MACHINE
,"\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey
);
279 F
=fopen("/proc/cpuinfo","r");
282 while (NULL
!=fgets(buf
,200,F
)) {
283 if (sscanf(buf
,"processor\t: %d",&x
)) {
288 RegCreateKey16(hkey
,buf
,&xhkey
);
290 if (sscanf(buf
,"cpu\t\t: %s",cpubuf
)) {
291 sprintf(buf
,"CPU %s",cpubuf
);
293 RegSetValueEx32A(xhkey
,"Identifier",0,REG_SZ
,buf
,strlen(buf
));
303 RegCreateKey16(hkey
,"0",&xhkey
);
304 RegSetValueEx32A(xhkey
,"Identifier",0,REG_SZ
,"CPU 386",strlen("CPU 386"));
306 RegOpenKey16(HKEY_LOCAL_MACHINE
,"\\HARDWARE\\DESCRIPTION\\System",&hkey
);
307 RegSetValueEx32A(hkey
,"Identifier",0,REG_SZ
,"SystemType WINE",strlen("SystemType WINE"));
309 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
313 * string RegisteredOwner
314 * string RegisteredOrganization
317 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
322 if (-1!=gethostname(buf
,200)) {
323 RegCreateKey16(HKEY_LOCAL_MACHINE
,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&xhkey
);
324 RegSetValueEx16(xhkey
,"ComputerName",0,REG_SZ
,buf
,strlen(buf
)+1);
328 /************************ SAVE Registry Function ****************************/
330 #define REGISTRY_SAVE_VERSION 0x00000001
332 /* Registry saveformat:
333 * If you change it, increase above number by 1, which will flush
334 * old registry database files.
337 * "WINE REGISTRY Version %d"
341 * valuename=lastmodified,type,data
345 * keyname,valuename,stringdata:
346 * the usual ascii characters from 0x00-0xff (well, not 0x00)
347 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
348 * ( "=\\\t" escaped in \uXXXX form.)
352 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
354 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
355 * SaveOnlyUpdatedKeys=yes
358 _save_check_tainted(LPKEYSTRUCT lpkey
) {
363 if (lpkey
->flags
& REG_OPTION_TAINTED
)
368 if (_save_check_tainted(lpkey
->nextsub
)) {
369 lpkey
->flags
|= REG_OPTION_TAINTED
;
378 _save_USTRING(FILE *F
,LPWSTR wstr
,int escapeeq
) {
391 if (escapeeq
&& *s
=='=')
394 fputc(*s
,F
); /* if \\ then put it twice. */
396 fprintf(F
,"\\u%04x",*((unsigned short*)s
));
404 _savesubkey(FILE *F
,LPKEYSTRUCT lpkey
,int level
,int all
) {
410 if ( !(lpxkey
->flags
& REG_OPTION_VOLATILE
) &&
411 (all
|| (lpxkey
->flags
& REG_OPTION_TAINTED
))
413 for (tabs
=level
;tabs
--;)
415 _save_USTRING(F
,lpxkey
->keyname
,1);
417 for (i
=0;i
<lpxkey
->nrofvalues
;i
++) {
418 LPKEYVALUE val
=lpxkey
->values
+i
;
420 for (tabs
=level
+1;tabs
--;)
422 _save_USTRING(F
,val
->name
,0);
424 fprintf(F
,"%ld,%ld,",val
->type
,val
->lastmodified
);
425 if ((1<<val
->type
) & UNICONVMASK
)
426 _save_USTRING(F
,(LPWSTR
)val
->data
,0);
428 for (j
=0;j
<val
->len
;j
++)
429 fprintf(F
,"%02x",*((unsigned char*)val
->data
+j
));
432 /* descend recursively */
433 if (!_savesubkey(F
,lpxkey
->nextsub
,level
+1,all
))
442 _savesubreg(FILE *F
,LPKEYSTRUCT lpkey
,int all
) {
443 fprintf(F
,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION
);
444 _save_check_tainted(lpkey
->nextsub
);
445 return _savesubkey(F
,lpkey
->nextsub
,0,all
);
449 _savereg(LPKEYSTRUCT lpkey
,char *fn
,int all
) {
454 fprintf(stddeb
,__FILE__
":_savereg:Couldn't open %s for writing: %s\n",
459 if (!_savesubreg(F
,lpkey
,all
)) {
462 fprintf(stddeb
,__FILE__
":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn
);
470 SHELL_SaveRegistry() {
478 if (RegOpenKey16(HKEY_CURRENT_USER
,KEY_REGISTRY
,&hkey
)!=ERROR_SUCCESS
) {
484 if ( (ERROR_SUCCESS
!=RegQueryValueEx32A(
496 if (lstrcmpi32A(buf
,"yes"))
498 pwd
=getpwuid(getuid());
499 if (pwd
!=NULL
&& pwd
->pw_dir
!=NULL
)
503 fn
=(char*)xmalloc( strlen(pwd
->pw_dir
) + strlen(WINE_PREFIX
) +
504 strlen(SAVE_CURRENT_USER
) + 2 );
505 strcpy(fn
,pwd
->pw_dir
);
506 strcat(fn
,WINE_PREFIX
);
507 /* create the directory. don't care about errorcodes. */
508 mkdir(fn
,0755); /* drwxr-xr-x */
509 strcat(fn
,"/"SAVE_CURRENT_USER
);
510 tmp
= (char*)xmalloc(strlen(fn
)+strlen(".tmp")+1);
511 strcpy(tmp
,fn
);strcat(tmp
,".tmp");
512 if (_savereg(key_current_user
,tmp
,all
)) {
513 if (-1==rename(tmp
,fn
)) {
514 perror("rename tmp registry");
520 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_LOCAL_MACHINE
)+2);
521 strcpy(fn
,pwd
->pw_dir
);
522 strcat(fn
,WINE_PREFIX
"/"SAVE_LOCAL_MACHINE
);
523 tmp
= (char*)xmalloc(strlen(fn
)+strlen(".tmp")+1);
524 strcpy(tmp
,fn
);strcat(tmp
,".tmp");
525 if (_savereg(key_local_machine
,tmp
,all
)) {
526 if (-1==rename(tmp
,fn
)) {
527 perror("rename tmp registry");
534 fprintf(stderr
,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
537 /************************ LOAD Registry Function ****************************/
540 _find_or_add_key(LPKEYSTRUCT lpkey
,LPWSTR keyname
) {
541 LPKEYSTRUCT lpxkey
,*lplpkey
;
543 lplpkey
= &(lpkey
->nextsub
);
546 if (!lstrcmpi32W(lpxkey
->keyname
,keyname
))
548 lplpkey
= &(lpxkey
->next
);
552 *lplpkey
= (LPKEYSTRUCT
)xmalloc(sizeof(KEYSTRUCT
));
554 memset(lpxkey
,'\0',sizeof(KEYSTRUCT
));
555 lpxkey
->keyname
= keyname
;
563 LPKEYSTRUCT lpkey
,LPWSTR name
,DWORD type
,LPBYTE data
,DWORD len
,
569 for (i
=0;i
<lpkey
->nrofvalues
;i
++) {
575 if ( val
->name
!=NULL
&&
576 !lstrcmpi32W(val
->name
,name
)
581 if (i
==lpkey
->nrofvalues
) {
582 lpkey
->values
= xrealloc(
584 (++lpkey
->nrofvalues
)*sizeof(KEYVALUE
)
587 memset(val
,'\0',sizeof(KEYVALUE
));
593 if (val
->lastmodified
<lastmodified
) {
594 val
->lastmodified
=lastmodified
;
605 /* reads a line including dynamically enlarging the readbuffer and throwing
609 _wine_read_line(FILE *F
,char **buf
,int *len
) {
618 s
=fgets(curread
,mylen
,F
);
621 if (NULL
==(s
=strchr(curread
,'\n'))) {
622 /* buffer wasn't large enough */
623 curoff
= strlen(*buf
);
624 *buf
= xrealloc(*buf
,*len
*2);
625 curread
= *buf
+ curoff
;
626 mylen
= *len
; /* we filled up the buffer and
627 * got new '*len' bytes to fill
635 /* throw away comments */
636 if (**buf
=='#' || **buf
==';') {
641 if (s
) /* got end of line */
647 /* converts a char* into a UNICODE string (up to a special char)
648 * and returns the position exactly after that string
651 _wine_read_USTRING(char *buf
,LPWSTR
*str
) {
655 /* read up to "=" or "\0" or "\n" */
658 /* empty string is the win3.1 default value(NULL)*/
662 *str
= (LPWSTR
)xmalloc(2*strlen(buf
)+2);
664 while (*s
&& (*s
!='\n') && (*s
!='=')) {
666 *ws
++=*((unsigned char*)s
++);
675 fprintf(stderr
,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s
,buf
);
683 memcpy(xbuf
,s
,4);xbuf
[4]='\0';
684 if (!sscanf(xbuf
,"%x",&wc
))
685 fprintf(stderr
,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf
,buf
);
687 *ws
++ =(unsigned short)wc
;
693 *str
= strdupW(*str
);
700 FILE *F
,LPKEYSTRUCT lpkey
,int level
,char **buf
,int *buflen
,int optflag
707 lpkey
->flags
|= optflag
;
709 /* good. we already got a line here ... so parse it */
719 fprintf(stderr
,"_load_subkey:Got a subhierarchy without resp. key?\n");
722 _wine_loadsubkey(F
,lpxkey
,level
+1,buf
,buflen
,optflag
);
725 /* let the caller handle this line */
726 if (i
<level
|| **buf
=='\0')
729 /* it can be: a value or a keyname. Parse the name first */
730 s
=_wine_read_USTRING(s
,&name
);
732 /* switch() default: hack to avoid gotos */
736 lpxkey
=_find_or_add_key(lpkey
,name
);
739 int len
,lastmodified
,type
;
742 fprintf(stderr
,"_wine_load_subkey:unexpected character: %c\n",*s
);
746 if (2!=sscanf(s
,"%d,%d,",&type
,&lastmodified
)) {
747 fprintf(stderr
,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf
);
753 if ((1<<type
) & UNICONVMASK
) {
754 s
=_wine_read_USTRING(s
,(LPWSTR
*)&data
);
756 len
= lstrlen32W((LPWSTR
)data
)*2+2;
761 data
= (LPBYTE
)xmalloc(len
+1);
762 for (i
=0;i
<len
;i
++) {
764 if (*s
>='0' && *s
<='9')
766 if (*s
>='a' && *s
<='f')
768 if (*s
>='A' && *s
<='F')
771 if (*s
>='0' && *s
<='9')
773 if (*s
>='a' && *s
<='f')
775 if (*s
>='A' && *s
<='F')
780 _find_or_add_value(lpkey
,name
,type
,data
,len
,lastmodified
);
783 /* read the next line */
784 if (!_wine_read_line(F
,buf
,buflen
))
791 _wine_loadsubreg(FILE *F
,LPKEYSTRUCT lpkey
,int optflag
) {
796 buf
=xmalloc(10);buflen
=10;
797 if (!_wine_read_line(F
,&buf
,&buflen
)) {
801 if (!sscanf(buf
,"WINE REGISTRY Version %d",&ver
)) {
805 if (ver
!=REGISTRY_SAVE_VERSION
) {
806 dprintf_reg(stddeb
,__FILE__
":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver
,buf
);
810 if (!_wine_read_line(F
,&buf
,&buflen
)) {
814 if (!_wine_loadsubkey(F
,lpkey
,0,&buf
,&buflen
,optflag
)) {
823 _wine_loadreg(LPKEYSTRUCT lpkey
,char *fn
,int optflag
) {
828 dprintf_reg(stddeb
,__FILE__
":Couldn't open %s for reading: %s\n",
833 if (!_wine_loadsubreg(F
,lpkey
,optflag
)) {
842 _copy_registry(LPKEYSTRUCT from
,LPKEYSTRUCT to
) {
849 lpxkey
= _find_or_add_key(to
,strdupW(from
->keyname
));
851 for (j
=0;j
<from
->nrofvalues
;j
++) {
855 valfrom
= from
->values
+j
;
857 if (name
) name
=strdupW(name
);
858 data
=(LPBYTE
)malloc(valfrom
->len
);
859 memcpy(data
,valfrom
->data
,valfrom
->len
);
867 valfrom
->lastmodified
870 _copy_registry(from
,lpxkey
);
875 /* WINDOWS 95 REGISTRY LOADER */
877 * Structure of a win95 registry database.
881 * 8 : DWORD offset_of_RGDB_part
882 * 0C..1F: ? (someone fill in please)
887 * 4..0x1B: ? (fill in)
888 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
890 * Disk Key Entry Structure:
891 * 00: DWORD - unknown
892 * 04: DWORD - unknown
893 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
894 * 0C: DWORD - disk address of PreviousLevel Key.
895 * 10: DWORD - disk address of Next Sublevel Key.
896 * 14: DWORD - disk address of Next Key (on same level).
897 * DKEP>18: WORD - Nr, Low Significant part.
898 * 1A: WORD - Nr, High Significant part.
900 * The disk address always points to the nr part of the previous key entry
901 * of the referenced key. Don't ask me why, or even if I got this correct
902 * from staring at 1kg of hexdumps. (DKEP)
904 * The number of the entry is the low byte of the Low Significant Part ored
905 * with 0x100 * (low byte of the High Significant part)
906 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
908 * There are two minor corrections to the position of that structure.
909 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
910 * the DKE reread from there.
911 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
912 * (FIXME: slightly better explanation needed here)
916 * 04: DWORD offset to next RGDB section (perhaps WORD)
921 * 00: DWORD nextkeyoffset - offset to the next disk key structure
922 * 08: WORD nrLS - low significant part of NR
923 * 0A: WORD nrHS - high significant part of NR
924 * 0C: DWORD bytesused - bytes used in this structure.
925 * 10: WORD name_len - length of name in bytes. without \0
926 * 12: WORD nr_of_values - number of values.
927 * 14: char name[name_len] - name string. No \0.
928 * 14+name_len: disk values
929 * nextkeyoffset: ... next disk key
932 * 00: DWORD type - value type (hmm, could be WORD too)
933 * 04: DWORD - unknown, usually 0
934 * 08: WORD namelen - length of Name. 0 means name=NULL
935 * 0C: WORD datalen - length of Data.
936 * 10: char name[namelen] - name, no \0
937 * 10+namelen: BYTE data[datalen] - data, without \0 if string
938 * 10+namelen+datalen: next values or disk key
940 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
941 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
942 * structure) and reading another RGDB_section.
943 * repeat until end of file.
945 * FIXME: this description needs some serious help, yes.
948 struct _w95keyvalue
{
950 unsigned short datalen
;
960 struct _w95keyvalue
*values
;
961 unsigned long dkeaddr
;
966 struct _w95key
*prevlvl
;
967 struct _w95key
*nextsub
;
968 struct _w95key
*next
;
971 /* fast lookup table dkeaddr->nr */
973 unsigned long dkeaddr
;
979 _w95_walk_tree(LPKEYSTRUCT lpkey
,struct _w95key
*key
) {
985 if (key
->name
== NULL
) {
986 fprintf(stderr
,"_w95_walk_tree:Please report: key with dkeaddr %lx not loaded, skipping hierarchy\n",
991 lpxkey
=_find_or_add_key(lpkey
,strdupA2W(key
->name
));
993 if (key
->nrofvals
<0) {
994 /* shouldn't happen */
995 fprintf(stderr
,"key %s already processed!\n",key
->name
);
999 for (i
=0;i
<key
->nrofvals
;i
++) {
1003 name
= strdupA2W(key
->values
[i
].name
);
1004 if (!*name
) name
= NULL
;
1005 free(key
->values
[i
].name
);
1007 len
= key
->values
[i
].datalen
;
1008 data
= key
->values
[i
].data
;
1009 if ((1<<key
->values
[i
].type
) & UNICONVMASK
) {
1010 data
= (BYTE
*)strdupA2W(data
);
1011 len
= lstrlen32W((LPWSTR
)data
)*2+2;
1012 free(key
->values
[i
].data
);
1017 key
->values
[i
].type
,
1020 key
->values
[i
].lastmodified
1027 key
->nrofvals
=-key
->nrofvals
-1;
1028 _w95_walk_tree(lpxkey
,key
->nextsub
);
1033 /* small helper function to adjust address offset (dkeaddrs) */
1034 static unsigned long
1035 _w95_adj_da(unsigned long dkeaddr
) {
1036 if ((dkeaddr
&0xFFF)<0x018) {
1039 diff
=0x1C-(dkeaddr
&0xFFF);
1040 return dkeaddr
+diff
;
1042 if (((dkeaddr
+0x1C)&0xFFF)<0x1C) {
1043 /* readjust to 0x000,
1044 * but ONLY if we are >0x1000 already
1046 if (dkeaddr
& ~0xFFF)
1047 return dkeaddr
& ~0xFFF;
1053 _w95dkecomp(struct _w95nr2da
*a
,struct _w95nr2da
*b
){return a
->dkeaddr
-b
->dkeaddr
;}
1055 static struct _w95key
*
1056 _w95dkelookup(unsigned long dkeaddr
,int n
,struct _w95nr2da
*nr2da
,struct _w95key
*keys
) {
1059 if (dkeaddr
== 0xFFFFFFFF)
1063 dkeaddr
=_w95_adj_da(dkeaddr
+0x1c);
1064 off
= (dkeaddr
-0x3c)/0x1c;
1066 if (nr2da
[(i
+off
)%n
].dkeaddr
== dkeaddr
)
1067 return keys
+nr2da
[(i
+off
)%n
].nr
;
1068 /* 0x3C happens often, just report unusual values */
1070 dprintf_reg(stddeb
,"search hasn't found dkeaddr %lx?\n",dkeaddr
);
1075 _w95_loadreg(char* fn
,LPKEYSTRUCT lpkey
) {
1076 /* Disk Key Entry structure (RGKN part) */
1080 unsigned long x3
;/*usually 0xFFFFFFFF */
1081 unsigned long prevlvl
;
1082 unsigned long nextsub
;
1084 unsigned short nrLS
;
1085 unsigned short nrMS
;
1087 /* Disk Key Header structure (RGDB part) */
1089 unsigned long nextkeyoff
;
1090 unsigned short nrLS
;
1091 unsigned short nrMS
;
1092 unsigned long bytesused
;
1093 unsigned short keynamelen
;
1094 unsigned short values
;
1097 /* disk key values or nothing */
1099 /* Disk Key Value structure */
1103 unsigned short valnamelen
;
1104 unsigned short valdatalen
;
1105 /* valname, valdata */
1107 struct _w95nr2da
*nr2da
;
1112 unsigned long nr
,pos
,i
,where
,version
,rgdbsection
,end
,off_next_rgdb
;
1113 struct _w95key
*keys
;
1115 unsigned char *data
,*curdata
,*nextrgdb
;
1117 BY_HANDLE_FILE_INFORMATION hfdinfo
;
1119 dprintf_reg(stddeb
,"Loading Win95 registry database '%s'\n",fn
);
1120 hfd
=OpenFile32(fn
,&ofs
,OF_READ
);
1121 if (hfd
==HFILE_ERROR32
)
1124 if (4!=_lread32(hfd
,magic
,4))
1126 if (strcmp(magic
,"CREG")) {
1127 fprintf(stddeb
,"%s is not a w95 registry.\n",fn
);
1130 if (4!=_lread32(hfd
,&version
,4))
1132 if (4!=_lread32(hfd
,&rgdbsection
,4))
1134 if (-1==_llseek32(hfd
,0x20,SEEK_SET
))
1136 if (4!=_lread32(hfd
,magic
,4))
1138 if (strcmp(magic
,"RGKN")) {
1139 dprintf_reg(stddeb
,"second IFF header not RGKN, but %s\n",magic
);
1143 /* STEP 1: Keylink structures */
1144 if (-1==_llseek32(hfd
,0x40,SEEK_SET
))
1149 nrofdkes
= (end
-where
)/sizeof(struct dke
)+100;
1150 data
= (char*)xmalloc(end
-where
);
1151 if ((end
-where
)!=_lread32(hfd
,data
,end
-where
))
1155 keys
= (struct _w95key
*)xmalloc(nrofdkes
* sizeof(struct _w95key
));
1156 memset(keys
,'\0',nrofdkes
*sizeof(struct _w95key
));
1157 nr2da
= (struct _w95nr2da
*)xmalloc(nrofdkes
* sizeof(struct _w95nr2da
));
1158 memset(nr2da
,'\0',nrofdkes
*sizeof(struct _w95nr2da
));
1160 for (i
=0;i
<nrofdkes
;i
++) {
1162 unsigned long dkeaddr
;
1164 pos
=curdata
-data
+0x40;
1165 memcpy(&dke
,curdata
,sizeof(dke
));
1166 curdata
+=sizeof(dke
);
1167 nr
= dke
.nrLS
+ (dke
.nrMS
<<8);
1169 if ((dkeaddr
&0xFFF)<0x018) {
1172 diff
=0x1C-(dkeaddr
&0xFFF);
1174 curdata
+=diff
-sizeof(dke
);
1175 memcpy(&dke
,curdata
,sizeof(dke
));
1176 nr
= dke
.nrLS
+ (dke
.nrMS
<<8);
1177 curdata
+=sizeof(dke
);
1179 if (((dkeaddr
+0x1C)&0xFFF)<0x1C) {
1180 /* readjust to 0x000,
1181 * but ONLY if we are >0x1000 already
1183 if (dkeaddr
& ~0xFFF)
1184 dkeaddr
= dkeaddr
& ~0xFFF;
1187 /* 0xFFFFFFFF happens often, just report unusual values */
1189 dprintf_reg(stddeb
,"nr %ld exceeds nrofdkes %d, skipping.\n",nr
,nrofdkes
);
1192 if (keys
[nr
].dkeaddr
) {
1195 for (x
=sizeof(dke
);x
--;)
1196 if (((char*)&dke
)[x
])
1199 break; /* finished reading if we got only 0 */
1201 if ( (dke
.next
!=(long)keys
[nr
].next
) ||
1202 (dke
.nextsub
!=(long)keys
[nr
].nextsub
) ||
1203 (dke
.prevlvl
!=(long)keys
[nr
].prevlvl
)
1205 dprintf_reg(stddeb
,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr
,keys
[nr
].dkeaddr
,dkeaddr
);
1210 nr2da
[i
].dkeaddr
= dkeaddr
;
1212 keys
[nr
].dkeaddr
= dkeaddr
;
1213 keys
[nr
].x1
= dke
.x1
;
1214 keys
[nr
].x2
= dke
.x2
;
1215 keys
[nr
].x3
= dke
.x3
;
1216 keys
[nr
].prevlvl
= (struct _w95key
*)dke
.prevlvl
;
1217 keys
[nr
].nextsub
= (struct _w95key
*)dke
.nextsub
;
1218 keys
[nr
].next
= (struct _w95key
*)dke
.next
;
1222 qsort(nr2da
,nrofdkes
,sizeof(nr2da
[0]),
1223 (int(*)(const void *,const void*))_w95dkecomp
);
1225 /* STEP 2: keydata & values */
1226 if (!GetFileInformationByHandle(hfd
,&hfdinfo
))
1228 end
= hfdinfo
.nFileSizeLow
;
1229 lastmodified
= DOSFS_FileTimeToUnixTime(&hfdinfo
.ftLastWriteTime
,NULL
);
1231 if (-1==_llseek32(hfd
,rgdbsection
,SEEK_SET
))
1233 data
= (char*)xmalloc(end
-rgdbsection
);
1234 if ((end
-rgdbsection
)!=_lread32(hfd
,data
,end
-rgdbsection
))
1238 memcpy(magic
,curdata
,4);
1239 memcpy(&off_next_rgdb
,curdata
+4,4);
1240 nextrgdb
= curdata
+off_next_rgdb
;
1241 if (strcmp(magic
,"RGDB")) {
1242 dprintf_reg(stddeb
,"third IFF header not RGDB, but %s\n",magic
);
1249 struct _w95key
*key
,xkey
;
1252 if (curdata
>=nextrgdb
) {
1254 if (!strncmp(curdata
,"RGDB",4)) {
1255 memcpy(&off_next_rgdb
,curdata
+4,4);
1256 nextrgdb
= curdata
+off_next_rgdb
;
1259 dprintf_reg(stddeb
,"at end of RGDB section, but no next header (%x of %lx). Breaking.\n",curdata
-data
,end
-rgdbsection
);
1263 #define XREAD(whereto,len) \
1264 if ((curdata-data+len)<end) {\
1265 memcpy(whereto,curdata,len);\
1270 XREAD(&dkh
,sizeof(dkh
));
1271 nr
= dkh
.nrLS
+ (dkh
.nrMS
<<8);
1272 if ((nr
>nrofdkes
) || (dkh
.nrLS
== 0xFFFF)) {
1273 if (dkh
.nrLS
== 0xFFFF) {
1274 /* skip over key using nextkeyoff */
1275 curdata
+=dkh
.nextkeyoff
-sizeof(struct dkh
);
1278 dprintf_reg(stddeb
,"haven't found nr %ld.\n",nr
);
1280 memset(key
,'\0',sizeof(xkey
));
1284 dprintf_reg(stddeb
,"key with nr=%ld has no dkeaddr?\n",nr
);
1286 key
->nrofvals
= dkh
.values
;
1287 key
->name
= (char*)xmalloc(dkh
.keynamelen
+1);
1289 XREAD(key
->name
,dkh
.keynamelen
);
1290 key
->name
[dkh
.keynamelen
]=0;
1291 if (key
->nrofvals
) {
1292 key
->values
= (struct _w95keyvalue
*)xmalloc(
1293 sizeof(struct _w95keyvalue
)*key
->nrofvals
1295 for (i
=0;i
<key
->nrofvals
;i
++) {
1298 XREAD(&dkv
,sizeof(dkv
));
1299 key
->values
[i
].type
= dkv
.type
;
1300 key
->values
[i
].name
= (char*)xmalloc(
1303 key
->values
[i
].datalen
= dkv
.valdatalen
;
1304 key
->values
[i
].data
= (unsigned char*)xmalloc(
1307 key
->values
[i
].x1
= dkv
.x1
;
1308 XREAD(key
->values
[i
].name
,dkv
.valnamelen
);
1309 XREAD(key
->values
[i
].data
,dkv
.valdatalen
);
1310 key
->values
[i
].data
[dkv
.valdatalen
]=0;
1311 key
->values
[i
].name
[dkv
.valnamelen
]=0;
1312 key
->values
[i
].lastmodified
=lastmodified
;
1315 if (bytesread
!= dkh
.nextkeyoff
) {
1316 if (dkh
.bytesused
!= bytesread
)
1318 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread
,dkh
.nextkeyoff
,
1321 curdata
+= dkh
.nextkeyoff
-bytesread
;
1323 key
->prevlvl
= _w95dkelookup((long)key
->prevlvl
,nrofdkes
,nr2da
,keys
);
1324 key
->nextsub
= _w95dkelookup((long)key
->nextsub
,nrofdkes
,nr2da
,keys
);
1325 key
->next
= _w95dkelookup((long)key
->next
,nrofdkes
,nr2da
,keys
);
1330 _w95_walk_tree(lpkey
,keys
);
1334 /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1337 reghack - windows 3.11 registry data format demo program.
1339 The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1340 a combined hash table and tree description, and finally a text table.
1342 The header is obvious from the struct header. The taboff1 and taboff2
1343 fields are always 0x20, and their usage is unknown.
1345 The 8-byte entry table has various entry types.
1347 tabent[0] is a root index. The second word has the index of the root of
1349 tabent[1..hashsize] is a hash table. The first word in the hash entry is
1350 the index of the key/value that has that hash. Data with the same
1351 hash value are on a circular list. The other three words in the
1352 hash entry are always zero.
1353 tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1354 entry: dirent and keyent/valent. They are identified by context.
1355 tabent[freeidx] is the first free entry. The first word in a free entry
1356 is the index of the next free entry. The last has 0 as a link.
1357 The other three words in the free list are probably irrelevant.
1359 Entries in text table are preceeded by a word at offset-2. This word
1360 has the value (2*index)+1, where index is the referring keyent/valent
1361 entry in the table. I have no suggestion for the 2* and the +1.
1362 Following the word, there are N bytes of data, as per the keyent/valent
1363 entry length. The offset of the keyent/valent entry is from the start
1364 of the text table to the first data byte.
1366 This information is not available from Microsoft. The data format is
1367 deduced from the reg.dat file by me. Mistakes may
1368 have been made. I claim no rights and give no guarantees for this program.
1370 Tor Sjøwall, tor@sn.no
1373 /* reg.dat header format */
1374 struct _w31_header
{
1375 char cookie
[8]; /* 'SHCC3.10' */
1376 unsigned long taboff1
; /* offset of hash table (??) = 0x20 */
1377 unsigned long taboff2
; /* offset of index table (??) = 0x20 */
1378 unsigned long tabcnt
; /* number of entries in index table */
1379 unsigned long textoff
; /* offset of text part */
1380 unsigned long textsize
; /* byte size of text part */
1381 unsigned short hashsize
; /* hash size */
1382 unsigned short freeidx
; /* free index */
1385 /* generic format of table entries */
1386 struct _w31_tabent
{
1387 unsigned short w0
, w1
, w2
, w3
;
1390 /* directory tabent: */
1391 struct _w31_dirent
{
1392 unsigned short sibling_idx
; /* table index of sibling dirent */
1393 unsigned short child_idx
; /* table index of child dirent */
1394 unsigned short key_idx
; /* table index of key keyent */
1395 unsigned short value_idx
; /* table index of value valent */
1399 struct _w31_keyent
{
1400 unsigned short hash_idx
; /* hash chain index for string */
1401 unsigned short refcnt
; /* reference count */
1402 unsigned short length
; /* length of string */
1403 unsigned short string_off
; /* offset of string in text table */
1407 struct _w31_valent
{
1408 unsigned short hash_idx
; /* hash chain index for string */
1409 unsigned short refcnt
; /* reference count */
1410 unsigned short length
; /* length of string */
1411 unsigned short string_off
; /* offset of string in text table */
1414 /* recursive helper function to display a directory tree */
1416 __w31_dumptree( unsigned short idx
,
1418 struct _w31_tabent
*tab
,
1419 struct _w31_header
*head
,
1421 time_t lastmodified
,
1424 struct _w31_dirent
*dir
;
1425 struct _w31_keyent
*key
;
1426 struct _w31_valent
*val
;
1427 LPKEYSTRUCT xlpkey
= NULL
;
1429 static char tail
[400];
1432 dir
=(struct _w31_dirent
*)&tab
[idx
];
1435 key
= (struct _w31_keyent
*)&tab
[dir
->key_idx
];
1437 memcpy(tail
,&txt
[key
->string_off
],key
->length
);
1438 tail
[key
->length
]='\0';
1439 /* all toplevel entries AND the entries in the
1440 * toplevel subdirectory belong to \SOFTWARE\Classes
1442 if (!level
&& !lstrcmp32A(tail
,".classes")) {
1443 __w31_dumptree(dir
->child_idx
,txt
,tab
,head
,lpkey
,lastmodified
,level
+1);
1444 idx
=dir
->sibling_idx
;
1447 name
=STRING32_DupAnsiToUni(tail
);
1449 xlpkey
=_find_or_add_key(lpkey
,name
);
1451 /* only add if leaf node or valued node */
1452 if (dir
->value_idx
!=0||dir
->child_idx
==0) {
1453 if (dir
->value_idx
) {
1454 val
=(struct _w31_valent
*)&tab
[dir
->value_idx
];
1455 memcpy(tail
,&txt
[val
->string_off
],val
->length
);
1456 tail
[val
->length
]='\0';
1457 value
=STRING32_DupAnsiToUni(tail
);
1458 _find_or_add_value(xlpkey
,NULL
,REG_SZ
,(LPBYTE
)value
,lstrlen32W(value
)*2+2,lastmodified
);
1462 dprintf_reg(stddeb
,"__w31_dumptree:strange: no directory key name, idx=%04x\n", idx
);
1464 __w31_dumptree(dir
->child_idx
,txt
,tab
,head
,xlpkey
,lastmodified
,level
+1);
1465 idx
=dir
->sibling_idx
;
1472 struct _w31_header head
;
1473 struct _w31_tabent
*tab
;
1477 BY_HANDLE_FILE_INFORMATION hfinfo
;
1478 time_t lastmodified
;
1482 hf
= OpenFile32("reg.dat",&ofs
,OF_READ
);
1483 if (hf
==HFILE_ERROR32
)
1486 /* read & dump header */
1487 if (sizeof(head
)!=_lread32(hf
,&head
,sizeof(head
))) {
1488 dprintf_reg(stddeb
,"_w31_loadreg:reg.dat is too short.\n");
1492 if (memcmp(head
.cookie
, "SHCC3.10", sizeof(head
.cookie
))!=0) {
1493 dprintf_reg(stddeb
,"_w31_loadreg:reg.dat has bad signature.\n");
1498 len
= head
.tabcnt
* sizeof(struct _w31_tabent
);
1499 /* read and dump index table */
1501 if (len
!=_lread32(hf
,tab
,len
)) {
1502 dprintf_reg(stderr
,"_w31_loadreg:couldn't read %d bytes.\n",len
);
1509 txt
= xmalloc(head
.textsize
);
1510 if (-1==_llseek32(hf
,head
.textoff
,SEEK_SET
)) {
1511 dprintf_reg(stderr
,"_w31_loadreg:couldn't seek to textblock.\n");
1517 if (head
.textsize
!=_lread32(hf
,txt
,head
.textsize
)) {
1518 dprintf_reg(stderr
,"_w31_loadreg:textblock too short (%d instead of %ld).\n",len
,head
.textsize
);
1525 if (!GetFileInformationByHandle(hf
,&hfinfo
)) {
1526 dprintf_reg(stderr
,"_w31_loadreg:GetFileInformationByHandle failed?.\n");
1532 lastmodified
= DOSFS_FileTimeToUnixTime(&hfinfo
.ftLastWriteTime
,NULL
);
1534 if (RegCreateKey16(HKEY_LOCAL_MACHINE
,"\\SOFTWARE\\Classes",&hkey
)!=ERROR_SUCCESS
)
1536 lpkey
= lookup_hkey(hkey
);
1537 __w31_dumptree(tab
[0].w1
,txt
,tab
,&head
,lpkey
,lastmodified
,0);
1545 SHELL_LoadRegistry() {
1552 if (key_classes_root
==NULL
)
1555 /* Load windows 3.1 entries */
1557 /* Load windows 95 entries */
1558 _w95_loadreg("C:\\system.1st", key_local_machine
);
1559 _w95_loadreg("system.dat", key_local_machine
);
1560 _w95_loadreg("user.dat", key_users
);
1562 /* the global user default is loaded under HKEY_USERS\\.Default */
1563 RegCreateKey16(HKEY_USERS
,".Default",&hkey
);
1564 lpkey
= lookup_hkey(hkey
);
1565 _wine_loadreg(lpkey
,SAVE_USERS_DEFAULT
,0);
1567 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1568 _copy_registry(lpkey
,key_current_user
);
1571 /* the global machine defaults */
1572 _wine_loadreg(key_local_machine
,SAVE_LOCAL_MACHINE_DEFAULT
,0);
1574 /* load the user saved registries */
1576 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1578 pwd
=getpwuid(getuid());
1579 if (pwd
!=NULL
&& pwd
->pw_dir
!=NULL
) {
1580 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_CURRENT_USER
)+2);
1581 strcpy(fn
,pwd
->pw_dir
);
1582 strcat(fn
,WINE_PREFIX
"/"SAVE_CURRENT_USER
);
1583 _wine_loadreg(key_current_user
,fn
,REG_OPTION_TAINTED
);
1585 fn
=(char*)xmalloc(strlen(pwd
->pw_dir
)+strlen(WINE_PREFIX
)+strlen(SAVE_LOCAL_MACHINE
)+2);
1586 strcpy(fn
,pwd
->pw_dir
);
1587 strcat(fn
,WINE_PREFIX
"/"SAVE_LOCAL_MACHINE
);
1588 _wine_loadreg(key_local_machine
,fn
,REG_OPTION_TAINTED
);
1591 fprintf(stderr
,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1592 if (ERROR_SUCCESS
==RegCreateKey16(HKEY_CURRENT_USER
,KEY_REGISTRY
,&hkey
)) {
1593 DWORD junk
,type
,len
;
1597 if (( RegQueryValueEx32A(
1604 )!=ERROR_SUCCESS
) ||
1607 RegSetValueEx32A(hkey
,VAL_SAVEUPDATED
,0,REG_SZ
,"yes",4);
1613 /********************* API FUNCTIONS ***************************************/
1617 * All functions are stubs to RegOpenKeyEx32W where all the
1620 * FIXME: security,options,desiredaccess,...
1623 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1624 * RegOpenKey32W -> RegOpenKeyEx32W
1627 /* RegOpenKeyExW [ADVAPI32.150] */
1628 DWORD WINAPI
RegOpenKeyEx32W(
1635 LPKEYSTRUCT lpNextKey
,lpxkey
;
1638 dprintf_reg(stddeb
,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1639 (LONG
)hkey
,W2C(lpszSubKey
,0),dwReserved
,samDesired
,retkey
1642 lpNextKey
= lookup_hkey(hkey
);
1644 return SHELL_ERROR_BADKEY
;
1645 if (!lpszSubKey
|| !*lpszSubKey
) {
1646 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1647 *retkey
=currenthandle
;
1648 return SHELL_ERROR_SUCCESS
;
1650 split_keypath(lpszSubKey
,&wps
,&wpc
);
1652 while ((i
<wpc
) && (wps
[i
][0]=='\0')) i
++;
1655 lpxkey
=lpNextKey
->nextsub
;
1657 if (!lstrcmpi32W(wps
[i
],lpxkey
->keyname
))
1659 lpxkey
=lpxkey
->next
;
1663 return SHELL_ERROR_BADKEY
;
1668 add_handle(++currenthandle
,lpxkey
,samDesired
);
1669 *retkey
= currenthandle
;
1671 return SHELL_ERROR_SUCCESS
;
1674 /* RegOpenKeyW [ADVAPI32.151] */
1675 DWORD WINAPI
RegOpenKey32W(
1680 dprintf_reg(stddeb
,"RegOpenKey32W(%lx,%s,%p)\n",
1681 (LONG
)hkey
,W2C(lpszSubKey
,0),retkey
1683 return RegOpenKeyEx32W(hkey
,lpszSubKey
,0,KEY_ALL_ACCESS
,retkey
);
1687 /* RegOpenKeyExA [ADVAPI32.149] */
1688 DWORD WINAPI
RegOpenKeyEx32A(
1698 dprintf_reg(stddeb
,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1699 (LONG
)hkey
,lpszSubKey
,dwReserved
,samDesired
,retkey
1702 lpszSubKeyW
=strdupA2W(lpszSubKey
);
1705 ret
=RegOpenKeyEx32W(hkey
,lpszSubKeyW
,dwReserved
,samDesired
,retkey
);
1711 /* RegOpenKeyA [ADVAPI32.148] */
1712 DWORD WINAPI
RegOpenKey32A(
1717 dprintf_reg(stddeb
,"RegOpenKey32A(%lx,%s,%p)\n",
1718 (LONG
)hkey
,lpszSubKey
,retkey
1720 return RegOpenKeyEx32A(hkey
,lpszSubKey
,0,KEY_ALL_ACCESS
,retkey
);
1723 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1724 DWORD WINAPI
RegOpenKey16(
1729 dprintf_reg(stddeb
,"RegOpenKey16(%lx,%s,%p)\n",
1730 (LONG
)hkey
,lpszSubKey
,retkey
1732 return RegOpenKey32A(hkey
,lpszSubKey
,retkey
);
1738 * All those functions convert their respective
1739 * arguments and call RegCreateKeyExW at the end.
1741 * FIXME: no security,no access attrib,no optionhandling yet.
1744 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1745 * RegCreateKey32W -> RegCreateKeyEx32W
1748 /* RegCreateKeyExW [ADVAPI32.131] */
1749 DWORD WINAPI
RegCreateKeyEx32W(
1756 LPSECURITY_ATTRIBUTES lpSecAttribs
,
1760 LPKEYSTRUCT
*lplpPrevKey
,lpNextKey
,lpxkey
;
1764 /*FIXME: handle security/access/whatever */
1765 dprintf_reg(stddeb
,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1777 lpNextKey
= lookup_hkey(hkey
);
1779 return SHELL_ERROR_BADKEY
;
1780 if (!lpszSubKey
|| !*lpszSubKey
) {
1781 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1782 *retkey
=currenthandle
;
1783 lpNextKey
->flags
|=REG_OPTION_TAINTED
;
1784 return SHELL_ERROR_SUCCESS
;
1786 split_keypath(lpszSubKey
,&wps
,&wpc
);
1788 while ((i
<wpc
) && (wps
[i
][0]=='\0')) i
++;
1791 lpxkey
=lpNextKey
->nextsub
;
1793 if (!lstrcmpi32W(wps
[i
],lpxkey
->keyname
))
1795 lpxkey
=lpxkey
->next
;
1803 add_handle(++currenthandle
,lpxkey
,samDesired
);
1804 lpxkey
->flags
|= REG_OPTION_TAINTED
;
1805 *retkey
= currenthandle
;
1807 *lpDispos
= REG_OPENED_EXISTING_KEY
;
1809 return SHELL_ERROR_SUCCESS
;
1811 /* good. now the hard part */
1813 lplpPrevKey
= &(lpNextKey
->nextsub
);
1814 lpxkey
= *lplpPrevKey
;
1816 lplpPrevKey
= &(lpxkey
->next
);
1817 lpxkey
= *lplpPrevKey
;
1819 *lplpPrevKey
=malloc(sizeof(KEYSTRUCT
));
1820 if (!*lplpPrevKey
) {
1822 return SHELL_ERROR_OUTOFMEMORY
;
1824 memset(*lplpPrevKey
,'\0',sizeof(KEYSTRUCT
));
1825 (*lplpPrevKey
)->keyname
= strdupW(wps
[i
]);
1826 (*lplpPrevKey
)->next
= NULL
;
1827 (*lplpPrevKey
)->nextsub
= NULL
;
1828 (*lplpPrevKey
)->values
= NULL
;
1829 (*lplpPrevKey
)->nrofvalues
= 0;
1830 (*lplpPrevKey
)->flags
= REG_OPTION_TAINTED
;
1832 (*lplpPrevKey
)->class = strdupW(lpszClass
);
1834 (*lplpPrevKey
)->class = NULL
;
1835 lpNextKey
= *lplpPrevKey
;
1838 add_handle(++currenthandle
,lpNextKey
,samDesired
);
1840 /*FIXME: flag handling correct? */
1841 lpNextKey
->flags
= fdwOptions
|REG_OPTION_TAINTED
;
1843 lpNextKey
->class = strdupW(lpszClass
);
1845 lpNextKey
->class = NULL
;
1846 *retkey
= currenthandle
;
1848 *lpDispos
= REG_CREATED_NEW_KEY
;
1850 return SHELL_ERROR_SUCCESS
;
1853 /* RegCreateKeyW [ADVAPI32.132] */
1854 DWORD WINAPI
RegCreateKey32W(
1861 dprintf_reg(stddeb
,"RegCreateKey32W(%lx,%s,%p)\n",
1862 (LONG
)hkey
,W2C(lpszSubKey
,0),retkey
1864 ret
=RegCreateKeyEx32W(
1865 hkey
, /* key handle */
1866 lpszSubKey
, /* subkey name */
1867 0, /* reserved = 0 */
1868 NULL
, /* lpszClass? FIXME: ? */
1869 REG_OPTION_NON_VOLATILE
, /* options */
1870 KEY_ALL_ACCESS
, /* desired access attribs */
1871 NULL
, /* lpsecurity attributes */
1872 retkey
, /* lpretkey */
1873 &junk
/* disposition value */
1878 /* RegCreateKeyExA [ADVAPI32.130] */
1879 DWORD WINAPI
RegCreateKeyEx32A(
1886 LPSECURITY_ATTRIBUTES lpSecAttribs
,
1890 LPWSTR lpszSubKeyW
,lpszClassW
;
1893 dprintf_reg(stddeb
,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1905 lpszSubKeyW
=strdupA2W(lpszSubKey
);
1909 lpszClassW
=strdupA2W(lpszClass
);
1912 ret
=RegCreateKeyEx32W(
1930 /* RegCreateKeyA [ADVAPI32.129] */
1931 DWORD WINAPI
RegCreateKey32A(
1938 dprintf_reg(stddeb
,"RegCreateKey32A(%lx,%s,%p)\n",
1939 (LONG
)hkey
,lpszSubKey
,retkey
1941 return RegCreateKeyEx32A(
1942 hkey
, /* key handle */
1943 lpszSubKey
, /* subkey name */
1944 0, /* reserved = 0 */
1945 NULL
, /* lpszClass? FIXME: ? */
1946 REG_OPTION_NON_VOLATILE
,/* options */
1947 KEY_ALL_ACCESS
, /* desired access attribs */
1948 NULL
, /* lpsecurity attributes */
1949 retkey
, /* lpretkey */
1950 &junk
/* disposition value */
1954 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1955 DWORD WINAPI
RegCreateKey16(
1960 dprintf_reg(stddeb
,"RegCreateKey16(%lx,%s,%p)\n",
1961 (LONG
)hkey
,lpszSubKey
,retkey
1963 return RegCreateKey32A(hkey
,lpszSubKey
,retkey
);
1967 * Query Value Functions
1968 * Win32 differs between keynames and valuenames.
1969 * multiple values may belong to one key, the special value
1970 * with name NULL is the default value used by the win31
1974 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1975 * RegQueryValue32W -> RegQueryValueEx32W
1978 /* RegQueryValueExW [ADVAPI32.158] */
1979 DWORD WINAPI
RegQueryValueEx32W(
1981 LPWSTR lpszValueName
,
1982 LPDWORD lpdwReserved
,
1990 dprintf_reg(stddeb
,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%ld)\n",
1991 hkey
,W2C(lpszValueName
,0),lpdwReserved
,lpdwType
,lpbData
,
1992 lpcbData
?*lpcbData
:0
1995 lpkey
= lookup_hkey(hkey
);
1997 return SHELL_ERROR_BADKEY
;
1998 if (lpszValueName
==NULL
) {
1999 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2000 if (lpkey
->values
[i
].name
==NULL
)
2003 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2004 if ( lpkey
->values
[i
].name
&&
2005 !lstrcmpi32W(lpszValueName
,lpkey
->values
[i
].name
)
2009 if (i
==lpkey
->nrofvalues
) {
2010 if (lpszValueName
==NULL
) {
2012 *(WCHAR
*)lpbData
= 0;
2017 return SHELL_ERROR_SUCCESS
;
2019 return SHELL_ERROR_BADKEY
;/*FIXME: correct return? */
2022 *lpdwType
= lpkey
->values
[i
].type
;
2023 if (lpbData
==NULL
) {
2025 return SHELL_ERROR_SUCCESS
;
2026 *lpcbData
= lpkey
->values
[i
].len
;
2027 return SHELL_ERROR_SUCCESS
;
2029 if (*lpcbData
<lpkey
->values
[i
].len
) {
2032 *lpcbData
= lpkey
->values
[i
].len
;
2033 return ERROR_MORE_DATA
;
2035 memcpy(lpbData
,lpkey
->values
[i
].data
,lpkey
->values
[i
].len
);
2036 *lpcbData
= lpkey
->values
[i
].len
;
2037 return SHELL_ERROR_SUCCESS
;
2040 /* RegQueryValueW [ADVAPI32.159] */
2041 DWORD WINAPI
RegQueryValue32W(
2050 dprintf_reg(stddeb
,"RegQueryValue32W(%x,%s,%p,%ld)\n->",
2051 hkey
,W2C(lpszSubKey
,0),lpszData
,
2052 lpcbData
?*lpcbData
:0
2055 /* only open subkey, if we really do descend */
2056 if (lpszSubKey
&& *lpszSubKey
) {
2057 ret
= RegOpenKey32W(hkey
,lpszSubKey
,&xhkey
);
2058 if (ret
!=ERROR_SUCCESS
)
2064 ret
= RegQueryValueEx32W(
2066 NULL
, /* varname NULL -> compat */
2067 NULL
, /* lpdwReserved, must be NULL */
2077 /* RegQueryValueExA [ADVAPI32.157] */
2078 DWORD WINAPI
RegQueryValueEx32A(
2080 LPSTR lpszValueName
,
2081 LPDWORD lpdwReserved
,
2086 LPWSTR lpszValueNameW
;
2092 dprintf_reg(stddeb
,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%ld)\n->",
2093 hkey
,lpszValueName
,lpdwReserved
,lpdwType
,lpbData
,
2094 lpcbData
?*lpcbData
:0
2098 buf
= (LPBYTE
)xmalloc((*lpcbData
)*2);
2099 myxlen
= *lpcbData
*2;
2104 myxlen
= *lpcbData
*2;
2110 lpszValueNameW
=strdupA2W(lpszValueName
);
2112 lpszValueNameW
=NULL
;
2116 ret
=RegQueryValueEx32W(
2126 if (ret
==ERROR_SUCCESS
) {
2128 if (UNICONVMASK
& (1<<(type
))) {
2129 /* convert UNICODE to ASCII */
2130 lstrcpyWtoA(lpbData
,(LPWSTR
)buf
);
2131 *lpcbData
= myxlen
/2;
2133 if (myxlen
>*lpcbData
)
2134 ret
= ERROR_MORE_DATA
;
2136 memcpy(lpbData
,buf
,myxlen
);
2141 if ((UNICONVMASK
& (1<<(type
))) && lpcbData
)
2142 *lpcbData
= myxlen
/2;
2145 if ((UNICONVMASK
& (1<<(type
))) && lpcbData
)
2146 *lpcbData
= myxlen
/2;
2153 /* RegQueryValueEx [KERNEL.225] */
2154 DWORD WINAPI
RegQueryValueEx16(
2156 LPSTR lpszValueName
,
2157 LPDWORD lpdwReserved
,
2162 dprintf_reg(stddeb
,"RegQueryValueEx16(%x,%s,%p,%p,%p,%ld)\n",
2163 hkey
,lpszValueName
,lpdwReserved
,lpdwType
,lpbData
,
2164 lpcbData
?*lpcbData
:0
2166 return RegQueryValueEx32A(
2176 /* RegQueryValueA [ADVAPI32.156] */
2177 DWORD WINAPI
RegQueryValue32A(
2186 dprintf_reg(stddeb
,"RegQueryValue32A(%x,%s,%p,%ld)\n",
2187 hkey
,lpszSubKey
,lpszData
,
2188 lpcbData
?*lpcbData
:0
2191 /* only open subkey, if we really do descend */
2192 if (lpszSubKey
&& *lpszSubKey
) {
2193 ret
= RegOpenKey16(hkey
,lpszSubKey
,&xhkey
);
2194 if (ret
!=ERROR_SUCCESS
)
2200 ret
= RegQueryValueEx32A(
2202 NULL
, /* lpszValueName NULL -> compat */
2203 NULL
, /* lpdwReserved, must be NULL */
2213 /* RegQueryValue [SHELL.6] [KERNEL.224] */
2214 DWORD WINAPI
RegQueryValue16(
2220 dprintf_reg(stddeb
,"RegQueryValue16(%x,%s,%p,%ld)\n",
2221 hkey
,lpszSubKey
,lpszData
,lpcbData
?*lpcbData
:0
2223 /* HACK: the 16bit RegQueryValue doesn't handle selectorblocks
2224 * anyway, so we just mask out the high 16 bit.
2225 * (this (not so much incidently;) hopefully fixes Aldus FH4)
2228 *lpcbData
&= 0xFFFF;
2229 return RegQueryValue32A(hkey
,lpszSubKey
,lpszData
,lpcbData
);
2233 * Setting values of Registry keys
2236 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
2237 * RegSetValue32W -> RegSetValueEx32W
2240 /* RegSetValueExW [ADVAPI32.170] */
2241 DWORD WINAPI
RegSetValueEx32W(
2243 LPWSTR lpszValueName
,
2252 dprintf_reg(stddeb
,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
2253 hkey
,W2C(lpszValueName
,0),dwReserved
,dwType
,lpbData
,cbData
2255 /* we no longer care about the lpbData type here... */
2256 lpkey
= lookup_hkey(hkey
);
2258 return SHELL_ERROR_BADKEY
;
2260 lpkey
->flags
|= REG_OPTION_TAINTED
;
2262 if (lpszValueName
==NULL
) {
2263 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2264 if (lpkey
->values
[i
].name
==NULL
)
2267 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2268 if ( lpkey
->values
[i
].name
&&
2269 !lstrcmpi32W(lpszValueName
,lpkey
->values
[i
].name
)
2273 if (i
==lpkey
->nrofvalues
) {
2274 lpkey
->values
= (LPKEYVALUE
)xrealloc(
2276 (lpkey
->nrofvalues
+1)*sizeof(KEYVALUE
)
2278 lpkey
->nrofvalues
++;
2279 memset(lpkey
->values
+i
,'\0',sizeof(KEYVALUE
));
2281 if (lpkey
->values
[i
].name
==NULL
)
2283 lpkey
->values
[i
].name
= strdupW(lpszValueName
);
2285 lpkey
->values
[i
].name
= NULL
;
2286 lpkey
->values
[i
].len
= cbData
;
2287 lpkey
->values
[i
].type
= dwType
;
2288 if (lpkey
->values
[i
].data
!=NULL
)
2289 free(lpkey
->values
[i
].data
);
2290 lpkey
->values
[i
].data
= (LPBYTE
)xmalloc(cbData
);
2291 lpkey
->values
[i
].lastmodified
= time(NULL
);
2292 memcpy(lpkey
->values
[i
].data
,lpbData
,cbData
);
2293 return SHELL_ERROR_SUCCESS
;
2296 /* RegSetValueExA [ADVAPI32.169] */
2297 DWORD WINAPI
RegSetValueEx32A(
2299 LPSTR lpszValueName
,
2306 LPWSTR lpszValueNameW
;
2309 dprintf_reg(stddeb
,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
2310 hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
2312 if ((1<<dwType
) & UNICONVMASK
) {
2313 buf
=(LPBYTE
)strdupA2W(lpbData
);
2314 cbData
=2*strlen(lpbData
)+2;
2318 lpszValueNameW
= strdupA2W(lpszValueName
);
2320 lpszValueNameW
= NULL
;
2321 ret
=RegSetValueEx32W(hkey
,lpszValueNameW
,dwReserved
,dwType
,buf
,cbData
);
2323 free(lpszValueNameW
);
2329 /* RegSetValueEx [KERNEL.226] */
2330 DWORD WINAPI
RegSetValueEx16(
2332 LPSTR lpszValueName
,
2338 dprintf_reg(stddeb
,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2339 hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
2341 return RegSetValueEx32A(hkey
,lpszValueName
,dwReserved
,dwType
,lpbData
,cbData
);
2344 /* RegSetValueW [ADVAPI32.171] */
2345 DWORD WINAPI
RegSetValue32W(
2355 dprintf_reg(stddeb
,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2356 hkey
,W2C(lpszSubKey
,0),dwType
,W2C(lpszData
,0),cbData
2358 if (lpszSubKey
&& *lpszSubKey
) {
2359 ret
=RegCreateKey32W(hkey
,lpszSubKey
,&xhkey
);
2360 if (ret
!=ERROR_SUCCESS
)
2364 if (dwType
!=REG_SZ
) {
2365 fprintf(stddeb
,"RegSetValueX called with dwType=%ld!\n",dwType
);
2368 if (cbData
!=2*lstrlen32W(lpszData
)+2) {
2369 dprintf_reg(stddeb
,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2370 cbData
,W2C(lpszData
,0),2*lstrlen32W(lpszData
)+2
2372 cbData
=2*lstrlen32W(lpszData
)+2;
2374 ret
=RegSetValueEx32W(xhkey
,NULL
,0,dwType
,(LPBYTE
)lpszData
,cbData
);
2380 /* RegSetValueA [ADVAPI32.168] */
2381 DWORD WINAPI
RegSetValue32A(
2391 dprintf_reg(stddeb
,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2392 hkey
,lpszSubKey
,dwType
,lpszData
,cbData
2394 if (lpszSubKey
&& *lpszSubKey
) {
2395 ret
=RegCreateKey16(hkey
,lpszSubKey
,&xhkey
);
2396 if (ret
!=ERROR_SUCCESS
)
2401 if (dwType
!=REG_SZ
) {
2402 dprintf_reg(stddeb
,"RegSetValueA called with dwType=%ld!\n",dwType
);
2405 if (cbData
!=strlen(lpszData
)+1)
2406 cbData
=strlen(lpszData
)+1;
2407 ret
=RegSetValueEx32A(xhkey
,NULL
,0,dwType
,(LPBYTE
)lpszData
,cbData
);
2413 /* RegSetValue [KERNEL.221] [SHELL.5] */
2414 DWORD WINAPI
RegSetValue16(
2422 dprintf_reg(stddeb
,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2423 hkey
,lpszSubKey
,dwType
,lpszData
,cbData
2425 ret
=RegSetValue32A(hkey
,lpszSubKey
,dwType
,lpszData
,cbData
);
2433 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2434 * RegEnumKey32W -> RegEnumKeyEx32W
2437 /* RegEnumKeyExW [ADVAPI32.139] */
2438 DWORD WINAPI
RegEnumKeyEx32W(
2443 LPDWORD lpdwReserved
,
2448 LPKEYSTRUCT lpkey
,lpxkey
;
2450 dprintf_reg(stddeb
,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2451 hkey
,iSubkey
,lpszName
,*lpcchName
,lpdwReserved
,lpszClass
,lpcchClass
,ft
2453 lpkey
=lookup_hkey(hkey
);
2455 return SHELL_ERROR_BADKEY
;
2456 if (!lpkey
->nextsub
)
2457 return ERROR_NO_MORE_ITEMS
;
2458 lpxkey
=lpkey
->nextsub
;
2459 while (iSubkey
&& lpxkey
) {
2461 lpxkey
=lpxkey
->next
;
2463 if (iSubkey
|| !lpxkey
)
2464 return ERROR_NO_MORE_ITEMS
;
2465 if (2*lstrlen32W(lpxkey
->keyname
)+2>*lpcchName
)
2466 return ERROR_MORE_DATA
;
2467 memcpy(lpszName
,lpxkey
->keyname
,lstrlen32W(lpxkey
->keyname
)*2+2);
2469 /* what should we write into it? */
2473 return ERROR_SUCCESS
;
2477 /* RegEnumKeyW [ADVAPI32.140] */
2478 DWORD WINAPI
RegEnumKey32W(
2486 dprintf_reg(stddeb
,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2487 hkey
,iSubkey
,lpszName
,lpcchName
2489 return RegEnumKeyEx32W(hkey
,iSubkey
,lpszName
,&lpcchName
,NULL
,NULL
,NULL
,&ft
);
2491 /* RegEnumKeyExA [ADVAPI32.138] */
2492 DWORD WINAPI
RegEnumKeyEx32A(
2497 LPDWORD lpdwReserved
,
2502 DWORD ret
,lpcchNameW
,lpcchClassW
;
2503 LPWSTR lpszNameW
,lpszClassW
;
2506 dprintf_reg(stddeb
,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2507 hkey
,iSubkey
,lpszName
,*lpcchName
,lpdwReserved
,lpszClass
,lpcchClass
,ft
2510 lpszNameW
= (LPWSTR
)xmalloc(*lpcchName
*2);
2511 lpcchNameW
= *lpcchName
*2;
2517 lpszClassW
= (LPWSTR
)xmalloc(*lpcchClass
*2);
2518 lpcchClassW
= *lpcchClass
*2;
2523 ret
=RegEnumKeyEx32W(
2533 if (ret
==ERROR_SUCCESS
) {
2534 lstrcpyWtoA(lpszName
,lpszNameW
);
2535 *lpcchName
=strlen(lpszName
);
2537 lstrcpyWtoA(lpszClass
,lpszClassW
);
2538 *lpcchClass
=strlen(lpszClass
);
2548 /* RegEnumKeyA [ADVAPI32.137] */
2549 DWORD WINAPI
RegEnumKey32A(
2557 dprintf_reg(stddeb
,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2558 hkey
,iSubkey
,lpszName
,lpcchName
2560 return RegEnumKeyEx32A(
2572 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2573 DWORD WINAPI
RegEnumKey16(
2579 dprintf_reg(stddeb
,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2580 hkey
,iSubkey
,lpszName
,lpcchName
2582 return RegEnumKey32A(hkey
,iSubkey
,lpszName
,lpcchName
);
2586 * Enumerate Registry Values
2589 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2592 /* RegEnumValueW [ADVAPI32.142] */
2593 DWORD WINAPI
RegEnumValue32W(
2598 LPDWORD lpdReserved
,
2606 dprintf_reg(stddeb
,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2607 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2609 lpkey
= lookup_hkey(hkey
);
2611 return SHELL_ERROR_BADKEY
;
2612 if (lpkey
->nrofvalues
<=iValue
)
2613 return ERROR_NO_MORE_ITEMS
;
2614 val
= lpkey
->values
+iValue
;
2617 if (lstrlen32W(val
->name
)*2+2>*lpcchValue
) {
2618 *lpcchValue
= lstrlen32W(val
->name
)*2+2;
2619 return ERROR_MORE_DATA
;
2621 memcpy(lpszValue
,val
->name
,2*lstrlen32W(val
->name
)+2);
2622 *lpcchValue
=lstrlen32W(val
->name
)*2+2;
2624 /* how to handle NULL value? */
2628 *lpdwType
=val
->type
;
2630 if (val
->len
>*lpcbData
)
2631 return ERROR_MORE_DATA
;
2632 memcpy(lpbData
,val
->data
,val
->len
);
2633 *lpcbData
= val
->len
;
2635 return SHELL_ERROR_SUCCESS
;
2638 /* RegEnumValueA [ADVAPI32.141] */
2639 DWORD WINAPI
RegEnumValue32A(
2644 LPDWORD lpdReserved
,
2651 DWORD ret
,lpcbDataW
;
2653 dprintf_reg(stddeb
,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2654 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2657 lpszValueW
= (LPWSTR
)xmalloc(*lpcchValue
*2);
2659 lpbDataW
= (LPBYTE
)xmalloc(*lpcbData
*2);
2660 lpcbDataW
= *lpcbData
*2;
2663 ret
=RegEnumValue32W(
2674 if (ret
==ERROR_SUCCESS
) {
2675 lstrcpyWtoA(lpszValue
,lpszValueW
);
2677 if ((1<<*lpdwType
) & UNICONVMASK
) {
2678 lstrcpyWtoA(lpbData
,(LPWSTR
)lpbDataW
);
2680 if (lpcbDataW
> *lpcbData
)
2681 ret
= ERROR_MORE_DATA
;
2683 memcpy(lpbData
,lpbDataW
,lpcbDataW
);
2685 *lpcbData
= lpcbDataW
;
2695 /* RegEnumValue [KERNEL.223] */
2696 DWORD WINAPI
RegEnumValue16(
2701 LPDWORD lpdReserved
,
2706 dprintf_reg(stddeb
,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2707 hkey
,iValue
,lpszValue
,lpcchValue
,lpdReserved
,lpdwType
,lpbData
,lpcbData
2709 return RegEnumValue32A(
2722 * Close registry key
2724 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2725 DWORD WINAPI
RegCloseKey(HKEY hkey
) {
2726 dprintf_reg(stddeb
,"RegCloseKey(%x)\n",hkey
);
2727 remove_handle(hkey
);
2728 return ERROR_SUCCESS
;
2731 * Delete registry key
2734 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2736 /* RegDeleteKeyW [ADVAPI32.134] */
2737 DWORD WINAPI
RegDeleteKey32W(HKEY hkey
,LPWSTR lpszSubKey
) {
2738 LPKEYSTRUCT
*lplpPrevKey
,lpNextKey
,lpxkey
;
2742 dprintf_reg(stddeb
,"RegDeleteKey32W(%x,%s)\n",
2743 hkey
,W2C(lpszSubKey
,0)
2745 lpNextKey
= lookup_hkey(hkey
);
2747 return SHELL_ERROR_BADKEY
;
2748 /* we need to know the previous key in the hier. */
2749 if (!lpszSubKey
|| !*lpszSubKey
)
2750 return SHELL_ERROR_BADKEY
;
2751 split_keypath(lpszSubKey
,&wps
,&wpc
);
2755 lpxkey
=lpNextKey
->nextsub
;
2757 if (!lstrcmpi32W(wps
[i
],lpxkey
->keyname
))
2759 lpxkey
=lpxkey
->next
;
2763 /* not found is success */
2764 return SHELL_ERROR_SUCCESS
;
2769 lpxkey
= lpNextKey
->nextsub
;
2770 lplpPrevKey
= &(lpNextKey
->nextsub
);
2772 if (!lstrcmpi32W(wps
[i
],lpxkey
->keyname
))
2774 lplpPrevKey
= &(lpxkey
->next
);
2775 lpxkey
= lpxkey
->next
;
2778 return SHELL_ERROR_SUCCESS
;
2779 if (lpxkey
->nextsub
)
2780 return SHELL_ERROR_CANTWRITE
;
2781 *lplpPrevKey
= lpxkey
->next
;
2782 free(lpxkey
->keyname
);
2784 free(lpxkey
->class);
2786 free(lpxkey
->values
);
2789 return SHELL_ERROR_SUCCESS
;
2792 /* RegDeleteKeyA [ADVAPI32.133] */
2793 DWORD WINAPI
RegDeleteKey32A(HKEY hkey
,LPCSTR lpszSubKey
) {
2797 dprintf_reg(stddeb
,"RegDeleteKey32A(%x,%s)\n",
2800 lpszSubKeyW
=HEAP_strdupAtoW(GetProcessHeap(),0,lpszSubKey
);
2801 ret
=RegDeleteKey32W(hkey
,lpszSubKeyW
);
2802 HeapFree(GetProcessHeap(),0,lpszSubKeyW
);
2806 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2807 DWORD WINAPI
RegDeleteKey16(HKEY hkey
,LPCSTR lpszSubKey
) {
2808 dprintf_reg(stddeb
,"RegDeleteKey16(%x,%s)\n",
2811 return RegDeleteKey32A(hkey
,lpszSubKey
);
2815 * Delete registry value
2818 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2820 /* RegDeleteValueW [ADVAPI32.136] */
2821 DWORD WINAPI
RegDeleteValue32W(HKEY hkey
,LPWSTR lpszValue
)
2827 dprintf_reg(stddeb
,"RegDeleteValue32W(%x,%s)\n",
2828 hkey
,W2C(lpszValue
,0)
2830 lpkey
=lookup_hkey(hkey
);
2832 return SHELL_ERROR_BADKEY
;
2834 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2835 if ( lpkey
->values
[i
].name
&&
2836 !lstrcmpi32W(lpkey
->values
[i
].name
,lpszValue
)
2840 for (i
=0;i
<lpkey
->nrofvalues
;i
++)
2841 if (lpkey
->values
[i
].name
==NULL
)
2844 if (i
==lpkey
->nrofvalues
)
2845 return SHELL_ERROR_BADKEY
;/*FIXME: correct errorcode? */
2846 val
= lpkey
->values
+i
;
2847 if (val
->name
) free(val
->name
);
2848 if (val
->data
) free(val
->data
);
2852 sizeof(KEYVALUE
)*(lpkey
->nrofvalues
-i
-1)
2854 lpkey
->values
= (LPKEYVALUE
)xrealloc(
2856 (lpkey
->nrofvalues
-1)*sizeof(KEYVALUE
)
2858 lpkey
->nrofvalues
--;
2859 return SHELL_ERROR_SUCCESS
;
2862 /* RegDeleteValueA [ADVAPI32.135] */
2863 DWORD WINAPI
RegDeleteValue32A(HKEY hkey
,LPSTR lpszValue
)
2868 dprintf_reg( stddeb
, "RegDeleteValue32A(%x,%s)\n", hkey
,lpszValue
);
2869 lpszValueW
=HEAP_strdupAtoW(GetProcessHeap(),0,lpszValue
);
2870 ret
=RegDeleteValue32W(hkey
,lpszValueW
);
2871 HeapFree(GetProcessHeap(),0,lpszValueW
);
2875 /* RegDeleteValue [KERNEL.222] */
2876 DWORD WINAPI
RegDeleteValue16(HKEY hkey
,LPSTR lpszValue
)
2878 dprintf_reg( stddeb
,"RegDeleteValue16(%x,%s)\n", hkey
,lpszValue
);
2879 return RegDeleteValue32A(hkey
,lpszValue
);
2882 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2883 DWORD WINAPI
RegFlushKey(HKEY hkey
)
2885 dprintf_reg(stddeb
,"RegFlushKey(%x), STUB.\n",hkey
);
2886 return SHELL_ERROR_SUCCESS
;
2889 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2891 /* RegQueryInfoKeyW [ADVAPI32.153] */
2892 DWORD WINAPI
RegQueryInfoKey32W(
2896 LPDWORD lpdwReserved
,
2898 LPDWORD lpcchMaxSubkey
,
2899 LPDWORD lpcchMaxClass
,
2901 LPDWORD lpcchMaxValueName
,
2902 LPDWORD lpccbMaxValueData
,
2903 LPDWORD lpcbSecurityDescriptor
,
2906 LPKEYSTRUCT lpkey
,lpxkey
;
2907 int nrofkeys
,maxsubkey
,maxclass
,maxvalues
,maxvname
,maxvdata
;
2910 dprintf_reg(stddeb
,"RegQueryInfoKey32W(%x,......)\n",hkey
);
2911 lpkey
=lookup_hkey(hkey
);
2913 return SHELL_ERROR_BADKEY
;
2916 if (lstrlen32W(lpkey
->class)*2+2>*lpcchClass
) {
2917 *lpcchClass
=lstrlen32W(lpkey
->class)*2;
2918 return ERROR_MORE_DATA
;
2920 *lpcchClass
=lstrlen32W(lpkey
->class)*2;
2921 memcpy(lpszClass
,lpkey
->class,lstrlen32W(lpkey
->class));
2928 *lpcchClass
= lstrlen32W(lpkey
->class)*2;
2930 lpxkey
=lpkey
->nextsub
;
2931 nrofkeys
=maxsubkey
=maxclass
=maxvalues
=maxvname
=maxvdata
=0;
2934 if (lstrlen32W(lpxkey
->keyname
)>maxsubkey
)
2935 maxsubkey
=lstrlen32W(lpxkey
->keyname
);
2936 if (lpxkey
->class && lstrlen32W(lpxkey
->class)>maxclass
)
2937 maxclass
=lstrlen32W(lpxkey
->class);
2938 if (lpxkey
->nrofvalues
>maxvalues
)
2939 maxvalues
=lpxkey
->nrofvalues
;
2940 for (i
=0;i
<lpxkey
->nrofvalues
;i
++) {
2941 LPKEYVALUE val
=lpxkey
->values
+i
;
2943 if (val
->name
&& lstrlen32W(val
->name
)>maxvname
)
2944 maxvname
=lstrlen32W(val
->name
);
2945 if (val
->len
>maxvdata
)
2948 lpxkey
=lpxkey
->next
;
2950 if (!maxclass
) maxclass
= 1;
2951 if (!maxvname
) maxvname
= 1;
2953 *lpcSubKeys
= nrofkeys
;
2955 *lpcchMaxSubkey
= maxsubkey
*2;
2957 *lpcchMaxClass
= maxclass
*2;
2959 *lpcValues
= maxvalues
;
2960 if (lpcchMaxValueName
)
2961 *lpcchMaxValueName
= maxvname
;
2962 if (lpccbMaxValueData
)
2963 *lpccbMaxValueData
= maxvdata
;
2964 return SHELL_ERROR_SUCCESS
;
2967 /* RegQueryInfoKeyA [ADVAPI32.152] */
2968 DWORD WINAPI
RegQueryInfoKey32A(
2972 LPDWORD lpdwReserved
,
2974 LPDWORD lpcchMaxSubkey
,
2975 LPDWORD lpcchMaxClass
,
2977 LPDWORD lpcchMaxValueName
,
2978 LPDWORD lpccbMaxValueData
,
2979 LPDWORD lpcbSecurityDescriptor
,
2985 dprintf_reg(stddeb
,"RegQueryInfoKey32A(%x,......)\n",hkey
);
2988 lpszClassW
= (LPWSTR
)xmalloc(*lpcchClass
);
2992 ret
=RegQueryInfoKey32W(
3003 lpcbSecurityDescriptor
,
3006 if (ret
==ERROR_SUCCESS
&& lpszClass
)
3007 lstrcpyWtoA(lpszClass
,lpszClassW
);
3014 if (lpcchMaxValueName
)
3015 *lpcchMaxValueName
/=2;
3020 /* RegConnectRegistryA [ADVAPI32.127] */
3021 DWORD WINAPI
RegConnectRegistry32A(LPCSTR machine
,HKEY hkey
,LPHKEY reskey
)
3023 fprintf(stderr
,"RegConnectRegistry32A(%s,%08x,%p), STUB.\n",
3026 return ERROR_FILE_NOT_FOUND
; /* FIXME */