Release 961222
[wine/multimedia.git] / misc / registry.c
blobece9fb0f578c240956ac5ffc2fda0e758488e173
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 "heap.h"
24 #include "dos_fs.h"
25 #include "string32.h"
26 #include "stddebug.h"
27 #include "debug.h"
28 #include "xmalloc.h"
29 #include "winreg.h"
31 #define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y))
33 /* FIXME: following defines should be configured global ... */
35 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
36 #define WINE_PREFIX "/.wine"
37 #define SAVE_USERS_DEFAULT "/usr/local/etc/wine.userreg"
38 #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
40 /* relative in ~user/.wine/ : */
41 #define SAVE_CURRENT_USER "user.reg"
42 #define SAVE_LOCAL_MACHINE "system.reg"
44 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
45 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
47 /* one value of a key */
48 typedef struct tagKEYVALUE
50 LPWSTR name; /* name of value (UNICODE) or NULL for win31 */
51 DWORD type; /* type of value */
52 DWORD len; /* length of data */
53 DWORD lastmodified; /* time of seconds since 1.1.1970 */
54 LPBYTE data; /* content, may be strings, binaries, etc. */
55 } KEYVALUE,*LPKEYVALUE;
57 /* a registry key */
58 typedef struct tagKEYSTRUCT
60 LPWSTR keyname; /* name of THIS key (UNICODE) */
61 DWORD flags; /* flags. */
62 LPWSTR class;
63 /* values */
64 DWORD nrofvalues; /* nr of values in THIS key */
65 LPKEYVALUE values; /* values in THIS key */
66 /* key management pointers */
67 struct tagKEYSTRUCT *next; /* next key on same hierarchy */
68 struct tagKEYSTRUCT *nextsub; /* keys that hang below THIS key */
69 } KEYSTRUCT, *LPKEYSTRUCT;
72 static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */
73 static KEYSTRUCT *key_current_user=NULL; /* user specific values */
74 static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
75 static KEYSTRUCT *key_users=NULL; /* all users? */
77 /* dynamic, not saved */
78 static KEYSTRUCT *key_performance_data=NULL;
79 static KEYSTRUCT *key_current_config=NULL;
80 static KEYSTRUCT *key_dyn_data=NULL;
82 /* what valuetypes do we need to convert? */
83 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
85 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
86 #define strdupW(x) STRING32_strdupW(x)
87 #define strchrW(a,c) STRING32_lstrchrW(a,c)
89 static struct openhandle {
90 LPKEYSTRUCT lpkey;
91 HKEY hkey;
92 REGSAM accessmask;
93 } *openhandles=NULL;
94 static int nrofopenhandles=0;
95 static int currenthandle=1;
97 static void
98 add_handle(HKEY hkey,LPKEYSTRUCT lpkey,REGSAM accessmask) {
99 int i;
101 for (i=0;i<nrofopenhandles;i++) {
102 if (openhandles[i].lpkey==lpkey) {
103 dprintf_reg(stddeb,"add_handle:Tried to add %p twice!\n",lpkey);
105 if (openhandles[i].hkey==hkey) {
106 dprintf_reg(stddeb,"add_handle:Tried to add %lx twice!\n",(LONG)hkey);
109 openhandles=xrealloc( openhandles,
110 sizeof(struct openhandle)*(nrofopenhandles+1)
112 openhandles[i].lpkey = lpkey;
113 openhandles[i].hkey = hkey;
114 openhandles[i].accessmask= accessmask;
115 nrofopenhandles++;
118 static LPKEYSTRUCT
119 get_handle(HKEY hkey) {
120 int i;
122 for (i=0;i<nrofopenhandles;i++)
123 if (openhandles[i].hkey==hkey)
124 return openhandles[i].lpkey;
125 dprintf_reg(stddeb,"get_handle:Didn't find handle %lx?\n",(LONG)hkey);
126 return NULL;
129 static void
130 remove_handle(HKEY hkey) {
131 int i;
133 for (i=0;i<nrofopenhandles;i++)
134 if (openhandles[i].hkey==hkey)
135 break;
136 if (i==nrofopenhandles) {
137 dprintf_reg(stddeb,"remove_handle:Didn't find handle %08x?\n",hkey);
138 return;
140 memcpy( openhandles+i,
141 openhandles+i+1,
142 sizeof(struct openhandle)*(nrofopenhandles-i-1)
144 openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
145 nrofopenhandles--;
146 return;
150 /* debug function, converts a unicode into a static memory area
151 * (sub for using two static strings, in case we need them in a single call)
153 LPSTR
154 W2C(LPCWSTR x,int sub) {
155 static LPSTR unicodedebug[2]={NULL,NULL};
156 if (x==NULL)
157 return "<NULL>";
158 if (sub!=0 && sub!=1)
159 return "<W2C:bad sub>";
160 if (unicodedebug[sub]) HeapFree( SystemHeap, 0, unicodedebug[sub] );
161 unicodedebug[sub] = HEAP_strdupWtoA( SystemHeap, 0, x );
162 return unicodedebug[sub];
165 static LPKEYSTRUCT
166 lookup_hkey(HKEY hkey) {
167 switch (hkey) {
168 case 0x00000000:
169 case 0x00000001:
170 case HKEY_CLASSES_ROOT:
171 return key_classes_root;
172 case HKEY_CURRENT_USER:
173 return key_current_user;
174 case HKEY_LOCAL_MACHINE:
175 return key_local_machine;
176 case HKEY_USERS:
177 return key_users;
178 case HKEY_PERFORMANCE_DATA:
179 return key_performance_data;
180 case HKEY_DYN_DATA:
181 return key_dyn_data;
182 case HKEY_CURRENT_CONFIG:
183 return key_current_config;
184 default:
185 dprintf_reg(stddeb,"lookup_hkey(%lx), special key!\n",
186 (LONG)hkey
188 return get_handle(hkey);
190 /*NOTREACHED*/
194 * splits the unicode string 'wp' into an array of strings.
195 * the array is allocated by this function.
196 * the number of components will be stored in 'wpc'
197 * Free the array using FREE_KEY_PATH
199 static void
200 split_keypath(LPCWSTR wp,LPWSTR **wpv,int *wpc) {
201 int i,j,len;
202 LPWSTR ws;
204 ws = strdupW(wp);
205 *wpc = 1;
206 for (i=0;ws[i];i++) {
207 if (ws[i]=='\\') {
208 ws[i]=0;
209 (*wpc)++;
212 len = i;
213 *wpv = (LPWSTR*)xmalloc(sizeof(LPWSTR)*(*wpc+2));
214 (*wpv)[0]= ws;
215 j = 1;
216 for (i=1;i<len;i++)
217 if (ws[i-1]==0)
218 (*wpv)[j++]=ws+i;
219 (*wpv)[j]=NULL;
221 #define FREE_KEY_PATH free(wps[0]);free(wps);
224 * Shell initialisation, allocates keys.
226 void SHELL_StartupRegistry();
227 void
228 SHELL_Init() {
229 struct passwd *pwd;
231 HKEY cl_r_hkey,c_u_hkey;
232 #define ADD_ROOT_KEY(xx) \
233 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
234 memset(xx,'\0',sizeof(KEYSTRUCT));\
235 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
237 ADD_ROOT_KEY(key_local_machine);
238 if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
239 fprintf(stderr,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
240 exit(1);
242 key_classes_root = lookup_hkey(cl_r_hkey);
244 ADD_ROOT_KEY(key_users);
246 #if 0
247 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
248 * (later, when a win32 registry editing tool becomes avail.)
250 while (pwd=getpwent()) {
251 if (pwd->pw_name == NULL)
252 continue;
253 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
254 RegCloseKey(c_u_hkey);
256 #endif
257 pwd=getpwuid(getuid());
258 if (pwd && pwd->pw_name) {
259 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
260 key_current_user = lookup_hkey(c_u_hkey);
261 } else {
262 ADD_ROOT_KEY(key_current_user);
264 ADD_ROOT_KEY(key_performance_data);
265 ADD_ROOT_KEY(key_current_config);
266 ADD_ROOT_KEY(key_dyn_data);
267 #undef ADD_ROOT_KEY
268 SHELL_StartupRegistry();
272 void
273 SHELL_StartupRegistry() {
274 HKEY hkey,xhkey=0;
275 FILE *F;
276 char buf[200],cpubuf[200];
278 RegCreateKey16(HKEY_DYN_DATA,"\\PerfStats\\StatData",&xhkey);
279 RegCloseKey(xhkey);
280 RegCreateKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey);
281 #ifdef linux
282 F=fopen("/proc/cpuinfo","r");
283 if (F) {
284 int procnr=-1,x;
285 while (NULL!=fgets(buf,200,F)) {
286 if (sscanf(buf,"processor\t: %d",&x)) {
287 sprintf(buf,"%d",x);
288 if (xhkey)
289 RegCloseKey(xhkey);
290 procnr=x;
291 RegCreateKey16(hkey,buf,&xhkey);
293 if (sscanf(buf,"cpu\t\t: %s",cpubuf)) {
294 sprintf(buf,"CPU %s",cpubuf);
295 if (xhkey)
296 RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,buf,strlen(buf));
299 fclose(F);
301 if (xhkey)
302 RegCloseKey(xhkey);
303 RegCloseKey(hkey);
304 #else
305 /* FIXME */
306 RegCreateKey16(hkey,"0",&xhkey);
307 RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,"CPU 386",strlen("CPU 386"));
308 #endif
309 RegOpenKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System",&hkey);
310 RegSetValueEx32A(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
311 RegCloseKey(hkey);
312 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
313 * CurrentVersion
314 * CurrentBuildNumber
315 * CurrentType
316 * string RegisteredOwner
317 * string RegisteredOrganization
320 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
321 * string SysContact
322 * string SysLocation
323 * SysServices
325 if (-1!=gethostname(buf,200)) {
326 RegCreateKey16(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&xhkey);
327 RegSetValueEx16(xhkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
328 RegCloseKey(xhkey);
331 /************************ SAVE Registry Function ****************************/
333 #define REGISTRY_SAVE_VERSION 0x00000001
335 /* Registry saveformat:
336 * If you change it, increase above number by 1, which will flush
337 * old registry database files.
339 * Global:
340 * "WINE REGISTRY Version %d"
341 * subkeys....
342 * Subkeys:
343 * keyname
344 * valuename=lastmodified,type,data
345 * ...
346 * subkeys
347 * ...
348 * keyname,valuename,stringdata:
349 * the usual ascii characters from 0x00-0xff (well, not 0x00)
350 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
351 * ( "=\\\t" escaped in \uXXXX form.)
352 * type,lastmodified:
353 * int
355 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
357 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
358 * SaveOnlyUpdatedKeys=yes
360 static int
361 _save_check_tainted(LPKEYSTRUCT lpkey) {
362 int tainted;
364 if (!lpkey)
365 return 0;
366 if (lpkey->flags & REG_OPTION_TAINTED)
367 tainted = 1;
368 else
369 tainted = 0;
370 while (lpkey) {
371 if (_save_check_tainted(lpkey->nextsub)) {
372 lpkey->flags |= REG_OPTION_TAINTED;
373 tainted = 1;
375 lpkey = lpkey->next;
377 return tainted;
380 static void
381 _save_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
382 LPWSTR s;
383 int doescape;
385 if (wstr==NULL)
386 return;
387 s=wstr;
388 while (*s) {
389 doescape=0;
390 if (*s>0xff)
391 doescape = 1;
392 if (*s=='\n')
393 doescape = 1;
394 if (escapeeq && *s=='=')
395 doescape = 1;
396 if (*s=='\\')
397 fputc(*s,F); /* if \\ than put it twice. */
398 if (doescape)
399 fprintf(F,"\\u%04x",*((unsigned short*)s));
400 else
401 fputc(*s,F);
402 s++;
406 static int
407 _savesubkey(FILE *F,LPKEYSTRUCT lpkey,int level,int all) {
408 LPKEYSTRUCT lpxkey;
409 int i,tabs,j;
411 lpxkey = lpkey;
412 while (lpxkey) {
413 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
414 (all || (lpxkey->flags & REG_OPTION_TAINTED))
416 for (tabs=level;tabs--;)
417 fputc('\t',F);
418 _save_USTRING(F,lpxkey->keyname,1);
419 fputs("\n",F);
420 for (i=0;i<lpxkey->nrofvalues;i++) {
421 LPKEYVALUE val=lpxkey->values+i;
423 for (tabs=level+1;tabs--;)
424 fputc('\t',F);
425 _save_USTRING(F,val->name,0);
426 fputc('=',F);
427 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
428 if ((1<<val->type) & UNICONVMASK)
429 _save_USTRING(F,(LPWSTR)val->data,0);
430 else
431 for (j=0;j<val->len;j++)
432 fprintf(F,"%02x",*((unsigned char*)val->data+j));
433 fputs("\n",F);
435 /* descend recursively */
436 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
437 return 0;
439 lpxkey=lpxkey->next;
441 return 1;
444 static int
445 _savesubreg(FILE *F,LPKEYSTRUCT lpkey,int all) {
446 fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
447 _save_check_tainted(lpkey->nextsub);
448 return _savesubkey(F,lpkey->nextsub,0,all);
451 static BOOL32
452 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
453 FILE *F;
455 F=fopen(fn,"w");
456 if (F==NULL) {
457 fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
458 fn,strerror(errno)
460 return FALSE;
462 if (!_savesubreg(F,lpkey,all)) {
463 fclose(F);
464 unlink(fn);
465 fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
466 return FALSE;
468 fclose(F);
469 return TRUE;
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)
504 char *tmp;
506 fn=(char*)xmalloc( strlen(pwd->pw_dir) + strlen(WINE_PREFIX) +
507 strlen(SAVE_CURRENT_USER) + 2 );
508 strcpy(fn,pwd->pw_dir);
509 strcat(fn,WINE_PREFIX);
510 /* create the directory. don't care about errorcodes. */
511 mkdir(fn,0755); /* drwxr-xr-x */
512 strcat(fn,"/"SAVE_CURRENT_USER);
513 tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
514 strcpy(tmp,fn);strcat(tmp,".tmp");
515 if (_savereg(key_current_user,tmp,all)) {
516 if (-1==rename(tmp,fn)) {
517 perror("rename tmp registry");
518 unlink(tmp);
521 free(tmp);
522 free(fn);
523 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
524 strcpy(fn,pwd->pw_dir);
525 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
526 tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
527 strcpy(tmp,fn);strcat(tmp,".tmp");
528 if (_savereg(key_local_machine,tmp,all)) {
529 if (-1==rename(tmp,fn)) {
530 perror("rename tmp registry");
531 unlink(tmp);
534 free(tmp);
535 free(fn);
536 } else
537 fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
540 /************************ LOAD Registry Function ****************************/
542 static LPKEYSTRUCT
543 _find_or_add_key(LPKEYSTRUCT lpkey,LPWSTR keyname) {
544 LPKEYSTRUCT lpxkey,*lplpkey;
546 lplpkey= &(lpkey->nextsub);
547 lpxkey = *lplpkey;
548 while (lpxkey) {
549 if (!lstrcmp32W(lpxkey->keyname,keyname))
550 break;
551 lplpkey = &(lpxkey->next);
552 lpxkey = *lplpkey;
554 if (lpxkey==NULL) {
555 *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
556 lpxkey = *lplpkey;
557 memset(lpxkey,'\0',sizeof(KEYSTRUCT));
558 lpxkey->keyname = keyname;
559 } else
560 free(keyname);
561 return lpxkey;
564 static void
565 _find_or_add_value(
566 LPKEYSTRUCT lpkey,LPWSTR name,DWORD type,LPBYTE data,DWORD len,
567 DWORD lastmodified
569 LPKEYVALUE val=NULL;
570 int i;
572 for (i=0;i<lpkey->nrofvalues;i++) {
573 val=lpkey->values+i;
574 if (name==NULL) {
575 if (val->name==NULL)
576 break;
577 } else {
578 if ( val->name!=NULL &&
579 !lstrcmp32W(val->name,name)
581 break;
584 if (i==lpkey->nrofvalues) {
585 lpkey->values = xrealloc(
586 lpkey->values,
587 (++lpkey->nrofvalues)*sizeof(KEYVALUE)
589 val=lpkey->values+i;
590 memset(val,'\0',sizeof(KEYVALUE));
591 val->name = name;
592 } else {
593 if (name)
594 free(name);
596 if (val->lastmodified<lastmodified) {
597 val->lastmodified=lastmodified;
598 val->type = type;
599 val->len = len;
600 if (val->data)
601 free(val->data);
602 val->data = data;
603 } else
604 free(data);
608 /* reads a line including dynamically enlarging the readbuffer and throwing
609 * away comments
611 static int
612 _wine_read_line(FILE *F,char **buf,int *len) {
613 char *s,*curread;
614 int mylen,curoff;
616 curread = *buf;
617 mylen = *len;
618 **buf = '\0';
619 while (1) {
620 while (1) {
621 s=fgets(curread,mylen,F);
622 if (s==NULL)
623 return 0; /* EOF */
624 if (NULL==(s=strchr(curread,'\n'))) {
625 /* buffer wasn't large enough */
626 curoff = strlen(*buf);
627 *buf = xrealloc(*buf,*len*2);
628 curread = *buf + curoff;
629 mylen = *len; /* we filled up the buffer and
630 * got new '*len' bytes to fill
632 *len = *len * 2;
633 } else {
634 *s='\0';
635 break;
638 /* throw away comments */
639 if (**buf=='#' || **buf==';') {
640 curread = *buf;
641 mylen = *len;
642 continue;
644 if (s) /* got end of line */
645 break;
647 return 1;
650 /* converts a char* into a UNICODE string (up to a special char)
651 * and returns the position exactly after that string
653 static char*
654 _wine_read_USTRING(char *buf,LPWSTR *str) {
655 char *s;
656 LPWSTR ws;
658 /* read up to "=" or "\0" or "\n" */
659 s = buf;
660 if (*s == '=') {
661 /* empty string is the win3.1 default value(NULL)*/
662 *str = NULL;
663 return s;
665 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
666 ws = *str;
667 while (*s && (*s!='\n') && (*s!='=')) {
668 if (*s!='\\')
669 *ws++=*((unsigned char*)s++);
670 else {
671 s++;
672 if (*s=='\\') {
673 *ws+='\\';
674 s++;
675 continue;
677 if (*s!='u') {
678 fprintf(stderr,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
679 *ws++='\\';
680 *ws++=*s++;
681 } else {
682 char xbuf[5];
683 int wc;
685 s++;
686 memcpy(xbuf,s,4);xbuf[4]='\0';
687 if (!sscanf(xbuf,"%x",&wc))
688 fprintf(stderr,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf);
689 s+=4;
690 *ws++ =(unsigned short)wc;
694 *ws = 0;
695 ws = *str;
696 *str = strdupW(*str);
697 free(ws);
698 return s;
701 static int
702 _wine_loadsubkey(
703 FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen,int optflag
705 LPKEYSTRUCT lpxkey;
706 int i;
707 char *s;
708 LPWSTR name;
710 lpkey->flags |= optflag;
712 /* good. we already got a line here ... so parse it */
713 lpxkey = NULL;
714 while (1) {
715 i=0;s=*buf;
716 while (*s=='\t') {
717 s++;
718 i++;
720 if (i>level) {
721 if (lpxkey==NULL) {
722 fprintf(stderr,"_load_subkey:Got a subhierarchy without resp. key?\n");
723 return 0;
725 _wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag);
726 continue;
728 /* let the caller handle this line */
729 if (i<level || **buf=='\0')
730 return 1;
732 /* it can be: a value or a keyname. Parse the name first */
733 s=_wine_read_USTRING(s,&name);
735 /* switch() default: hack to avoid gotos */
736 switch (0) {
737 default:
738 if (*s=='\0') {
739 lpxkey=_find_or_add_key(lpkey,name);
740 } else {
741 LPBYTE data;
742 int len,lastmodified,type;
744 if (*s!='=') {
745 fprintf(stderr,"_wine_load_subkey:unexpected character: %c\n",*s);
746 break;
748 s++;
749 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
750 fprintf(stderr,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf);
751 break;
753 /* skip the 2 , */
754 s=strchr(s,',');s++;
755 s=strchr(s,',');s++;
756 if ((1<<type) & UNICONVMASK) {
757 s=_wine_read_USTRING(s,(LPWSTR*)&data);
758 if (data)
759 len = lstrlen32W((LPWSTR)data)*2+2;
760 else
761 len = 0;
762 } else {
763 len=strlen(s)/2;
764 data = (LPBYTE)xmalloc(len+1);
765 for (i=0;i<len;i++) {
766 data[i]=0;
767 if (*s>='0' && *s<='9')
768 data[i]=(*s-'0')<<4;
769 if (*s>='a' && *s<='f')
770 data[i]=(*s-'a')<<4;
771 if (*s>='A' && *s<='F')
772 data[i]=(*s-'A')<<4;
773 s++;
774 if (*s>='0' && *s<='9')
775 data[i]|=*s-'0';
776 if (*s>='a' && *s<='f')
777 data[i]|=*s-'a';
778 if (*s>='A' && *s<='F')
779 data[i]|=*s-'A';
780 s++;
783 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
786 /* read the next line */
787 if (!_wine_read_line(F,buf,buflen))
788 return 1;
790 return 1;
793 static int
794 _wine_loadsubreg(FILE *F,LPKEYSTRUCT lpkey,int optflag) {
795 int ver;
796 char *buf;
797 int buflen;
799 buf=xmalloc(10);buflen=10;
800 if (!_wine_read_line(F,&buf,&buflen)) {
801 free(buf);
802 return 0;
804 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
805 free(buf);
806 return 0;
808 if (ver!=REGISTRY_SAVE_VERSION) {
809 dprintf_reg(stddeb,__FILE__":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
810 free(buf);
811 return 0;
813 if (!_wine_read_line(F,&buf,&buflen)) {
814 free(buf);
815 return 0;
817 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
818 free(buf);
819 return 0;
821 free(buf);
822 return 1;
825 static void
826 _wine_loadreg(LPKEYSTRUCT lpkey,char *fn,int optflag) {
827 FILE *F;
829 F=fopen(fn,"rb");
830 if (F==NULL) {
831 dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n",
832 fn,strerror(errno)
834 return;
836 if (!_wine_loadsubreg(F,lpkey,optflag)) {
837 fclose(F);
838 unlink(fn);
839 return;
841 fclose(F);
844 static void
845 _copy_registry(LPKEYSTRUCT from,LPKEYSTRUCT to) {
846 LPKEYSTRUCT lpxkey;
847 int j;
848 LPKEYVALUE valfrom;
850 from=from->nextsub;
851 while (from) {
852 lpxkey = _find_or_add_key(to,strdupW(from->keyname));
854 for (j=0;j<from->nrofvalues;j++) {
855 LPWSTR name;
856 LPBYTE data;
858 valfrom = from->values+j;
859 name=valfrom->name;
860 if (name) name=strdupW(name);
861 data=(LPBYTE)malloc(valfrom->len);
862 memcpy(data,valfrom->data,valfrom->len);
864 _find_or_add_value(
865 lpxkey,
866 name,
867 valfrom->type,
868 data,
869 valfrom->len,
870 valfrom->lastmodified
873 _copy_registry(from,lpxkey);
874 from = from->next;
878 /* WINDOWS 95 REGISTRY LOADER */
880 * Structure of a win95 registry database.
881 * main header:
882 * 0 : "CREG" - magic
883 * 4 : DWORD version
884 * 8 : DWORD offset_of_RGDB_part
885 * 0C..1F: ? (someone fill in please)
887 * 20: RGKN_section:
888 * header:
889 * 0 : "RGKN" - magic
890 * 4..0x1B: ? (fill in)
891 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
893 * Disk Key Entry Structure:
894 * 00: DWORD - unknown
895 * 04: DWORD - unknown
896 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
897 * 0C: DWORD - disk address of PreviousLevel Key.
898 * 10: DWORD - disk address of Next Sublevel Key.
899 * 14: DWORD - disk address of Next Key (on same level).
900 * DKEP>18: WORD - Nr, Low Significant part.
901 * 1A: WORD - Nr, High Significant part.
903 * The disk address always points to the nr part of the previous key entry
904 * of the referenced key. Don't ask me why, or even if I got this correct
905 * from staring at 1kg of hexdumps. (DKEP)
907 * The number of the entry is the low byte of the Low Significant Part ored
908 * with 0x100 * (low byte of the High Significant part)
909 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
911 * There are two minor corrections to the position of that structure.
912 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
913 * the DKE reread from there.
914 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
915 * (FIXME: slightly better explanation needed here)
917 * RGDB_section:
918 * 00: "RGDB" - magic
919 * 04: DWORD offset to next RGDB section (perhaps WORD)
920 * 08...1F: ?
921 * 20.....: disk keys
923 * disk key:
924 * 00: DWORD nextkeyoffset - offset to the next disk key structure
925 * 08: WORD nrLS - low significant part of NR
926 * 0A: WORD nrHS - high significant part of NR
927 * 0C: DWORD bytesused - bytes used in this structure.
928 * 10: WORD name_len - length of name in bytes. without \0
929 * 12: WORD nr_of_values - number of values.
930 * 14: char name[name_len] - name string. No \0.
931 * 14+name_len: disk values
932 * nextkeyoffset: ... next disk key
934 * disk value:
935 * 00: DWORD type - value type (hmm, could be WORD too)
936 * 04: DWORD - unknown, usually 0
937 * 08: WORD namelen - length of Name. 0 means name=NULL
938 * 0C: WORD datalen - length of Data.
939 * 10: char name[namelen] - name, no \0
940 * 10+namelen: BYTE data[datalen] - data, without \0 if string
941 * 10+namelen+datalen: next values or disk key
943 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
944 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
945 * structure) and reading another RGDB_section.
946 * repeat until end of file.
948 * FIXME: this description needs some serious help, yes.
951 struct _w95keyvalue {
952 unsigned long type;
953 unsigned short datalen;
954 char *name;
955 unsigned char *data;
956 unsigned long x1;
957 int lastmodified;
960 struct _w95key {
961 char *name;
962 int nrofvals;
963 struct _w95keyvalue *values;
964 unsigned long dkeaddr;
965 unsigned long x1;
966 unsigned long x2;
967 unsigned long x3;
968 unsigned long xx1;
969 struct _w95key *prevlvl;
970 struct _w95key *nextsub;
971 struct _w95key *next;
974 /* fast lookup table dkeaddr->nr */
975 struct _w95nr2da {
976 unsigned long dkeaddr;
977 unsigned long nr;
981 static void
982 _w95_walk_tree(LPKEYSTRUCT lpkey,struct _w95key *key) {
983 int i;
984 LPKEYSTRUCT lpxkey;
985 LPWSTR name;
987 while (key) {
988 if (key->name == NULL) {
989 fprintf(stderr,"_w95_walk_tree:Please report: key with dkeaddr %lx not loaded, skipping hierarchy\n",
990 key->dkeaddr
992 return;
994 lpxkey=_find_or_add_key(lpkey,strdupA2W(key->name));
996 if (key->nrofvals<0) {
997 /* shouldn't happen */
998 fprintf(stderr,"key %s already processed!\n",key->name);
999 key = key->next;
1000 continue;
1002 for (i=0;i<key->nrofvals;i++) {
1003 LPBYTE data;
1004 int len;
1006 name = strdupA2W(key->values[i].name);
1007 if (!*name) name = NULL;
1008 free(key->values[i].name);
1010 len = key->values[i].datalen;
1011 data = key->values[i].data;
1012 if ((1<<key->values[i].type) & UNICONVMASK) {
1013 data = (BYTE*)strdupA2W(data);
1014 len = lstrlen32W((LPWSTR)data)*2+2;
1015 free(key->values[i].data);
1017 _find_or_add_value(
1018 lpxkey,
1019 name,
1020 key->values[i].type,
1021 data,
1022 len,
1023 key->values[i].lastmodified
1026 if (key->values) {
1027 free(key->values);
1028 key->values = NULL;
1030 key->nrofvals=-key->nrofvals-1;
1031 _w95_walk_tree(lpxkey,key->nextsub);
1032 key=key->next;
1036 /* small helper function to adjust address offset (dkeaddrs) */
1037 static unsigned long
1038 _w95_adj_da(unsigned long dkeaddr) {
1039 if ((dkeaddr&0xFFF)<0x018) {
1040 int diff;
1042 diff=0x1C-(dkeaddr&0xFFF);
1043 return dkeaddr+diff;
1045 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1046 /* readjust to 0x000,
1047 * but ONLY if we are >0x1000 already
1049 if (dkeaddr & ~0xFFF)
1050 return dkeaddr & ~0xFFF;
1052 return dkeaddr;
1055 static int
1056 _w95dkecomp(struct _w95nr2da *a,struct _w95nr2da *b){return a->dkeaddr-b->dkeaddr;}
1058 static struct _w95key*
1059 _w95dkelookup(unsigned long dkeaddr,int n,struct _w95nr2da *nr2da,struct _w95key *keys) {
1060 int i,off;
1062 if (dkeaddr == 0xFFFFFFFF)
1063 return NULL;
1064 if (dkeaddr<0x20)
1065 return NULL;
1066 dkeaddr=_w95_adj_da(dkeaddr+0x1c);
1067 off = (dkeaddr-0x3c)/0x1c;
1068 for (i=0;i<n;i++)
1069 if (nr2da[(i+off)%n].dkeaddr == dkeaddr)
1070 return keys+nr2da[(i+off)%n].nr;
1071 /* 0x3C happens often, just report unusual values */
1072 if (dkeaddr!=0x3c)
1073 dprintf_reg(stddeb,"search hasn't found dkeaddr %lx?\n",dkeaddr);
1074 return NULL;
1077 static void
1078 _w95_loadreg(char* fn,LPKEYSTRUCT lpkey) {
1079 /* Disk Key Entry structure (RGKN part) */
1080 struct dke {
1081 unsigned long x1;
1082 unsigned long x2;
1083 unsigned long x3;/*usually 0xFFFFFFFF */
1084 unsigned long prevlvl;
1085 unsigned long nextsub;
1086 unsigned long next;
1087 unsigned short nrLS;
1088 unsigned short nrMS;
1090 /* Disk Key Header structure (RGDB part) */
1091 struct dkh {
1092 unsigned long nextkeyoff;
1093 unsigned short nrLS;
1094 unsigned short nrMS;
1095 unsigned long bytesused;
1096 unsigned short keynamelen;
1097 unsigned short values;
1098 unsigned long xx1;
1099 /* keyname */
1100 /* disk key values or nothing */
1102 /* Disk Key Value structure */
1103 struct dkv {
1104 unsigned long type;
1105 unsigned long x1;
1106 unsigned short valnamelen;
1107 unsigned short valdatalen;
1108 /* valname, valdata */
1110 struct _w95nr2da *nr2da;
1112 HFILE hfd;
1113 int lastmodified;
1114 char magic[5];
1115 unsigned long nr,pos,i,where,version,rgdbsection,end,off_next_rgdb;
1116 struct _w95key *keys;
1117 int nrofdkes;
1118 unsigned char *data,*curdata,*nextrgdb;
1119 OFSTRUCT ofs;
1120 BY_HANDLE_FILE_INFORMATION hfdinfo;
1122 dprintf_reg(stddeb,"Loading Win95 registry database '%s'\n",fn);
1123 hfd=OpenFile(fn,&ofs,OF_READ);
1124 if (hfd==HFILE_ERROR)
1125 return;
1126 magic[4]=0;
1127 if (4!=_lread32(hfd,magic,4))
1128 return;
1129 if (strcmp(magic,"CREG")) {
1130 fprintf(stddeb,"%s is not a w95 registry.\n",fn);
1131 return;
1133 if (4!=_lread32(hfd,&version,4))
1134 return;
1135 if (4!=_lread32(hfd,&rgdbsection,4))
1136 return;
1137 if (-1==_llseek(hfd,0x20,SEEK_SET))
1138 return;
1139 if (4!=_lread32(hfd,magic,4))
1140 return;
1141 if (strcmp(magic,"RGKN")) {
1142 dprintf_reg(stddeb,"second IFF header not RGKN, but %s\n",magic);
1143 return;
1146 /* STEP 1: Keylink structures */
1147 if (-1==_llseek(hfd,0x40,SEEK_SET))
1148 return;
1149 where = 0x40;
1150 end = rgdbsection;
1152 nrofdkes = (end-where)/sizeof(struct dke)+100;
1153 data = (char*)xmalloc(end-where);
1154 if ((end-where)!=_lread32(hfd,data,end-where))
1155 return;
1156 curdata = data;
1158 keys = (struct _w95key*)xmalloc(nrofdkes * sizeof(struct _w95key));
1159 memset(keys,'\0',nrofdkes*sizeof(struct _w95key));
1160 nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
1161 memset(nr2da,'\0',nrofdkes*sizeof(struct _w95nr2da));
1163 for (i=0;i<nrofdkes;i++) {
1164 struct dke dke;
1165 unsigned long dkeaddr;
1167 pos=curdata-data+0x40;
1168 memcpy(&dke,curdata,sizeof(dke));
1169 curdata+=sizeof(dke);
1170 nr = dke.nrLS + (dke.nrMS<<8);
1171 dkeaddr=pos-4;
1172 if ((dkeaddr&0xFFF)<0x018) {
1173 int diff;
1175 diff=0x1C-(dkeaddr&0xFFF);
1176 dkeaddr+=diff;
1177 curdata+=diff-sizeof(dke);
1178 memcpy(&dke,curdata,sizeof(dke));
1179 nr = dke.nrLS + (dke.nrMS<<8);
1180 curdata+=sizeof(dke);
1182 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1183 /* readjust to 0x000,
1184 * but ONLY if we are >0x1000 already
1186 if (dkeaddr & ~0xFFF)
1187 dkeaddr = dkeaddr & ~0xFFF;
1189 if (nr>nrofdkes) {
1190 /* 0xFFFFFFFF happens often, just report unusual values */
1191 if (nr!=0xFFFFFFFF)
1192 dprintf_reg(stddeb,"nr %ld exceeds nrofdkes %d, skipping.\n",nr,nrofdkes);
1193 continue;
1195 if (keys[nr].dkeaddr) {
1196 int x;
1198 for (x=sizeof(dke);x--;)
1199 if (((char*)&dke)[x])
1200 break;
1201 if (x==-1)
1202 break; /* finished reading if we got only 0 */
1203 if (nr) {
1204 if ( (dke.next!=(long)keys[nr].next) ||
1205 (dke.nextsub!=(long)keys[nr].nextsub) ||
1206 (dke.prevlvl!=(long)keys[nr].prevlvl)
1208 dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[nr].dkeaddr,dkeaddr);
1210 continue;
1212 nr2da[i].nr = nr;
1213 nr2da[i].dkeaddr = dkeaddr;
1215 keys[nr].dkeaddr = dkeaddr;
1216 keys[nr].x1 = dke.x1;
1217 keys[nr].x2 = dke.x2;
1218 keys[nr].x3 = dke.x3;
1219 keys[nr].prevlvl= (struct _w95key*)dke.prevlvl;
1220 keys[nr].nextsub= (struct _w95key*)dke.nextsub;
1221 keys[nr].next = (struct _w95key*)dke.next;
1223 free(data);
1225 qsort(nr2da,nrofdkes,sizeof(nr2da[0]),
1226 (int(*)(const void *,const void*))_w95dkecomp);
1228 /* STEP 2: keydata & values */
1229 if (!GetFileInformationByHandle(hfd,&hfdinfo))
1230 return;
1231 end = hfdinfo.nFileSizeLow;
1232 lastmodified = DOSFS_FileTimeToUnixTime(&(hfdinfo.ftLastWriteTime));
1234 if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
1235 return;
1236 data = (char*)xmalloc(end-rgdbsection);
1237 if ((end-rgdbsection)!=_lread32(hfd,data,end-rgdbsection))
1238 return;
1239 _lclose(hfd);
1240 curdata = data;
1241 memcpy(magic,curdata,4);
1242 memcpy(&off_next_rgdb,curdata+4,4);
1243 nextrgdb = curdata+off_next_rgdb;
1244 if (strcmp(magic,"RGDB")) {
1245 dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
1246 return;
1248 curdata=data+0x20;
1249 while (1) {
1250 struct dkh dkh;
1251 int bytesread;
1252 struct _w95key *key,xkey;
1254 bytesread = 0;
1255 if (curdata>=nextrgdb) {
1256 curdata = nextrgdb;
1257 if (!strncmp(curdata,"RGDB",4)) {
1258 memcpy(&off_next_rgdb,curdata+4,4);
1259 nextrgdb = curdata+off_next_rgdb;
1260 curdata+=0x20;
1261 } else {
1262 dprintf_reg(stddeb,"at end of RGDB section, but no next header (%x of %lx). Breaking.\n",curdata-data,end-rgdbsection);
1263 break;
1266 #define XREAD(whereto,len) \
1267 if ((curdata-data+len)<end) {\
1268 memcpy(whereto,curdata,len);\
1269 curdata+=len;\
1270 bytesread+=len;\
1273 XREAD(&dkh,sizeof(dkh));
1274 nr = dkh.nrLS + (dkh.nrMS<<8);
1275 if ((nr>nrofdkes) || (dkh.nrLS == 0xFFFF)) {
1276 if (dkh.nrLS == 0xFFFF) {
1277 /* skip over key using nextkeyoff */
1278 curdata+=dkh.nextkeyoff-sizeof(struct dkh);
1279 continue;
1281 dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
1282 key = &xkey;
1283 memset(key,'\0',sizeof(xkey));
1284 } else {
1285 key = keys+nr;
1286 if (!key->dkeaddr)
1287 dprintf_reg(stddeb,"key with nr=%ld has no dkeaddr?\n",nr);
1289 key->nrofvals = dkh.values;
1290 key->name = (char*)xmalloc(dkh.keynamelen+1);
1291 key->xx1 = dkh.xx1;
1292 XREAD(key->name,dkh.keynamelen);
1293 key->name[dkh.keynamelen]=0;
1294 if (key->nrofvals) {
1295 key->values = (struct _w95keyvalue*)xmalloc(
1296 sizeof(struct _w95keyvalue)*key->nrofvals
1298 for (i=0;i<key->nrofvals;i++) {
1299 struct dkv dkv;
1301 XREAD(&dkv,sizeof(dkv));
1302 key->values[i].type = dkv.type;
1303 key->values[i].name = (char*)xmalloc(
1304 dkv.valnamelen+1
1306 key->values[i].datalen = dkv.valdatalen;
1307 key->values[i].data = (unsigned char*)xmalloc(
1308 dkv.valdatalen+1
1310 key->values[i].x1 = dkv.x1;
1311 XREAD(key->values[i].name,dkv.valnamelen);
1312 XREAD(key->values[i].data,dkv.valdatalen);
1313 key->values[i].data[dkv.valdatalen]=0;
1314 key->values[i].name[dkv.valnamelen]=0;
1315 key->values[i].lastmodified=lastmodified;
1318 if (bytesread != dkh.nextkeyoff) {
1319 if (dkh.bytesused != bytesread)
1320 dprintf_reg(stddeb,
1321 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread,dkh.nextkeyoff,
1322 dkh.bytesused
1324 curdata += dkh.nextkeyoff-bytesread;
1326 key->prevlvl = _w95dkelookup((long)key->prevlvl,nrofdkes,nr2da,keys);
1327 key->nextsub = _w95dkelookup((long)key->nextsub,nrofdkes,nr2da,keys);
1328 key->next = _w95dkelookup((long)key->next,nrofdkes,nr2da,keys);
1329 if (!bytesread)
1330 break;
1332 free(data);
1333 _w95_walk_tree(lpkey,keys);
1334 free(keys);
1337 /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1340 reghack - windows 3.11 registry data format demo program.
1342 The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1343 a combined hash table and tree description, and finally a text table.
1345 The header is obvious from the struct header. The taboff1 and taboff2
1346 fields are always 0x20, and their usage is unknown.
1348 The 8-byte entry table has various entry types.
1350 tabent[0] is a root index. The second word has the index of the root of
1351 the directory.
1352 tabent[1..hashsize] is a hash table. The first word in the hash entry is
1353 the index of the key/value that has that hash. Data with the same
1354 hash value are on a circular list. The other three words in the
1355 hash entry are always zero.
1356 tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1357 entry: dirent and keyent/valent. They are identified by context.
1358 tabent[freeidx] is the first free entry. The first word in a free entry
1359 is the index of the next free entry. The last has 0 as a link.
1360 The other three words in the free list are probably irrelevant.
1362 Entries in text table are preceeded by a word at offset-2. This word
1363 has the value (2*index)+1, where index is the referring keyent/valent
1364 entry in the table. I have no suggestion for the 2* and the +1.
1365 Following the word, there are N bytes of data, as per the keyent/valent
1366 entry length. The offset of the keyent/valent entry is from the start
1367 of the text table to the first data byte.
1369 This information is not available from Microsoft. The data format is
1370 deduced from the reg.dat file by me. Mistakes may
1371 have been made. I claim no rights and give no guarantees for this program.
1373 Tor Sjøwall, tor@sn.no
1376 /* reg.dat header format */
1377 struct _w31_header {
1378 char cookie[8]; /* 'SHCC3.10' */
1379 unsigned long taboff1; /* offset of hash table (??) = 0x20 */
1380 unsigned long taboff2; /* offset of index table (??) = 0x20 */
1381 unsigned long tabcnt; /* number of entries in index table */
1382 unsigned long textoff; /* offset of text part */
1383 unsigned long textsize; /* byte size of text part */
1384 unsigned short hashsize; /* hash size */
1385 unsigned short freeidx; /* free index */
1388 /* generic format of table entries */
1389 struct _w31_tabent {
1390 unsigned short w0, w1, w2, w3;
1393 /* directory tabent: */
1394 struct _w31_dirent {
1395 unsigned short sibling_idx; /* table index of sibling dirent */
1396 unsigned short child_idx; /* table index of child dirent */
1397 unsigned short key_idx; /* table index of key keyent */
1398 unsigned short value_idx; /* table index of value valent */
1401 /* key tabent: */
1402 struct _w31_keyent {
1403 unsigned short hash_idx; /* hash chain index for string */
1404 unsigned short refcnt; /* reference count */
1405 unsigned short length; /* length of string */
1406 unsigned short string_off; /* offset of string in text table */
1409 /* value tabent: */
1410 struct _w31_valent {
1411 unsigned short hash_idx; /* hash chain index for string */
1412 unsigned short refcnt; /* reference count */
1413 unsigned short length; /* length of string */
1414 unsigned short string_off; /* offset of string in text table */
1417 /* recursive helper function to display a directory tree */
1418 void
1419 __w31_dumptree( unsigned short idx,
1420 unsigned char *txt,
1421 struct _w31_tabent *tab,
1422 struct _w31_header *head,
1423 LPKEYSTRUCT lpkey,
1424 time_t lastmodified,
1425 int level
1427 struct _w31_dirent *dir;
1428 struct _w31_keyent *key;
1429 struct _w31_valent *val;
1430 LPKEYSTRUCT xlpkey = NULL;
1431 LPWSTR name,value;
1432 static char tail[400];
1434 while (idx!=0) {
1435 dir=(struct _w31_dirent*)&tab[idx];
1437 if (dir->key_idx) {
1438 key = (struct _w31_keyent*)&tab[dir->key_idx];
1440 memcpy(tail,&txt[key->string_off],key->length);
1441 tail[key->length]='\0';
1442 /* all toplevel entries AND the entries in the
1443 * toplevel subdirectory belong to \SOFTWARE\Classes
1445 if (!level && !lstrcmp32A(tail,".classes")) {
1446 __w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1);
1447 idx=dir->sibling_idx;
1448 continue;
1450 name=STRING32_DupAnsiToUni(tail);
1452 xlpkey=_find_or_add_key(lpkey,name);
1454 /* only add if leaf node or valued node */
1455 if (dir->value_idx!=0||dir->child_idx==0) {
1456 if (dir->value_idx) {
1457 val=(struct _w31_valent*)&tab[dir->value_idx];
1458 memcpy(tail,&txt[val->string_off],val->length);
1459 tail[val->length]='\0';
1460 value=STRING32_DupAnsiToUni(tail);
1461 _find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlen32W(value)*2+2,lastmodified);
1464 } else {
1465 dprintf_reg(stddeb,"__w31_dumptree:strange: no directory key name, idx=%04x\n", idx);
1467 __w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1);
1468 idx=dir->sibling_idx;
1472 void
1473 _w31_loadreg() {
1474 HFILE hf;
1475 struct _w31_header head;
1476 struct _w31_tabent *tab;
1477 unsigned char *txt;
1478 int len;
1479 OFSTRUCT ofs;
1480 BY_HANDLE_FILE_INFORMATION hfinfo;
1481 time_t lastmodified;
1482 HKEY hkey;
1483 LPKEYSTRUCT lpkey;
1485 hf = OpenFile("reg.dat",&ofs,OF_READ);
1486 if (hf==HFILE_ERROR)
1487 return;
1489 /* read & dump header */
1490 if (sizeof(head)!=_lread32(hf,&head,sizeof(head))) {
1491 dprintf_reg(stddeb,"_w31_loadreg:reg.dat is too short.\n");
1492 _lclose(hf);
1493 return;
1495 if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
1496 dprintf_reg(stddeb,"_w31_loadreg:reg.dat has bad signature.\n");
1497 _lclose(hf);
1498 return;
1501 len = head.tabcnt * sizeof(struct _w31_tabent);
1502 /* read and dump index table */
1503 tab = xmalloc(len);
1504 if (len!=_lread32(hf,tab,len)) {
1505 dprintf_reg(stderr,"_w31_loadreg:couldn't read %d bytes.\n",len);
1506 free(tab);
1507 _lclose(hf);
1508 return;
1511 /* read text */
1512 txt = xmalloc(head.textsize);
1513 if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
1514 dprintf_reg(stderr,"_w31_loadreg:couldn't seek to textblock.\n");
1515 free(tab);
1516 free(txt);
1517 _lclose(hf);
1518 return;
1520 if (head.textsize!=_lread32(hf,txt,head.textsize)) {
1521 dprintf_reg(stderr,"_w31_loadreg:textblock too short (%d instead of %ld).\n",len,head.textsize);
1522 free(tab);
1523 free(txt);
1524 _lclose(hf);
1525 return;
1528 if (!GetFileInformationByHandle(hf,&hfinfo)) {
1529 dprintf_reg(stderr,"_w31_loadreg:GetFileInformationByHandle failed?.\n");
1530 free(tab);
1531 free(txt);
1532 _lclose(hf);
1533 return;
1535 lastmodified = DOSFS_FileTimeToUnixTime(&(hfinfo.ftLastWriteTime));
1537 if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&hkey)!=ERROR_SUCCESS)
1538 return;
1539 lpkey = lookup_hkey(hkey);
1540 __w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
1541 free(tab);
1542 free(txt);
1543 _lclose(hf);
1544 return;
1547 void
1548 SHELL_LoadRegistry() {
1549 char *fn;
1550 struct passwd *pwd;
1551 LPKEYSTRUCT lpkey;
1552 HKEY hkey;
1555 if (key_classes_root==NULL)
1556 SHELL_Init();
1558 /* Load windows 3.1 entries */
1559 _w31_loadreg();
1560 /* Load windows 95 entries */
1561 _w95_loadreg("C:\\system.1st", key_local_machine);
1562 _w95_loadreg("system.dat", key_local_machine);
1563 _w95_loadreg("user.dat", key_users);
1565 /* the global user default is loaded under HKEY_USERS\\.Default */
1566 RegCreateKey16(HKEY_USERS,".Default",&hkey);
1567 lpkey = lookup_hkey(hkey);
1568 _wine_loadreg(lpkey,SAVE_USERS_DEFAULT,0);
1570 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1571 _copy_registry(lpkey,key_current_user);
1572 RegCloseKey(hkey);
1574 /* the global machine defaults */
1575 _wine_loadreg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT,0);
1577 /* load the user saved registries */
1579 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1581 pwd=getpwuid(getuid());
1582 if (pwd!=NULL && pwd->pw_dir!=NULL) {
1583 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
1584 strcpy(fn,pwd->pw_dir);
1585 strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
1586 _wine_loadreg(key_current_user,fn,REG_OPTION_TAINTED);
1587 free(fn);
1588 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
1589 strcpy(fn,pwd->pw_dir);
1590 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1591 _wine_loadreg(key_local_machine,fn,REG_OPTION_TAINTED);
1592 free(fn);
1593 } else
1594 fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1595 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) {
1596 DWORD junk,type,len;
1597 char data[5];
1599 len=4;
1600 if (( RegQueryValueEx32A(
1601 hkey,
1602 VAL_SAVEUPDATED,
1603 &junk,
1604 &type,
1605 data,
1606 &len
1607 )!=ERROR_SUCCESS) ||
1608 type != REG_SZ
1610 RegSetValueEx32A(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1611 RegCloseKey(hkey);
1616 /********************* API FUNCTIONS ***************************************/
1618 * Open Keys.
1620 * All functions are stubs to RegOpenKeyEx32W where all the
1621 * magic happens.
1623 * FIXME: security,options,desiredaccess,...
1625 * Callpath:
1626 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1627 * RegOpenKey32W -> RegOpenKeyEx32W
1630 /* RegOpenKeyExW [ADVAPI32.150] */
1631 DWORD RegOpenKeyEx32W(
1632 HKEY hkey,
1633 LPCWSTR lpszSubKey,
1634 DWORD dwReserved,
1635 REGSAM samDesired,
1636 LPHKEY retkey
1638 LPKEYSTRUCT lpNextKey,lpxkey;
1639 LPWSTR *wps;
1640 int wpc,i;
1641 dprintf_reg(stddeb,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1642 (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey
1645 lpNextKey = lookup_hkey(hkey);
1646 if (!lpNextKey)
1647 return SHELL_ERROR_BADKEY;
1648 if (!lpszSubKey || !*lpszSubKey) {
1649 add_handle(++currenthandle,lpNextKey,samDesired);
1650 *retkey=currenthandle;
1651 return SHELL_ERROR_SUCCESS;
1653 split_keypath(lpszSubKey,&wps,&wpc);
1654 i = 0;
1655 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1656 lpxkey = lpNextKey;
1657 while (wps[i]) {
1658 lpxkey=lpNextKey->nextsub;
1659 while (lpxkey) {
1660 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1661 break;
1662 lpxkey=lpxkey->next;
1664 if (!lpxkey) {
1665 FREE_KEY_PATH;
1666 return SHELL_ERROR_BADKEY;
1668 i++;
1669 lpNextKey = lpxkey;
1671 add_handle(++currenthandle,lpxkey,samDesired);
1672 *retkey = currenthandle;
1673 FREE_KEY_PATH;
1674 return SHELL_ERROR_SUCCESS;
1677 /* RegOpenKeyW [ADVAPI32.151] */
1678 DWORD RegOpenKey32W(
1679 HKEY hkey,
1680 LPCWSTR lpszSubKey,
1681 LPHKEY retkey
1683 dprintf_reg(stddeb,"RegOpenKey32W(%lx,%s,%p)\n",
1684 (LONG)hkey,W2C(lpszSubKey,0),retkey
1686 return RegOpenKeyEx32W(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1690 /* RegOpenKeyExA [ADVAPI32.149] */
1691 DWORD RegOpenKeyEx32A(
1692 HKEY hkey,
1693 LPCSTR lpszSubKey,
1694 DWORD dwReserved,
1695 REGSAM samDesired,
1696 LPHKEY retkey
1698 LPWSTR lpszSubKeyW;
1699 DWORD ret;
1701 dprintf_reg(stddeb,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1702 (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey
1704 if (lpszSubKey)
1705 lpszSubKeyW=strdupA2W(lpszSubKey);
1706 else
1707 lpszSubKeyW=NULL;
1708 ret=RegOpenKeyEx32W(hkey,lpszSubKeyW,dwReserved,samDesired,retkey);
1709 if (lpszSubKeyW)
1710 free(lpszSubKeyW);
1711 return ret;
1714 /* RegOpenKeyA [ADVAPI32.148] */
1715 DWORD RegOpenKey32A(
1716 HKEY hkey,
1717 LPCSTR lpszSubKey,
1718 LPHKEY retkey
1720 dprintf_reg(stddeb,"RegOpenKey32A(%lx,%s,%p)\n",
1721 (LONG)hkey,lpszSubKey,retkey
1723 return RegOpenKeyEx32A(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1726 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1727 DWORD RegOpenKey16(
1728 HKEY hkey,
1729 LPCSTR lpszSubKey,
1730 LPHKEY retkey
1732 dprintf_reg(stddeb,"RegOpenKey16(%lx,%s,%p)\n",
1733 (LONG)hkey,lpszSubKey,retkey
1735 return RegOpenKey32A(hkey,lpszSubKey,retkey);
1739 * Create keys
1741 * All those functions convert their respective
1742 * arguments and call RegCreateKeyExW at the end.
1744 * FIXME: no security,no access attrib,no optionhandling yet.
1746 * Callpath:
1747 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1748 * RegCreateKey32W -> RegCreateKeyEx32W
1751 /* RegCreateKeyExW [ADVAPI32.131] */
1752 DWORD RegCreateKeyEx32W(
1753 HKEY hkey,
1754 LPCWSTR lpszSubKey,
1755 DWORD dwReserved,
1756 LPWSTR lpszClass,
1757 DWORD fdwOptions,
1758 REGSAM samDesired,
1759 LPSECURITY_ATTRIBUTES lpSecAttribs,
1760 LPHKEY retkey,
1761 LPDWORD lpDispos
1763 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
1764 LPWSTR *wps;
1765 int wpc,i;
1767 /*FIXME: handle security/access/whatever */
1768 dprintf_reg(stddeb,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1769 (LONG)hkey,
1770 W2C(lpszSubKey,0),
1771 dwReserved,
1772 W2C(lpszClass,1),
1773 fdwOptions,
1774 samDesired,
1775 lpSecAttribs,
1776 retkey,
1777 lpDispos
1780 lpNextKey = lookup_hkey(hkey);
1781 if (!lpNextKey)
1782 return SHELL_ERROR_BADKEY;
1783 if (!lpszSubKey || !*lpszSubKey) {
1784 add_handle(++currenthandle,lpNextKey,samDesired);
1785 *retkey=currenthandle;
1786 lpNextKey->flags|=REG_OPTION_TAINTED;
1787 return SHELL_ERROR_SUCCESS;
1789 split_keypath(lpszSubKey,&wps,&wpc);
1790 i = 0;
1791 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1792 lpxkey = lpNextKey;
1793 while (wps[i]) {
1794 lpxkey=lpNextKey->nextsub;
1795 while (lpxkey) {
1796 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1797 break;
1798 lpxkey=lpxkey->next;
1800 if (!lpxkey)
1801 break;
1802 i++;
1803 lpNextKey = lpxkey;
1805 if (lpxkey) {
1806 add_handle(++currenthandle,lpxkey,samDesired);
1807 lpxkey->flags |= REG_OPTION_TAINTED;
1808 *retkey = currenthandle;
1809 if (lpDispos)
1810 *lpDispos = REG_OPENED_EXISTING_KEY;
1811 FREE_KEY_PATH;
1812 return SHELL_ERROR_SUCCESS;
1814 /* good. now the hard part */
1815 while (wps[i]) {
1816 lplpPrevKey = &(lpNextKey->nextsub);
1817 lpxkey = *lplpPrevKey;
1818 while (lpxkey) {
1819 lplpPrevKey = &(lpxkey->next);
1820 lpxkey = *lplpPrevKey;
1822 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
1823 if (!*lplpPrevKey) {
1824 FREE_KEY_PATH;
1825 return SHELL_ERROR_OUTOFMEMORY;
1827 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
1828 (*lplpPrevKey)->keyname = strdupW(wps[i]);
1829 (*lplpPrevKey)->next = NULL;
1830 (*lplpPrevKey)->nextsub = NULL;
1831 (*lplpPrevKey)->values = NULL;
1832 (*lplpPrevKey)->nrofvalues = 0;
1833 (*lplpPrevKey)->flags = REG_OPTION_TAINTED;
1834 if (lpszClass)
1835 (*lplpPrevKey)->class = strdupW(lpszClass);
1836 else
1837 (*lplpPrevKey)->class = NULL;
1838 lpNextKey = *lplpPrevKey;
1839 i++;
1841 add_handle(++currenthandle,lpNextKey,samDesired);
1843 /*FIXME: flag handling correct? */
1844 lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
1845 if (lpszClass)
1846 lpNextKey->class = strdupW(lpszClass);
1847 else
1848 lpNextKey->class = NULL;
1849 *retkey = currenthandle;
1850 if (lpDispos)
1851 *lpDispos = REG_CREATED_NEW_KEY;
1852 FREE_KEY_PATH;
1853 return SHELL_ERROR_SUCCESS;
1856 /* RegCreateKeyW [ADVAPI32.132] */
1857 DWORD RegCreateKey32W(
1858 HKEY hkey,
1859 LPCWSTR lpszSubKey,
1860 LPHKEY retkey
1862 DWORD junk,ret;
1864 dprintf_reg(stddeb,"RegCreateKey32W(%lx,%s,%p)\n",
1865 (LONG)hkey,W2C(lpszSubKey,0),retkey
1867 ret=RegCreateKeyEx32W(
1868 hkey, /* key handle */
1869 lpszSubKey, /* subkey name */
1870 0, /* reserved = 0 */
1871 NULL, /* lpszClass? FIXME: ? */
1872 REG_OPTION_NON_VOLATILE, /* options */
1873 KEY_ALL_ACCESS, /* desired access attribs */
1874 NULL, /* lpsecurity attributes */
1875 retkey, /* lpretkey */
1876 &junk /* disposition value */
1878 return ret;
1881 /* RegCreateKeyExA [ADVAPI32.130] */
1882 DWORD RegCreateKeyEx32A(
1883 HKEY hkey,
1884 LPCSTR lpszSubKey,
1885 DWORD dwReserved,
1886 LPSTR lpszClass,
1887 DWORD fdwOptions,
1888 REGSAM samDesired,
1889 LPSECURITY_ATTRIBUTES lpSecAttribs,
1890 LPHKEY retkey,
1891 LPDWORD lpDispos
1893 LPWSTR lpszSubKeyW,lpszClassW;
1894 DWORD ret;
1896 dprintf_reg(stddeb,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1897 (LONG)hkey,
1898 lpszSubKey,
1899 dwReserved,
1900 lpszClass,
1901 fdwOptions,
1902 samDesired,
1903 lpSecAttribs,
1904 retkey,
1905 lpDispos
1907 if (lpszSubKey)
1908 lpszSubKeyW=strdupA2W(lpszSubKey);
1909 else
1910 lpszSubKeyW=NULL;
1911 if (lpszClass)
1912 lpszClassW=strdupA2W(lpszClass);
1913 else
1914 lpszClassW=NULL;
1915 ret=RegCreateKeyEx32W(
1916 hkey,
1917 lpszSubKeyW,
1918 dwReserved,
1919 lpszClassW,
1920 fdwOptions,
1921 samDesired,
1922 lpSecAttribs,
1923 retkey,
1924 lpDispos
1926 if (lpszSubKeyW)
1927 free(lpszSubKeyW);
1928 if (lpszClassW)
1929 free(lpszClassW);
1930 return ret;
1933 /* RegCreateKeyA [ADVAPI32.129] */
1934 DWORD RegCreateKey32A(
1935 HKEY hkey,
1936 LPCSTR lpszSubKey,
1937 LPHKEY retkey
1939 DWORD junk;
1941 dprintf_reg(stddeb,"RegCreateKey32A(%lx,%s,%p)\n",
1942 (LONG)hkey,lpszSubKey,retkey
1944 return RegCreateKeyEx32A(
1945 hkey, /* key handle */
1946 lpszSubKey, /* subkey name */
1947 0, /* reserved = 0 */
1948 NULL, /* lpszClass? FIXME: ? */
1949 REG_OPTION_NON_VOLATILE,/* options */
1950 KEY_ALL_ACCESS, /* desired access attribs */
1951 NULL, /* lpsecurity attributes */
1952 retkey, /* lpretkey */
1953 &junk /* disposition value */
1957 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1958 DWORD RegCreateKey16(
1959 HKEY hkey,
1960 LPCSTR lpszSubKey,
1961 LPHKEY retkey
1963 dprintf_reg(stddeb,"RegCreateKey16(%lx,%s,%p)\n",
1964 (LONG)hkey,lpszSubKey,retkey
1966 return RegCreateKey32A(hkey,lpszSubKey,retkey);
1970 * Query Value Functions
1971 * Win32 differs between keynames and valuenames.
1972 * multiple values may belong to one key, the special value
1973 * with name NULL is the default value used by the win31
1974 * compat functions.
1976 * Callpath:
1977 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1978 * RegQueryValue32W -> RegQueryValueEx32W
1981 /* RegQueryValueExW [ADVAPI32.158] */
1982 DWORD RegQueryValueEx32W(
1983 HKEY hkey,
1984 LPWSTR lpszValueName,
1985 LPDWORD lpdwReserved,
1986 LPDWORD lpdwType,
1987 LPBYTE lpbData,
1988 LPDWORD lpcbData
1990 LPKEYSTRUCT lpkey;
1991 int i;
1993 dprintf_reg(stddeb,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%ld)\n",
1994 hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,
1995 lpcbData?*lpcbData:0
1998 lpkey = lookup_hkey(hkey);
1999 if (!lpkey)
2000 return SHELL_ERROR_BADKEY;
2001 if (lpszValueName==NULL) {
2002 for (i=0;i<lpkey->nrofvalues;i++)
2003 if (lpkey->values[i].name==NULL)
2004 break;
2005 } else {
2006 for (i=0;i<lpkey->nrofvalues;i++)
2007 if ( lpkey->values[i].name &&
2008 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
2010 break;
2012 if (i==lpkey->nrofvalues) {
2013 if (lpszValueName==NULL) {
2014 if (lpbData) {
2015 *(WCHAR*)lpbData = 0;
2016 *lpcbData = 2;
2018 if (lpdwType)
2019 *lpdwType = REG_SZ;
2020 return SHELL_ERROR_SUCCESS;
2022 return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
2024 if (lpdwType)
2025 *lpdwType = lpkey->values[i].type;
2026 if (lpbData==NULL) {
2027 if (lpcbData==NULL)
2028 return SHELL_ERROR_SUCCESS;
2029 *lpcbData = lpkey->values[i].len;
2030 return SHELL_ERROR_SUCCESS;
2032 if (*lpcbData<lpkey->values[i].len) {
2033 *(WCHAR*)lpbData
2034 = 0;
2035 *lpcbData = lpkey->values[i].len;
2036 return ERROR_MORE_DATA;
2038 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
2039 *lpcbData = lpkey->values[i].len;
2040 return SHELL_ERROR_SUCCESS;
2043 /* RegQueryValueW [ADVAPI32.159] */
2044 DWORD RegQueryValue32W(
2045 HKEY hkey,
2046 LPWSTR lpszSubKey,
2047 LPWSTR lpszData,
2048 LPDWORD lpcbData
2050 HKEY xhkey;
2051 DWORD ret,lpdwType;
2053 dprintf_reg(stddeb,"RegQueryValue32W(%x,%s,%p,%ld)\n->",
2054 hkey,W2C(lpszSubKey,0),lpszData,
2055 lpcbData?*lpcbData:0
2058 /* only open subkey, if we really do descend */
2059 if (lpszSubKey && *lpszSubKey) {
2060 ret = RegOpenKey32W(hkey,lpszSubKey,&xhkey);
2061 if (ret!=ERROR_SUCCESS)
2062 return ret;
2063 } else
2064 xhkey = hkey;
2066 lpdwType = REG_SZ;
2067 ret = RegQueryValueEx32W(
2068 xhkey,
2069 NULL, /* varname NULL -> compat */
2070 NULL, /* lpdwReserved, must be NULL */
2071 &lpdwType,
2072 (LPBYTE)lpszData,
2073 lpcbData
2075 if (xhkey!=hkey)
2076 RegCloseKey(xhkey);
2077 return ret;
2080 /* RegQueryValueExA [ADVAPI32.157] */
2081 DWORD RegQueryValueEx32A(
2082 HKEY hkey,
2083 LPSTR lpszValueName,
2084 LPDWORD lpdwReserved,
2085 LPDWORD lpdwType,
2086 LPBYTE lpbData,
2087 LPDWORD lpcbData
2089 LPWSTR lpszValueNameW;
2090 LPBYTE buf;
2091 DWORD ret,myxlen;
2092 DWORD *mylen;
2093 DWORD type;
2095 dprintf_reg(stddeb,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%ld)\n->",
2096 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
2097 lpcbData?*lpcbData:0
2099 if (lpbData) {
2100 /* double buffer */
2101 buf = (LPBYTE)xmalloc((*lpcbData)*2);
2102 myxlen = *lpcbData*2;
2103 mylen = &myxlen;
2104 } else {
2105 buf=NULL;
2106 if (lpcbData) {
2107 myxlen = *lpcbData*2;
2108 mylen = &myxlen;
2109 } else
2110 mylen = NULL;
2112 if (lpszValueName)
2113 lpszValueNameW=strdupA2W(lpszValueName);
2114 else
2115 lpszValueNameW=NULL;
2117 if (lpdwType)
2118 type=*lpdwType;
2119 ret=RegQueryValueEx32W(
2120 hkey,
2121 lpszValueNameW,
2122 lpdwReserved,
2123 &type,
2124 buf,
2125 mylen
2127 if (lpdwType)
2128 *lpdwType=type;
2129 if (ret==ERROR_SUCCESS) {
2130 if (buf) {
2131 if (UNICONVMASK & (1<<(type))) {
2132 /* convert UNICODE to ASCII */
2133 lstrcpyWtoA(lpbData,(LPWSTR)buf);
2134 *lpcbData = myxlen/2;
2135 } else {
2136 if (myxlen>*lpcbData)
2137 ret = ERROR_MORE_DATA;
2138 else
2139 memcpy(lpbData,buf,myxlen);
2141 *lpcbData = myxlen;
2143 } else {
2144 if ((UNICONVMASK & (1<<(type))) && lpcbData)
2145 *lpcbData = myxlen/2;
2147 } else {
2148 if ((UNICONVMASK & (1<<(type))) && lpcbData)
2149 *lpcbData = myxlen/2;
2151 if (buf)
2152 free(buf);
2153 return ret;
2156 /* RegQueryValueEx [KERNEL.225] */
2157 DWORD RegQueryValueEx16(
2158 HKEY hkey,
2159 LPSTR lpszValueName,
2160 LPDWORD lpdwReserved,
2161 LPDWORD lpdwType,
2162 LPBYTE lpbData,
2163 LPDWORD lpcbData
2165 dprintf_reg(stddeb,"RegQueryValueEx16(%x,%s,%p,%p,%p,%ld)\n",
2166 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
2167 lpcbData?*lpcbData:0
2169 return RegQueryValueEx32A(
2170 hkey,
2171 lpszValueName,
2172 lpdwReserved,
2173 lpdwType,
2174 lpbData,
2175 lpcbData
2179 /* RegQueryValueA [ADVAPI32.156] */
2180 DWORD RegQueryValue32A(
2181 HKEY hkey,
2182 LPSTR lpszSubKey,
2183 LPSTR lpszData,
2184 LPDWORD lpcbData
2186 HKEY xhkey;
2187 DWORD ret,lpdwType;
2189 dprintf_reg(stddeb,"RegQueryValue32A(%x,%s,%p,%ld)\n",
2190 hkey,lpszSubKey,lpszData,
2191 lpcbData?*lpcbData:0
2194 /* only open subkey, if we really do descend */
2195 if (lpszSubKey && *lpszSubKey) {
2196 ret = RegOpenKey16(hkey,lpszSubKey,&xhkey);
2197 if (ret!=ERROR_SUCCESS)
2198 return ret;
2199 } else
2200 xhkey = hkey;
2202 lpdwType = REG_SZ;
2203 ret = RegQueryValueEx32A(
2204 xhkey,
2205 NULL, /* lpszValueName NULL -> compat */
2206 NULL, /* lpdwReserved, must be NULL */
2207 &lpdwType,
2208 (LPBYTE)lpszData,
2209 lpcbData
2211 if (xhkey!=hkey)
2212 RegCloseKey(xhkey);
2213 return ret;
2216 /* RegQueryValue [SHELL.6] [KERNEL.224] */
2217 DWORD RegQueryValue16(
2218 HKEY hkey,
2219 LPSTR lpszSubKey,
2220 LPSTR lpszData,
2221 LPDWORD lpcbData
2223 dprintf_reg(stddeb,"RegQueryValue16(%x,%s,%p,%ld)\n",
2224 hkey,lpszSubKey,lpszData,lpcbData?*lpcbData:0
2226 /* HACK: the 16bit RegQueryValue doesn't handle selectorblocks
2227 * anyway, so we just mask out the high 16 bit.
2228 * (this (not so much incidently;) hopefully fixes Aldus FH4)
2230 if (lpcbData)
2231 *lpcbData &= 0xFFFF;
2232 return RegQueryValue32A(hkey,lpszSubKey,lpszData,lpcbData);
2236 * Setting values of Registry keys
2238 * Callpath:
2239 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
2240 * RegSetValue32W -> RegSetValueEx32W
2243 /* RegSetValueExW [ADVAPI32.170] */
2244 DWORD RegSetValueEx32W(
2245 HKEY hkey,
2246 LPWSTR lpszValueName,
2247 DWORD dwReserved,
2248 DWORD dwType,
2249 LPBYTE lpbData,
2250 DWORD cbData
2252 LPKEYSTRUCT lpkey;
2253 int i;
2255 dprintf_reg(stddeb,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
2256 hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData
2258 /* we no longer care about the lpbData type here... */
2259 lpkey = lookup_hkey(hkey);
2260 if (!lpkey)
2261 return SHELL_ERROR_BADKEY;
2263 lpkey->flags |= REG_OPTION_TAINTED;
2265 if (lpszValueName==NULL) {
2266 for (i=0;i<lpkey->nrofvalues;i++)
2267 if (lpkey->values[i].name==NULL)
2268 break;
2269 } else {
2270 for (i=0;i<lpkey->nrofvalues;i++)
2271 if ( lpkey->values[i].name &&
2272 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
2274 break;
2276 if (i==lpkey->nrofvalues) {
2277 lpkey->values = (LPKEYVALUE)xrealloc(
2278 lpkey->values,
2279 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
2281 lpkey->nrofvalues++;
2282 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
2284 if (lpkey->values[i].name==NULL)
2285 if (lpszValueName)
2286 lpkey->values[i].name = strdupW(lpszValueName);
2287 else
2288 lpkey->values[i].name = NULL;
2289 lpkey->values[i].len = cbData;
2290 lpkey->values[i].type = dwType;
2291 if (lpkey->values[i].data !=NULL)
2292 free(lpkey->values[i].data);
2293 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
2294 lpkey->values[i].lastmodified = time(NULL);
2295 memcpy(lpkey->values[i].data,lpbData,cbData);
2296 return SHELL_ERROR_SUCCESS;
2299 /* RegSetValueExA [ADVAPI32.169] */
2300 DWORD RegSetValueEx32A(
2301 HKEY hkey,
2302 LPSTR lpszValueName,
2303 DWORD dwReserved,
2304 DWORD dwType,
2305 LPBYTE lpbData,
2306 DWORD cbData
2308 LPBYTE buf;
2309 LPWSTR lpszValueNameW;
2310 DWORD ret;
2312 dprintf_reg(stddeb,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
2313 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2315 if ((1<<dwType) & UNICONVMASK) {
2316 buf=(LPBYTE)strdupA2W(lpbData);
2317 cbData=2*strlen(lpbData)+2;
2318 } else
2319 buf=lpbData;
2320 if (lpszValueName)
2321 lpszValueNameW = strdupA2W(lpszValueName);
2322 else
2323 lpszValueNameW = NULL;
2324 ret=RegSetValueEx32W(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
2325 if (lpszValueNameW)
2326 free(lpszValueNameW);
2327 if (buf!=lpbData)
2328 free(buf);
2329 return ret;
2332 /* RegSetValueEx [KERNEL.226] */
2333 DWORD RegSetValueEx16(
2334 HKEY hkey,
2335 LPSTR lpszValueName,
2336 DWORD dwReserved,
2337 DWORD dwType,
2338 LPBYTE lpbData,
2339 DWORD cbData
2341 dprintf_reg(stddeb,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2342 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2344 return RegSetValueEx32A(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData);
2347 /* RegSetValueW [ADVAPI32.171] */
2348 DWORD RegSetValue32W(
2349 HKEY hkey,
2350 LPCWSTR lpszSubKey,
2351 DWORD dwType,
2352 LPCWSTR lpszData,
2353 DWORD cbData
2355 HKEY xhkey;
2356 DWORD ret;
2358 dprintf_reg(stddeb,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2359 hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
2361 if (lpszSubKey && *lpszSubKey) {
2362 ret=RegCreateKey32W(hkey,lpszSubKey,&xhkey);
2363 if (ret!=ERROR_SUCCESS)
2364 return ret;
2365 } else
2366 xhkey=hkey;
2367 if (dwType!=REG_SZ) {
2368 fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
2369 dwType=REG_SZ;
2371 if (cbData!=2*lstrlen32W(lpszData)+2) {
2372 dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2373 cbData,W2C(lpszData,0),2*lstrlen32W(lpszData)+2
2375 cbData=2*lstrlen32W(lpszData)+2;
2377 ret=RegSetValueEx32W(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2378 if (hkey!=xhkey)
2379 RegCloseKey(xhkey);
2380 return ret;
2383 /* RegSetValueA [ADVAPI32.168] */
2384 DWORD RegSetValue32A(
2385 HKEY hkey,
2386 LPCSTR lpszSubKey,
2387 DWORD dwType,
2388 LPCSTR lpszData,
2389 DWORD cbData
2391 DWORD ret;
2392 HKEY xhkey;
2394 dprintf_reg(stddeb,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2395 hkey,lpszSubKey,dwType,lpszData,cbData
2397 if (lpszSubKey && *lpszSubKey) {
2398 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
2399 if (ret!=ERROR_SUCCESS)
2400 return ret;
2401 } else
2402 xhkey=hkey;
2404 if (dwType!=REG_SZ) {
2405 dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType);
2406 dwType=REG_SZ;
2408 if (cbData!=strlen(lpszData)+1)
2409 cbData=strlen(lpszData)+1;
2410 ret=RegSetValueEx32A(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2411 if (xhkey!=hkey)
2412 RegCloseKey(xhkey);
2413 return ret;
2416 /* RegSetValue [KERNEL.221] [SHELL.5] */
2417 DWORD RegSetValue16(
2418 HKEY hkey,
2419 LPCSTR lpszSubKey,
2420 DWORD dwType,
2421 LPCSTR lpszData,
2422 DWORD cbData
2424 DWORD ret;
2425 dprintf_reg(stddeb,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2426 hkey,lpszSubKey,dwType,lpszData,cbData
2428 ret=RegSetValue32A(hkey,lpszSubKey,dwType,lpszData,cbData);
2429 return ret;
2433 * Key Enumeration
2435 * Callpath:
2436 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2437 * RegEnumKey32W -> RegEnumKeyEx32W
2440 /* RegEnumKeyExW [ADVAPI32.139] */
2441 DWORD RegEnumKeyEx32W(
2442 HKEY hkey,
2443 DWORD iSubkey,
2444 LPWSTR lpszName,
2445 LPDWORD lpcchName,
2446 LPDWORD lpdwReserved,
2447 LPWSTR lpszClass,
2448 LPDWORD lpcchClass,
2449 FILETIME *ft
2451 LPKEYSTRUCT lpkey,lpxkey;
2453 dprintf_reg(stddeb,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2454 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2456 lpkey=lookup_hkey(hkey);
2457 if (!lpkey)
2458 return SHELL_ERROR_BADKEY;
2459 if (!lpkey->nextsub)
2460 return ERROR_NO_MORE_ITEMS;
2461 lpxkey=lpkey->nextsub;
2462 while (iSubkey && lpxkey) {
2463 iSubkey--;
2464 lpxkey=lpxkey->next;
2466 if (iSubkey || !lpxkey)
2467 return ERROR_NO_MORE_ITEMS;
2468 if (2*lstrlen32W(lpxkey->keyname)+2>*lpcchName)
2469 return ERROR_MORE_DATA;
2470 memcpy(lpszName,lpxkey->keyname,lstrlen32W(lpxkey->keyname)*2+2);
2471 if (lpszClass) {
2472 /* what should we write into it? */
2473 *lpszClass = 0;
2474 *lpcchClass = 2;
2476 return ERROR_SUCCESS;
2480 /* RegEnumKeyW [ADVAPI32.140] */
2481 DWORD RegEnumKey32W(
2482 HKEY hkey,
2483 DWORD iSubkey,
2484 LPWSTR lpszName,
2485 DWORD lpcchName
2487 FILETIME ft;
2489 dprintf_reg(stddeb,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2490 hkey,iSubkey,lpszName,lpcchName
2492 return RegEnumKeyEx32W(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
2494 /* RegEnumKeyExA [ADVAPI32.138] */
2495 DWORD RegEnumKeyEx32A(
2496 HKEY hkey,
2497 DWORD iSubkey,
2498 LPSTR lpszName,
2499 LPDWORD lpcchName,
2500 LPDWORD lpdwReserved,
2501 LPSTR lpszClass,
2502 LPDWORD lpcchClass,
2503 FILETIME *ft
2505 DWORD ret,lpcchNameW,lpcchClassW;
2506 LPWSTR lpszNameW,lpszClassW;
2509 dprintf_reg(stddeb,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2510 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2512 if (lpszName) {
2513 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
2514 lpcchNameW = *lpcchName*2;
2515 } else {
2516 lpszNameW = NULL;
2517 lpcchNameW = 0;
2519 if (lpszClass) {
2520 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
2521 lpcchClassW = *lpcchClass*2;
2522 } else {
2523 lpszClassW =0;
2524 lpcchClassW=0;
2526 ret=RegEnumKeyEx32W(
2527 hkey,
2528 iSubkey,
2529 lpszNameW,
2530 &lpcchNameW,
2531 lpdwReserved,
2532 lpszClassW,
2533 &lpcchClassW,
2536 if (ret==ERROR_SUCCESS) {
2537 lstrcpyWtoA(lpszName,lpszNameW);
2538 *lpcchName=strlen(lpszName);
2539 if (lpszClassW) {
2540 lstrcpyWtoA(lpszClass,lpszClassW);
2541 *lpcchClass=strlen(lpszClass);
2544 if (lpszNameW)
2545 free(lpszNameW);
2546 if (lpszClassW)
2547 free(lpszClassW);
2548 return ret;
2551 /* RegEnumKeyA [ADVAPI32.137] */
2552 DWORD RegEnumKey32A(
2553 HKEY hkey,
2554 DWORD iSubkey,
2555 LPSTR lpszName,
2556 DWORD lpcchName
2558 FILETIME ft;
2560 dprintf_reg(stddeb,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2561 hkey,iSubkey,lpszName,lpcchName
2563 return RegEnumKeyEx32A(
2564 hkey,
2565 iSubkey,
2566 lpszName,
2567 &lpcchName,
2568 NULL,
2569 NULL,
2570 NULL,
2575 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2576 DWORD RegEnumKey16(
2577 HKEY hkey,
2578 DWORD iSubkey,
2579 LPSTR lpszName,
2580 DWORD lpcchName
2582 dprintf_reg(stddeb,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2583 hkey,iSubkey,lpszName,lpcchName
2585 return RegEnumKey32A(hkey,iSubkey,lpszName,lpcchName);
2589 * Enumerate Registry Values
2591 * Callpath:
2592 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2595 /* RegEnumValueW [ADVAPI32.142] */
2596 DWORD RegEnumValue32W(
2597 HKEY hkey,
2598 DWORD iValue,
2599 LPWSTR lpszValue,
2600 LPDWORD lpcchValue,
2601 LPDWORD lpdReserved,
2602 LPDWORD lpdwType,
2603 LPBYTE lpbData,
2604 LPDWORD lpcbData
2606 LPKEYSTRUCT lpkey;
2607 LPKEYVALUE val;
2609 dprintf_reg(stddeb,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2610 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2612 lpkey = lookup_hkey(hkey);
2613 if (!lpkey)
2614 return SHELL_ERROR_BADKEY;
2615 if (lpkey->nrofvalues<=iValue)
2616 return ERROR_NO_MORE_ITEMS;
2617 val = lpkey->values+iValue;
2619 if (val->name) {
2620 if (lstrlen32W(val->name)*2+2>*lpcchValue) {
2621 *lpcchValue = lstrlen32W(val->name)*2+2;
2622 return ERROR_MORE_DATA;
2624 memcpy(lpszValue,val->name,2*lstrlen32W(val->name)+2);
2625 *lpcchValue=lstrlen32W(val->name)*2+2;
2626 } else {
2627 /* how to handle NULL value? */
2628 *lpszValue = 0;
2629 *lpcchValue = 2;
2631 *lpdwType=val->type;
2632 if (lpbData) {
2633 if (val->len>*lpcbData)
2634 return ERROR_MORE_DATA;
2635 memcpy(lpbData,val->data,val->len);
2636 *lpcbData = val->len;
2638 return SHELL_ERROR_SUCCESS;
2641 /* RegEnumValueA [ADVAPI32.141] */
2642 DWORD RegEnumValue32A(
2643 HKEY hkey,
2644 DWORD iValue,
2645 LPSTR lpszValue,
2646 LPDWORD lpcchValue,
2647 LPDWORD lpdReserved,
2648 LPDWORD lpdwType,
2649 LPBYTE lpbData,
2650 LPDWORD lpcbData
2652 LPWSTR lpszValueW;
2653 LPBYTE lpbDataW;
2654 DWORD ret,lpcbDataW;
2656 dprintf_reg(stddeb,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2657 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2660 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
2661 if (lpbData) {
2662 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
2663 lpcbDataW = *lpcbData*2;
2664 } else
2665 lpbDataW = NULL;
2666 ret=RegEnumValue32W(
2667 hkey,
2668 iValue,
2669 lpszValueW,
2670 lpcchValue,
2671 lpdReserved,
2672 lpdwType,
2673 lpbDataW,
2674 &lpcbDataW
2677 if (ret==ERROR_SUCCESS) {
2678 lstrcpyWtoA(lpszValue,lpszValueW);
2679 if (lpbData) {
2680 if ((1<<*lpdwType) & UNICONVMASK) {
2681 lstrcpyWtoA(lpbData,(LPWSTR)lpbDataW);
2682 } else {
2683 if (lpcbDataW > *lpcbData)
2684 ret = ERROR_MORE_DATA;
2685 else
2686 memcpy(lpbData,lpbDataW,lpcbDataW);
2688 *lpcbData = lpcbDataW;
2691 if (lpbDataW)
2692 free(lpbDataW);
2693 if (lpszValueW)
2694 free(lpszValueW);
2695 return ret;
2698 /* RegEnumValue [KERNEL.223] */
2699 DWORD RegEnumValue16(
2700 HKEY hkey,
2701 DWORD iValue,
2702 LPSTR lpszValue,
2703 LPDWORD lpcchValue,
2704 LPDWORD lpdReserved,
2705 LPDWORD lpdwType,
2706 LPBYTE lpbData,
2707 LPDWORD lpcbData
2709 dprintf_reg(stddeb,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2710 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2712 return RegEnumValue32A(
2713 hkey,
2714 iValue,
2715 lpszValue,
2716 lpcchValue,
2717 lpdReserved,
2718 lpdwType,
2719 lpbData,
2720 lpcbData
2725 * Close registry key
2727 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2728 DWORD RegCloseKey(HKEY hkey) {
2729 dprintf_reg(stddeb,"RegCloseKey(%x)\n",hkey);
2730 remove_handle(hkey);
2731 return ERROR_SUCCESS;
2734 * Delete registry key
2736 * Callpath:
2737 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2739 /* RegDeleteKeyW [ADVAPI32.134] */
2740 DWORD RegDeleteKey32W(HKEY hkey,LPWSTR lpszSubKey) {
2741 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2742 LPWSTR *wps;
2743 int wpc,i;
2745 dprintf_reg(stddeb,"RegDeleteKey32W(%x,%s)\n",
2746 hkey,W2C(lpszSubKey,0)
2748 lpNextKey = lookup_hkey(hkey);
2749 if (!lpNextKey)
2750 return SHELL_ERROR_BADKEY;
2751 /* we need to know the previous key in the hier. */
2752 if (!lpszSubKey || !*lpszSubKey)
2753 return SHELL_ERROR_BADKEY;
2754 split_keypath(lpszSubKey,&wps,&wpc);
2755 i = 0;
2756 lpxkey = lpNextKey;
2757 while (i<wpc-1) {
2758 lpxkey=lpNextKey->nextsub;
2759 while (lpxkey) {
2760 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2761 break;
2762 lpxkey=lpxkey->next;
2764 if (!lpxkey) {
2765 FREE_KEY_PATH;
2766 /* not found is success */
2767 return SHELL_ERROR_SUCCESS;
2769 i++;
2770 lpNextKey = lpxkey;
2772 lpxkey = lpNextKey->nextsub;
2773 lplpPrevKey = &(lpNextKey->nextsub);
2774 while (lpxkey) {
2775 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2776 break;
2777 lplpPrevKey = &(lpxkey->next);
2778 lpxkey = lpxkey->next;
2780 if (!lpxkey)
2781 return SHELL_ERROR_SUCCESS;
2782 if (lpxkey->nextsub)
2783 return SHELL_ERROR_CANTWRITE;
2784 *lplpPrevKey = lpxkey->next;
2785 free(lpxkey->keyname);
2786 if (lpxkey->class)
2787 free(lpxkey->class);
2788 if (lpxkey->values)
2789 free(lpxkey->values);
2790 free(lpxkey);
2791 FREE_KEY_PATH;
2792 return SHELL_ERROR_SUCCESS;
2795 /* RegDeleteKeyA [ADVAPI32.133] */
2796 DWORD RegDeleteKey32A(HKEY hkey,LPCSTR lpszSubKey) {
2797 LPWSTR lpszSubKeyW;
2798 DWORD ret;
2800 dprintf_reg(stddeb,"RegDeleteKey32A(%x,%s)\n",
2801 hkey,lpszSubKey
2803 lpszSubKeyW=strdupA2W(lpszSubKey);
2804 ret=RegDeleteKey32W(hkey,lpszSubKeyW);
2805 free(lpszSubKeyW);
2806 return ret;
2809 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2810 DWORD RegDeleteKey16(HKEY hkey,LPCSTR lpszSubKey) {
2811 dprintf_reg(stddeb,"RegDeleteKey16(%x,%s)\n",
2812 hkey,lpszSubKey
2814 return RegDeleteKey32A(hkey,lpszSubKey);
2818 * Delete registry value
2820 * Callpath:
2821 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2823 /* RegDeleteValueW [ADVAPI32.136] */
2824 DWORD RegDeleteValue32W(HKEY hkey,LPWSTR lpszValue) {
2825 DWORD i;
2826 LPKEYSTRUCT lpkey;
2827 LPKEYVALUE val;
2829 dprintf_reg(stddeb,"RegDeleteValue32W(%x,%s)\n",
2830 hkey,W2C(lpszValue,0)
2832 lpkey=lookup_hkey(hkey);
2833 if (!lpkey)
2834 return SHELL_ERROR_BADKEY;
2835 if (lpszValue) {
2836 for (i=0;i<lpkey->nrofvalues;i++)
2837 if ( lpkey->values[i].name &&
2838 !lstrcmp32W(lpkey->values[i].name,lpszValue)
2840 break;
2841 } else {
2842 for (i=0;i<lpkey->nrofvalues;i++)
2843 if (lpkey->values[i].name==NULL)
2844 break;
2846 if (i==lpkey->nrofvalues)
2847 return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */
2848 val = lpkey->values+i;
2849 if (val->name) free(val->name);
2850 if (val->data) free(val->data);
2851 memcpy(
2852 lpkey->values+i,
2853 lpkey->values+i+1,
2854 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
2856 lpkey->values = (LPKEYVALUE)xrealloc(
2857 lpkey->values,
2858 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
2860 lpkey->nrofvalues--;
2861 return SHELL_ERROR_SUCCESS;
2864 /* RegDeleteValueA [ADVAPI32.135] */
2865 DWORD RegDeleteValue32A(HKEY hkey,LPSTR lpszValue) {
2866 LPWSTR lpszValueW;
2867 DWORD ret;
2869 dprintf_reg( stddeb, "RegDeleteValue32A(%x,%s)\n", hkey,lpszValue );
2870 if (lpszValue)
2871 lpszValueW=strdupA2W(lpszValue);
2872 else
2873 lpszValueW=NULL;
2874 ret=RegDeleteValue32W(hkey,lpszValueW);
2875 if (lpszValueW)
2876 free(lpszValueW);
2877 return ret;
2880 /* RegDeleteValue [KERNEL.222] */
2881 DWORD RegDeleteValue16(HKEY hkey,LPSTR lpszValue) {
2882 dprintf_reg( stddeb,"RegDeleteValue16(%x,%s)\n", hkey,lpszValue );
2883 return RegDeleteValue32A(hkey,lpszValue);
2886 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2887 DWORD RegFlushKey(HKEY hkey) {
2888 dprintf_reg(stddeb,"RegFlushKey(%x), STUB.\n",hkey);
2889 return SHELL_ERROR_SUCCESS;
2892 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2894 /* RegQueryInfoKeyW [ADVAPI32.153] */
2895 DWORD RegQueryInfoKey32W(
2896 HKEY hkey,
2897 LPWSTR lpszClass,
2898 LPDWORD lpcchClass,
2899 LPDWORD lpdwReserved,
2900 LPDWORD lpcSubKeys,
2901 LPDWORD lpcchMaxSubkey,
2902 LPDWORD lpcchMaxClass,
2903 LPDWORD lpcValues,
2904 LPDWORD lpcchMaxValueName,
2905 LPDWORD lpccbMaxValueData,
2906 LPDWORD lpcbSecurityDescriptor,
2907 FILETIME *ft
2909 LPKEYSTRUCT lpkey,lpxkey;
2910 int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata;
2911 int i;
2913 dprintf_reg(stddeb,"RegQueryInfoKey32W(%x,......)\n",hkey);
2914 lpkey=lookup_hkey(hkey);
2915 if (!lpkey)
2916 return SHELL_ERROR_BADKEY;
2917 if (lpszClass) {
2918 if (lpkey->class) {
2919 if (lstrlen32W(lpkey->class)*2+2>*lpcchClass) {
2920 *lpcchClass=lstrlen32W(lpkey->class)*2;
2921 return ERROR_MORE_DATA;
2923 *lpcchClass=lstrlen32W(lpkey->class)*2;
2924 memcpy(lpszClass,lpkey->class,lstrlen32W(lpkey->class));
2925 } else {
2926 *lpszClass = 0;
2927 *lpcchClass = 0;
2929 } else {
2930 if (lpcchClass)
2931 *lpcchClass = lstrlen32W(lpkey->class)*2;
2933 lpxkey=lpkey->nextsub;
2934 nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
2935 while (lpxkey) {
2936 nrofkeys++;
2937 if (lstrlen32W(lpxkey->keyname)>maxsubkey)
2938 maxsubkey=lstrlen32W(lpxkey->keyname);
2939 if (lpxkey->class && lstrlen32W(lpxkey->class)>maxclass)
2940 maxclass=lstrlen32W(lpxkey->class);
2941 if (lpxkey->nrofvalues>maxvalues)
2942 maxvalues=lpxkey->nrofvalues;
2943 for (i=0;i<lpxkey->nrofvalues;i++) {
2944 LPKEYVALUE val=lpxkey->values+i;
2946 if (val->name && lstrlen32W(val->name)>maxvname)
2947 maxvname=lstrlen32W(val->name);
2948 if (val->len>maxvdata)
2949 maxvdata=val->len;
2951 lpxkey=lpxkey->next;
2953 if (!maxclass) maxclass = 1;
2954 if (!maxvname) maxvname = 1;
2955 if (lpcSubKeys)
2956 *lpcSubKeys = nrofkeys;
2957 if (lpcchMaxSubkey)
2958 *lpcchMaxSubkey = maxsubkey*2;
2959 if (lpcchMaxClass)
2960 *lpcchMaxClass = maxclass*2;
2961 if (lpcValues)
2962 *lpcValues = maxvalues;
2963 if (lpcchMaxValueName)
2964 *lpcchMaxValueName= maxvname;
2965 if (lpccbMaxValueData)
2966 *lpccbMaxValueData= maxvdata;
2967 return SHELL_ERROR_SUCCESS;
2970 /* RegQueryInfoKeyA [ADVAPI32.152] */
2971 DWORD RegQueryInfoKey32A(
2972 HKEY hkey,
2973 LPSTR lpszClass,
2974 LPDWORD lpcchClass,
2975 LPDWORD lpdwReserved,
2976 LPDWORD lpcSubKeys,
2977 LPDWORD lpcchMaxSubkey,
2978 LPDWORD lpcchMaxClass,
2979 LPDWORD lpcValues,
2980 LPDWORD lpcchMaxValueName,
2981 LPDWORD lpccbMaxValueData,
2982 LPDWORD lpcbSecurityDescriptor,
2983 FILETIME *ft
2985 LPWSTR lpszClassW;
2986 DWORD ret;
2988 dprintf_reg(stddeb,"RegQueryInfoKey32A(%x,......)\n",hkey);
2989 if (lpszClass) {
2990 *lpcchClass*= 2;
2991 lpszClassW = (LPWSTR)xmalloc(*lpcchClass);
2993 } else
2994 lpszClassW = NULL;
2995 ret=RegQueryInfoKey32W(
2996 hkey,
2997 lpszClassW,
2998 lpcchClass,
2999 lpdwReserved,
3000 lpcSubKeys,
3001 lpcchMaxSubkey,
3002 lpcchMaxClass,
3003 lpcValues,
3004 lpcchMaxValueName,
3005 lpccbMaxValueData,
3006 lpcbSecurityDescriptor,
3009 if (ret==ERROR_SUCCESS)
3010 lstrcpyWtoA(lpszClass,lpszClassW);
3011 if (lpcchClass)
3012 *lpcchClass/=2;
3013 if (lpcchMaxSubkey)
3014 *lpcchMaxSubkey/=2;
3015 if (lpcchMaxClass)
3016 *lpcchMaxClass/=2;
3017 if (lpcchMaxValueName)
3018 *lpcchMaxValueName/=2;
3019 if (lpszClassW)
3020 free(lpszClassW);
3021 return ret;