Release 960528
[wine/gsoc-2012-control.git] / misc / registry.c
blobfaaf190651d84abe05217d7f87b8232833db0aa4
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 "string32.h"
23 #include "stddebug.h"
24 #include "debug.h"
25 #include "xmalloc.h"
26 #include "winreg.h"
28 #define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y))
30 /* FIXME: following defines should be configured global ... */
32 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
33 #define WINE_PREFIX "/.wine"
34 #define SAVE_USERS_DEFAULT "/usr/local/etc/wine.userreg"
35 #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
37 /* relative in ~user/.wine/ : */
38 #define SAVE_CURRENT_USER "user.reg"
39 #define SAVE_LOCAL_MACHINE "system.reg"
41 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
42 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
44 static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */
45 static KEYSTRUCT *key_current_user=NULL; /* user specific values */
46 static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
47 static KEYSTRUCT *key_users=NULL; /* all users? */
49 /* dynamic, not saved */
50 static KEYSTRUCT *key_performance_data=NULL;
51 static KEYSTRUCT *key_current_config=NULL;
52 static KEYSTRUCT *key_dyn_data=NULL;
54 /* what valuetypes do we need to convert? */
55 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
57 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
58 #define strdupW2A(x) STRING32_DupUniToAnsi(x)
59 #define strdupW(x) STRING32_strdupW(x)
60 #define strcmpW(a,b) STRING32_lstrcmpW(a,b)
61 #define strcmpniW(a,b) STRING32_lstrcmpniW(a,b)
62 #define strchrW(a,c) STRING32_lstrchrW(a,c)
63 #define strlenW(a) STRING32_UniLen(a)
64 #define strcpyWA(a,b) STRING32_UniToAnsi(a,b)
66 static struct openhandle {
67 LPKEYSTRUCT lpkey;
68 HKEY hkey;
69 REGSAM accessmask;
70 } *openhandles=NULL;
71 static int nrofopenhandles=0;
72 static int currenthandle=1;
74 static void
75 add_handle(HKEY hkey,LPKEYSTRUCT lpkey,REGSAM accessmask) {
76 int i;
78 for (i=0;i<nrofopenhandles;i++) {
79 if (openhandles[i].lpkey==lpkey) {
80 dprintf_reg(stddeb,"add_handle:Tried to add %p twice!\n",lpkey);
82 if (openhandles[i].hkey==hkey) {
83 dprintf_reg(stddeb,"add_handle:Tried to add %lx twice!\n",(LONG)hkey);
86 openhandles=xrealloc( openhandles,
87 sizeof(struct openhandle)*(nrofopenhandles+1)
89 openhandles[i].lpkey = lpkey;
90 openhandles[i].hkey = hkey;
91 openhandles[i].accessmask= accessmask;
92 nrofopenhandles++;
95 static LPKEYSTRUCT
96 get_handle(HKEY hkey) {
97 int i;
99 for (i=0;i<nrofopenhandles;i++)
100 if (openhandles[i].hkey==hkey)
101 return openhandles[i].lpkey;
102 dprintf_reg(stddeb,"get_handle:Didn't find handle %lx?\n",(LONG)hkey);
103 return NULL;
106 static void
107 remove_handle(HKEY hkey) {
108 int i;
110 for (i=0;i<nrofopenhandles;i++)
111 if (openhandles[i].hkey==hkey)
112 break;
113 if (i==nrofopenhandles) {
114 dprintf_reg(stddeb,"remove_handle:Didn't find handle %08x?\n",hkey);
115 return;
117 memcpy( openhandles+i,
118 openhandles+i+1,
119 sizeof(struct openhandle)*(nrofopenhandles-i-1)
121 openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
122 nrofopenhandles--;
123 return;
127 /* debug function, converts a unicode into a static memory area
128 * (sub for using two static strings, in case we need them in a single call)
130 LPSTR
131 W2C(LPCWSTR x,int sub) {
132 static LPSTR unicodedebug[2]={NULL,NULL};
133 if (x==NULL)
134 return "<NULL>";
135 if (sub!=0 && sub!=1)
136 return "<W2C:bad sub>";
137 if (unicodedebug[sub]) free(unicodedebug[sub]);
138 unicodedebug[sub] = strdupW2A(x);
139 return unicodedebug[sub];
142 static LPKEYSTRUCT
143 lookup_hkey(HKEY hkey) {
144 switch (hkey) {
145 case 0x00000000:
146 case 0x00000001:
147 case HKEY_CLASSES_ROOT:
148 return key_classes_root;
149 case HKEY_CURRENT_USER:
150 return key_current_user;
151 case HKEY_LOCAL_MACHINE:
152 return key_local_machine;
153 case HKEY_USERS:
154 return key_users;
155 case HKEY_PERFORMANCE_DATA:
156 return key_performance_data;
157 case HKEY_DYN_DATA:
158 return key_dyn_data;
159 case HKEY_CURRENT_CONFIG:
160 return key_current_config;
161 default:
162 dprintf_reg(stddeb,"lookup_hkey(%lx), special key!\n",
163 (LONG)hkey
165 return get_handle(hkey);
167 /*NOTREACHED*/
171 * splits the unicode string 'wp' into an array of strings.
172 * the array is allocated by this function.
173 * the number of components will be stored in 'wpc'
174 * Free the array using FREE_KEY_PATH
176 static void
177 split_keypath(LPCWSTR wp,LPWSTR **wpv,int *wpc) {
178 int i,j,len;
179 LPWSTR ws;
181 ws = strdupW(wp);
182 *wpc = 1;
183 for (i=0;ws[i];i++) {
184 if (ws[i]=='\\') {
185 ws[i]=0;
186 (*wpc)++;
189 len = i;
190 *wpv = (LPWSTR*)xmalloc(sizeof(LPWSTR)*(*wpc+2));
191 (*wpv)[0]= ws;
192 j = 1;
193 for (i=1;i<len;i++)
194 if (ws[i-1]==0)
195 (*wpv)[j++]=ws+i;
196 (*wpv)[j]=NULL;
198 #define FREE_KEY_PATH free(wps[0]);free(wps);
201 * Shell initialisation, allocates keys.
203 void
204 SHELL_Init() {
205 struct passwd *pwd;
207 HKEY cl_r_hkey,c_u_hkey;
208 #define ADD_ROOT_KEY(xx) \
209 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
210 memset(xx,'\0',sizeof(KEYSTRUCT));\
211 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
213 ADD_ROOT_KEY(key_local_machine);
214 if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
215 fprintf(stderr,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
216 exit(1);
218 key_classes_root = lookup_hkey(cl_r_hkey);
220 ADD_ROOT_KEY(key_users);
222 #if 0
223 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
224 * (later, when a win32 registry editing tool becomes avail.)
226 while (pwd=getpwent()) {
227 if (pwd->pw_name == NULL)
228 continue;
229 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
230 RegCloseKey(c_u_hkey);
232 #endif
233 pwd=getpwuid(getuid());
234 if (pwd && pwd->pw_name) {
235 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
236 key_current_user = lookup_hkey(c_u_hkey);
237 } else {
238 ADD_ROOT_KEY(key_current_user);
240 ADD_ROOT_KEY(key_performance_data);
241 ADD_ROOT_KEY(key_current_config);
242 ADD_ROOT_KEY(key_dyn_data);
243 #undef ADD_ROOT_KEY
246 /************************ SAVE Registry Function ****************************/
248 #define REGISTRY_SAVE_VERSION 0x00000001
250 /* Registry saveformat:
251 * If you change it, increase above number by 1, which will flush
252 * old registry database files.
254 * Global:
255 * "WINE REGISTRY Version %d"
256 * subkeys....
257 * Subkeys:
258 * keyname
259 * valuename=lastmodified,type,data
260 * ...
261 * subkeys
262 * ...
263 * keyname,valuename,stringdata:
264 * the usual ascii characters from 0x00-0xff (well, not 0x00)
265 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
266 * ( "=\\\t" escaped in \uXXXX form.)
267 * type,lastmodified:
268 * int
270 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
272 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
273 * SaveOnlyUpdatedKeys=yes
275 static int
276 _save_check_tainted(LPKEYSTRUCT lpkey) {
277 int tainted;
279 if (!lpkey)
280 return 0;
281 if (lpkey->flags & REG_OPTION_TAINTED)
282 tainted = 1;
283 else
284 tainted = 0;
285 while (lpkey) {
286 if (_save_check_tainted(lpkey->nextsub)) {
287 lpkey->flags |= REG_OPTION_TAINTED;
288 tainted = 1;
290 lpkey = lpkey->next;
292 return tainted;
295 static void
296 _save_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
297 LPWSTR s;
298 int doescape;
300 if (wstr==NULL)
301 return;
302 s=wstr;
303 while (*s) {
304 doescape=0;
305 if (*s>0xff)
306 doescape = 1;
307 if (*s=='\n')
308 doescape = 1;
309 if (escapeeq && *s=='=')
310 doescape = 1;
311 if (*s=='\\')
312 fputc(*s,F); /* if \\ than put it twice. */
313 if (doescape)
314 fprintf(F,"\\u%04x",*((unsigned short*)s));
315 else
316 fputc(*s,F);
317 s++;
321 static int
322 _savesubkey(FILE *F,LPKEYSTRUCT lpkey,int level,int all) {
323 LPKEYSTRUCT lpxkey;
324 int i,tabs,j;
326 lpxkey = lpkey;
327 while (lpxkey) {
328 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
329 (all || (lpxkey->flags & REG_OPTION_TAINTED))
331 for (tabs=level;tabs--;)
332 fputc('\t',F);
333 _save_USTRING(F,lpxkey->keyname,1);
334 fputs("\n",F);
335 for (i=0;i<lpxkey->nrofvalues;i++) {
336 LPKEYVALUE val=lpxkey->values+i;
338 for (tabs=level+1;tabs--;)
339 fputc('\t',F);
340 _save_USTRING(F,val->name,0);
341 fputc('=',F);
342 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
343 if ((1<<val->type) & UNICONVMASK)
344 _save_USTRING(F,(LPWSTR)val->data,0);
345 else
346 for (j=0;j<val->len;j++)
347 fprintf(F,"%02x",*((unsigned char*)val->data+j));
348 fputs("\n",F);
350 /* descend recursively */
351 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
352 return 0;
354 lpxkey=lpxkey->next;
356 return 1;
359 static int
360 _savesubreg(FILE *F,LPKEYSTRUCT lpkey,int all) {
361 fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
362 _save_check_tainted(lpkey->nextsub);
363 return _savesubkey(F,lpkey->nextsub,0,all);
366 static void
367 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
368 FILE *F;
370 F=fopen(fn,"w");
371 if (F==NULL) {
372 fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
373 fn,strerror(errno)
375 return;
377 if (!_savesubreg(F,lpkey,all)) {
378 fclose(F);
379 unlink(fn);
380 fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
381 return;
383 fclose(F);
386 void
387 SHELL_SaveRegistry() {
388 char *fn;
389 struct passwd *pwd;
390 char buf[4];
391 HKEY hkey;
392 int all;
394 all=0;
395 if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) {
396 strcpy(buf,"yes");
397 } else {
398 DWORD len,junk,type;
400 len=4;
401 if ( (ERROR_SUCCESS!=RegQueryValueEx32A(
402 hkey,
403 VAL_SAVEUPDATED,
404 &junk,
405 &type,
406 buf,
407 &len
408 ))|| (type!=REG_SZ)
410 strcpy(buf,"yes");
411 RegCloseKey(hkey);
413 if (strcasecmp(buf,"yes"))
414 all=1;
415 pwd=getpwuid(getuid());
416 if (pwd!=NULL && pwd->pw_dir!=NULL) {
417 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2);
418 strcpy(fn,pwd->pw_dir);
419 strcat(fn,WINE_PREFIX);
420 /* create the directory. don't care about errorcodes. */
421 mkdir(fn,0755); /* drwxr-xr-x */
422 strcat(fn,"/"SAVE_CURRENT_USER);
423 _savereg(key_current_user,fn,all);
424 free(fn);
425 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
426 strcpy(fn,pwd->pw_dir);
427 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
428 _savereg(key_local_machine,fn,all);
429 free(fn);
430 } else
431 fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
434 /************************ LOAD Registry Function ****************************/
436 static LPKEYSTRUCT
437 _find_or_add_key(LPKEYSTRUCT lpkey,LPWSTR keyname) {
438 LPKEYSTRUCT lpxkey,*lplpkey;
440 lplpkey= &(lpkey->nextsub);
441 lpxkey = *lplpkey;
442 while (lpxkey) {
443 if (!strcmpW(lpxkey->keyname,keyname))
444 break;
445 lplpkey = &(lpxkey->next);
446 lpxkey = *lplpkey;
448 if (lpxkey==NULL) {
449 *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
450 lpxkey = *lplpkey;
451 memset(lpxkey,'\0',sizeof(KEYSTRUCT));
452 lpxkey->keyname = keyname;
453 } else
454 free(keyname);
455 return lpxkey;
458 static void
459 _find_or_add_value(
460 LPKEYSTRUCT lpkey,LPWSTR name,DWORD type,LPBYTE data,DWORD len,
461 DWORD lastmodified
463 LPKEYVALUE val=NULL;
464 int i;
466 for (i=0;i<lpkey->nrofvalues;i++) {
467 val=lpkey->values+i;
468 if (name==NULL) {
469 if (val->name==NULL)
470 break;
471 } else {
472 if ( val->name!=NULL &&
473 !strcmpW(val->name,name)
475 break;
478 if (i==lpkey->nrofvalues) {
479 lpkey->values = xrealloc(
480 lpkey->values,
481 (++lpkey->nrofvalues)*sizeof(KEYVALUE)
483 val=lpkey->values+i;
484 memset(val,'\0',sizeof(KEYVALUE));
485 val->name = name;
486 } else {
487 if (name)
488 free(name);
490 if (val->lastmodified<lastmodified) {
491 val->lastmodified=lastmodified;
492 val->type = type;
493 val->len = len;
494 if (val->data)
495 free(val->data);
496 val->data = data;
497 } else
498 free(data);
502 /* reads a line including dynamically enlarging the readbuffer and throwing
503 * away comments
505 static int
506 _wine_read_line(FILE *F,char **buf,int *len) {
507 char *s,*curread;
508 int mylen,curoff;
510 curread = *buf;
511 mylen = *len;
512 **buf = '\0';
513 while (1) {
514 while (1) {
515 s=fgets(curread,mylen,F);
516 if (s==NULL)
517 return 0; /* EOF */
518 if (NULL==(s=strchr(curread,'\n'))) {
519 /* buffer wasn't large enough */
520 curoff = strlen(*buf);
521 *buf = xrealloc(*buf,*len*2);
522 curread = *buf + curoff;
523 mylen = *len; /* we filled up the buffer and
524 * got new '*len' bytes to fill
526 *len = *len * 2;
527 } else {
528 *s='\0';
529 break;
532 /* throw away comments */
533 if (**buf=='#' || **buf==';') {
534 curread = *buf;
535 mylen = *len;
536 continue;
538 if (s) /* got end of line */
539 break;
541 return 1;
544 /* converts a char* into a UNICODE string (up to a special char)
545 * and returns the position exactly after that string
547 static char*
548 _wine_read_USTRING(char *buf,LPWSTR *str) {
549 char *s;
550 LPWSTR ws;
552 /* read up to "=" or "\0" or "\n" */
553 s = buf;
554 if (*s == '=') {
555 /* empty string is the win3.1 default value(NULL)*/
556 *str = NULL;
557 return s;
559 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
560 ws = *str;
561 while (*s && (*s!='\n') && (*s!='=')) {
562 if (*s!='\\')
563 *ws++=*((unsigned char*)s++);
564 else {
565 s++;
566 if (*s=='\\') {
567 *ws+='\\';
568 s++;
569 continue;
571 if (*s!='u') {
572 fprintf(stderr,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
573 *ws++='\\';
574 *ws++=*s++;
575 } else {
576 char xbuf[5];
577 int wc;
579 s++;
580 memcpy(xbuf,s,4);xbuf[4]='\0';
581 if (!sscanf(xbuf,"%x",&wc))
582 fprintf(stderr,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf);
583 s+=4;
584 *ws++ =(unsigned short)wc;
588 *ws = 0;
589 ws = *str;
590 *str = strdupW(*str);
591 free(ws);
592 return s;
595 static int
596 _wine_loadsubkey(
597 FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen,int optflag
599 LPKEYSTRUCT lpxkey;
600 int i;
601 char *s;
602 LPWSTR name;
604 lpkey->flags |= optflag;
606 /* good. we already got a line here ... so parse it */
607 lpxkey = NULL;
608 while (1) {
609 i=0;s=*buf;
610 while (*s=='\t') {
611 s++;
612 i++;
614 if (i>level) {
615 if (lpxkey==NULL) {
616 fprintf(stderr,"_load_subkey:Got a subhierarchy without resp. key?\n");
617 return 0;
619 _wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag);
620 continue;
622 /* let the caller handle this line */
623 if (i<level || **buf=='\0')
624 return 1;
626 /* it can be: a value or a keyname. Parse the name first */
627 s=_wine_read_USTRING(s,&name);
629 /* switch() default: hack to avoid gotos */
630 switch (0) {
631 default:
632 if (*s=='\0') {
633 lpxkey=_find_or_add_key(lpkey,name);
634 } else {
635 LPBYTE data;
636 int len,lastmodified,type;
638 if (*s!='=') {
639 fprintf(stderr,"_wine_load_subkey:unexpected character: %c\n",*s);
640 break;
642 s++;
643 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
644 fprintf(stderr,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf);
645 break;
647 /* skip the 2 , */
648 s=strchr(s,',');s++;
649 s=strchr(s,',');s++;
650 if ((1<<type) & UNICONVMASK) {
651 s=_wine_read_USTRING(s,(LPWSTR*)&data);
652 if (data)
653 len = strlenW((LPWSTR)data)*2+2;
654 else
655 len = 0;
656 } else {
657 len=strlen(s)/2;
658 data = (LPBYTE)xmalloc(len+1);
659 for (i=0;i<len;i++) {
660 data[i]=0;
661 if (*s>='0' && *s<='9')
662 data[i]=(*s-'0')<<4;
663 if (*s>='a' && *s<='f')
664 data[i]=(*s-'a')<<4;
665 if (*s>='A' && *s<='F')
666 data[i]=(*s-'A')<<4;
667 s++;
668 if (*s>='0' && *s<='9')
669 data[i]|=*s-'0';
670 if (*s>='a' && *s<='f')
671 data[i]|=*s-'a';
672 if (*s>='A' && *s<='F')
673 data[i]|=*s-'A';
674 s++;
677 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
680 /* read the next line */
681 if (!_wine_read_line(F,buf,buflen))
682 return 1;
684 return 1;
687 static int
688 _wine_loadsubreg(FILE *F,LPKEYSTRUCT lpkey,int optflag) {
689 int ver;
690 char *buf;
691 int buflen;
693 buf=xmalloc(10);buflen=10;
694 if (!_wine_read_line(F,&buf,&buflen)) {
695 free(buf);
696 return 0;
698 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
699 free(buf);
700 return 0;
702 if (ver!=REGISTRY_SAVE_VERSION) {
703 dprintf_reg(stddeb,__FILE__":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
704 free(buf);
705 return 0;
707 if (!_wine_read_line(F,&buf,&buflen)) {
708 free(buf);
709 return 0;
711 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
712 free(buf);
713 return 0;
715 free(buf);
716 return 1;
719 static void
720 _wine_loadreg(LPKEYSTRUCT lpkey,char *fn,int optflag) {
721 FILE *F;
723 F=fopen(fn,"rb");
724 if (F==NULL) {
725 dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n",
726 fn,strerror(errno)
728 return;
730 if (!_wine_loadsubreg(F,lpkey,optflag)) {
731 fclose(F);
732 unlink(fn);
733 return;
735 fclose(F);
738 static void
739 _copy_registry(LPKEYSTRUCT from,LPKEYSTRUCT to) {
740 LPKEYSTRUCT lpxkey;
741 int j;
742 LPKEYVALUE valfrom;
744 from=from->nextsub;
745 while (from) {
746 lpxkey = _find_or_add_key(to,strdupW(from->keyname));
748 for (j=0;j<from->nrofvalues;j++) {
749 LPWSTR name;
750 LPBYTE data;
752 valfrom = from->values+j;
753 name=valfrom->name;
754 if (name) name=strdupW(name);
755 data=(LPBYTE)malloc(valfrom->len);
756 memcpy(data,valfrom->data,valfrom->len);
758 _find_or_add_value(
759 lpxkey,
760 name,
761 valfrom->type,
762 data,
763 valfrom->len,
764 valfrom->lastmodified
767 _copy_registry(from,lpxkey);
768 from = from->next;
772 /* WINDOWS 95 REGISTRY LOADER */
774 * Structure of a win95 registry database.
775 * main header:
776 * 0 : "CREG" - magic
777 * 4 : DWORD version
778 * 8 : DWORD offset_of_RGDB_part
779 * 0C..1F: ? (someone fill in please)
781 * 20: RGKN_section:
782 * header:
783 * 0 : "RGKN" - magic
784 * 4..0x1B: ? (fill in)
785 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
787 * Disk Key Entry Structure:
788 * 00: DWORD - unknown
789 * 04: DWORD - unknown
790 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
791 * 0C: DWORD - disk address of PreviousLevel Key.
792 * 10: DWORD - disk address of Next Sublevel Key.
793 * 14: DWORD - disk address of Next Key (on same level).
794 * DKEP>18: WORD - Nr, Low Significant part.
795 * 1A: WORD - Nr, High Significant part.
797 * The disk address always points to the nr part of the previous key entry
798 * of the referenced key. Don't ask me why, or even if I got this correct
799 * from staring at 1kg of hexdumps. (DKEP)
801 * The number of the entry is the low byte of the Low Significant Part ored
802 * with 0x100 * (low byte of the High Significant part)
803 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
805 * There are two minor corrections to the position of that structure.
806 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
807 * the DKE reread from there.
808 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
809 * (FIXME: slightly better explanation needed here)
811 * RGDB_section:
812 * 00: "RGDB" - magic
813 * 04: DWORD offset to next RGDB section (perhaps WORD)
814 * 08...1F: ?
815 * 20.....: disk keys
817 * disk key:
818 * 00: DWORD nextkeyoffset - offset to the next disk key structure
819 * 08: WORD nrLS - low significant part of NR
820 * 0A: WORD nrHS - high significant part of NR
821 * 0C: DWORD bytesused - bytes used in this structure.
822 * 10: WORD name_len - length of name in bytes. without \0
823 * 12: WORD nr_of_values - number of values.
824 * 14: char name[name_len] - name string. No \0.
825 * 14+name_len: disk values
826 * nextkeyoffset: ... next disk key
828 * disk value:
829 * 00: DWORD type - value type (hmm, could be WORD too)
830 * 04: DWORD - unknown, usually 0
831 * 08: WORD namelen - length of Name. 0 means name=NULL
832 * 0C: WORD datalen - length of Data.
833 * 10: char name[namelen] - name, no \0
834 * 10+namelen: BYTE data[datalen] - data, without \0 if string
835 * 10+namelen+datalen: next values or disk key
837 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
838 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
839 * structure) and reading another RGDB_section.
840 * repeat until end of file.
842 * FIXME: this description needs some serious help, yes.
845 struct _w95keyvalue {
846 unsigned long type;
847 unsigned short datalen;
848 char *name;
849 unsigned char *data;
850 unsigned long x1;
851 int lastmodified;
854 struct _w95key {
855 char *name;
856 int nrofvals;
857 struct _w95keyvalue *values;
858 unsigned long dkeaddr;
859 unsigned long x1;
860 unsigned long x2;
861 unsigned long x3;
862 unsigned long xx1;
863 struct _w95key *prevlvl;
864 struct _w95key *nextsub;
865 struct _w95key *next;
868 /* fast lookup table dkeaddr->nr */
869 struct _w95nr2da {
870 unsigned long dkeaddr;
871 unsigned long nr;
875 static void
876 _w95_walk_tree(LPKEYSTRUCT lpkey,struct _w95key *key) {
877 int i;
878 LPKEYSTRUCT lpxkey;
879 LPWSTR name;
881 while (key) {
882 if (key->name == NULL) {
883 fprintf(stderr,"key with dkeaddr %lx not loaded, skipping hierarchy\n",
884 key->dkeaddr
886 key = key->next;
887 continue;
889 lpxkey=_find_or_add_key(lpkey,strdupA2W(key->name));
891 if (key->nrofvals<0) {
892 /* shouldn't happen */
893 fprintf(stderr,"key %s already processed!\n",key->name);
894 key = key->next;
895 continue;
897 for (i=0;i<key->nrofvals;i++) {
898 LPBYTE data;
899 int len;
901 name = strdupA2W(key->values[i].name);
902 if (!*name) name = NULL;
903 free(key->values[i].name);
905 len = key->values[i].datalen;
906 data = key->values[i].data;
907 if ((1<<key->values[i].type) & UNICONVMASK) {
908 data = (BYTE*)strdupA2W(data);
909 len = strlenW((LPWSTR)data)*2+2;
910 free(key->values[i].data);
912 _find_or_add_value(
913 lpxkey,
914 name,
915 key->values[i].type,
916 data,
917 len,
918 key->values[i].lastmodified
921 if (key->values) {
922 free(key->values);
923 key->values = NULL;
925 key->nrofvals=-key->nrofvals-1;
926 _w95_walk_tree(lpxkey,key->nextsub);
927 key=key->next;
931 /* small helper function to adjust address offset (dkeaddrs) */
932 static unsigned long
933 _w95_adj_da(unsigned long dkeaddr) {
934 if ((dkeaddr&0xFFF)<0x018) {
935 int diff;
937 diff=0x1C-(dkeaddr&0xFFF);
938 return dkeaddr+diff;
940 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
941 /* readjust to 0x000,
942 * but ONLY if we are >0x1000 already
944 if (dkeaddr & ~0xFFF)
945 return dkeaddr & ~0xFFF;
947 return dkeaddr;
950 static int
951 _w95dkecomp(struct _w95nr2da *a,struct _w95nr2da *b){return a->dkeaddr-b->dkeaddr;}
953 static struct _w95key*
954 _w95dkelookup(unsigned long dkeaddr,int n,struct _w95nr2da *nr2da,struct _w95key *keys) {
955 int i,off;
957 if (dkeaddr == 0xFFFFFFFF)
958 return NULL;
959 if (dkeaddr<0x20)
960 return NULL;
961 dkeaddr=_w95_adj_da(dkeaddr+0x1c);
962 off = (dkeaddr-0x3c)/0x1c;
963 for (i=0;i<n;i++)
964 if (nr2da[(i+off)%n].dkeaddr == dkeaddr)
965 return keys+nr2da[(i+off)%n].nr;
966 fprintf(stderr,"search didn't found dkeaddr %lx?\n",dkeaddr);
967 return NULL;
970 static void
971 _w95_loadreg(char* fn,LPKEYSTRUCT lpkey) {
972 /* Disk Key Entry structure (RGKN part) */
973 struct dke {
974 unsigned long x1;
975 unsigned long x2;
976 unsigned long x3;/*usually 0xFFFFFFFF */
977 unsigned long prevlvl;
978 unsigned long nextsub;
979 unsigned long next;
980 unsigned short nrLS;
981 unsigned short nrMS;
983 /* Disk Key Header structure (RGDB part) */
984 struct dkh {
985 unsigned long nextkeyoff;
986 unsigned short nrLS;
987 unsigned short nrMS;
988 unsigned long bytesused;
989 unsigned short keynamelen;
990 unsigned short values;
991 unsigned long xx1;
992 /* keyname */
993 /* disk key values or nothing */
995 /* Disk Key Value structure */
996 struct dkv {
997 unsigned long type;
998 unsigned long x1;
999 unsigned short valnamelen;
1000 unsigned short valdatalen;
1001 /* valname, valdata */
1003 struct _w95nr2da *nr2da;
1005 HFILE hfd;
1006 int fd,lastmodified;
1007 char magic[5];
1008 unsigned long nr,pos,i,where,version,rgdbsection,end,off_next_rgdb;
1009 struct _w95key *keys;
1010 int nrofdkes;
1011 unsigned char *data,*curdata,*nextrgdb;
1012 OFSTRUCT ofs;
1013 struct stat stbuf;
1015 dprintf_reg(stddeb,"Loading Win95 registry database '%s'\n",fn);
1016 hfd=OpenFile(fn,&ofs,OF_READ);
1017 if (hfd==HFILE_ERROR)
1018 return;
1019 fd = FILE_GetUnixHandle(hfd);
1020 magic[4]=0;
1021 if (4!=read(fd,magic,4))
1022 return;
1023 if (strcmp(magic,"CREG")) {
1024 fprintf(stddeb,"%s is not a w95 registry.\n",fn);
1025 return;
1027 if (4!=read(fd,&version,4))
1028 return;
1029 if (4!=read(fd,&rgdbsection,4))
1030 return;
1031 if (-1==lseek(fd,0x20,SEEK_SET))
1032 return;
1033 if (4!=read(fd,magic,4))
1034 return;
1035 if (strcmp(magic,"RGKN")) {
1036 dprintf_reg(stddeb,"second IFF header not RGKN, but %s\n",magic);
1037 return;
1040 /* STEP 1: Keylink structures */
1041 if (-1==lseek(fd,0x40,SEEK_SET))
1042 return;
1043 where = 0x40;
1044 end = rgdbsection;
1046 nrofdkes = (end-where)/sizeof(struct dke);
1047 data = (char*)xmalloc(end-where);
1048 if ((end-where)!=read(fd,data,end-where))
1049 return;
1050 curdata = data;
1052 keys = (struct _w95key*)xmalloc(nrofdkes * sizeof(struct _w95key));
1053 memset(keys,'\0',nrofdkes*sizeof(struct _w95key));
1054 nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
1056 for (i=0;i<nrofdkes;i++) {
1057 struct dke dke;
1058 unsigned long dkeaddr;
1060 pos=curdata-data+0x40;
1061 memcpy(&dke,curdata,sizeof(dke));
1062 curdata+=sizeof(dke);
1063 nr = dke.nrLS + (dke.nrMS<<8);
1064 dkeaddr=pos-4;
1065 if ((dkeaddr&0xFFF)<0x018) {
1066 int diff;
1068 diff=0x1C-(dkeaddr&0xFFF);
1069 dkeaddr+=diff;
1070 curdata+=diff-sizeof(dke);
1071 memcpy(&dke,curdata,sizeof(dke));
1072 nr = dke.nrLS + (dke.nrMS<<8);
1073 curdata+=sizeof(dke);
1075 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1076 /* readjust to 0x000,
1077 * but ONLY if we are >0x1000 already
1079 if (dkeaddr & ~0xFFF)
1080 dkeaddr = dkeaddr & ~0xFFF;
1082 if (nr>nrofdkes) {
1083 dprintf_reg(stddeb,"nr %ld exceeds nrofdkes %d, skipping.\n",nr,nrofdkes);
1084 continue;
1086 if (keys[nr].dkeaddr) {
1087 int x;
1089 for (x=sizeof(dke);x--;)
1090 if (((char*)&dke)[x])
1091 break;
1092 if (x==-1)
1093 break; /* finished reading if we got only 0 */
1094 if (nr)
1095 dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[nr].dkeaddr,dkeaddr);
1096 continue;
1098 nr2da[i].nr = nr;
1099 nr2da[i].dkeaddr = dkeaddr;
1101 keys[nr].dkeaddr = dkeaddr;
1102 keys[nr].x1 = dke.x1;
1103 keys[nr].x2 = dke.x2;
1104 keys[nr].x3 = dke.x3;
1105 keys[nr].prevlvl= (struct _w95key*)dke.prevlvl;
1106 keys[nr].nextsub= (struct _w95key*)dke.nextsub;
1107 keys[nr].next = (struct _w95key*)dke.next;
1109 free(data);
1111 qsort(nr2da,nrofdkes,sizeof(nr2da[0]),_w95dkecomp);
1113 /* STEP 2: keydata & values */
1114 if (-1==fstat(fd,&stbuf))
1115 return;
1116 end = stbuf.st_size;
1117 lastmodified = stbuf.st_mtime;
1119 if (-1==lseek(fd,rgdbsection,SEEK_SET))
1120 return;
1121 data = (char*)xmalloc(end-rgdbsection);
1122 if ((end-rgdbsection)!=read(fd,data,end-rgdbsection))
1123 return;
1124 _lclose(hfd);
1125 curdata = data;
1126 memcpy(magic,curdata,4);
1127 memcpy(&off_next_rgdb,curdata+4,4);
1128 nextrgdb = curdata+off_next_rgdb;
1129 if (strcmp(magic,"RGDB")) {
1130 dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
1131 return;
1133 curdata=data+0x20;
1134 while (1) {
1135 struct dkh dkh;
1136 int bytesread;
1137 struct _w95key *key,xkey;
1139 bytesread = 0;
1140 if (curdata>=nextrgdb) {
1141 curdata = nextrgdb;
1142 if (!strncmp(curdata,"RGDB",4)) {
1143 memcpy(&off_next_rgdb,curdata+4,4);
1144 nextrgdb = curdata+off_next_rgdb;
1145 curdata+=0x20;
1146 } else {
1147 dprintf_reg(stddeb,"at end of RGDB section, but no next header. Breaking.\n");
1148 break;
1151 #define XREAD(whereto,len) \
1152 if ((curdata-data+len)<end) {\
1153 memcpy(whereto,curdata,len);\
1154 curdata+=len;\
1155 bytesread+=len;\
1158 XREAD(&dkh,sizeof(dkh));
1159 nr = dkh.nrLS + (dkh.nrMS<<8);
1160 if (nr>nrofdkes) {
1161 if (dkh.nrLS == 0xFFFF) {
1162 curdata+= dkh.nextkeyoff - bytesread;
1163 XREAD(magic,4);
1164 if (strcmp(magic,"RGDB")) {
1165 if ((curdata-data)<end)
1166 dprintf_reg(stddeb,"while skipping to next RGDB block found magic %s\n",magic);
1167 break;
1169 curdata+=0x1c;
1170 continue;
1172 if (dkh.nrLS == 0xFFFE) {
1173 dprintf_reg(stddeb,"0xFFFE at %x\n",curdata-data);
1174 break;
1176 dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
1177 key = &xkey;
1178 memset(key,'\0',sizeof(xkey));
1179 } else {
1180 key = keys+nr;
1181 if (!key->dkeaddr)
1182 dprintf_reg(stddeb,"key with nr=%ld has no dkeaddr?\n",nr);
1184 key->nrofvals = dkh.values;
1185 key->name = (char*)xmalloc(dkh.keynamelen+1);
1186 key->xx1 = dkh.xx1;
1187 XREAD(key->name,dkh.keynamelen);
1188 key->name[dkh.keynamelen]=0;
1189 if (key->nrofvals) {
1190 key->values = (struct _w95keyvalue*)xmalloc(
1191 sizeof(struct _w95keyvalue)*key->nrofvals
1193 for (i=0;i<key->nrofvals;i++) {
1194 struct dkv dkv;
1196 XREAD(&dkv,sizeof(dkv));
1197 key->values[i].type = dkv.type;
1198 key->values[i].name = (char*)xmalloc(
1199 dkv.valnamelen+1
1201 key->values[i].datalen = dkv.valdatalen;
1202 key->values[i].data = (unsigned char*)xmalloc(
1203 dkv.valdatalen+1
1205 key->values[i].x1 = dkv.x1;
1206 XREAD(key->values[i].name,dkv.valnamelen);
1207 XREAD(key->values[i].data,dkv.valdatalen);
1208 key->values[i].data[dkv.valdatalen]=0;
1209 key->values[i].name[dkv.valnamelen]=0;
1210 key->values[i].lastmodified=lastmodified;
1213 if (bytesread != dkh.nextkeyoff) {
1214 if (dkh.bytesused != bytesread)
1215 dprintf_reg(stddeb,
1216 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread,dkh.nextkeyoff,
1217 dkh.bytesused
1219 curdata += dkh.nextkeyoff-bytesread;
1221 key->prevlvl = _w95dkelookup((long)key->prevlvl,nrofdkes,nr2da,keys);
1222 key->nextsub = _w95dkelookup((long)key->nextsub,nrofdkes,nr2da,keys);
1223 key->next = _w95dkelookup((long)key->next,nrofdkes,nr2da,keys);
1224 if (!bytesread)
1225 break;
1227 free(data);
1228 _w95_walk_tree(lpkey,keys);
1229 free(keys);
1232 void
1233 SHELL_LoadRegistry() {
1234 char *fn;
1235 struct passwd *pwd;
1236 LPKEYSTRUCT lpkey;
1237 HKEY hkey;
1240 if (key_classes_root==NULL)
1241 SHELL_Init();
1243 /* Load windows 95 entries */
1244 _w95_loadreg("C:\\system.1st", key_local_machine);
1245 _w95_loadreg("system.dat", key_local_machine);
1246 _w95_loadreg("user.dat", key_users);
1248 /* FIXME: win3.1 reg.dat loader still missing */
1250 /* the global user default is loaded under HKEY_USERS\\.Default */
1251 RegCreateKey16(HKEY_USERS,".Default",&hkey);
1252 lpkey = lookup_hkey(hkey);
1253 _wine_loadreg(lpkey,SAVE_USERS_DEFAULT,0);
1255 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1256 _copy_registry(lpkey,key_current_user);
1257 RegCloseKey(hkey);
1259 /* the global machine defaults */
1260 _wine_loadreg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT,0);
1262 /* load the user saved registries */
1264 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1266 pwd=getpwuid(getuid());
1267 if (pwd!=NULL && pwd->pw_dir!=NULL) {
1268 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
1269 strcpy(fn,pwd->pw_dir);
1270 strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
1271 _wine_loadreg(key_current_user,fn,REG_OPTION_TAINTED);
1272 free(fn);
1273 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
1274 strcpy(fn,pwd->pw_dir);
1275 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1276 _wine_loadreg(key_local_machine,fn,REG_OPTION_TAINTED);
1277 free(fn);
1278 } else
1279 fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1280 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) {
1281 DWORD junk,type,len;
1282 char data[5];
1284 len=4;
1285 if (( RegQueryValueEx32A(
1286 hkey,
1287 VAL_SAVEUPDATED,
1288 &junk,
1289 &type,
1290 data,
1291 &len
1292 )!=ERROR_SUCCESS) ||
1293 type != REG_SZ
1295 RegSetValueEx32A(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1296 RegCloseKey(hkey);
1301 /********************* API FUNCTIONS ***************************************/
1303 * Open Keys.
1305 * All functions are stubs to RegOpenKeyEx32W where all the
1306 * magic happens.
1308 * FIXME: security,options,desiredaccess,...
1310 * Callpath:
1311 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1312 * RegOpenKey32W -> RegOpenKeyEx32W
1315 /* RegOpenKeyExW [ADVAPI32.150] */
1316 DWORD RegOpenKeyEx32W(
1317 HKEY hkey,
1318 LPCWSTR lpszSubKey,
1319 DWORD dwReserved,
1320 REGSAM samDesired,
1321 LPHKEY retkey
1323 LPKEYSTRUCT lpNextKey,lpxkey;
1324 LPWSTR *wps;
1325 int wpc,i;
1326 dprintf_reg(stddeb,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1327 (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey
1330 lpNextKey = lookup_hkey(hkey);
1331 if (!lpNextKey)
1332 return SHELL_ERROR_BADKEY;
1333 if (!lpszSubKey || !*lpszSubKey) {
1334 add_handle(++currenthandle,lpNextKey,samDesired);
1335 *retkey=currenthandle;
1336 return SHELL_ERROR_SUCCESS;
1338 split_keypath(lpszSubKey,&wps,&wpc);
1339 i = 0;
1340 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1341 lpxkey = lpNextKey;
1342 while (i<wpc) {
1343 lpxkey=lpNextKey->nextsub;
1344 while (lpxkey) {
1345 if (!strcmpW(wps[i],lpxkey->keyname))
1346 break;
1347 lpxkey=lpxkey->next;
1349 if (!lpxkey) {
1350 FREE_KEY_PATH;
1351 return SHELL_ERROR_BADKEY;
1353 i++;
1354 lpNextKey = lpxkey;
1356 add_handle(++currenthandle,lpxkey,samDesired);
1357 *retkey = currenthandle;
1358 FREE_KEY_PATH;
1359 return SHELL_ERROR_SUCCESS;
1362 /* RegOpenKeyW [ADVAPI32.151] */
1363 DWORD RegOpenKey32W(
1364 HKEY hkey,
1365 LPCWSTR lpszSubKey,
1366 LPHKEY retkey
1368 dprintf_reg(stddeb,"RegOpenKey32W(%lx,%s,%p)\n",
1369 (LONG)hkey,W2C(lpszSubKey,0),retkey
1371 return RegOpenKeyEx32W(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1375 /* RegOpenKeyExA [ADVAPI32.149] */
1376 DWORD RegOpenKeyEx32A(
1377 HKEY hkey,
1378 LPCSTR lpszSubKey,
1379 DWORD dwReserved,
1380 REGSAM samDesired,
1381 LPHKEY retkey
1383 LPWSTR lpszSubKeyW;
1384 DWORD ret;
1386 dprintf_reg(stddeb,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1387 (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey
1389 if (lpszSubKey)
1390 lpszSubKeyW=strdupA2W(lpszSubKey);
1391 else
1392 lpszSubKeyW=NULL;
1393 ret=RegOpenKeyEx32W(hkey,lpszSubKeyW,dwReserved,samDesired,retkey);
1394 if (lpszSubKeyW)
1395 free(lpszSubKeyW);
1396 return ret;
1399 /* RegOpenKeyA [ADVAPI32.148] */
1400 DWORD RegOpenKey32A(
1401 HKEY hkey,
1402 LPCSTR lpszSubKey,
1403 LPHKEY retkey
1405 dprintf_reg(stddeb,"RegOpenKey32A(%lx,%s,%p)\n",
1406 (LONG)hkey,lpszSubKey,retkey
1408 return RegOpenKeyEx32A(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1411 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1412 DWORD RegOpenKey16(
1413 HKEY hkey,
1414 LPCSTR lpszSubKey,
1415 LPHKEY retkey
1417 dprintf_reg(stddeb,"RegOpenKey16(%lx,%s,%p)\n",
1418 (LONG)hkey,lpszSubKey,retkey
1420 return RegOpenKey32A(hkey,lpszSubKey,retkey);
1424 * Create keys
1426 * All those functions convert their respective
1427 * arguments and call RegCreateKeyExW at the end.
1429 * FIXME: no security,no access attrib,no optionhandling yet.
1431 * Callpath:
1432 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1433 * RegCreateKey32W -> RegCreateKeyEx32W
1436 /* RegCreateKeyExW [ADVAPI32.131] */
1437 DWORD RegCreateKeyEx32W(
1438 HKEY hkey,
1439 LPCWSTR lpszSubKey,
1440 DWORD dwReserved,
1441 LPWSTR lpszClass,
1442 DWORD fdwOptions,
1443 REGSAM samDesired,
1444 LPSECURITY_ATTRIBUTES lpSecAttribs,
1445 LPHKEY retkey,
1446 LPDWORD lpDispos
1448 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
1449 LPWSTR *wps;
1450 int wpc,i;
1452 /*FIXME: handle security/access/whatever */
1453 dprintf_reg(stddeb,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1454 (LONG)hkey,
1455 W2C(lpszSubKey,0),
1456 dwReserved,
1457 W2C(lpszClass,1),
1458 fdwOptions,
1459 samDesired,
1460 lpSecAttribs,
1461 retkey,
1462 lpDispos
1465 lpNextKey = lookup_hkey(hkey);
1466 if (!lpNextKey)
1467 return SHELL_ERROR_BADKEY;
1468 if (!lpszSubKey || !*lpszSubKey) {
1469 add_handle(++currenthandle,lpNextKey,samDesired);
1470 *retkey=currenthandle;
1471 return SHELL_ERROR_SUCCESS;
1473 split_keypath(lpszSubKey,&wps,&wpc);
1474 i = 0;
1475 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1476 lpxkey = lpNextKey;
1477 while (i<wpc) {
1478 lpxkey=lpNextKey->nextsub;
1479 while (lpxkey) {
1480 if (!strcmpW(wps[i],lpxkey->keyname))
1481 break;
1482 lpxkey=lpxkey->next;
1484 if (!lpxkey)
1485 break;
1486 i++;
1487 lpNextKey = lpxkey;
1489 if (lpxkey) {
1490 add_handle(++currenthandle,lpxkey,samDesired);
1491 *retkey = currenthandle;
1492 *lpDispos = REG_OPENED_EXISTING_KEY;
1493 FREE_KEY_PATH;
1494 return SHELL_ERROR_SUCCESS;
1496 /* good. now the hard part */
1497 while (i<wpc) {
1498 lplpPrevKey = &(lpNextKey->nextsub);
1499 lpxkey = *lplpPrevKey;
1500 while (lpxkey) {
1501 lplpPrevKey = &(lpxkey->next);
1502 lpxkey = *lplpPrevKey;
1504 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
1505 if (!*lplpPrevKey) {
1506 FREE_KEY_PATH;
1507 return SHELL_ERROR_OUTOFMEMORY;
1509 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
1510 (*lplpPrevKey)->keyname = strdupW(wps[i]);
1511 (*lplpPrevKey)->next = NULL;
1512 (*lplpPrevKey)->nextsub = NULL;
1513 (*lplpPrevKey)->values = NULL;
1514 (*lplpPrevKey)->nrofvalues = 0;
1515 if (lpszClass)
1516 (*lplpPrevKey)->class = strdupW(lpszClass);
1517 else
1518 (*lplpPrevKey)->class = NULL;
1519 lpNextKey = *lplpPrevKey;
1520 i++;
1522 add_handle(++currenthandle,lpNextKey,samDesired);
1524 /*FIXME: flag handling correct? */
1525 lpNextKey->flags= fdwOptions;
1526 if (lpszClass)
1527 lpNextKey->class = strdupW(lpszClass);
1528 else
1529 lpNextKey->class = NULL;
1530 lpNextKey->flags|=REG_OPTION_TAINTED;
1531 *retkey = currenthandle;
1532 *lpDispos = REG_CREATED_NEW_KEY;
1533 FREE_KEY_PATH;
1534 return SHELL_ERROR_SUCCESS;
1537 /* RegCreateKeyW [ADVAPI32.132] */
1538 DWORD RegCreateKey32W(
1539 HKEY hkey,
1540 LPCWSTR lpszSubKey,
1541 LPHKEY retkey
1543 DWORD junk,ret;
1545 dprintf_reg(stddeb,"RegCreateKey32W(%lx,%s,%p)\n",
1546 (LONG)hkey,W2C(lpszSubKey,0),retkey
1548 ret=RegCreateKeyEx32W(
1549 hkey, /* key handle */
1550 lpszSubKey, /* subkey name */
1551 0, /* reserved = 0 */
1552 NULL, /* lpszClass? FIXME: ? */
1553 REG_OPTION_NON_VOLATILE, /* options */
1554 KEY_ALL_ACCESS, /* desired access attribs */
1555 NULL, /* lpsecurity attributes */
1556 retkey, /* lpretkey */
1557 &junk /* disposition value */
1559 return ret;
1562 /* RegCreateKeyExA [ADVAPI32.130] */
1563 DWORD RegCreateKeyEx32A(
1564 HKEY hkey,
1565 LPCSTR lpszSubKey,
1566 DWORD dwReserved,
1567 LPSTR lpszClass,
1568 DWORD fdwOptions,
1569 REGSAM samDesired,
1570 LPSECURITY_ATTRIBUTES lpSecAttribs,
1571 LPHKEY retkey,
1572 LPDWORD lpDispos
1574 LPWSTR lpszSubKeyW,lpszClassW;
1575 DWORD ret;
1577 dprintf_reg(stddeb,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1578 (LONG)hkey,
1579 lpszSubKey,
1580 dwReserved,
1581 lpszClass,
1582 fdwOptions,
1583 samDesired,
1584 lpSecAttribs,
1585 retkey,
1586 lpDispos
1588 if (lpszSubKey)
1589 lpszSubKeyW=strdupA2W(lpszSubKey);
1590 else
1591 lpszSubKeyW=NULL;
1592 if (lpszClass)
1593 lpszClassW=strdupA2W(lpszClass);
1594 else
1595 lpszClassW=NULL;
1596 ret=RegCreateKeyEx32W(
1597 hkey,
1598 lpszSubKeyW,
1599 dwReserved,
1600 lpszClassW,
1601 fdwOptions,
1602 samDesired,
1603 lpSecAttribs,
1604 retkey,
1605 lpDispos
1607 if (lpszSubKeyW)
1608 free(lpszSubKeyW);
1609 if (lpszClassW)
1610 free(lpszClassW);
1611 return ret;
1614 /* RegCreateKeyA [ADVAPI32.129] */
1615 DWORD RegCreateKey32A(
1616 HKEY hkey,
1617 LPCSTR lpszSubKey,
1618 LPHKEY retkey
1620 DWORD junk;
1622 dprintf_reg(stddeb,"RegCreateKey32A(%lx,%s,%p)\n",
1623 (LONG)hkey,lpszSubKey,retkey
1625 return RegCreateKeyEx32A(
1626 hkey, /* key handle */
1627 lpszSubKey, /* subkey name */
1628 0, /* reserved = 0 */
1629 NULL, /* lpszClass? FIXME: ? */
1630 REG_OPTION_NON_VOLATILE,/* options */
1631 KEY_ALL_ACCESS, /* desired access attribs */
1632 NULL, /* lpsecurity attributes */
1633 retkey, /* lpretkey */
1634 &junk /* disposition value */
1638 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1639 DWORD RegCreateKey16(
1640 HKEY hkey,
1641 LPCSTR lpszSubKey,
1642 LPHKEY retkey
1644 dprintf_reg(stddeb,"RegCreateKey16(%lx,%s,%p)\n",
1645 (LONG)hkey,lpszSubKey,retkey
1647 return RegCreateKey32A(hkey,lpszSubKey,retkey);
1651 * Query Value Functions
1652 * Win32 differs between keynames and valuenames.
1653 * multiple values may belong to one key, the special value
1654 * with name NULL is the default value used by the win31
1655 * compat functions.
1657 * Callpath:
1658 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1659 * RegQueryValue32W -> RegQueryValueEx32W
1662 /* RegQueryValueExW [ADVAPI32.158] */
1663 DWORD RegQueryValueEx32W(
1664 HKEY hkey,
1665 LPWSTR lpszValueName,
1666 LPDWORD lpdwReserved,
1667 LPDWORD lpdwType,
1668 LPBYTE lpbData,
1669 LPDWORD lpcbData
1671 LPKEYSTRUCT lpkey;
1672 int i;
1674 dprintf_reg(stddeb,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%p)\n",
1675 hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,lpcbData
1678 lpkey = lookup_hkey(hkey);
1679 if (!lpkey)
1680 return SHELL_ERROR_BADKEY;
1681 if (lpszValueName==NULL) {
1682 for (i=0;i<lpkey->nrofvalues;i++)
1683 if (lpkey->values[i].name==NULL)
1684 break;
1685 } else {
1686 for (i=0;i<lpkey->nrofvalues;i++)
1687 if (!strcmpW(lpszValueName,lpkey->values[i].name))
1688 break;
1690 if (i==lpkey->nrofvalues) {
1691 if (lpszValueName==NULL) {
1692 *(WCHAR*)lpbData = 0;
1693 *lpcbData = 2;
1694 *lpdwType = REG_SZ;
1695 return SHELL_ERROR_SUCCESS;
1697 return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
1699 if (lpdwType)
1700 *lpdwType = lpkey->values[i].type;
1701 if (lpbData==NULL) {
1702 if (lpcbData==NULL)
1703 return SHELL_ERROR_SUCCESS;
1704 *lpcbData = lpkey->values[i].len;
1705 return SHELL_ERROR_SUCCESS;
1707 if (*lpcbData<lpkey->values[i].len) {
1708 *(WCHAR*)lpbData
1709 = 0;
1710 *lpcbData = lpkey->values[i].len;
1711 return ERROR_MORE_DATA;
1713 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
1714 *lpcbData = lpkey->values[i].len;
1715 return SHELL_ERROR_SUCCESS;
1718 /* RegQueryValueW [ADVAPI32.159] */
1719 DWORD RegQueryValue32W(
1720 HKEY hkey,
1721 LPWSTR lpszSubKey,
1722 LPWSTR lpszData,
1723 LPDWORD lpcbData
1725 HKEY xhkey;
1726 DWORD ret,lpdwType;
1728 dprintf_reg(stddeb,"RegQueryValue32W(%x,%s,%p,%p)\n->",
1729 hkey,W2C(lpszSubKey,0),lpszData,lpcbData
1732 /* only open subkey, if we really do descend */
1733 if (lpszSubKey && *lpszSubKey) {
1734 ret = RegOpenKey32W(hkey,lpszSubKey,&xhkey);
1735 if (ret!=ERROR_SUCCESS)
1736 return ret;
1737 } else
1738 xhkey = hkey;
1740 lpdwType = REG_SZ;
1741 ret = RegQueryValueEx32W(
1742 xhkey,
1743 NULL, /* varname NULL -> compat */
1744 NULL, /* lpdwReserved, must be NULL */
1745 &lpdwType,
1746 (LPBYTE)lpszData,
1747 lpcbData
1749 if (xhkey!=hkey)
1750 RegCloseKey(xhkey);
1751 return ret;
1754 /* RegQueryValueExA [ADVAPI32.157] */
1755 DWORD RegQueryValueEx32A(
1756 HKEY hkey,
1757 LPSTR lpszValueName,
1758 LPDWORD lpdwReserved,
1759 LPDWORD lpdwType,
1760 LPBYTE lpbData,
1761 LPDWORD lpcbData
1763 LPWSTR lpszValueNameW;
1764 LPBYTE buf;
1765 DWORD ret,myxlen;
1766 DWORD *mylen;
1768 dprintf_reg(stddeb,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%p)\n->",
1769 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData
1771 if (lpbData) {
1772 /* double buffer */
1773 buf = (LPBYTE)xmalloc((*lpcbData)*2);
1774 myxlen = *lpcbData*2;
1775 mylen = &myxlen;
1776 } else {
1777 buf=NULL;
1778 if (lpcbData) {
1779 myxlen = *lpcbData*2;
1780 mylen = &myxlen;
1782 mylen = NULL;
1784 if (lpszValueName)
1785 lpszValueNameW=strdupA2W(lpszValueName);
1786 else
1787 lpszValueNameW=NULL;
1789 ret=RegQueryValueEx32W(
1790 hkey,
1791 lpszValueNameW,
1792 lpdwReserved,
1793 lpdwType,
1794 buf,
1795 mylen
1798 if (ret==ERROR_SUCCESS) {
1799 if (buf) {
1800 if (UNICONVMASK & (1<<(*lpdwType))) {
1801 /* convert UNICODE to ASCII */
1802 strcpyWA(lpbData,(LPWSTR)buf);
1803 *lpcbData = myxlen/2;
1804 } else {
1805 if (myxlen>*lpcbData)
1806 ret = ERROR_MORE_DATA;
1807 else
1808 memcpy(lpbData,buf,myxlen);
1810 *lpcbData = myxlen;
1812 } else {
1813 if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
1814 *lpcbData = myxlen/2;
1816 } else {
1817 if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
1818 *lpcbData = myxlen/2;
1820 if (buf)
1821 free(buf);
1822 return ret;
1825 /* RegQueryValueEx [KERNEL.225] */
1826 DWORD RegQueryValueEx16(
1827 HKEY hkey,
1828 LPSTR lpszValueName,
1829 LPDWORD lpdwReserved,
1830 LPDWORD lpdwType,
1831 LPBYTE lpbData,
1832 LPDWORD lpcbData
1834 dprintf_reg(stddeb,"RegQueryValueEx16(%x,%s,%p,%p,%p,%p)\n",
1835 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData
1837 return RegQueryValueEx32A(
1838 hkey,
1839 lpszValueName,
1840 lpdwReserved,
1841 lpdwType,
1842 lpbData,
1843 lpcbData
1847 /* RegQueryValueA [ADVAPI32.156] */
1848 DWORD RegQueryValue32A(
1849 HKEY hkey,
1850 LPSTR lpszSubKey,
1851 LPSTR lpszData,
1852 LPDWORD lpcbData
1854 HKEY xhkey;
1855 DWORD ret,lpdwType;
1857 dprintf_reg(stddeb,"RegQueryValue32A(%x,%s,%p,%p)\n",
1858 hkey,lpszSubKey,lpszData,lpcbData
1861 /* only open subkey, if we really do descend */
1862 if (lpszSubKey && *lpszSubKey) {
1863 ret = RegOpenKey16(hkey,lpszSubKey,&xhkey);
1864 if (ret!=ERROR_SUCCESS)
1865 return ret;
1866 } else
1867 xhkey = hkey;
1869 lpdwType = REG_SZ;
1870 ret = RegQueryValueEx32A(
1871 xhkey,
1872 NULL, /* lpszValueName NULL -> compat */
1873 NULL, /* lpdwReserved, must be NULL */
1874 &lpdwType,
1875 (LPBYTE)lpszData,
1876 lpcbData
1878 if (xhkey!=hkey)
1879 RegCloseKey(xhkey);
1880 return ret;
1883 /* RegQueryValue [SHELL.6] [KERNEL.224] */
1884 DWORD RegQueryValue16(
1885 HKEY hkey,
1886 LPSTR lpszSubKey,
1887 LPSTR lpszData,
1888 LPDWORD lpcbData
1890 dprintf_reg(stddeb,"RegQueryValue16(%x,%s,%p,%p)\n",
1891 hkey,lpszSubKey,lpszData,lpcbData
1893 return RegQueryValue32A(hkey,lpszSubKey,lpszData,lpcbData);
1897 * Setting values of Registry keys
1899 * Callpath:
1900 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
1901 * RegSetValue32W -> RegSetValueEx32W
1904 /* RegSetValueExW [ADVAPI32.170] */
1905 DWORD RegSetValueEx32W(
1906 HKEY hkey,
1907 LPWSTR lpszValueName,
1908 DWORD dwReserved,
1909 DWORD dwType,
1910 LPBYTE lpbData,
1911 DWORD cbData
1913 LPKEYSTRUCT lpkey;
1914 int i;
1916 dprintf_reg(stddeb,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
1917 hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData
1919 /* we no longer care about the lpbData type here... */
1920 lpkey = lookup_hkey(hkey);
1921 if (!lpkey)
1922 return SHELL_ERROR_BADKEY;
1924 lpkey->flags |= REG_OPTION_TAINTED;
1926 if (lpszValueName==NULL) {
1927 for (i=0;i<lpkey->nrofvalues;i++)
1928 if (lpkey->values[i].name==NULL)
1929 break;
1930 } else {
1931 for (i=0;i<lpkey->nrofvalues;i++)
1932 if (!strcmpW(lpszValueName,lpkey->values[i].name))
1933 break;
1935 if (i==lpkey->nrofvalues) {
1936 lpkey->values = (LPKEYVALUE)xrealloc(
1937 lpkey->values,
1938 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
1940 lpkey->nrofvalues++;
1941 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
1943 if (lpkey->values[i].name==NULL)
1944 if (lpszValueName)
1945 lpkey->values[i].name = strdupW(lpszValueName);
1946 else
1947 lpkey->values[i].name = NULL;
1948 lpkey->values[i].len = cbData;
1949 lpkey->values[i].type = dwType;
1950 if (lpkey->values[i].data !=NULL)
1951 free(lpkey->values[i].data);
1952 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
1953 lpkey->values[i].lastmodified = time(NULL);
1954 memcpy(lpkey->values[i].data,lpbData,cbData);
1955 return SHELL_ERROR_SUCCESS;
1958 /* RegSetValueExA [ADVAPI32.169] */
1959 DWORD RegSetValueEx32A(
1960 HKEY hkey,
1961 LPSTR lpszValueName,
1962 DWORD dwReserved,
1963 DWORD dwType,
1964 LPBYTE lpbData,
1965 DWORD cbData
1967 LPBYTE buf;
1968 LPWSTR lpszValueNameW;
1969 DWORD ret;
1971 dprintf_reg(stddeb,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
1972 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
1974 if ((1<<dwType) & UNICONVMASK) {
1975 buf=(LPBYTE)strdupA2W(lpbData);
1976 cbData=2*strlen(lpbData)+2;
1977 } else
1978 buf=lpbData;
1979 if (lpszValueName)
1980 lpszValueNameW = strdupA2W(lpszValueName);
1981 else
1982 lpszValueNameW = NULL;
1983 ret=RegSetValueEx32W(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
1984 if (lpszValueNameW)
1985 free(lpszValueNameW);
1986 if (buf!=lpbData)
1987 free(buf);
1988 return ret;
1991 /* RegSetValueEx [KERNEL.226] */
1992 DWORD RegSetValueEx16(
1993 HKEY hkey,
1994 LPSTR lpszValueName,
1995 DWORD dwReserved,
1996 DWORD dwType,
1997 LPBYTE lpbData,
1998 DWORD cbData
2000 dprintf_reg(stddeb,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2001 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2003 return RegSetValueEx32A(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData);
2006 /* RegSetValueW [ADVAPI32.171] */
2007 DWORD RegSetValue32W(
2008 HKEY hkey,
2009 LPCWSTR lpszSubKey,
2010 DWORD dwType,
2011 LPCWSTR lpszData,
2012 DWORD cbData
2014 HKEY xhkey;
2015 DWORD ret;
2017 dprintf_reg(stddeb,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2018 hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
2020 if (lpszSubKey && *lpszSubKey) {
2021 ret=RegCreateKey32W(hkey,lpszSubKey,&xhkey);
2022 if (ret!=ERROR_SUCCESS)
2023 return ret;
2024 } else
2025 xhkey=hkey;
2026 if (dwType!=REG_SZ) {
2027 fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
2028 dwType=REG_SZ;
2030 if (cbData!=2*strlenW(lpszData)+2) {
2031 dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2032 cbData,W2C(lpszData,0),2*strlenW(lpszData)+2
2034 cbData=2*strlenW(lpszData)+2;
2036 ret=RegSetValueEx32W(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2037 if (hkey!=xhkey)
2038 RegCloseKey(xhkey);
2039 return ret;
2042 /* RegSetValueA [ADVAPI32.168] */
2043 DWORD RegSetValue32A(
2044 HKEY hkey,
2045 LPCSTR lpszSubKey,
2046 DWORD dwType,
2047 LPCSTR lpszData,
2048 DWORD cbData
2050 DWORD ret;
2051 HKEY xhkey;
2053 dprintf_reg(stddeb,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2054 hkey,lpszSubKey,dwType,lpszData,cbData
2056 if (lpszSubKey && *lpszSubKey) {
2057 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
2058 if (ret!=ERROR_SUCCESS)
2059 return ret;
2060 } else
2061 xhkey=hkey;
2063 if (dwType!=REG_SZ) {
2064 dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType);
2065 dwType=REG_SZ;
2067 if (cbData!=strlen(lpszData)+1)
2068 cbData=strlen(lpszData)+1;
2069 ret=RegSetValueEx32A(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2070 if (xhkey!=hkey)
2071 RegCloseKey(xhkey);
2072 return ret;
2075 /* RegSetValue [KERNEL.221] [SHELL.5] */
2076 DWORD RegSetValue16(
2077 HKEY hkey,
2078 LPCSTR lpszSubKey,
2079 DWORD dwType,
2080 LPCSTR lpszData,
2081 DWORD cbData
2083 DWORD ret;
2084 dprintf_reg(stddeb,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2085 hkey,lpszSubKey,dwType,lpszData,cbData
2087 ret=RegSetValue32A(hkey,lpszSubKey,dwType,lpszData,cbData);
2088 return ret;
2092 * Key Enumeration
2094 * Callpath:
2095 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2096 * RegEnumKey32W -> RegEnumKeyEx32W
2099 /* RegEnumKeyExW [ADVAPI32.139] */
2100 DWORD RegEnumKeyEx32W(
2101 HKEY hkey,
2102 DWORD iSubkey,
2103 LPWSTR lpszName,
2104 LPDWORD lpcchName,
2105 LPDWORD lpdwReserved,
2106 LPWSTR lpszClass,
2107 LPDWORD lpcchClass,
2108 FILETIME *ft
2110 LPKEYSTRUCT lpkey,lpxkey;
2112 dprintf_reg(stddeb,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2113 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2115 lpkey=lookup_hkey(hkey);
2116 if (!lpkey)
2117 return SHELL_ERROR_BADKEY;
2118 if (!lpkey->nextsub)
2119 return ERROR_NO_MORE_ITEMS;
2120 lpxkey=lpkey->nextsub;
2121 while (iSubkey && lpxkey) {
2122 iSubkey--;
2123 lpxkey=lpxkey->next;
2125 if (iSubkey || !lpxkey)
2126 return ERROR_NO_MORE_ITEMS;
2127 if (2*strlenW(lpxkey->keyname)+2>*lpcchName)
2128 return ERROR_MORE_DATA;
2129 memcpy(lpszName,lpxkey->keyname,strlenW(lpxkey->keyname)*2+2);
2130 if (lpszClass) {
2131 /* what should we write into it? */
2132 *lpszClass = 0;
2133 *lpcchClass = 2;
2135 return ERROR_SUCCESS;
2139 /* RegEnumKeyW [ADVAPI32.140] */
2140 DWORD RegEnumKey32W(
2141 HKEY hkey,
2142 DWORD iSubkey,
2143 LPWSTR lpszName,
2144 DWORD lpcchName
2146 FILETIME ft;
2148 dprintf_reg(stddeb,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2149 hkey,iSubkey,lpszName,lpcchName
2151 return RegEnumKeyEx32W(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
2153 /* RegEnumKeyExA [ADVAPI32.138] */
2154 DWORD RegEnumKeyEx32A(
2155 HKEY hkey,
2156 DWORD iSubkey,
2157 LPSTR lpszName,
2158 LPDWORD lpcchName,
2159 LPDWORD lpdwReserved,
2160 LPSTR lpszClass,
2161 LPDWORD lpcchClass,
2162 FILETIME *ft
2164 DWORD ret,lpcchNameW,lpcchClassW;
2165 LPWSTR lpszNameW,lpszClassW;
2168 dprintf_reg(stddeb,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2169 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2171 if (lpszName) {
2172 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
2173 lpcchNameW = *lpcchName*2;
2174 } else {
2175 lpszNameW = NULL;
2176 lpcchNameW = 0;
2178 if (lpszClass) {
2179 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
2180 lpcchClassW = *lpcchClass*2;
2181 } else {
2182 lpszClassW =0;
2183 lpcchClassW=0;
2185 ret=RegEnumKeyEx32W(
2186 hkey,
2187 iSubkey,
2188 lpszNameW,
2189 &lpcchNameW,
2190 lpdwReserved,
2191 lpszClassW,
2192 &lpcchClassW,
2195 if (ret==ERROR_SUCCESS) {
2196 strcpyWA(lpszName,lpszNameW);
2197 *lpcchName=strlen(lpszName);
2198 if (lpszClassW) {
2199 strcpyWA(lpszClass,lpszClassW);
2200 *lpcchClass=strlen(lpszClass);
2203 if (lpszNameW)
2204 free(lpszNameW);
2205 if (lpszClassW)
2206 free(lpszClassW);
2207 return ret;
2210 /* RegEnumKeyA [ADVAPI32.137] */
2211 DWORD RegEnumKey32A(
2212 HKEY hkey,
2213 DWORD iSubkey,
2214 LPSTR lpszName,
2215 DWORD lpcchName
2217 FILETIME ft;
2219 dprintf_reg(stddeb,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2220 hkey,iSubkey,lpszName,lpcchName
2222 return RegEnumKeyEx32A(
2223 hkey,
2224 iSubkey,
2225 lpszName,
2226 &lpcchName,
2227 NULL,
2228 NULL,
2229 NULL,
2234 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2235 DWORD RegEnumKey16(
2236 HKEY hkey,
2237 DWORD iSubkey,
2238 LPSTR lpszName,
2239 DWORD lpcchName
2241 dprintf_reg(stddeb,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2242 hkey,iSubkey,lpszName,lpcchName
2244 return RegEnumKey32A(hkey,iSubkey,lpszName,lpcchName);
2248 * Enumerate Registry Values
2250 * Callpath:
2251 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2254 /* RegEnumValueW [ADVAPI32.142] */
2255 DWORD RegEnumValue32W(
2256 HKEY hkey,
2257 DWORD iValue,
2258 LPWSTR lpszValue,
2259 LPDWORD lpcchValue,
2260 LPDWORD lpdReserved,
2261 LPDWORD lpdwType,
2262 LPBYTE lpbData,
2263 LPDWORD lpcbData
2265 LPKEYSTRUCT lpkey;
2266 LPKEYVALUE val;
2268 dprintf_reg(stddeb,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2269 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2271 lpkey = lookup_hkey(hkey);
2272 if (!lpkey)
2273 return SHELL_ERROR_BADKEY;
2274 if (lpkey->nrofvalues<=iValue)
2275 return ERROR_NO_MORE_ITEMS;
2276 val = lpkey->values+iValue;
2278 if (val->name) {
2279 if (strlenW(val->name)*2+2>*lpcchValue) {
2280 *lpcchValue = strlenW(val->name)*2+2;
2281 return ERROR_MORE_DATA;
2283 memcpy(lpszValue,val->name,2*strlenW(val->name)+2);
2284 *lpcchValue=strlenW(val->name)*2+2;
2285 } else {
2286 /* how to handle NULL value? */
2287 *lpszValue = 0;
2288 *lpcchValue = 2;
2290 *lpdwType=val->type;
2291 if (lpbData) {
2292 if (val->len>*lpcbData)
2293 return ERROR_MORE_DATA;
2294 memcpy(lpbData,val->data,val->len);
2295 *lpcbData = val->len;
2297 return SHELL_ERROR_SUCCESS;
2300 /* RegEnumValueA [ADVAPI32.141] */
2301 DWORD RegEnumValue32A(
2302 HKEY hkey,
2303 DWORD iValue,
2304 LPSTR lpszValue,
2305 LPDWORD lpcchValue,
2306 LPDWORD lpdReserved,
2307 LPDWORD lpdwType,
2308 LPBYTE lpbData,
2309 LPDWORD lpcbData
2311 LPWSTR lpszValueW;
2312 LPBYTE lpbDataW;
2313 DWORD ret,lpcbDataW;
2315 dprintf_reg(stddeb,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2316 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2319 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
2320 if (lpbData) {
2321 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
2322 lpcbDataW = *lpcbData*2;
2323 } else
2324 lpbDataW = NULL;
2325 ret=RegEnumValue32W(
2326 hkey,
2327 iValue,
2328 lpszValueW,
2329 lpcchValue,
2330 lpdReserved,
2331 lpdwType,
2332 lpbDataW,
2333 &lpcbDataW
2336 if (ret==ERROR_SUCCESS) {
2337 strcpyWA(lpszValue,lpszValueW);
2338 if (lpbData) {
2339 if ((1<<*lpdwType) & UNICONVMASK) {
2340 strcpyWA(lpbData,(LPWSTR)lpbDataW);
2341 } else {
2342 if (lpcbDataW > *lpcbData)
2343 ret = ERROR_MORE_DATA;
2344 else
2345 memcpy(lpbData,lpbDataW,lpcbDataW);
2347 *lpcbData = lpcbDataW;
2350 if (lpbDataW)
2351 free(lpbDataW);
2352 if (lpszValueW)
2353 free(lpszValueW);
2354 return ret;
2357 /* RegEnumValue [KERNEL.223] */
2358 DWORD RegEnumValue16(
2359 HKEY hkey,
2360 DWORD iValue,
2361 LPSTR lpszValue,
2362 LPDWORD lpcchValue,
2363 LPDWORD lpdReserved,
2364 LPDWORD lpdwType,
2365 LPBYTE lpbData,
2366 LPDWORD lpcbData
2368 dprintf_reg(stddeb,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2369 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2371 return RegEnumValue32A(
2372 hkey,
2373 iValue,
2374 lpszValue,
2375 lpcchValue,
2376 lpdReserved,
2377 lpdwType,
2378 lpbData,
2379 lpcbData
2384 * Close registry key
2386 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2387 DWORD RegCloseKey(HKEY hkey) {
2388 dprintf_reg(stddeb,"RegCloseKey(%x)\n",hkey);
2389 remove_handle(hkey);
2390 return ERROR_SUCCESS;
2393 * Delete registry key
2395 * Callpath:
2396 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2398 /* RegDeleteKeyW [ADVAPI32.134] */
2399 DWORD RegDeleteKey32W(HKEY hkey,LPWSTR lpszSubKey) {
2400 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2401 LPWSTR *wps;
2402 int wpc,i;
2404 dprintf_reg(stddeb,"RegDeleteKey32W(%x,%s)\n",
2405 hkey,W2C(lpszSubKey,0)
2407 lpNextKey = lookup_hkey(hkey);
2408 if (!lpNextKey)
2409 return SHELL_ERROR_BADKEY;
2410 /* we need to know the previous key in the hier. */
2411 if (!lpszSubKey || !*lpszSubKey)
2412 return SHELL_ERROR_BADKEY;
2413 split_keypath(lpszSubKey,&wps,&wpc);
2414 i = 0;
2415 lpxkey = lpNextKey;
2416 while (i<wpc-1) {
2417 lpxkey=lpNextKey->nextsub;
2418 while (lpxkey) {
2419 if (!strcmpW(wps[i],lpxkey->keyname))
2420 break;
2421 lpxkey=lpxkey->next;
2423 if (!lpxkey) {
2424 FREE_KEY_PATH;
2425 /* not found is success */
2426 return SHELL_ERROR_SUCCESS;
2428 i++;
2429 lpNextKey = lpxkey;
2431 lpxkey = lpNextKey->nextsub;
2432 lplpPrevKey = &(lpNextKey->nextsub);
2433 while (lpxkey) {
2434 if (!strcmpW(wps[i],lpxkey->keyname))
2435 break;
2436 lplpPrevKey = &(lpxkey->next);
2437 lpxkey = lpxkey->next;
2439 if (!lpxkey)
2440 return SHELL_ERROR_SUCCESS;
2441 if (lpxkey->nextsub)
2442 return SHELL_ERROR_CANTWRITE;
2443 *lplpPrevKey = lpxkey->next;
2444 free(lpxkey->keyname);
2445 if (lpxkey->class)
2446 free(lpxkey->class);
2447 if (lpxkey->values)
2448 free(lpxkey->values);
2449 free(lpxkey);
2450 FREE_KEY_PATH;
2451 return SHELL_ERROR_SUCCESS;
2454 /* RegDeleteKeyA [ADVAPI32.133] */
2455 DWORD RegDeleteKey32A(HKEY hkey,LPCSTR lpszSubKey) {
2456 LPWSTR lpszSubKeyW;
2457 DWORD ret;
2459 dprintf_reg(stddeb,"RegDeleteKey32A(%x,%s)\n",
2460 hkey,lpszSubKey
2462 lpszSubKeyW=strdupA2W(lpszSubKey);
2463 ret=RegDeleteKey32W(hkey,lpszSubKeyW);
2464 free(lpszSubKeyW);
2465 return ret;
2468 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2469 DWORD RegDeleteKey16(HKEY hkey,LPCSTR lpszSubKey) {
2470 dprintf_reg(stddeb,"RegDeleteKey16(%x,%s)\n",
2471 hkey,lpszSubKey
2473 return RegDeleteKey32A(hkey,lpszSubKey);
2477 * Delete registry value
2479 * Callpath:
2480 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2482 /* RegDeleteValueW [ADVAPI32.136] */
2483 DWORD RegDeleteValue32W(HKEY hkey,LPWSTR lpszValue) {
2484 DWORD i;
2485 LPKEYSTRUCT lpkey;
2486 LPKEYVALUE val;
2488 dprintf_reg(stddeb,"RegDeleteValue32W(%x,%s)\n",
2489 hkey,W2C(lpszValue,0)
2491 lpkey=lookup_hkey(hkey);
2492 if (!lpkey)
2493 return SHELL_ERROR_BADKEY;
2494 if (lpszValue) {
2495 for (i=0;i<lpkey->nrofvalues;i++)
2496 if (!strcmpW(lpkey->values[i].name,lpszValue))
2497 break;
2498 } else {
2499 for (i=0;i<lpkey->nrofvalues;i++)
2500 if (lpkey->values[i].name==NULL)
2501 break;
2503 if (i==lpkey->nrofvalues)
2504 return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */
2505 val = lpkey->values+i;
2506 if (val->name) free(val->name);
2507 if (val->data) free(val->data);
2508 memcpy(
2509 lpkey->values+i,
2510 lpkey->values+i+1,
2511 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
2513 lpkey->values = (LPKEYVALUE)xrealloc(
2514 lpkey->values,
2515 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
2517 lpkey->nrofvalues--;
2518 return SHELL_ERROR_SUCCESS;
2521 /* RegDeleteValueA [ADVAPI32.135] */
2522 DWORD RegDeleteValue32A(HKEY hkey,LPSTR lpszValue) {
2523 LPWSTR lpszValueW;
2524 DWORD ret;
2526 dprintf_reg( stddeb, "RegDeleteValue32A(%x,%s)\n", hkey,lpszValue );
2527 if (lpszValue)
2528 lpszValueW=strdupA2W(lpszValue);
2529 else
2530 lpszValueW=NULL;
2531 ret=RegDeleteValue32W(hkey,lpszValueW);
2532 if (lpszValueW)
2533 free(lpszValueW);
2534 return ret;
2537 /* RegDeleteValue [KERNEL.222] */
2538 DWORD RegDeleteValue16(HKEY hkey,LPSTR lpszValue) {
2539 dprintf_reg( stddeb,"RegDeleteValue16(%x,%s)\n", hkey,lpszValue );
2540 return RegDeleteValue32A(hkey,lpszValue);
2543 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2544 DWORD RegFlushKey(HKEY hkey) {
2545 dprintf_reg(stddeb,"RegFlushKey(%x), STUB.\n",hkey);
2546 return SHELL_ERROR_SUCCESS;
2549 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2551 /* RegQueryInfoKeyW [ADVAPI32.153] */
2552 DWORD RegQueryInfoKey32W(
2553 HKEY hkey,
2554 LPWSTR lpszClass,
2555 LPDWORD lpcchClass,
2556 LPDWORD lpdwReserved,
2557 LPDWORD lpcSubKeys,
2558 LPDWORD lpcchMaxSubkey,
2559 LPDWORD lpcchMaxClass,
2560 LPDWORD lpcValues,
2561 LPDWORD lpcchMaxValueName,
2562 LPDWORD lpccbMaxValueData,
2563 LPDWORD lpcbSecurityDescriptor,
2564 FILETIME *ft
2566 LPKEYSTRUCT lpkey,lpxkey;
2567 int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata;
2568 int i;
2570 dprintf_reg(stddeb,"RegQueryInfoKey32W(%x,......)\n",hkey);
2571 lpkey=lookup_hkey(hkey);
2572 if (!lpkey)
2573 return SHELL_ERROR_BADKEY;
2574 if (lpszClass) {
2575 if (lpkey->class) {
2576 if (strlenW(lpkey->class)*2+2>*lpcchClass) {
2577 *lpcchClass=strlenW(lpkey->class)*2;
2578 return ERROR_MORE_DATA;
2580 *lpcchClass=strlenW(lpkey->class)*2;
2581 memcpy(lpszClass,lpkey->class,strlenW(lpkey->class));
2582 } else {
2583 *lpszClass = 0;
2584 *lpcchClass = 0;
2586 } else {
2587 if (lpcchClass)
2588 *lpcchClass = strlenW(lpkey->class)*2;
2590 lpxkey=lpkey->nextsub;
2591 nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
2592 while (lpxkey) {
2593 nrofkeys++;
2594 if (strlenW(lpxkey->keyname)>maxsubkey)
2595 maxsubkey=strlenW(lpxkey->keyname);
2596 if (lpxkey->class && strlenW(lpxkey->class)>maxclass)
2597 maxclass=strlenW(lpxkey->class);
2598 if (lpxkey->nrofvalues>maxvalues)
2599 maxvalues=lpxkey->nrofvalues;
2600 for (i=0;i<lpxkey->nrofvalues;i++) {
2601 LPKEYVALUE val=lpxkey->values+i;
2603 if (val->name && strlenW(val->name)>maxvname)
2604 maxvname=strlenW(val->name);
2605 if (val->len>maxvdata)
2606 maxvdata=val->len;
2608 lpxkey=lpxkey->next;
2610 if (!maxclass) maxclass = 1;
2611 if (!maxvname) maxvname = 1;
2612 if (lpcSubKeys)
2613 *lpcSubKeys = nrofkeys;
2614 if (lpcchMaxSubkey)
2615 *lpcchMaxSubkey = maxsubkey*2;
2616 if (lpcchMaxClass)
2617 *lpcchMaxClass = maxclass*2;
2618 if (lpcValues)
2619 *lpcValues = maxvalues;
2620 if (lpcchMaxValueName)
2621 *lpcchMaxValueName= maxvname;
2622 if (lpccbMaxValueData)
2623 *lpccbMaxValueData= maxvdata;
2624 return SHELL_ERROR_SUCCESS;
2627 /* RegQueryInfoKeyA [ADVAPI32.152] */
2628 DWORD RegQueryInfoKey32A(
2629 HKEY hkey,
2630 LPSTR lpszClass,
2631 LPDWORD lpcchClass,
2632 LPDWORD lpdwReserved,
2633 LPDWORD lpcSubKeys,
2634 LPDWORD lpcchMaxSubkey,
2635 LPDWORD lpcchMaxClass,
2636 LPDWORD lpcValues,
2637 LPDWORD lpcchMaxValueName,
2638 LPDWORD lpccbMaxValueData,
2639 LPDWORD lpcbSecurityDescriptor,
2640 FILETIME *ft
2642 LPWSTR lpszClassW;
2643 DWORD ret;
2645 dprintf_reg(stddeb,"RegQueryInfoKey32A(%x,......)\n",hkey);
2646 if (lpszClass) {
2647 *lpcchClass*= 2;
2648 lpszClassW = (LPWSTR)xmalloc(*lpcchClass);
2650 } else
2651 lpszClassW = NULL;
2652 ret=RegQueryInfoKey32W(
2653 hkey,
2654 lpszClassW,
2655 lpcchClass,
2656 lpdwReserved,
2657 lpcSubKeys,
2658 lpcchMaxSubkey,
2659 lpcchMaxClass,
2660 lpcValues,
2661 lpcchMaxValueName,
2662 lpccbMaxValueData,
2663 lpcbSecurityDescriptor,
2666 if (ret==ERROR_SUCCESS)
2667 strcpyWA(lpszClass,lpszClassW);
2668 if (lpcchClass)
2669 *lpcchClass/=2;
2670 if (lpcchMaxSubkey)
2671 *lpcchMaxSubkey/=2;
2672 if (lpcchMaxClass)
2673 *lpcchMaxClass/=2;
2674 if (lpcchMaxValueName)
2675 *lpcchMaxValueName/=2;
2676 if (lpszClassW)
2677 free(lpszClassW);
2678 return ret;