Release 961102
[wine/hacks.git] / misc / registry.c
blobb5ba088a9b348cda32941ed0b5385c63dd6ef69a
1 /*
2 * Registry Functions
4 * Copyright 1996 Marcus Meissner
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <malloc.h>
11 #include <unistd.h>
12 #include <ctype.h>
13 #include <errno.h>
14 #include <sys/types.h>
15 #include <sys/fcntl.h>
16 #include <sys/stat.h>
17 #include <pwd.h>
18 #include <time.h>
19 #include "windows.h"
20 #include "win.h"
21 #include "winerror.h"
22 #include "file.h"
23 #include "string32.h"
24 #include "stddebug.h"
25 #include "debug.h"
26 #include "xmalloc.h"
27 #include "winreg.h"
29 #define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y))
31 /* FIXME: following defines should be configured global ... */
33 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
34 #define WINE_PREFIX "/.wine"
35 #define SAVE_USERS_DEFAULT "/usr/local/etc/wine.userreg"
36 #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
38 /* relative in ~user/.wine/ : */
39 #define SAVE_CURRENT_USER "user.reg"
40 #define SAVE_LOCAL_MACHINE "system.reg"
42 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
43 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
45 /* one value of a key */
46 typedef struct tagKEYVALUE
48 LPWSTR name; /* name of value (UNICODE) or NULL for win31 */
49 DWORD type; /* type of value */
50 DWORD len; /* length of data */
51 DWORD lastmodified; /* time of seconds since 1.1.1970 */
52 LPBYTE data; /* content, may be strings, binaries, etc. */
53 } KEYVALUE,*LPKEYVALUE;
55 /* a registry key */
56 typedef struct tagKEYSTRUCT
58 LPWSTR keyname; /* name of THIS key (UNICODE) */
59 DWORD flags; /* flags. */
60 LPWSTR class;
61 /* values */
62 DWORD nrofvalues; /* nr of values in THIS key */
63 LPKEYVALUE values; /* values in THIS key */
64 /* key management pointers */
65 struct tagKEYSTRUCT *next; /* next key on same hierarchy */
66 struct tagKEYSTRUCT *nextsub; /* keys that hang below THIS key */
67 } KEYSTRUCT, *LPKEYSTRUCT;
70 static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */
71 static KEYSTRUCT *key_current_user=NULL; /* user specific values */
72 static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
73 static KEYSTRUCT *key_users=NULL; /* all users? */
75 /* dynamic, not saved */
76 static KEYSTRUCT *key_performance_data=NULL;
77 static KEYSTRUCT *key_current_config=NULL;
78 static KEYSTRUCT *key_dyn_data=NULL;
80 /* what valuetypes do we need to convert? */
81 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
83 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
84 #define strdupW2A(x) STRING32_DupUniToAnsi(x)
85 #define strdupW(x) STRING32_strdupW(x)
86 #define strcmpniW(a,b) STRING32_lstrcmpniW(a,b)
87 #define strchrW(a,c) STRING32_lstrchrW(a,c)
88 #define strcpyWA(a,b) STRING32_UniToAnsi(a,b)
90 static struct openhandle {
91 LPKEYSTRUCT lpkey;
92 HKEY hkey;
93 REGSAM accessmask;
94 } *openhandles=NULL;
95 static int nrofopenhandles=0;
96 static int currenthandle=1;
98 static void
99 add_handle(HKEY hkey,LPKEYSTRUCT lpkey,REGSAM accessmask) {
100 int i;
102 for (i=0;i<nrofopenhandles;i++) {
103 if (openhandles[i].lpkey==lpkey) {
104 dprintf_reg(stddeb,"add_handle:Tried to add %p twice!\n",lpkey);
106 if (openhandles[i].hkey==hkey) {
107 dprintf_reg(stddeb,"add_handle:Tried to add %lx twice!\n",(LONG)hkey);
110 openhandles=xrealloc( openhandles,
111 sizeof(struct openhandle)*(nrofopenhandles+1)
113 openhandles[i].lpkey = lpkey;
114 openhandles[i].hkey = hkey;
115 openhandles[i].accessmask= accessmask;
116 nrofopenhandles++;
119 static LPKEYSTRUCT
120 get_handle(HKEY hkey) {
121 int i;
123 for (i=0;i<nrofopenhandles;i++)
124 if (openhandles[i].hkey==hkey)
125 return openhandles[i].lpkey;
126 dprintf_reg(stddeb,"get_handle:Didn't find handle %lx?\n",(LONG)hkey);
127 return NULL;
130 static void
131 remove_handle(HKEY hkey) {
132 int i;
134 for (i=0;i<nrofopenhandles;i++)
135 if (openhandles[i].hkey==hkey)
136 break;
137 if (i==nrofopenhandles) {
138 dprintf_reg(stddeb,"remove_handle:Didn't find handle %08x?\n",hkey);
139 return;
141 memcpy( openhandles+i,
142 openhandles+i+1,
143 sizeof(struct openhandle)*(nrofopenhandles-i-1)
145 openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
146 nrofopenhandles--;
147 return;
151 /* debug function, converts a unicode into a static memory area
152 * (sub for using two static strings, in case we need them in a single call)
154 LPSTR
155 W2C(LPCWSTR x,int sub) {
156 static LPSTR unicodedebug[2]={NULL,NULL};
157 if (x==NULL)
158 return "<NULL>";
159 if (sub!=0 && sub!=1)
160 return "<W2C:bad sub>";
161 if (unicodedebug[sub]) free(unicodedebug[sub]);
162 unicodedebug[sub] = strdupW2A(x);
163 return unicodedebug[sub];
166 static LPKEYSTRUCT
167 lookup_hkey(HKEY hkey) {
168 switch (hkey) {
169 case 0x00000000:
170 case 0x00000001:
171 case HKEY_CLASSES_ROOT:
172 return key_classes_root;
173 case HKEY_CURRENT_USER:
174 return key_current_user;
175 case HKEY_LOCAL_MACHINE:
176 return key_local_machine;
177 case HKEY_USERS:
178 return key_users;
179 case HKEY_PERFORMANCE_DATA:
180 return key_performance_data;
181 case HKEY_DYN_DATA:
182 return key_dyn_data;
183 case HKEY_CURRENT_CONFIG:
184 return key_current_config;
185 default:
186 dprintf_reg(stddeb,"lookup_hkey(%lx), special key!\n",
187 (LONG)hkey
189 return get_handle(hkey);
191 /*NOTREACHED*/
195 * splits the unicode string 'wp' into an array of strings.
196 * the array is allocated by this function.
197 * the number of components will be stored in 'wpc'
198 * Free the array using FREE_KEY_PATH
200 static void
201 split_keypath(LPCWSTR wp,LPWSTR **wpv,int *wpc) {
202 int i,j,len;
203 LPWSTR ws;
205 ws = strdupW(wp);
206 *wpc = 1;
207 for (i=0;ws[i];i++) {
208 if (ws[i]=='\\') {
209 ws[i]=0;
210 (*wpc)++;
213 len = i;
214 *wpv = (LPWSTR*)xmalloc(sizeof(LPWSTR)*(*wpc+2));
215 (*wpv)[0]= ws;
216 j = 1;
217 for (i=1;i<len;i++)
218 if (ws[i-1]==0)
219 (*wpv)[j++]=ws+i;
220 (*wpv)[j]=NULL;
222 #define FREE_KEY_PATH free(wps[0]);free(wps);
225 * Shell initialisation, allocates keys.
227 void SHELL_StartupRegistry();
228 void
229 SHELL_Init() {
230 struct passwd *pwd;
232 HKEY cl_r_hkey,c_u_hkey;
233 #define ADD_ROOT_KEY(xx) \
234 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
235 memset(xx,'\0',sizeof(KEYSTRUCT));\
236 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
238 ADD_ROOT_KEY(key_local_machine);
239 if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
240 fprintf(stderr,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
241 exit(1);
243 key_classes_root = lookup_hkey(cl_r_hkey);
245 ADD_ROOT_KEY(key_users);
247 #if 0
248 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
249 * (later, when a win32 registry editing tool becomes avail.)
251 while (pwd=getpwent()) {
252 if (pwd->pw_name == NULL)
253 continue;
254 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
255 RegCloseKey(c_u_hkey);
257 #endif
258 pwd=getpwuid(getuid());
259 if (pwd && pwd->pw_name) {
260 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
261 key_current_user = lookup_hkey(c_u_hkey);
262 } else {
263 ADD_ROOT_KEY(key_current_user);
265 ADD_ROOT_KEY(key_performance_data);
266 ADD_ROOT_KEY(key_current_config);
267 ADD_ROOT_KEY(key_dyn_data);
268 #undef ADD_ROOT_KEY
269 SHELL_StartupRegistry();
273 void
274 SHELL_StartupRegistry() {
275 HKEY hkey,xhkey=0;
276 FILE *F;
277 char buf[200],cpubuf[200];
279 RegCreateKey16(HKEY_DYN_DATA,"\\PerfStats\\StatData",&xhkey);
280 RegCloseKey(xhkey);
281 RegCreateKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey);
282 #ifdef linux
283 F=fopen("/proc/cpuinfo","r");
284 if (F) {
285 int procnr=-1,x;
286 while (NULL!=fgets(buf,200,F)) {
287 if (sscanf(buf,"processor\t: %d",&x)) {
288 sprintf(buf,"%d",x);
289 if (xhkey)
290 RegCloseKey(xhkey);
291 procnr=x;
292 RegCreateKey16(hkey,buf,&xhkey);
294 if (sscanf(buf,"cpu\t\t: %s",cpubuf)) {
295 sprintf(buf,"CPU %s",cpubuf);
296 if (xhkey)
297 RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,buf,strlen(buf));
300 fclose(F);
302 if (xhkey)
303 RegCloseKey(xhkey);
304 RegCloseKey(hkey);
305 #else
306 /* FIXME */
307 RegCreateKey16(hkey,"0",&xhkey);
308 RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,"CPU 386",strlen("CPU 386"));
309 #endif
310 RegOpenKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System",&hkey);
311 RegSetValueEx32A(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
312 RegCloseKey(hkey);
313 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
314 * CurrentVersion
315 * CurrentBuildNumber
316 * CurrentType
317 * string RegisteredOwner
318 * string RegisteredOrganization
321 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
322 * string SysContact
323 * string SysLocation
324 * SysServices
326 if (-1!=gethostname(buf,200)) {
327 RegCreateKey16(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&xhkey);
328 RegSetValueEx16(xhkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
329 RegCloseKey(xhkey);
332 /************************ SAVE Registry Function ****************************/
334 #define REGISTRY_SAVE_VERSION 0x00000001
336 /* Registry saveformat:
337 * If you change it, increase above number by 1, which will flush
338 * old registry database files.
340 * Global:
341 * "WINE REGISTRY Version %d"
342 * subkeys....
343 * Subkeys:
344 * keyname
345 * valuename=lastmodified,type,data
346 * ...
347 * subkeys
348 * ...
349 * keyname,valuename,stringdata:
350 * the usual ascii characters from 0x00-0xff (well, not 0x00)
351 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
352 * ( "=\\\t" escaped in \uXXXX form.)
353 * type,lastmodified:
354 * int
356 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
358 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
359 * SaveOnlyUpdatedKeys=yes
361 static int
362 _save_check_tainted(LPKEYSTRUCT lpkey) {
363 int tainted;
365 if (!lpkey)
366 return 0;
367 if (lpkey->flags & REG_OPTION_TAINTED)
368 tainted = 1;
369 else
370 tainted = 0;
371 while (lpkey) {
372 if (_save_check_tainted(lpkey->nextsub)) {
373 lpkey->flags |= REG_OPTION_TAINTED;
374 tainted = 1;
376 lpkey = lpkey->next;
378 return tainted;
381 static void
382 _save_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
383 LPWSTR s;
384 int doescape;
386 if (wstr==NULL)
387 return;
388 s=wstr;
389 while (*s) {
390 doescape=0;
391 if (*s>0xff)
392 doescape = 1;
393 if (*s=='\n')
394 doescape = 1;
395 if (escapeeq && *s=='=')
396 doescape = 1;
397 if (*s=='\\')
398 fputc(*s,F); /* if \\ than put it twice. */
399 if (doescape)
400 fprintf(F,"\\u%04x",*((unsigned short*)s));
401 else
402 fputc(*s,F);
403 s++;
407 static int
408 _savesubkey(FILE *F,LPKEYSTRUCT lpkey,int level,int all) {
409 LPKEYSTRUCT lpxkey;
410 int i,tabs,j;
412 lpxkey = lpkey;
413 while (lpxkey) {
414 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
415 (all || (lpxkey->flags & REG_OPTION_TAINTED))
417 for (tabs=level;tabs--;)
418 fputc('\t',F);
419 _save_USTRING(F,lpxkey->keyname,1);
420 fputs("\n",F);
421 for (i=0;i<lpxkey->nrofvalues;i++) {
422 LPKEYVALUE val=lpxkey->values+i;
424 for (tabs=level+1;tabs--;)
425 fputc('\t',F);
426 _save_USTRING(F,val->name,0);
427 fputc('=',F);
428 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
429 if ((1<<val->type) & UNICONVMASK)
430 _save_USTRING(F,(LPWSTR)val->data,0);
431 else
432 for (j=0;j<val->len;j++)
433 fprintf(F,"%02x",*((unsigned char*)val->data+j));
434 fputs("\n",F);
436 /* descend recursively */
437 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
438 return 0;
440 lpxkey=lpxkey->next;
442 return 1;
445 static int
446 _savesubreg(FILE *F,LPKEYSTRUCT lpkey,int all) {
447 fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
448 _save_check_tainted(lpkey->nextsub);
449 return _savesubkey(F,lpkey->nextsub,0,all);
452 static void
453 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
454 FILE *F;
456 F=fopen(fn,"w");
457 if (F==NULL) {
458 fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
459 fn,strerror(errno)
461 return;
463 if (!_savesubreg(F,lpkey,all)) {
464 fclose(F);
465 unlink(fn);
466 fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
467 return;
469 fclose(F);
472 void
473 SHELL_SaveRegistry() {
474 char *fn;
475 struct passwd *pwd;
476 char buf[4];
477 HKEY hkey;
478 int all;
480 all=0;
481 if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) {
482 strcpy(buf,"yes");
483 } else {
484 DWORD len,junk,type;
486 len=4;
487 if ( (ERROR_SUCCESS!=RegQueryValueEx32A(
488 hkey,
489 VAL_SAVEUPDATED,
490 &junk,
491 &type,
492 buf,
493 &len
494 ))|| (type!=REG_SZ)
496 strcpy(buf,"yes");
497 RegCloseKey(hkey);
499 if (lstrcmpi32A(buf,"yes"))
500 all=1;
501 pwd=getpwuid(getuid());
502 if (pwd!=NULL && pwd->pw_dir!=NULL) {
503 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2);
504 strcpy(fn,pwd->pw_dir);
505 strcat(fn,WINE_PREFIX);
506 /* create the directory. don't care about errorcodes. */
507 mkdir(fn,0755); /* drwxr-xr-x */
508 strcat(fn,"/"SAVE_CURRENT_USER);
509 _savereg(key_current_user,fn,all);
510 free(fn);
511 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
512 strcpy(fn,pwd->pw_dir);
513 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
514 _savereg(key_local_machine,fn,all);
515 free(fn);
516 } else
517 fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
520 /************************ LOAD Registry Function ****************************/
522 static LPKEYSTRUCT
523 _find_or_add_key(LPKEYSTRUCT lpkey,LPWSTR keyname) {
524 LPKEYSTRUCT lpxkey,*lplpkey;
526 lplpkey= &(lpkey->nextsub);
527 lpxkey = *lplpkey;
528 while (lpxkey) {
529 if (!lstrcmp32W(lpxkey->keyname,keyname))
530 break;
531 lplpkey = &(lpxkey->next);
532 lpxkey = *lplpkey;
534 if (lpxkey==NULL) {
535 *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
536 lpxkey = *lplpkey;
537 memset(lpxkey,'\0',sizeof(KEYSTRUCT));
538 lpxkey->keyname = keyname;
539 } else
540 free(keyname);
541 return lpxkey;
544 static void
545 _find_or_add_value(
546 LPKEYSTRUCT lpkey,LPWSTR name,DWORD type,LPBYTE data,DWORD len,
547 DWORD lastmodified
549 LPKEYVALUE val=NULL;
550 int i;
552 for (i=0;i<lpkey->nrofvalues;i++) {
553 val=lpkey->values+i;
554 if (name==NULL) {
555 if (val->name==NULL)
556 break;
557 } else {
558 if ( val->name!=NULL &&
559 !lstrcmp32W(val->name,name)
561 break;
564 if (i==lpkey->nrofvalues) {
565 lpkey->values = xrealloc(
566 lpkey->values,
567 (++lpkey->nrofvalues)*sizeof(KEYVALUE)
569 val=lpkey->values+i;
570 memset(val,'\0',sizeof(KEYVALUE));
571 val->name = name;
572 } else {
573 if (name)
574 free(name);
576 if (val->lastmodified<lastmodified) {
577 val->lastmodified=lastmodified;
578 val->type = type;
579 val->len = len;
580 if (val->data)
581 free(val->data);
582 val->data = data;
583 } else
584 free(data);
588 /* reads a line including dynamically enlarging the readbuffer and throwing
589 * away comments
591 static int
592 _wine_read_line(FILE *F,char **buf,int *len) {
593 char *s,*curread;
594 int mylen,curoff;
596 curread = *buf;
597 mylen = *len;
598 **buf = '\0';
599 while (1) {
600 while (1) {
601 s=fgets(curread,mylen,F);
602 if (s==NULL)
603 return 0; /* EOF */
604 if (NULL==(s=strchr(curread,'\n'))) {
605 /* buffer wasn't large enough */
606 curoff = strlen(*buf);
607 *buf = xrealloc(*buf,*len*2);
608 curread = *buf + curoff;
609 mylen = *len; /* we filled up the buffer and
610 * got new '*len' bytes to fill
612 *len = *len * 2;
613 } else {
614 *s='\0';
615 break;
618 /* throw away comments */
619 if (**buf=='#' || **buf==';') {
620 curread = *buf;
621 mylen = *len;
622 continue;
624 if (s) /* got end of line */
625 break;
627 return 1;
630 /* converts a char* into a UNICODE string (up to a special char)
631 * and returns the position exactly after that string
633 static char*
634 _wine_read_USTRING(char *buf,LPWSTR *str) {
635 char *s;
636 LPWSTR ws;
638 /* read up to "=" or "\0" or "\n" */
639 s = buf;
640 if (*s == '=') {
641 /* empty string is the win3.1 default value(NULL)*/
642 *str = NULL;
643 return s;
645 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
646 ws = *str;
647 while (*s && (*s!='\n') && (*s!='=')) {
648 if (*s!='\\')
649 *ws++=*((unsigned char*)s++);
650 else {
651 s++;
652 if (*s=='\\') {
653 *ws+='\\';
654 s++;
655 continue;
657 if (*s!='u') {
658 fprintf(stderr,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
659 *ws++='\\';
660 *ws++=*s++;
661 } else {
662 char xbuf[5];
663 int wc;
665 s++;
666 memcpy(xbuf,s,4);xbuf[4]='\0';
667 if (!sscanf(xbuf,"%x",&wc))
668 fprintf(stderr,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf);
669 s+=4;
670 *ws++ =(unsigned short)wc;
674 *ws = 0;
675 ws = *str;
676 *str = strdupW(*str);
677 free(ws);
678 return s;
681 static int
682 _wine_loadsubkey(
683 FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen,int optflag
685 LPKEYSTRUCT lpxkey;
686 int i;
687 char *s;
688 LPWSTR name;
690 lpkey->flags |= optflag;
692 /* good. we already got a line here ... so parse it */
693 lpxkey = NULL;
694 while (1) {
695 i=0;s=*buf;
696 while (*s=='\t') {
697 s++;
698 i++;
700 if (i>level) {
701 if (lpxkey==NULL) {
702 fprintf(stderr,"_load_subkey:Got a subhierarchy without resp. key?\n");
703 return 0;
705 _wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag);
706 continue;
708 /* let the caller handle this line */
709 if (i<level || **buf=='\0')
710 return 1;
712 /* it can be: a value or a keyname. Parse the name first */
713 s=_wine_read_USTRING(s,&name);
715 /* switch() default: hack to avoid gotos */
716 switch (0) {
717 default:
718 if (*s=='\0') {
719 lpxkey=_find_or_add_key(lpkey,name);
720 } else {
721 LPBYTE data;
722 int len,lastmodified,type;
724 if (*s!='=') {
725 fprintf(stderr,"_wine_load_subkey:unexpected character: %c\n",*s);
726 break;
728 s++;
729 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
730 fprintf(stderr,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf);
731 break;
733 /* skip the 2 , */
734 s=strchr(s,',');s++;
735 s=strchr(s,',');s++;
736 if ((1<<type) & UNICONVMASK) {
737 s=_wine_read_USTRING(s,(LPWSTR*)&data);
738 if (data)
739 len = lstrlen32W((LPWSTR)data)*2+2;
740 else
741 len = 0;
742 } else {
743 len=strlen(s)/2;
744 data = (LPBYTE)xmalloc(len+1);
745 for (i=0;i<len;i++) {
746 data[i]=0;
747 if (*s>='0' && *s<='9')
748 data[i]=(*s-'0')<<4;
749 if (*s>='a' && *s<='f')
750 data[i]=(*s-'a')<<4;
751 if (*s>='A' && *s<='F')
752 data[i]=(*s-'A')<<4;
753 s++;
754 if (*s>='0' && *s<='9')
755 data[i]|=*s-'0';
756 if (*s>='a' && *s<='f')
757 data[i]|=*s-'a';
758 if (*s>='A' && *s<='F')
759 data[i]|=*s-'A';
760 s++;
763 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
766 /* read the next line */
767 if (!_wine_read_line(F,buf,buflen))
768 return 1;
770 return 1;
773 static int
774 _wine_loadsubreg(FILE *F,LPKEYSTRUCT lpkey,int optflag) {
775 int ver;
776 char *buf;
777 int buflen;
779 buf=xmalloc(10);buflen=10;
780 if (!_wine_read_line(F,&buf,&buflen)) {
781 free(buf);
782 return 0;
784 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
785 free(buf);
786 return 0;
788 if (ver!=REGISTRY_SAVE_VERSION) {
789 dprintf_reg(stddeb,__FILE__":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
790 free(buf);
791 return 0;
793 if (!_wine_read_line(F,&buf,&buflen)) {
794 free(buf);
795 return 0;
797 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
798 free(buf);
799 return 0;
801 free(buf);
802 return 1;
805 static void
806 _wine_loadreg(LPKEYSTRUCT lpkey,char *fn,int optflag) {
807 FILE *F;
809 F=fopen(fn,"rb");
810 if (F==NULL) {
811 dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n",
812 fn,strerror(errno)
814 return;
816 if (!_wine_loadsubreg(F,lpkey,optflag)) {
817 fclose(F);
818 unlink(fn);
819 return;
821 fclose(F);
824 static void
825 _copy_registry(LPKEYSTRUCT from,LPKEYSTRUCT to) {
826 LPKEYSTRUCT lpxkey;
827 int j;
828 LPKEYVALUE valfrom;
830 from=from->nextsub;
831 while (from) {
832 lpxkey = _find_or_add_key(to,strdupW(from->keyname));
834 for (j=0;j<from->nrofvalues;j++) {
835 LPWSTR name;
836 LPBYTE data;
838 valfrom = from->values+j;
839 name=valfrom->name;
840 if (name) name=strdupW(name);
841 data=(LPBYTE)malloc(valfrom->len);
842 memcpy(data,valfrom->data,valfrom->len);
844 _find_or_add_value(
845 lpxkey,
846 name,
847 valfrom->type,
848 data,
849 valfrom->len,
850 valfrom->lastmodified
853 _copy_registry(from,lpxkey);
854 from = from->next;
858 /* WINDOWS 95 REGISTRY LOADER */
860 * Structure of a win95 registry database.
861 * main header:
862 * 0 : "CREG" - magic
863 * 4 : DWORD version
864 * 8 : DWORD offset_of_RGDB_part
865 * 0C..1F: ? (someone fill in please)
867 * 20: RGKN_section:
868 * header:
869 * 0 : "RGKN" - magic
870 * 4..0x1B: ? (fill in)
871 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
873 * Disk Key Entry Structure:
874 * 00: DWORD - unknown
875 * 04: DWORD - unknown
876 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
877 * 0C: DWORD - disk address of PreviousLevel Key.
878 * 10: DWORD - disk address of Next Sublevel Key.
879 * 14: DWORD - disk address of Next Key (on same level).
880 * DKEP>18: WORD - Nr, Low Significant part.
881 * 1A: WORD - Nr, High Significant part.
883 * The disk address always points to the nr part of the previous key entry
884 * of the referenced key. Don't ask me why, or even if I got this correct
885 * from staring at 1kg of hexdumps. (DKEP)
887 * The number of the entry is the low byte of the Low Significant Part ored
888 * with 0x100 * (low byte of the High Significant part)
889 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
891 * There are two minor corrections to the position of that structure.
892 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
893 * the DKE reread from there.
894 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
895 * (FIXME: slightly better explanation needed here)
897 * RGDB_section:
898 * 00: "RGDB" - magic
899 * 04: DWORD offset to next RGDB section (perhaps WORD)
900 * 08...1F: ?
901 * 20.....: disk keys
903 * disk key:
904 * 00: DWORD nextkeyoffset - offset to the next disk key structure
905 * 08: WORD nrLS - low significant part of NR
906 * 0A: WORD nrHS - high significant part of NR
907 * 0C: DWORD bytesused - bytes used in this structure.
908 * 10: WORD name_len - length of name in bytes. without \0
909 * 12: WORD nr_of_values - number of values.
910 * 14: char name[name_len] - name string. No \0.
911 * 14+name_len: disk values
912 * nextkeyoffset: ... next disk key
914 * disk value:
915 * 00: DWORD type - value type (hmm, could be WORD too)
916 * 04: DWORD - unknown, usually 0
917 * 08: WORD namelen - length of Name. 0 means name=NULL
918 * 0C: WORD datalen - length of Data.
919 * 10: char name[namelen] - name, no \0
920 * 10+namelen: BYTE data[datalen] - data, without \0 if string
921 * 10+namelen+datalen: next values or disk key
923 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
924 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
925 * structure) and reading another RGDB_section.
926 * repeat until end of file.
928 * FIXME: this description needs some serious help, yes.
931 struct _w95keyvalue {
932 unsigned long type;
933 unsigned short datalen;
934 char *name;
935 unsigned char *data;
936 unsigned long x1;
937 int lastmodified;
940 struct _w95key {
941 char *name;
942 int nrofvals;
943 struct _w95keyvalue *values;
944 unsigned long dkeaddr;
945 unsigned long x1;
946 unsigned long x2;
947 unsigned long x3;
948 unsigned long xx1;
949 struct _w95key *prevlvl;
950 struct _w95key *nextsub;
951 struct _w95key *next;
954 /* fast lookup table dkeaddr->nr */
955 struct _w95nr2da {
956 unsigned long dkeaddr;
957 unsigned long nr;
961 static void
962 _w95_walk_tree(LPKEYSTRUCT lpkey,struct _w95key *key) {
963 int i;
964 LPKEYSTRUCT lpxkey;
965 LPWSTR name;
967 while (key) {
968 if (key->name == NULL) {
969 fprintf(stderr,"_w95_walk_tree:Please report: key with dkeaddr %lx not loaded, skipping hierarchy\n",
970 key->dkeaddr
972 return;
974 lpxkey=_find_or_add_key(lpkey,strdupA2W(key->name));
976 if (key->nrofvals<0) {
977 /* shouldn't happen */
978 fprintf(stderr,"key %s already processed!\n",key->name);
979 key = key->next;
980 continue;
982 for (i=0;i<key->nrofvals;i++) {
983 LPBYTE data;
984 int len;
986 name = strdupA2W(key->values[i].name);
987 if (!*name) name = NULL;
988 free(key->values[i].name);
990 len = key->values[i].datalen;
991 data = key->values[i].data;
992 if ((1<<key->values[i].type) & UNICONVMASK) {
993 data = (BYTE*)strdupA2W(data);
994 len = lstrlen32W((LPWSTR)data)*2+2;
995 free(key->values[i].data);
997 _find_or_add_value(
998 lpxkey,
999 name,
1000 key->values[i].type,
1001 data,
1002 len,
1003 key->values[i].lastmodified
1006 if (key->values) {
1007 free(key->values);
1008 key->values = NULL;
1010 key->nrofvals=-key->nrofvals-1;
1011 _w95_walk_tree(lpxkey,key->nextsub);
1012 key=key->next;
1016 /* small helper function to adjust address offset (dkeaddrs) */
1017 static unsigned long
1018 _w95_adj_da(unsigned long dkeaddr) {
1019 if ((dkeaddr&0xFFF)<0x018) {
1020 int diff;
1022 diff=0x1C-(dkeaddr&0xFFF);
1023 return dkeaddr+diff;
1025 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1026 /* readjust to 0x000,
1027 * but ONLY if we are >0x1000 already
1029 if (dkeaddr & ~0xFFF)
1030 return dkeaddr & ~0xFFF;
1032 return dkeaddr;
1035 static int
1036 _w95dkecomp(struct _w95nr2da *a,struct _w95nr2da *b){return a->dkeaddr-b->dkeaddr;}
1038 static struct _w95key*
1039 _w95dkelookup(unsigned long dkeaddr,int n,struct _w95nr2da *nr2da,struct _w95key *keys) {
1040 int i,off;
1042 if (dkeaddr == 0xFFFFFFFF)
1043 return NULL;
1044 if (dkeaddr<0x20)
1045 return NULL;
1046 dkeaddr=_w95_adj_da(dkeaddr+0x1c);
1047 off = (dkeaddr-0x3c)/0x1c;
1048 for (i=0;i<n;i++)
1049 if (nr2da[(i+off)%n].dkeaddr == dkeaddr)
1050 return keys+nr2da[(i+off)%n].nr;
1051 /* 0x3C happens often, just report unusual values */
1052 if (dkeaddr!=0x3c)
1053 dprintf_reg(stddeb,"search hasn't found dkeaddr %lx?\n",dkeaddr);
1054 return NULL;
1057 extern time_t FileTimeToUnixTime(FILETIME*);
1059 static void
1060 _w95_loadreg(char* fn,LPKEYSTRUCT lpkey) {
1061 /* Disk Key Entry structure (RGKN part) */
1062 struct dke {
1063 unsigned long x1;
1064 unsigned long x2;
1065 unsigned long x3;/*usually 0xFFFFFFFF */
1066 unsigned long prevlvl;
1067 unsigned long nextsub;
1068 unsigned long next;
1069 unsigned short nrLS;
1070 unsigned short nrMS;
1072 /* Disk Key Header structure (RGDB part) */
1073 struct dkh {
1074 unsigned long nextkeyoff;
1075 unsigned short nrLS;
1076 unsigned short nrMS;
1077 unsigned long bytesused;
1078 unsigned short keynamelen;
1079 unsigned short values;
1080 unsigned long xx1;
1081 /* keyname */
1082 /* disk key values or nothing */
1084 /* Disk Key Value structure */
1085 struct dkv {
1086 unsigned long type;
1087 unsigned long x1;
1088 unsigned short valnamelen;
1089 unsigned short valdatalen;
1090 /* valname, valdata */
1092 struct _w95nr2da *nr2da;
1094 HFILE hfd;
1095 int lastmodified;
1096 char magic[5];
1097 unsigned long nr,pos,i,where,version,rgdbsection,end,off_next_rgdb;
1098 struct _w95key *keys;
1099 int nrofdkes;
1100 unsigned char *data,*curdata,*nextrgdb;
1101 OFSTRUCT ofs;
1102 BY_HANDLE_FILE_INFORMATION hfdinfo;
1104 dprintf_reg(stddeb,"Loading Win95 registry database '%s'\n",fn);
1105 hfd=OpenFile(fn,&ofs,OF_READ);
1106 if (hfd==HFILE_ERROR)
1107 return;
1108 magic[4]=0;
1109 if (4!=_lread32(hfd,magic,4))
1110 return;
1111 if (strcmp(magic,"CREG")) {
1112 fprintf(stddeb,"%s is not a w95 registry.\n",fn);
1113 return;
1115 if (4!=_lread32(hfd,&version,4))
1116 return;
1117 if (4!=_lread32(hfd,&rgdbsection,4))
1118 return;
1119 if (-1==_llseek(hfd,0x20,SEEK_SET))
1120 return;
1121 if (4!=_lread32(hfd,magic,4))
1122 return;
1123 if (strcmp(magic,"RGKN")) {
1124 dprintf_reg(stddeb,"second IFF header not RGKN, but %s\n",magic);
1125 return;
1128 /* STEP 1: Keylink structures */
1129 if (-1==_llseek(hfd,0x40,SEEK_SET))
1130 return;
1131 where = 0x40;
1132 end = rgdbsection;
1134 nrofdkes = (end-where)/sizeof(struct dke)+100;
1135 data = (char*)xmalloc(end-where);
1136 if ((end-where)!=_lread32(hfd,data,end-where))
1137 return;
1138 curdata = data;
1140 keys = (struct _w95key*)xmalloc(nrofdkes * sizeof(struct _w95key));
1141 memset(keys,'\0',nrofdkes*sizeof(struct _w95key));
1142 nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
1143 memset(nr2da,'\0',nrofdkes*sizeof(struct _w95nr2da));
1145 for (i=0;i<nrofdkes;i++) {
1146 struct dke dke;
1147 unsigned long dkeaddr;
1149 pos=curdata-data+0x40;
1150 memcpy(&dke,curdata,sizeof(dke));
1151 curdata+=sizeof(dke);
1152 nr = dke.nrLS + (dke.nrMS<<8);
1153 dkeaddr=pos-4;
1154 if ((dkeaddr&0xFFF)<0x018) {
1155 int diff;
1157 diff=0x1C-(dkeaddr&0xFFF);
1158 dkeaddr+=diff;
1159 curdata+=diff-sizeof(dke);
1160 memcpy(&dke,curdata,sizeof(dke));
1161 nr = dke.nrLS + (dke.nrMS<<8);
1162 curdata+=sizeof(dke);
1164 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1165 /* readjust to 0x000,
1166 * but ONLY if we are >0x1000 already
1168 if (dkeaddr & ~0xFFF)
1169 dkeaddr = dkeaddr & ~0xFFF;
1171 if (nr>nrofdkes) {
1172 /* 0xFFFFFFFF happens often, just report unusual values */
1173 if (nr!=0xFFFFFFFF)
1174 dprintf_reg(stddeb,"nr %ld exceeds nrofdkes %d, skipping.\n",nr,nrofdkes);
1175 continue;
1177 if (keys[nr].dkeaddr) {
1178 int x;
1180 for (x=sizeof(dke);x--;)
1181 if (((char*)&dke)[x])
1182 break;
1183 if (x==-1)
1184 break; /* finished reading if we got only 0 */
1185 if (nr) {
1186 if ( (dke.next!=(long)keys[nr].next) ||
1187 (dke.nextsub!=(long)keys[nr].nextsub) ||
1188 (dke.prevlvl!=(long)keys[nr].prevlvl)
1190 dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[nr].dkeaddr,dkeaddr);
1192 continue;
1194 nr2da[i].nr = nr;
1195 nr2da[i].dkeaddr = dkeaddr;
1197 keys[nr].dkeaddr = dkeaddr;
1198 keys[nr].x1 = dke.x1;
1199 keys[nr].x2 = dke.x2;
1200 keys[nr].x3 = dke.x3;
1201 keys[nr].prevlvl= (struct _w95key*)dke.prevlvl;
1202 keys[nr].nextsub= (struct _w95key*)dke.nextsub;
1203 keys[nr].next = (struct _w95key*)dke.next;
1205 free(data);
1207 qsort(nr2da,nrofdkes,sizeof(nr2da[0]),
1208 (int(*)(const void *,const void*))_w95dkecomp);
1210 /* STEP 2: keydata & values */
1211 if (!GetFileInformationByHandle(hfd,&hfdinfo))
1212 return;
1213 end = hfdinfo.nFileSizeLow;
1214 lastmodified = FileTimeToUnixTime(&(hfdinfo.ftLastWriteTime));
1216 if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
1217 return;
1218 data = (char*)xmalloc(end-rgdbsection);
1219 if ((end-rgdbsection)!=_lread32(hfd,data,end-rgdbsection))
1220 return;
1221 _lclose(hfd);
1222 curdata = data;
1223 memcpy(magic,curdata,4);
1224 memcpy(&off_next_rgdb,curdata+4,4);
1225 nextrgdb = curdata+off_next_rgdb;
1226 if (strcmp(magic,"RGDB")) {
1227 dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
1228 return;
1230 curdata=data+0x20;
1231 while (1) {
1232 struct dkh dkh;
1233 int bytesread;
1234 struct _w95key *key,xkey;
1236 bytesread = 0;
1237 if (curdata>=nextrgdb) {
1238 curdata = nextrgdb;
1239 if (!strncmp(curdata,"RGDB",4)) {
1240 memcpy(&off_next_rgdb,curdata+4,4);
1241 nextrgdb = curdata+off_next_rgdb;
1242 curdata+=0x20;
1243 } else {
1244 dprintf_reg(stddeb,"at end of RGDB section, but no next header (%x of %lx). Breaking.\n",curdata-data,end-rgdbsection);
1245 break;
1248 #define XREAD(whereto,len) \
1249 if ((curdata-data+len)<end) {\
1250 memcpy(whereto,curdata,len);\
1251 curdata+=len;\
1252 bytesread+=len;\
1255 XREAD(&dkh,sizeof(dkh));
1256 nr = dkh.nrLS + (dkh.nrMS<<8);
1257 if ((nr>nrofdkes) || (dkh.nrLS == 0xFFFF)) {
1258 if (dkh.nrLS == 0xFFFF) {
1259 /* skip over key using nextkeyoff */
1260 curdata+=dkh.nextkeyoff-sizeof(struct dkh);
1261 continue;
1263 dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
1264 key = &xkey;
1265 memset(key,'\0',sizeof(xkey));
1266 } else {
1267 key = keys+nr;
1268 if (!key->dkeaddr)
1269 dprintf_reg(stddeb,"key with nr=%ld has no dkeaddr?\n",nr);
1271 key->nrofvals = dkh.values;
1272 key->name = (char*)xmalloc(dkh.keynamelen+1);
1273 key->xx1 = dkh.xx1;
1274 XREAD(key->name,dkh.keynamelen);
1275 key->name[dkh.keynamelen]=0;
1276 if (key->nrofvals) {
1277 key->values = (struct _w95keyvalue*)xmalloc(
1278 sizeof(struct _w95keyvalue)*key->nrofvals
1280 for (i=0;i<key->nrofvals;i++) {
1281 struct dkv dkv;
1283 XREAD(&dkv,sizeof(dkv));
1284 key->values[i].type = dkv.type;
1285 key->values[i].name = (char*)xmalloc(
1286 dkv.valnamelen+1
1288 key->values[i].datalen = dkv.valdatalen;
1289 key->values[i].data = (unsigned char*)xmalloc(
1290 dkv.valdatalen+1
1292 key->values[i].x1 = dkv.x1;
1293 XREAD(key->values[i].name,dkv.valnamelen);
1294 XREAD(key->values[i].data,dkv.valdatalen);
1295 key->values[i].data[dkv.valdatalen]=0;
1296 key->values[i].name[dkv.valnamelen]=0;
1297 key->values[i].lastmodified=lastmodified;
1300 if (bytesread != dkh.nextkeyoff) {
1301 if (dkh.bytesused != bytesread)
1302 dprintf_reg(stddeb,
1303 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread,dkh.nextkeyoff,
1304 dkh.bytesused
1306 curdata += dkh.nextkeyoff-bytesread;
1308 key->prevlvl = _w95dkelookup((long)key->prevlvl,nrofdkes,nr2da,keys);
1309 key->nextsub = _w95dkelookup((long)key->nextsub,nrofdkes,nr2da,keys);
1310 key->next = _w95dkelookup((long)key->next,nrofdkes,nr2da,keys);
1311 if (!bytesread)
1312 break;
1314 free(data);
1315 _w95_walk_tree(lpkey,keys);
1316 free(keys);
1319 void
1320 SHELL_LoadRegistry() {
1321 char *fn;
1322 struct passwd *pwd;
1323 LPKEYSTRUCT lpkey;
1324 HKEY hkey;
1327 if (key_classes_root==NULL)
1328 SHELL_Init();
1330 /* Load windows 95 entries */
1331 _w95_loadreg("C:\\system.1st", key_local_machine);
1332 _w95_loadreg("system.dat", key_local_machine);
1333 _w95_loadreg("user.dat", key_users);
1335 /* FIXME: win3.1 reg.dat loader still missing */
1337 /* the global user default is loaded under HKEY_USERS\\.Default */
1338 RegCreateKey16(HKEY_USERS,".Default",&hkey);
1339 lpkey = lookup_hkey(hkey);
1340 _wine_loadreg(lpkey,SAVE_USERS_DEFAULT,0);
1342 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1343 _copy_registry(lpkey,key_current_user);
1344 RegCloseKey(hkey);
1346 /* the global machine defaults */
1347 _wine_loadreg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT,0);
1349 /* load the user saved registries */
1351 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1353 pwd=getpwuid(getuid());
1354 if (pwd!=NULL && pwd->pw_dir!=NULL) {
1355 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
1356 strcpy(fn,pwd->pw_dir);
1357 strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
1358 _wine_loadreg(key_current_user,fn,REG_OPTION_TAINTED);
1359 free(fn);
1360 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
1361 strcpy(fn,pwd->pw_dir);
1362 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1363 _wine_loadreg(key_local_machine,fn,REG_OPTION_TAINTED);
1364 free(fn);
1365 } else
1366 fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1367 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) {
1368 DWORD junk,type,len;
1369 char data[5];
1371 len=4;
1372 if (( RegQueryValueEx32A(
1373 hkey,
1374 VAL_SAVEUPDATED,
1375 &junk,
1376 &type,
1377 data,
1378 &len
1379 )!=ERROR_SUCCESS) ||
1380 type != REG_SZ
1382 RegSetValueEx32A(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1383 RegCloseKey(hkey);
1388 /********************* API FUNCTIONS ***************************************/
1390 * Open Keys.
1392 * All functions are stubs to RegOpenKeyEx32W where all the
1393 * magic happens.
1395 * FIXME: security,options,desiredaccess,...
1397 * Callpath:
1398 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1399 * RegOpenKey32W -> RegOpenKeyEx32W
1402 /* RegOpenKeyExW [ADVAPI32.150] */
1403 DWORD RegOpenKeyEx32W(
1404 HKEY hkey,
1405 LPCWSTR lpszSubKey,
1406 DWORD dwReserved,
1407 REGSAM samDesired,
1408 LPHKEY retkey
1410 LPKEYSTRUCT lpNextKey,lpxkey;
1411 LPWSTR *wps;
1412 int wpc,i;
1413 dprintf_reg(stddeb,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1414 (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey
1417 lpNextKey = lookup_hkey(hkey);
1418 if (!lpNextKey)
1419 return SHELL_ERROR_BADKEY;
1420 if (!lpszSubKey || !*lpszSubKey) {
1421 add_handle(++currenthandle,lpNextKey,samDesired);
1422 *retkey=currenthandle;
1423 return SHELL_ERROR_SUCCESS;
1425 split_keypath(lpszSubKey,&wps,&wpc);
1426 i = 0;
1427 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1428 lpxkey = lpNextKey;
1429 while (i<wpc) {
1430 lpxkey=lpNextKey->nextsub;
1431 while (lpxkey) {
1432 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1433 break;
1434 lpxkey=lpxkey->next;
1436 if (!lpxkey) {
1437 FREE_KEY_PATH;
1438 return SHELL_ERROR_BADKEY;
1440 i++;
1441 lpNextKey = lpxkey;
1443 add_handle(++currenthandle,lpxkey,samDesired);
1444 *retkey = currenthandle;
1445 FREE_KEY_PATH;
1446 return SHELL_ERROR_SUCCESS;
1449 /* RegOpenKeyW [ADVAPI32.151] */
1450 DWORD RegOpenKey32W(
1451 HKEY hkey,
1452 LPCWSTR lpszSubKey,
1453 LPHKEY retkey
1455 dprintf_reg(stddeb,"RegOpenKey32W(%lx,%s,%p)\n",
1456 (LONG)hkey,W2C(lpszSubKey,0),retkey
1458 return RegOpenKeyEx32W(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1462 /* RegOpenKeyExA [ADVAPI32.149] */
1463 DWORD RegOpenKeyEx32A(
1464 HKEY hkey,
1465 LPCSTR lpszSubKey,
1466 DWORD dwReserved,
1467 REGSAM samDesired,
1468 LPHKEY retkey
1470 LPWSTR lpszSubKeyW;
1471 DWORD ret;
1473 dprintf_reg(stddeb,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1474 (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey
1476 if (lpszSubKey)
1477 lpszSubKeyW=strdupA2W(lpszSubKey);
1478 else
1479 lpszSubKeyW=NULL;
1480 ret=RegOpenKeyEx32W(hkey,lpszSubKeyW,dwReserved,samDesired,retkey);
1481 if (lpszSubKeyW)
1482 free(lpszSubKeyW);
1483 return ret;
1486 /* RegOpenKeyA [ADVAPI32.148] */
1487 DWORD RegOpenKey32A(
1488 HKEY hkey,
1489 LPCSTR lpszSubKey,
1490 LPHKEY retkey
1492 dprintf_reg(stddeb,"RegOpenKey32A(%lx,%s,%p)\n",
1493 (LONG)hkey,lpszSubKey,retkey
1495 return RegOpenKeyEx32A(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1498 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1499 DWORD RegOpenKey16(
1500 HKEY hkey,
1501 LPCSTR lpszSubKey,
1502 LPHKEY retkey
1504 dprintf_reg(stddeb,"RegOpenKey16(%lx,%s,%p)\n",
1505 (LONG)hkey,lpszSubKey,retkey
1507 return RegOpenKey32A(hkey,lpszSubKey,retkey);
1511 * Create keys
1513 * All those functions convert their respective
1514 * arguments and call RegCreateKeyExW at the end.
1516 * FIXME: no security,no access attrib,no optionhandling yet.
1518 * Callpath:
1519 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1520 * RegCreateKey32W -> RegCreateKeyEx32W
1523 /* RegCreateKeyExW [ADVAPI32.131] */
1524 DWORD RegCreateKeyEx32W(
1525 HKEY hkey,
1526 LPCWSTR lpszSubKey,
1527 DWORD dwReserved,
1528 LPWSTR lpszClass,
1529 DWORD fdwOptions,
1530 REGSAM samDesired,
1531 LPSECURITY_ATTRIBUTES lpSecAttribs,
1532 LPHKEY retkey,
1533 LPDWORD lpDispos
1535 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
1536 LPWSTR *wps;
1537 int wpc,i;
1539 /*FIXME: handle security/access/whatever */
1540 dprintf_reg(stddeb,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1541 (LONG)hkey,
1542 W2C(lpszSubKey,0),
1543 dwReserved,
1544 W2C(lpszClass,1),
1545 fdwOptions,
1546 samDesired,
1547 lpSecAttribs,
1548 retkey,
1549 lpDispos
1552 lpNextKey = lookup_hkey(hkey);
1553 if (!lpNextKey)
1554 return SHELL_ERROR_BADKEY;
1555 if (!lpszSubKey || !*lpszSubKey) {
1556 add_handle(++currenthandle,lpNextKey,samDesired);
1557 *retkey=currenthandle;
1558 lpNextKey->flags|=REG_OPTION_TAINTED;
1559 return SHELL_ERROR_SUCCESS;
1561 split_keypath(lpszSubKey,&wps,&wpc);
1562 i = 0;
1563 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1564 lpxkey = lpNextKey;
1565 while (wps[i]) {
1566 lpxkey=lpNextKey->nextsub;
1567 while (lpxkey) {
1568 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1569 break;
1570 lpxkey=lpxkey->next;
1572 if (!lpxkey)
1573 break;
1574 i++;
1575 lpNextKey = lpxkey;
1577 if (lpxkey) {
1578 add_handle(++currenthandle,lpxkey,samDesired);
1579 lpxkey->flags |= REG_OPTION_TAINTED;
1580 *retkey = currenthandle;
1581 if (lpDispos)
1582 *lpDispos = REG_OPENED_EXISTING_KEY;
1583 FREE_KEY_PATH;
1584 return SHELL_ERROR_SUCCESS;
1586 /* good. now the hard part */
1587 while (wps[i]) {
1588 lplpPrevKey = &(lpNextKey->nextsub);
1589 lpxkey = *lplpPrevKey;
1590 while (lpxkey) {
1591 lplpPrevKey = &(lpxkey->next);
1592 lpxkey = *lplpPrevKey;
1594 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
1595 if (!*lplpPrevKey) {
1596 FREE_KEY_PATH;
1597 return SHELL_ERROR_OUTOFMEMORY;
1599 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
1600 (*lplpPrevKey)->keyname = strdupW(wps[i]);
1601 (*lplpPrevKey)->next = NULL;
1602 (*lplpPrevKey)->nextsub = NULL;
1603 (*lplpPrevKey)->values = NULL;
1604 (*lplpPrevKey)->nrofvalues = 0;
1605 (*lplpPrevKey)->flags = REG_OPTION_TAINTED;
1606 if (lpszClass)
1607 (*lplpPrevKey)->class = strdupW(lpszClass);
1608 else
1609 (*lplpPrevKey)->class = NULL;
1610 lpNextKey = *lplpPrevKey;
1611 i++;
1613 add_handle(++currenthandle,lpNextKey,samDesired);
1615 /*FIXME: flag handling correct? */
1616 lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
1617 if (lpszClass)
1618 lpNextKey->class = strdupW(lpszClass);
1619 else
1620 lpNextKey->class = NULL;
1621 *retkey = currenthandle;
1622 if (lpDispos)
1623 *lpDispos = REG_CREATED_NEW_KEY;
1624 FREE_KEY_PATH;
1625 return SHELL_ERROR_SUCCESS;
1628 /* RegCreateKeyW [ADVAPI32.132] */
1629 DWORD RegCreateKey32W(
1630 HKEY hkey,
1631 LPCWSTR lpszSubKey,
1632 LPHKEY retkey
1634 DWORD junk,ret;
1636 dprintf_reg(stddeb,"RegCreateKey32W(%lx,%s,%p)\n",
1637 (LONG)hkey,W2C(lpszSubKey,0),retkey
1639 ret=RegCreateKeyEx32W(
1640 hkey, /* key handle */
1641 lpszSubKey, /* subkey name */
1642 0, /* reserved = 0 */
1643 NULL, /* lpszClass? FIXME: ? */
1644 REG_OPTION_NON_VOLATILE, /* options */
1645 KEY_ALL_ACCESS, /* desired access attribs */
1646 NULL, /* lpsecurity attributes */
1647 retkey, /* lpretkey */
1648 &junk /* disposition value */
1650 return ret;
1653 /* RegCreateKeyExA [ADVAPI32.130] */
1654 DWORD RegCreateKeyEx32A(
1655 HKEY hkey,
1656 LPCSTR lpszSubKey,
1657 DWORD dwReserved,
1658 LPSTR lpszClass,
1659 DWORD fdwOptions,
1660 REGSAM samDesired,
1661 LPSECURITY_ATTRIBUTES lpSecAttribs,
1662 LPHKEY retkey,
1663 LPDWORD lpDispos
1665 LPWSTR lpszSubKeyW,lpszClassW;
1666 DWORD ret;
1668 dprintf_reg(stddeb,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1669 (LONG)hkey,
1670 lpszSubKey,
1671 dwReserved,
1672 lpszClass,
1673 fdwOptions,
1674 samDesired,
1675 lpSecAttribs,
1676 retkey,
1677 lpDispos
1679 if (lpszSubKey)
1680 lpszSubKeyW=strdupA2W(lpszSubKey);
1681 else
1682 lpszSubKeyW=NULL;
1683 if (lpszClass)
1684 lpszClassW=strdupA2W(lpszClass);
1685 else
1686 lpszClassW=NULL;
1687 ret=RegCreateKeyEx32W(
1688 hkey,
1689 lpszSubKeyW,
1690 dwReserved,
1691 lpszClassW,
1692 fdwOptions,
1693 samDesired,
1694 lpSecAttribs,
1695 retkey,
1696 lpDispos
1698 if (lpszSubKeyW)
1699 free(lpszSubKeyW);
1700 if (lpszClassW)
1701 free(lpszClassW);
1702 return ret;
1705 /* RegCreateKeyA [ADVAPI32.129] */
1706 DWORD RegCreateKey32A(
1707 HKEY hkey,
1708 LPCSTR lpszSubKey,
1709 LPHKEY retkey
1711 DWORD junk;
1713 dprintf_reg(stddeb,"RegCreateKey32A(%lx,%s,%p)\n",
1714 (LONG)hkey,lpszSubKey,retkey
1716 return RegCreateKeyEx32A(
1717 hkey, /* key handle */
1718 lpszSubKey, /* subkey name */
1719 0, /* reserved = 0 */
1720 NULL, /* lpszClass? FIXME: ? */
1721 REG_OPTION_NON_VOLATILE,/* options */
1722 KEY_ALL_ACCESS, /* desired access attribs */
1723 NULL, /* lpsecurity attributes */
1724 retkey, /* lpretkey */
1725 &junk /* disposition value */
1729 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1730 DWORD RegCreateKey16(
1731 HKEY hkey,
1732 LPCSTR lpszSubKey,
1733 LPHKEY retkey
1735 dprintf_reg(stddeb,"RegCreateKey16(%lx,%s,%p)\n",
1736 (LONG)hkey,lpszSubKey,retkey
1738 return RegCreateKey32A(hkey,lpszSubKey,retkey);
1742 * Query Value Functions
1743 * Win32 differs between keynames and valuenames.
1744 * multiple values may belong to one key, the special value
1745 * with name NULL is the default value used by the win31
1746 * compat functions.
1748 * Callpath:
1749 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1750 * RegQueryValue32W -> RegQueryValueEx32W
1753 /* RegQueryValueExW [ADVAPI32.158] */
1754 DWORD RegQueryValueEx32W(
1755 HKEY hkey,
1756 LPWSTR lpszValueName,
1757 LPDWORD lpdwReserved,
1758 LPDWORD lpdwType,
1759 LPBYTE lpbData,
1760 LPDWORD lpcbData
1762 LPKEYSTRUCT lpkey;
1763 int i;
1765 dprintf_reg(stddeb,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%ld)\n",
1766 hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,
1767 lpcbData?*lpcbData:0
1770 lpkey = lookup_hkey(hkey);
1771 if (!lpkey)
1772 return SHELL_ERROR_BADKEY;
1773 if (lpszValueName==NULL) {
1774 for (i=0;i<lpkey->nrofvalues;i++)
1775 if (lpkey->values[i].name==NULL)
1776 break;
1777 } else {
1778 for (i=0;i<lpkey->nrofvalues;i++)
1779 if ( lpkey->values[i].name &&
1780 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
1782 break;
1784 if (i==lpkey->nrofvalues) {
1785 if (lpszValueName==NULL) {
1786 if (lpbData) {
1787 *(WCHAR*)lpbData = 0;
1788 *lpcbData = 2;
1790 if (lpdwType)
1791 *lpdwType = REG_SZ;
1792 return SHELL_ERROR_SUCCESS;
1794 return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
1796 if (lpdwType)
1797 *lpdwType = lpkey->values[i].type;
1798 if (lpbData==NULL) {
1799 if (lpcbData==NULL)
1800 return SHELL_ERROR_SUCCESS;
1801 *lpcbData = lpkey->values[i].len;
1802 return SHELL_ERROR_SUCCESS;
1804 if (*lpcbData<lpkey->values[i].len) {
1805 *(WCHAR*)lpbData
1806 = 0;
1807 *lpcbData = lpkey->values[i].len;
1808 return ERROR_MORE_DATA;
1810 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
1811 *lpcbData = lpkey->values[i].len;
1812 return SHELL_ERROR_SUCCESS;
1815 /* RegQueryValueW [ADVAPI32.159] */
1816 DWORD RegQueryValue32W(
1817 HKEY hkey,
1818 LPWSTR lpszSubKey,
1819 LPWSTR lpszData,
1820 LPDWORD lpcbData
1822 HKEY xhkey;
1823 DWORD ret,lpdwType;
1825 dprintf_reg(stddeb,"RegQueryValue32W(%x,%s,%p,%ld)\n->",
1826 hkey,W2C(lpszSubKey,0),lpszData,
1827 lpcbData?*lpcbData:0
1830 /* only open subkey, if we really do descend */
1831 if (lpszSubKey && *lpszSubKey) {
1832 ret = RegOpenKey32W(hkey,lpszSubKey,&xhkey);
1833 if (ret!=ERROR_SUCCESS)
1834 return ret;
1835 } else
1836 xhkey = hkey;
1838 lpdwType = REG_SZ;
1839 ret = RegQueryValueEx32W(
1840 xhkey,
1841 NULL, /* varname NULL -> compat */
1842 NULL, /* lpdwReserved, must be NULL */
1843 &lpdwType,
1844 (LPBYTE)lpszData,
1845 lpcbData
1847 if (xhkey!=hkey)
1848 RegCloseKey(xhkey);
1849 return ret;
1852 /* RegQueryValueExA [ADVAPI32.157] */
1853 DWORD RegQueryValueEx32A(
1854 HKEY hkey,
1855 LPSTR lpszValueName,
1856 LPDWORD lpdwReserved,
1857 LPDWORD lpdwType,
1858 LPBYTE lpbData,
1859 LPDWORD lpcbData
1861 LPWSTR lpszValueNameW;
1862 LPBYTE buf;
1863 DWORD ret,myxlen;
1864 DWORD *mylen;
1865 DWORD type;
1867 dprintf_reg(stddeb,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%ld)\n->",
1868 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
1869 lpcbData?*lpcbData:0
1871 if (lpbData) {
1872 /* double buffer */
1873 buf = (LPBYTE)xmalloc((*lpcbData)*2);
1874 myxlen = *lpcbData*2;
1875 mylen = &myxlen;
1876 } else {
1877 buf=NULL;
1878 if (lpcbData) {
1879 myxlen = *lpcbData*2;
1880 mylen = &myxlen;
1881 } else
1882 mylen = NULL;
1884 if (lpszValueName)
1885 lpszValueNameW=strdupA2W(lpszValueName);
1886 else
1887 lpszValueNameW=NULL;
1889 if (lpdwType)
1890 type=*lpdwType;
1891 ret=RegQueryValueEx32W(
1892 hkey,
1893 lpszValueNameW,
1894 lpdwReserved,
1895 &type,
1896 buf,
1897 mylen
1899 if (lpdwType)
1900 *lpdwType=type;
1901 if (ret==ERROR_SUCCESS) {
1902 if (buf) {
1903 if (UNICONVMASK & (1<<(type))) {
1904 /* convert UNICODE to ASCII */
1905 strcpyWA(lpbData,(LPWSTR)buf);
1906 *lpcbData = myxlen/2;
1907 } else {
1908 if (myxlen>*lpcbData)
1909 ret = ERROR_MORE_DATA;
1910 else
1911 memcpy(lpbData,buf,myxlen);
1913 *lpcbData = myxlen;
1915 } else {
1916 if ((UNICONVMASK & (1<<(type))) && lpcbData)
1917 *lpcbData = myxlen/2;
1919 } else {
1920 if ((UNICONVMASK & (1<<(type))) && lpcbData)
1921 *lpcbData = myxlen/2;
1923 if (buf)
1924 free(buf);
1925 return ret;
1928 /* RegQueryValueEx [KERNEL.225] */
1929 DWORD RegQueryValueEx16(
1930 HKEY hkey,
1931 LPSTR lpszValueName,
1932 LPDWORD lpdwReserved,
1933 LPDWORD lpdwType,
1934 LPBYTE lpbData,
1935 LPDWORD lpcbData
1937 dprintf_reg(stddeb,"RegQueryValueEx16(%x,%s,%p,%p,%p,%ld)\n",
1938 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
1939 lpcbData?*lpcbData:0
1941 return RegQueryValueEx32A(
1942 hkey,
1943 lpszValueName,
1944 lpdwReserved,
1945 lpdwType,
1946 lpbData,
1947 lpcbData
1951 /* RegQueryValueA [ADVAPI32.156] */
1952 DWORD RegQueryValue32A(
1953 HKEY hkey,
1954 LPSTR lpszSubKey,
1955 LPSTR lpszData,
1956 LPDWORD lpcbData
1958 HKEY xhkey;
1959 DWORD ret,lpdwType;
1961 dprintf_reg(stddeb,"RegQueryValue32A(%x,%s,%p,%ld)\n",
1962 hkey,lpszSubKey,lpszData,
1963 lpcbData?*lpcbData:0
1966 /* only open subkey, if we really do descend */
1967 if (lpszSubKey && *lpszSubKey) {
1968 ret = RegOpenKey16(hkey,lpszSubKey,&xhkey);
1969 if (ret!=ERROR_SUCCESS)
1970 return ret;
1971 } else
1972 xhkey = hkey;
1974 lpdwType = REG_SZ;
1975 ret = RegQueryValueEx32A(
1976 xhkey,
1977 NULL, /* lpszValueName NULL -> compat */
1978 NULL, /* lpdwReserved, must be NULL */
1979 &lpdwType,
1980 (LPBYTE)lpszData,
1981 lpcbData
1983 if (xhkey!=hkey)
1984 RegCloseKey(xhkey);
1985 return ret;
1988 /* RegQueryValue [SHELL.6] [KERNEL.224] */
1989 DWORD RegQueryValue16(
1990 HKEY hkey,
1991 LPSTR lpszSubKey,
1992 LPSTR lpszData,
1993 LPDWORD lpcbData
1995 dprintf_reg(stddeb,"RegQueryValue16(%x,%s,%p,%ld)\n",
1996 hkey,lpszSubKey,lpszData,lpcbData?*lpcbData:0
1998 /* HACK: the 16bit RegQueryValue doesn't handle selectorblocks
1999 * anyway, so we just mask out the high 16 bit.
2000 * (this (not so much incidently;) hopefully fixes Aldus FH4)
2002 if (lpcbData)
2003 *lpcbData &= 0xFFFF;
2004 return RegQueryValue32A(hkey,lpszSubKey,lpszData,lpcbData);
2008 * Setting values of Registry keys
2010 * Callpath:
2011 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
2012 * RegSetValue32W -> RegSetValueEx32W
2015 /* RegSetValueExW [ADVAPI32.170] */
2016 DWORD RegSetValueEx32W(
2017 HKEY hkey,
2018 LPWSTR lpszValueName,
2019 DWORD dwReserved,
2020 DWORD dwType,
2021 LPBYTE lpbData,
2022 DWORD cbData
2024 LPKEYSTRUCT lpkey;
2025 int i;
2027 dprintf_reg(stddeb,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
2028 hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData
2030 /* we no longer care about the lpbData type here... */
2031 lpkey = lookup_hkey(hkey);
2032 if (!lpkey)
2033 return SHELL_ERROR_BADKEY;
2035 lpkey->flags |= REG_OPTION_TAINTED;
2037 if (lpszValueName==NULL) {
2038 for (i=0;i<lpkey->nrofvalues;i++)
2039 if (lpkey->values[i].name==NULL)
2040 break;
2041 } else {
2042 for (i=0;i<lpkey->nrofvalues;i++)
2043 if ( lpkey->values[i].name &&
2044 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
2046 break;
2048 if (i==lpkey->nrofvalues) {
2049 lpkey->values = (LPKEYVALUE)xrealloc(
2050 lpkey->values,
2051 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
2053 lpkey->nrofvalues++;
2054 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
2056 if (lpkey->values[i].name==NULL)
2057 if (lpszValueName)
2058 lpkey->values[i].name = strdupW(lpszValueName);
2059 else
2060 lpkey->values[i].name = NULL;
2061 lpkey->values[i].len = cbData;
2062 lpkey->values[i].type = dwType;
2063 if (lpkey->values[i].data !=NULL)
2064 free(lpkey->values[i].data);
2065 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
2066 lpkey->values[i].lastmodified = time(NULL);
2067 memcpy(lpkey->values[i].data,lpbData,cbData);
2068 return SHELL_ERROR_SUCCESS;
2071 /* RegSetValueExA [ADVAPI32.169] */
2072 DWORD RegSetValueEx32A(
2073 HKEY hkey,
2074 LPSTR lpszValueName,
2075 DWORD dwReserved,
2076 DWORD dwType,
2077 LPBYTE lpbData,
2078 DWORD cbData
2080 LPBYTE buf;
2081 LPWSTR lpszValueNameW;
2082 DWORD ret;
2084 dprintf_reg(stddeb,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
2085 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2087 if ((1<<dwType) & UNICONVMASK) {
2088 buf=(LPBYTE)strdupA2W(lpbData);
2089 cbData=2*strlen(lpbData)+2;
2090 } else
2091 buf=lpbData;
2092 if (lpszValueName)
2093 lpszValueNameW = strdupA2W(lpszValueName);
2094 else
2095 lpszValueNameW = NULL;
2096 ret=RegSetValueEx32W(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
2097 if (lpszValueNameW)
2098 free(lpszValueNameW);
2099 if (buf!=lpbData)
2100 free(buf);
2101 return ret;
2104 /* RegSetValueEx [KERNEL.226] */
2105 DWORD RegSetValueEx16(
2106 HKEY hkey,
2107 LPSTR lpszValueName,
2108 DWORD dwReserved,
2109 DWORD dwType,
2110 LPBYTE lpbData,
2111 DWORD cbData
2113 dprintf_reg(stddeb,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2114 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2116 return RegSetValueEx32A(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData);
2119 /* RegSetValueW [ADVAPI32.171] */
2120 DWORD RegSetValue32W(
2121 HKEY hkey,
2122 LPCWSTR lpszSubKey,
2123 DWORD dwType,
2124 LPCWSTR lpszData,
2125 DWORD cbData
2127 HKEY xhkey;
2128 DWORD ret;
2130 dprintf_reg(stddeb,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2131 hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
2133 if (lpszSubKey && *lpszSubKey) {
2134 ret=RegCreateKey32W(hkey,lpszSubKey,&xhkey);
2135 if (ret!=ERROR_SUCCESS)
2136 return ret;
2137 } else
2138 xhkey=hkey;
2139 if (dwType!=REG_SZ) {
2140 fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
2141 dwType=REG_SZ;
2143 if (cbData!=2*lstrlen32W(lpszData)+2) {
2144 dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2145 cbData,W2C(lpszData,0),2*lstrlen32W(lpszData)+2
2147 cbData=2*lstrlen32W(lpszData)+2;
2149 ret=RegSetValueEx32W(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2150 if (hkey!=xhkey)
2151 RegCloseKey(xhkey);
2152 return ret;
2155 /* RegSetValueA [ADVAPI32.168] */
2156 DWORD RegSetValue32A(
2157 HKEY hkey,
2158 LPCSTR lpszSubKey,
2159 DWORD dwType,
2160 LPCSTR lpszData,
2161 DWORD cbData
2163 DWORD ret;
2164 HKEY xhkey;
2166 dprintf_reg(stddeb,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2167 hkey,lpszSubKey,dwType,lpszData,cbData
2169 if (lpszSubKey && *lpszSubKey) {
2170 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
2171 if (ret!=ERROR_SUCCESS)
2172 return ret;
2173 } else
2174 xhkey=hkey;
2176 if (dwType!=REG_SZ) {
2177 dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType);
2178 dwType=REG_SZ;
2180 if (cbData!=strlen(lpszData)+1)
2181 cbData=strlen(lpszData)+1;
2182 ret=RegSetValueEx32A(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2183 if (xhkey!=hkey)
2184 RegCloseKey(xhkey);
2185 return ret;
2188 /* RegSetValue [KERNEL.221] [SHELL.5] */
2189 DWORD RegSetValue16(
2190 HKEY hkey,
2191 LPCSTR lpszSubKey,
2192 DWORD dwType,
2193 LPCSTR lpszData,
2194 DWORD cbData
2196 DWORD ret;
2197 dprintf_reg(stddeb,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2198 hkey,lpszSubKey,dwType,lpszData,cbData
2200 ret=RegSetValue32A(hkey,lpszSubKey,dwType,lpszData,cbData);
2201 return ret;
2205 * Key Enumeration
2207 * Callpath:
2208 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2209 * RegEnumKey32W -> RegEnumKeyEx32W
2212 /* RegEnumKeyExW [ADVAPI32.139] */
2213 DWORD RegEnumKeyEx32W(
2214 HKEY hkey,
2215 DWORD iSubkey,
2216 LPWSTR lpszName,
2217 LPDWORD lpcchName,
2218 LPDWORD lpdwReserved,
2219 LPWSTR lpszClass,
2220 LPDWORD lpcchClass,
2221 FILETIME *ft
2223 LPKEYSTRUCT lpkey,lpxkey;
2225 dprintf_reg(stddeb,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2226 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2228 lpkey=lookup_hkey(hkey);
2229 if (!lpkey)
2230 return SHELL_ERROR_BADKEY;
2231 if (!lpkey->nextsub)
2232 return ERROR_NO_MORE_ITEMS;
2233 lpxkey=lpkey->nextsub;
2234 while (iSubkey && lpxkey) {
2235 iSubkey--;
2236 lpxkey=lpxkey->next;
2238 if (iSubkey || !lpxkey)
2239 return ERROR_NO_MORE_ITEMS;
2240 if (2*lstrlen32W(lpxkey->keyname)+2>*lpcchName)
2241 return ERROR_MORE_DATA;
2242 memcpy(lpszName,lpxkey->keyname,lstrlen32W(lpxkey->keyname)*2+2);
2243 if (lpszClass) {
2244 /* what should we write into it? */
2245 *lpszClass = 0;
2246 *lpcchClass = 2;
2248 return ERROR_SUCCESS;
2252 /* RegEnumKeyW [ADVAPI32.140] */
2253 DWORD RegEnumKey32W(
2254 HKEY hkey,
2255 DWORD iSubkey,
2256 LPWSTR lpszName,
2257 DWORD lpcchName
2259 FILETIME ft;
2261 dprintf_reg(stddeb,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2262 hkey,iSubkey,lpszName,lpcchName
2264 return RegEnumKeyEx32W(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
2266 /* RegEnumKeyExA [ADVAPI32.138] */
2267 DWORD RegEnumKeyEx32A(
2268 HKEY hkey,
2269 DWORD iSubkey,
2270 LPSTR lpszName,
2271 LPDWORD lpcchName,
2272 LPDWORD lpdwReserved,
2273 LPSTR lpszClass,
2274 LPDWORD lpcchClass,
2275 FILETIME *ft
2277 DWORD ret,lpcchNameW,lpcchClassW;
2278 LPWSTR lpszNameW,lpszClassW;
2281 dprintf_reg(stddeb,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2282 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2284 if (lpszName) {
2285 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
2286 lpcchNameW = *lpcchName*2;
2287 } else {
2288 lpszNameW = NULL;
2289 lpcchNameW = 0;
2291 if (lpszClass) {
2292 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
2293 lpcchClassW = *lpcchClass*2;
2294 } else {
2295 lpszClassW =0;
2296 lpcchClassW=0;
2298 ret=RegEnumKeyEx32W(
2299 hkey,
2300 iSubkey,
2301 lpszNameW,
2302 &lpcchNameW,
2303 lpdwReserved,
2304 lpszClassW,
2305 &lpcchClassW,
2308 if (ret==ERROR_SUCCESS) {
2309 strcpyWA(lpszName,lpszNameW);
2310 *lpcchName=strlen(lpszName);
2311 if (lpszClassW) {
2312 strcpyWA(lpszClass,lpszClassW);
2313 *lpcchClass=strlen(lpszClass);
2316 if (lpszNameW)
2317 free(lpszNameW);
2318 if (lpszClassW)
2319 free(lpszClassW);
2320 return ret;
2323 /* RegEnumKeyA [ADVAPI32.137] */
2324 DWORD RegEnumKey32A(
2325 HKEY hkey,
2326 DWORD iSubkey,
2327 LPSTR lpszName,
2328 DWORD lpcchName
2330 FILETIME ft;
2332 dprintf_reg(stddeb,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2333 hkey,iSubkey,lpszName,lpcchName
2335 return RegEnumKeyEx32A(
2336 hkey,
2337 iSubkey,
2338 lpszName,
2339 &lpcchName,
2340 NULL,
2341 NULL,
2342 NULL,
2347 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2348 DWORD RegEnumKey16(
2349 HKEY hkey,
2350 DWORD iSubkey,
2351 LPSTR lpszName,
2352 DWORD lpcchName
2354 dprintf_reg(stddeb,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2355 hkey,iSubkey,lpszName,lpcchName
2357 return RegEnumKey32A(hkey,iSubkey,lpszName,lpcchName);
2361 * Enumerate Registry Values
2363 * Callpath:
2364 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2367 /* RegEnumValueW [ADVAPI32.142] */
2368 DWORD RegEnumValue32W(
2369 HKEY hkey,
2370 DWORD iValue,
2371 LPWSTR lpszValue,
2372 LPDWORD lpcchValue,
2373 LPDWORD lpdReserved,
2374 LPDWORD lpdwType,
2375 LPBYTE lpbData,
2376 LPDWORD lpcbData
2378 LPKEYSTRUCT lpkey;
2379 LPKEYVALUE val;
2381 dprintf_reg(stddeb,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2382 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2384 lpkey = lookup_hkey(hkey);
2385 if (!lpkey)
2386 return SHELL_ERROR_BADKEY;
2387 if (lpkey->nrofvalues<=iValue)
2388 return ERROR_NO_MORE_ITEMS;
2389 val = lpkey->values+iValue;
2391 if (val->name) {
2392 if (lstrlen32W(val->name)*2+2>*lpcchValue) {
2393 *lpcchValue = lstrlen32W(val->name)*2+2;
2394 return ERROR_MORE_DATA;
2396 memcpy(lpszValue,val->name,2*lstrlen32W(val->name)+2);
2397 *lpcchValue=lstrlen32W(val->name)*2+2;
2398 } else {
2399 /* how to handle NULL value? */
2400 *lpszValue = 0;
2401 *lpcchValue = 2;
2403 *lpdwType=val->type;
2404 if (lpbData) {
2405 if (val->len>*lpcbData)
2406 return ERROR_MORE_DATA;
2407 memcpy(lpbData,val->data,val->len);
2408 *lpcbData = val->len;
2410 return SHELL_ERROR_SUCCESS;
2413 /* RegEnumValueA [ADVAPI32.141] */
2414 DWORD RegEnumValue32A(
2415 HKEY hkey,
2416 DWORD iValue,
2417 LPSTR lpszValue,
2418 LPDWORD lpcchValue,
2419 LPDWORD lpdReserved,
2420 LPDWORD lpdwType,
2421 LPBYTE lpbData,
2422 LPDWORD lpcbData
2424 LPWSTR lpszValueW;
2425 LPBYTE lpbDataW;
2426 DWORD ret,lpcbDataW;
2428 dprintf_reg(stddeb,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2429 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2432 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
2433 if (lpbData) {
2434 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
2435 lpcbDataW = *lpcbData*2;
2436 } else
2437 lpbDataW = NULL;
2438 ret=RegEnumValue32W(
2439 hkey,
2440 iValue,
2441 lpszValueW,
2442 lpcchValue,
2443 lpdReserved,
2444 lpdwType,
2445 lpbDataW,
2446 &lpcbDataW
2449 if (ret==ERROR_SUCCESS) {
2450 strcpyWA(lpszValue,lpszValueW);
2451 if (lpbData) {
2452 if ((1<<*lpdwType) & UNICONVMASK) {
2453 strcpyWA(lpbData,(LPWSTR)lpbDataW);
2454 } else {
2455 if (lpcbDataW > *lpcbData)
2456 ret = ERROR_MORE_DATA;
2457 else
2458 memcpy(lpbData,lpbDataW,lpcbDataW);
2460 *lpcbData = lpcbDataW;
2463 if (lpbDataW)
2464 free(lpbDataW);
2465 if (lpszValueW)
2466 free(lpszValueW);
2467 return ret;
2470 /* RegEnumValue [KERNEL.223] */
2471 DWORD RegEnumValue16(
2472 HKEY hkey,
2473 DWORD iValue,
2474 LPSTR lpszValue,
2475 LPDWORD lpcchValue,
2476 LPDWORD lpdReserved,
2477 LPDWORD lpdwType,
2478 LPBYTE lpbData,
2479 LPDWORD lpcbData
2481 dprintf_reg(stddeb,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2482 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2484 return RegEnumValue32A(
2485 hkey,
2486 iValue,
2487 lpszValue,
2488 lpcchValue,
2489 lpdReserved,
2490 lpdwType,
2491 lpbData,
2492 lpcbData
2497 * Close registry key
2499 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2500 DWORD RegCloseKey(HKEY hkey) {
2501 dprintf_reg(stddeb,"RegCloseKey(%x)\n",hkey);
2502 remove_handle(hkey);
2503 return ERROR_SUCCESS;
2506 * Delete registry key
2508 * Callpath:
2509 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2511 /* RegDeleteKeyW [ADVAPI32.134] */
2512 DWORD RegDeleteKey32W(HKEY hkey,LPWSTR lpszSubKey) {
2513 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2514 LPWSTR *wps;
2515 int wpc,i;
2517 dprintf_reg(stddeb,"RegDeleteKey32W(%x,%s)\n",
2518 hkey,W2C(lpszSubKey,0)
2520 lpNextKey = lookup_hkey(hkey);
2521 if (!lpNextKey)
2522 return SHELL_ERROR_BADKEY;
2523 /* we need to know the previous key in the hier. */
2524 if (!lpszSubKey || !*lpszSubKey)
2525 return SHELL_ERROR_BADKEY;
2526 split_keypath(lpszSubKey,&wps,&wpc);
2527 i = 0;
2528 lpxkey = lpNextKey;
2529 while (i<wpc-1) {
2530 lpxkey=lpNextKey->nextsub;
2531 while (lpxkey) {
2532 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2533 break;
2534 lpxkey=lpxkey->next;
2536 if (!lpxkey) {
2537 FREE_KEY_PATH;
2538 /* not found is success */
2539 return SHELL_ERROR_SUCCESS;
2541 i++;
2542 lpNextKey = lpxkey;
2544 lpxkey = lpNextKey->nextsub;
2545 lplpPrevKey = &(lpNextKey->nextsub);
2546 while (lpxkey) {
2547 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2548 break;
2549 lplpPrevKey = &(lpxkey->next);
2550 lpxkey = lpxkey->next;
2552 if (!lpxkey)
2553 return SHELL_ERROR_SUCCESS;
2554 if (lpxkey->nextsub)
2555 return SHELL_ERROR_CANTWRITE;
2556 *lplpPrevKey = lpxkey->next;
2557 free(lpxkey->keyname);
2558 if (lpxkey->class)
2559 free(lpxkey->class);
2560 if (lpxkey->values)
2561 free(lpxkey->values);
2562 free(lpxkey);
2563 FREE_KEY_PATH;
2564 return SHELL_ERROR_SUCCESS;
2567 /* RegDeleteKeyA [ADVAPI32.133] */
2568 DWORD RegDeleteKey32A(HKEY hkey,LPCSTR lpszSubKey) {
2569 LPWSTR lpszSubKeyW;
2570 DWORD ret;
2572 dprintf_reg(stddeb,"RegDeleteKey32A(%x,%s)\n",
2573 hkey,lpszSubKey
2575 lpszSubKeyW=strdupA2W(lpszSubKey);
2576 ret=RegDeleteKey32W(hkey,lpszSubKeyW);
2577 free(lpszSubKeyW);
2578 return ret;
2581 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2582 DWORD RegDeleteKey16(HKEY hkey,LPCSTR lpszSubKey) {
2583 dprintf_reg(stddeb,"RegDeleteKey16(%x,%s)\n",
2584 hkey,lpszSubKey
2586 return RegDeleteKey32A(hkey,lpszSubKey);
2590 * Delete registry value
2592 * Callpath:
2593 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2595 /* RegDeleteValueW [ADVAPI32.136] */
2596 DWORD RegDeleteValue32W(HKEY hkey,LPWSTR lpszValue) {
2597 DWORD i;
2598 LPKEYSTRUCT lpkey;
2599 LPKEYVALUE val;
2601 dprintf_reg(stddeb,"RegDeleteValue32W(%x,%s)\n",
2602 hkey,W2C(lpszValue,0)
2604 lpkey=lookup_hkey(hkey);
2605 if (!lpkey)
2606 return SHELL_ERROR_BADKEY;
2607 if (lpszValue) {
2608 for (i=0;i<lpkey->nrofvalues;i++)
2609 if ( lpkey->values[i].name &&
2610 !lstrcmp32W(lpkey->values[i].name,lpszValue)
2612 break;
2613 } else {
2614 for (i=0;i<lpkey->nrofvalues;i++)
2615 if (lpkey->values[i].name==NULL)
2616 break;
2618 if (i==lpkey->nrofvalues)
2619 return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */
2620 val = lpkey->values+i;
2621 if (val->name) free(val->name);
2622 if (val->data) free(val->data);
2623 memcpy(
2624 lpkey->values+i,
2625 lpkey->values+i+1,
2626 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
2628 lpkey->values = (LPKEYVALUE)xrealloc(
2629 lpkey->values,
2630 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
2632 lpkey->nrofvalues--;
2633 return SHELL_ERROR_SUCCESS;
2636 /* RegDeleteValueA [ADVAPI32.135] */
2637 DWORD RegDeleteValue32A(HKEY hkey,LPSTR lpszValue) {
2638 LPWSTR lpszValueW;
2639 DWORD ret;
2641 dprintf_reg( stddeb, "RegDeleteValue32A(%x,%s)\n", hkey,lpszValue );
2642 if (lpszValue)
2643 lpszValueW=strdupA2W(lpszValue);
2644 else
2645 lpszValueW=NULL;
2646 ret=RegDeleteValue32W(hkey,lpszValueW);
2647 if (lpszValueW)
2648 free(lpszValueW);
2649 return ret;
2652 /* RegDeleteValue [KERNEL.222] */
2653 DWORD RegDeleteValue16(HKEY hkey,LPSTR lpszValue) {
2654 dprintf_reg( stddeb,"RegDeleteValue16(%x,%s)\n", hkey,lpszValue );
2655 return RegDeleteValue32A(hkey,lpszValue);
2658 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2659 DWORD RegFlushKey(HKEY hkey) {
2660 dprintf_reg(stddeb,"RegFlushKey(%x), STUB.\n",hkey);
2661 return SHELL_ERROR_SUCCESS;
2664 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2666 /* RegQueryInfoKeyW [ADVAPI32.153] */
2667 DWORD RegQueryInfoKey32W(
2668 HKEY hkey,
2669 LPWSTR lpszClass,
2670 LPDWORD lpcchClass,
2671 LPDWORD lpdwReserved,
2672 LPDWORD lpcSubKeys,
2673 LPDWORD lpcchMaxSubkey,
2674 LPDWORD lpcchMaxClass,
2675 LPDWORD lpcValues,
2676 LPDWORD lpcchMaxValueName,
2677 LPDWORD lpccbMaxValueData,
2678 LPDWORD lpcbSecurityDescriptor,
2679 FILETIME *ft
2681 LPKEYSTRUCT lpkey,lpxkey;
2682 int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata;
2683 int i;
2685 dprintf_reg(stddeb,"RegQueryInfoKey32W(%x,......)\n",hkey);
2686 lpkey=lookup_hkey(hkey);
2687 if (!lpkey)
2688 return SHELL_ERROR_BADKEY;
2689 if (lpszClass) {
2690 if (lpkey->class) {
2691 if (lstrlen32W(lpkey->class)*2+2>*lpcchClass) {
2692 *lpcchClass=lstrlen32W(lpkey->class)*2;
2693 return ERROR_MORE_DATA;
2695 *lpcchClass=lstrlen32W(lpkey->class)*2;
2696 memcpy(lpszClass,lpkey->class,lstrlen32W(lpkey->class));
2697 } else {
2698 *lpszClass = 0;
2699 *lpcchClass = 0;
2701 } else {
2702 if (lpcchClass)
2703 *lpcchClass = lstrlen32W(lpkey->class)*2;
2705 lpxkey=lpkey->nextsub;
2706 nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
2707 while (lpxkey) {
2708 nrofkeys++;
2709 if (lstrlen32W(lpxkey->keyname)>maxsubkey)
2710 maxsubkey=lstrlen32W(lpxkey->keyname);
2711 if (lpxkey->class && lstrlen32W(lpxkey->class)>maxclass)
2712 maxclass=lstrlen32W(lpxkey->class);
2713 if (lpxkey->nrofvalues>maxvalues)
2714 maxvalues=lpxkey->nrofvalues;
2715 for (i=0;i<lpxkey->nrofvalues;i++) {
2716 LPKEYVALUE val=lpxkey->values+i;
2718 if (val->name && lstrlen32W(val->name)>maxvname)
2719 maxvname=lstrlen32W(val->name);
2720 if (val->len>maxvdata)
2721 maxvdata=val->len;
2723 lpxkey=lpxkey->next;
2725 if (!maxclass) maxclass = 1;
2726 if (!maxvname) maxvname = 1;
2727 if (lpcSubKeys)
2728 *lpcSubKeys = nrofkeys;
2729 if (lpcchMaxSubkey)
2730 *lpcchMaxSubkey = maxsubkey*2;
2731 if (lpcchMaxClass)
2732 *lpcchMaxClass = maxclass*2;
2733 if (lpcValues)
2734 *lpcValues = maxvalues;
2735 if (lpcchMaxValueName)
2736 *lpcchMaxValueName= maxvname;
2737 if (lpccbMaxValueData)
2738 *lpccbMaxValueData= maxvdata;
2739 return SHELL_ERROR_SUCCESS;
2742 /* RegQueryInfoKeyA [ADVAPI32.152] */
2743 DWORD RegQueryInfoKey32A(
2744 HKEY hkey,
2745 LPSTR lpszClass,
2746 LPDWORD lpcchClass,
2747 LPDWORD lpdwReserved,
2748 LPDWORD lpcSubKeys,
2749 LPDWORD lpcchMaxSubkey,
2750 LPDWORD lpcchMaxClass,
2751 LPDWORD lpcValues,
2752 LPDWORD lpcchMaxValueName,
2753 LPDWORD lpccbMaxValueData,
2754 LPDWORD lpcbSecurityDescriptor,
2755 FILETIME *ft
2757 LPWSTR lpszClassW;
2758 DWORD ret;
2760 dprintf_reg(stddeb,"RegQueryInfoKey32A(%x,......)\n",hkey);
2761 if (lpszClass) {
2762 *lpcchClass*= 2;
2763 lpszClassW = (LPWSTR)xmalloc(*lpcchClass);
2765 } else
2766 lpszClassW = NULL;
2767 ret=RegQueryInfoKey32W(
2768 hkey,
2769 lpszClassW,
2770 lpcchClass,
2771 lpdwReserved,
2772 lpcSubKeys,
2773 lpcchMaxSubkey,
2774 lpcchMaxClass,
2775 lpcValues,
2776 lpcchMaxValueName,
2777 lpccbMaxValueData,
2778 lpcbSecurityDescriptor,
2781 if (ret==ERROR_SUCCESS)
2782 strcpyWA(lpszClass,lpszClassW);
2783 if (lpcchClass)
2784 *lpcchClass/=2;
2785 if (lpcchMaxSubkey)
2786 *lpcchMaxSubkey/=2;
2787 if (lpcchMaxClass)
2788 *lpcchMaxClass/=2;
2789 if (lpcchMaxValueName)
2790 *lpcchMaxValueName/=2;
2791 if (lpszClassW)
2792 free(lpszClassW);
2793 return ret;