4 * Copyright 1996 Marcus Meissner
14 #include <sys/types.h>
15 #include <sys/fcntl.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 {
71 static int nrofopenhandles=0;
72 static int currenthandle=1;
75 add_handle(HKEY hkey,LPKEYSTRUCT lpkey,REGSAM accessmask) {
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;
96 get_handle(HKEY hkey) {
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);
107 remove_handle(HKEY hkey) {
110 for (i=0;i<nrofopenhandles;i++)
111 if (openhandles[i].hkey==hkey)
113 if (i==nrofopenhandles) {
114 dprintf_reg(stddeb,"remove_handle:Didn't find handle %08x?\n",hkey);
117 memcpy( openhandles+i,
119 sizeof(struct openhandle)*(nrofopenhandles-i-1)
121 openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
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)
131 W2C(LPCWSTR x,int sub) {
132 static LPSTR unicodedebug[2]={NULL,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];
143 lookup_hkey(HKEY hkey) {
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;
155 case HKEY_PERFORMANCE_DATA:
156 return key_performance_data;
159 case HKEY_CURRENT_CONFIG:
160 return key_current_config;
162 dprintf_reg(stddeb,"lookup_hkey(%lx), special key!\n",
165 return get_handle(hkey);
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
177 split_keypath(LPCWSTR wp,LPWSTR **wpv,int *wpc) {
183 for (i=0;ws[i];i++) {
190 *wpv = (LPWSTR*)xmalloc(sizeof(LPWSTR)*(*wpc+2));
198 #define FREE_KEY_PATH free(wps[0]);free(wps);
201 * Shell initialisation, allocates keys.
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");
218 key_classes_root = lookup_hkey(cl_r_hkey);
220 ADD_ROOT_KEY(key_users);
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)
229 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
230 RegCloseKey(c_u_hkey);
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);
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);
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.
255 * "WINE REGISTRY Version %d"
259 * valuename=lastmodified,type,data
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.)
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
276 _save_check_tainted(LPKEYSTRUCT lpkey) {
281 if (lpkey->flags & REG_OPTION_TAINTED)
286 if (_save_check_tainted(lpkey->nextsub)) {
287 lpkey->flags |= REG_OPTION_TAINTED;
296 _save_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
309 if (escapeeq && *s=='=')
312 fputc(*s,F); /* if \\ than put it twice. */
314 fprintf(F,"\\u%04x",*((unsigned short*)s));
322 _savesubkey(FILE *F,LPKEYSTRUCT lpkey,int level,int all) {
328 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
329 (all || (lpxkey->flags & REG_OPTION_TAINTED))
331 for (tabs=level;tabs--;)
333 _save_USTRING(F,lpxkey->keyname,1);
335 for (i=0;i<lpxkey->nrofvalues;i++) {
336 LPKEYVALUE val=lpxkey->values+i;
338 for (tabs=level+1;tabs--;)
340 _save_USTRING(F,val->name,0);
342 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
343 if ((1<<val->type) & UNICONVMASK)
344 _save_USTRING(F,(LPWSTR)val->data,0);
346 for (j=0;j<val->len;j++)
347 fprintf(F,"%02x",*((unsigned char*)val->data+j));
350 /* descend recursively */
351 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
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);
367 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
372 fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
377 if (!_savesubreg(F,lpkey,all)) {
380 fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
387 SHELL_SaveRegistry() {
395 if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) {
401 if ( (ERROR_SUCCESS!=RegQueryValueEx32A(
413 if (strcasecmp(buf,"yes"))
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);
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);
431 fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
434 /************************ LOAD Registry Function ****************************/
437 _find_or_add_key(LPKEYSTRUCT lpkey,LPWSTR keyname) {
438 LPKEYSTRUCT lpxkey,*lplpkey;
440 lplpkey= &(lpkey->nextsub);
443 if (!strcmpW(lpxkey->keyname,keyname))
445 lplpkey = &(lpxkey->next);
449 *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
451 memset(lpxkey,'\0',sizeof(KEYSTRUCT));
452 lpxkey->keyname = keyname;
460 LPKEYSTRUCT lpkey,LPWSTR name,DWORD type,LPBYTE data,DWORD len,
466 for (i=0;i<lpkey->nrofvalues;i++) {
472 if ( val->name!=NULL &&
473 !strcmpW(val->name,name)
478 if (i==lpkey->nrofvalues) {
479 lpkey->values = xrealloc(
481 (++lpkey->nrofvalues)*sizeof(KEYVALUE)
484 memset(val,'\0',sizeof(KEYVALUE));
490 if (val->lastmodified<lastmodified) {
491 val->lastmodified=lastmodified;
502 /* reads a line including dynamically enlarging the readbuffer and throwing
506 _wine_read_line(FILE *F,char **buf,int *len) {
515 s=fgets(curread,mylen,F);
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
532 /* throw away comments */
533 if (**buf=='#' || **buf==';') {
538 if (s) /* got end of line */
544 /* converts a char* into a UNICODE string (up to a special char)
545 * and returns the position exactly after that string
548 _wine_read_USTRING(char *buf,LPWSTR *str) {
552 /* read up to "=" or "\0" or "\n" */
555 /* empty string is the win3.1 default value(NULL)*/
559 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
561 while (*s && (*s!='\n') && (*s!='=')) {
563 *ws++=*((unsigned char*)s++);
572 fprintf(stderr,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
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);
584 *ws++ =(unsigned short)wc;
590 *str = strdupW(*str);
597 FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen,int optflag
604 lpkey->flags |= optflag;
606 /* good. we already got a line here ... so parse it */
616 fprintf(stderr,"_load_subkey:Got a subhierarchy without resp. key?\n");
619 _wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag);
622 /* let the caller handle this line */
623 if (i<level || **buf=='\0')
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 */
633 lpxkey=_find_or_add_key(lpkey,name);
636 int len,lastmodified,type;
639 fprintf(stderr,"_wine_load_subkey:unexpected character: %c\n",*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);
650 if ((1<<type) & UNICONVMASK) {
651 s=_wine_read_USTRING(s,(LPWSTR*)&data);
653 len = strlenW((LPWSTR)data)*2+2;
658 data = (LPBYTE)xmalloc(len+1);
659 for (i=0;i<len;i++) {
661 if (*s>='0' && *s<='9')
663 if (*s>='a' && *s<='f')
665 if (*s>='A' && *s<='F')
668 if (*s>='0' && *s<='9')
670 if (*s>='a' && *s<='f')
672 if (*s>='A' && *s<='F')
677 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
680 /* read the next line */
681 if (!_wine_read_line(F,buf,buflen))
688 _wine_loadsubreg(FILE *F,LPKEYSTRUCT lpkey,int optflag) {
693 buf=xmalloc(10);buflen=10;
694 if (!_wine_read_line(F,&buf,&buflen)) {
698 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
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);
707 if (!_wine_read_line(F,&buf,&buflen)) {
711 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
720 _wine_loadreg(LPKEYSTRUCT lpkey,char *fn,int optflag) {
725 dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n",
730 if (!_wine_loadsubreg(F,lpkey,optflag)) {
739 _copy_registry(LPKEYSTRUCT from,LPKEYSTRUCT to) {
746 lpxkey = _find_or_add_key(to,strdupW(from->keyname));
748 for (j=0;j<from->nrofvalues;j++) {
752 valfrom = from->values+j;
754 if (name) name=strdupW(name);
755 data=(LPBYTE)malloc(valfrom->len);
756 memcpy(data,valfrom->data,valfrom->len);
764 valfrom->lastmodified
767 _copy_registry(from,lpxkey);
772 /* WINDOWS 95 REGISTRY LOADER */
774 * Structure of a win95 registry database.
778 * 8 : DWORD offset_of_RGDB_part
779 * 0C..1F: ? (someone fill in please)
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)
817 * 00: DWORD nextkeyoffset - offset to the next disk key structure
818 * 08: WORD nrLS - low significant part of NR
819 * 0A: WORD nrHS - high significant part of NR
820 * 0C: DWORD bytesused - bytes used in this structure.
821 * 10: WORD name_len - length of name in bytes. without \0
822 * 12: WORD nr_of_values - number of values.
823 * 14: char name[name_len] - name string. No \0.
824 * 14+name_len: disk values
825 * nextkeyoffset: ... next disk key
828 * 00: DWORD type - value type (hmm, could be WORD too)
829 * 04: DWORD - unknown, usually 0
830 * 08: WORD namelen - length of Name. 0 means name=NULL
831 * 0C: WORD datalen - length of Data.
832 * 10: char name[namelen] - name, no \0
833 * 10+namelen: BYTE data[datalen] - data, without \0 if string
834 * 10+namelen+datalen: next values or disk key
836 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
837 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
838 * structure) and reading another RGDB_section.
839 * repeat until end of file.
841 * FIXME: this description needs some serious help, yes.
844 struct _w95keyvalue {
846 unsigned short datalen;
856 struct _w95keyvalue *values;
857 unsigned long dkeaddr;
862 struct _w95key *prevlvl;
863 struct _w95key *nextsub;
864 struct _w95key *next;
867 /* fast lookup table dkeaddr->nr */
869 unsigned long dkeaddr;
875 _w95_walk_tree(LPKEYSTRUCT lpkey,struct _w95key *key) {
881 if (key->name == NULL) {
882 fprintf(stderr,"key with dkeaddr %lx not loaded, skipping hierarchy\n",
888 lpxkey=_find_or_add_key(lpkey,strdupA2W(key->name));
890 if (key->nrofvals<0) {
891 /* shouldn't happen */
892 fprintf(stderr,"key %s already processed!\n",key->name);
896 for (i=0;i<key->nrofvals;i++) {
900 name = strdupA2W(key->values[i].name);
901 if (!*name) name = NULL;
902 free(key->values[i].name);
904 len = key->values[i].datalen;
905 data = key->values[i].data;
906 if ((1<<key->values[i].type) & UNICONVMASK) {
907 data = (BYTE*)strdupA2W(data);
908 len = strlenW((LPWSTR)data)*2+2;
909 free(key->values[i].data);
917 key->values[i].lastmodified
924 key->nrofvals=-key->nrofvals-1;
925 _w95_walk_tree(lpxkey,key->nextsub);
930 /* small helper function to adjust address offset (dkeaddrs) */
932 _w95_adj_da(unsigned long dkeaddr) {
933 if ((dkeaddr&0xFFF)<0x018) {
936 diff=0x1C-(dkeaddr&0xFFF);
939 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
940 /* readjust to 0x000,
941 * but ONLY if we are >0x1000 already
943 if (dkeaddr & ~0xFFF)
944 return dkeaddr & ~0xFFF;
950 _w95dkecomp(struct _w95nr2da *a,struct _w95nr2da *b){return a->dkeaddr-b->dkeaddr;}
952 static struct _w95key*
953 _w95dkelookup(unsigned long dkeaddr,int n,struct _w95nr2da *nr2da,struct _w95key *keys) {
956 if (dkeaddr == 0xFFFFFFFF)
960 dkeaddr=_w95_adj_da(dkeaddr+0x1c);
961 off = (dkeaddr-0x3c)/0x1c;
963 if (nr2da[(i+off)%n].dkeaddr == dkeaddr)
964 return keys+nr2da[(i+off)%n].nr;
965 fprintf(stderr,"search didn't found dkeaddr %lx?\n",dkeaddr);
970 _w95_loadreg(char* fn,LPKEYSTRUCT lpkey) {
971 /* Disk Key Entry structure (RGKN part) */
975 unsigned long x3;/*usually 0xFFFFFFFF */
976 unsigned long prevlvl;
977 unsigned long nextsub;
982 /* Disk Key Header structure (RGDB part) */
984 unsigned long nextkeyoff;
987 unsigned long bytesused;
988 unsigned short keynamelen;
989 unsigned short values;
992 /* disk key values or nothing */
994 /* Disk Key Value structure */
998 unsigned short valnamelen;
999 unsigned short valdatalen;
1000 /* valname, valdata */
1002 struct _w95nr2da *nr2da;
1005 int fd,lastmodified;
1007 unsigned long nr,pos,i,where,version,rgdbsection,end;
1008 struct _w95key *keys;
1010 unsigned char *data,*curdata;
1014 dprintf_reg(stddeb,"Loading Win95 registry database '%s'\n",fn);
1015 hfd=OpenFile(fn,&ofs,OF_READ);
1016 if (hfd==HFILE_ERROR)
1018 fd = FILE_GetUnixHandle(hfd);
1020 if (4!=read(fd,magic,4))
1022 if (strcmp(magic,"CREG")) {
1023 fprintf(stddeb,"%s is not a w95 registry.\n",fn);
1026 if (4!=read(fd,&version,4))
1028 if (4!=read(fd,&rgdbsection,4))
1030 if (-1==lseek(fd,0x20,SEEK_SET))
1032 if (4!=read(fd,magic,4))
1034 if (strcmp(magic,"RGKN")) {
1035 dprintf_reg(stddeb,"second IFF header not RGKN, but %s\n",magic);
1039 /* STEP 1: Keylink structures */
1040 if (-1==lseek(fd,0x40,SEEK_SET))
1045 nrofdkes = (end-where)/sizeof(struct dke);
1046 data = (char*)xmalloc(end-where);
1047 if ((end-where)!=read(fd,data,end-where))
1051 keys = (struct _w95key*)xmalloc(nrofdkes * sizeof(struct _w95key));
1052 memset(keys,'\0',nrofdkes*sizeof(struct _w95key));
1053 nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
1055 for (i=0;i<nrofdkes;i++) {
1057 unsigned long dkeaddr;
1059 pos=curdata-data+0x40;
1060 memcpy(&dke,curdata,sizeof(dke));
1061 curdata+=sizeof(dke);
1062 nr = dke.nrLS + (dke.nrMS<<8);
1064 if ((dkeaddr&0xFFF)<0x018) {
1067 diff=0x1C-(dkeaddr&0xFFF);
1069 curdata+=diff-sizeof(dke);
1070 memcpy(&dke,curdata,sizeof(dke));
1071 nr = dke.nrLS + (dke.nrMS<<8);
1072 curdata+=sizeof(dke);
1074 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1075 /* readjust to 0x000,
1076 * but ONLY if we are >0x1000 already
1078 if (dkeaddr & ~0xFFF)
1079 dkeaddr = dkeaddr & ~0xFFF;
1082 dprintf_reg(stddeb,"nr %ld exceeds nrofdkes %d, skipping.\n",nr,nrofdkes);
1085 if (keys[nr].dkeaddr) {
1087 dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[i].dkeaddr,dkeaddr);
1091 nr2da[i].dkeaddr = dkeaddr;
1093 keys[nr].dkeaddr = dkeaddr;
1094 keys[nr].x1 = dke.x1;
1095 keys[nr].x2 = dke.x2;
1096 keys[nr].x3 = dke.x3;
1097 keys[nr].prevlvl= (struct _w95key*)dke.prevlvl;
1098 keys[nr].nextsub= (struct _w95key*)dke.nextsub;
1099 keys[nr].next = (struct _w95key*)dke.next;
1103 qsort(nr2da,nrofdkes,sizeof(nr2da[0]),_w95dkecomp);
1105 /* STEP 2: keydata & values */
1106 if (-1==fstat(fd,&stbuf))
1108 end = stbuf.st_size;
1109 lastmodified = stbuf.st_mtime;
1111 if (-1==lseek(fd,rgdbsection,SEEK_SET))
1113 data = (char*)xmalloc(end-rgdbsection);
1114 if ((end-rgdbsection)!=read(fd,data,end-rgdbsection))
1118 memcpy(magic,curdata,4);
1120 if (strcmp(magic,"RGDB")) {
1121 dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
1128 struct _w95key *key,xkey;
1131 #define XREAD(whereto,len) \
1132 if ((curdata-data+len)<end) {\
1133 memcpy(whereto,curdata,len);\
1138 XREAD(&dkh,sizeof(dkh));
1139 nr = dkh.nrLS + (dkh.nrMS<<8);
1141 if (dkh.nrLS == 0xFFFF) {
1142 curdata+= dkh.nextkeyoff - bytesread;
1144 if (strcmp(magic,"RGDB")) {
1145 if ((curdata-data)<end)
1146 dprintf_reg(stddeb,"while skipping to next RGDB block found magic %s\n",magic);
1152 if (dkh.nrLS == 0xFFFE) {
1153 dprintf_reg(stddeb,"0xFFFE at %lx\n",lseek(fd,0,SEEK_CUR)-bytesread);
1156 dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
1158 memset(key,'\0',sizeof(xkey));
1162 dprintf_reg(stddeb,"key with nr=%ld has no dkeaddr?\n",nr);
1164 key->nrofvals = dkh.values;
1165 key->name = (char*)xmalloc(dkh.keynamelen+1);
1167 XREAD(key->name,dkh.keynamelen);
1168 key->name[dkh.keynamelen]=0;
1169 if (key->nrofvals) {
1170 key->values = (struct _w95keyvalue*)xmalloc(
1171 sizeof(struct _w95keyvalue)*key->nrofvals
1173 for (i=0;i<key->nrofvals;i++) {
1176 XREAD(&dkv,sizeof(dkv));
1177 key->values[i].type = dkv.type;
1178 key->values[i].name = (char*)xmalloc(
1181 key->values[i].datalen = dkv.valdatalen;
1182 key->values[i].data = (unsigned char*)xmalloc(
1185 key->values[i].x1 = dkv.x1;
1186 XREAD(key->values[i].name,dkv.valnamelen);
1187 XREAD(key->values[i].data,dkv.valdatalen);
1188 key->values[i].data[dkv.valdatalen]=0;
1189 key->values[i].name[dkv.valnamelen]=0;
1190 key->values[i].lastmodified=lastmodified;
1193 if (bytesread != dkh.nextkeyoff) {
1194 if (dkh.bytesused != bytesread)
1196 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread,dkh.nextkeyoff,
1199 curdata += dkh.nextkeyoff-bytesread;
1201 key->prevlvl = _w95dkelookup((long)key->prevlvl,nrofdkes,nr2da,keys);
1202 key->nextsub = _w95dkelookup((long)key->nextsub,nrofdkes,nr2da,keys);
1203 key->next = _w95dkelookup((long)key->next,nrofdkes,nr2da,keys);
1208 _w95_walk_tree(lpkey,keys);
1213 SHELL_LoadRegistry() {
1220 if (key_classes_root==NULL)
1223 /* Load windows 95 entries */
1224 _w95_loadreg("C:\\system.1st", key_local_machine);
1225 _w95_loadreg("system.dat", key_local_machine);
1226 _w95_loadreg("user.dat", key_users);
1228 /* FIXME: win3.1 reg.dat loader still missing */
1230 /* the global user default is loaded under HKEY_USERS\\.Default */
1231 RegCreateKey16(HKEY_USERS,".Default",&hkey);
1232 lpkey = lookup_hkey(hkey);
1233 _wine_loadreg(lpkey,SAVE_USERS_DEFAULT,0);
1235 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1236 _copy_registry(lpkey,key_current_user);
1239 /* the global machine defaults */
1240 _wine_loadreg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT,0);
1242 /* load the user saved registries */
1244 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1246 pwd=getpwuid(getuid());
1247 if (pwd!=NULL && pwd->pw_dir!=NULL) {
1248 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
1249 strcpy(fn,pwd->pw_dir);
1250 strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
1251 _wine_loadreg(key_current_user,fn,REG_OPTION_TAINTED);
1253 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
1254 strcpy(fn,pwd->pw_dir);
1255 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1256 _wine_loadreg(key_local_machine,fn,REG_OPTION_TAINTED);
1259 fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1260 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) {
1261 DWORD junk,type,len;
1265 if (( RegQueryValueEx32A(
1272 )!=ERROR_SUCCESS) ||
1275 RegSetValueEx32A(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1281 /********************* API FUNCTIONS ***************************************/
1285 * All functions are stubs to RegOpenKeyEx32W where all the
1288 * FIXME: security,options,desiredaccess,...
1291 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1292 * RegOpenKey32W -> RegOpenKeyEx32W
1295 /* RegOpenKeyExW [ADVAPI32.150] */
1296 DWORD RegOpenKeyEx32W(
1303 LPKEYSTRUCT lpNextKey,lpxkey;
1306 dprintf_reg(stddeb,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1307 (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey
1310 lpNextKey = lookup_hkey(hkey);
1312 return SHELL_ERROR_BADKEY;
1313 if (!lpszSubKey || !*lpszSubKey) {
1314 add_handle(++currenthandle,lpNextKey,samDesired);
1315 *retkey=currenthandle;
1316 return SHELL_ERROR_SUCCESS;
1318 split_keypath(lpszSubKey,&wps,&wpc);
1320 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1323 lpxkey=lpNextKey->nextsub;
1325 if (!strcmpW(wps[i],lpxkey->keyname))
1327 lpxkey=lpxkey->next;
1331 return SHELL_ERROR_BADKEY;
1336 add_handle(++currenthandle,lpxkey,samDesired);
1337 *retkey = currenthandle;
1339 return SHELL_ERROR_SUCCESS;
1342 /* RegOpenKeyW [ADVAPI32.151] */
1343 DWORD RegOpenKey32W(
1348 dprintf_reg(stddeb,"RegOpenKey32W(%lx,%s,%p)\n",
1349 (LONG)hkey,W2C(lpszSubKey,0),retkey
1351 return RegOpenKeyEx32W(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1355 /* RegOpenKeyExA [ADVAPI32.149] */
1356 DWORD RegOpenKeyEx32A(
1366 dprintf_reg(stddeb,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1367 (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey
1370 lpszSubKeyW=strdupA2W(lpszSubKey);
1373 ret=RegOpenKeyEx32W(hkey,lpszSubKeyW,dwReserved,samDesired,retkey);
1379 /* RegOpenKeyA [ADVAPI32.148] */
1380 DWORD RegOpenKey32A(
1385 dprintf_reg(stddeb,"RegOpenKey32A(%lx,%s,%p)\n",
1386 (LONG)hkey,lpszSubKey,retkey
1388 return RegOpenKeyEx32A(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1391 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1397 dprintf_reg(stddeb,"RegOpenKey16(%lx,%s,%p)\n",
1398 (LONG)hkey,lpszSubKey,retkey
1400 return RegOpenKey32A(hkey,lpszSubKey,retkey);
1406 * All those functions convert their respective
1407 * arguments and call RegCreateKeyExW at the end.
1409 * FIXME: no security,no access attrib,no optionhandling yet.
1412 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1413 * RegCreateKey32W -> RegCreateKeyEx32W
1416 /* RegCreateKeyExW [ADVAPI32.131] */
1417 DWORD RegCreateKeyEx32W(
1424 LPSECURITY_ATTRIBUTES lpSecAttribs,
1428 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
1432 /*FIXME: handle security/access/whatever */
1433 dprintf_reg(stddeb,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1445 lpNextKey = lookup_hkey(hkey);
1447 return SHELL_ERROR_BADKEY;
1448 if (!lpszSubKey || !*lpszSubKey) {
1449 add_handle(++currenthandle,lpNextKey,samDesired);
1450 *retkey=currenthandle;
1451 return SHELL_ERROR_SUCCESS;
1453 split_keypath(lpszSubKey,&wps,&wpc);
1455 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1458 lpxkey=lpNextKey->nextsub;
1460 if (!strcmpW(wps[i],lpxkey->keyname))
1462 lpxkey=lpxkey->next;
1470 add_handle(++currenthandle,lpxkey,samDesired);
1471 *retkey = currenthandle;
1472 *lpDispos = REG_OPENED_EXISTING_KEY;
1474 return SHELL_ERROR_SUCCESS;
1476 /* good. now the hard part */
1478 lplpPrevKey = &(lpNextKey->nextsub);
1479 lpxkey = *lplpPrevKey;
1481 lplpPrevKey = &(lpxkey->next);
1482 lpxkey = *lplpPrevKey;
1484 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
1485 if (!*lplpPrevKey) {
1487 return SHELL_ERROR_OUTOFMEMORY;
1489 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
1490 (*lplpPrevKey)->keyname = strdupW(wps[i]);
1491 (*lplpPrevKey)->next = NULL;
1492 (*lplpPrevKey)->nextsub = NULL;
1493 (*lplpPrevKey)->values = NULL;
1494 (*lplpPrevKey)->nrofvalues = 0;
1496 (*lplpPrevKey)->class = strdupW(lpszClass);
1498 (*lplpPrevKey)->class = NULL;
1499 lpNextKey = *lplpPrevKey;
1502 add_handle(++currenthandle,lpNextKey,samDesired);
1504 /*FIXME: flag handling correct? */
1505 lpNextKey->flags= fdwOptions;
1507 lpNextKey->class = strdupW(lpszClass);
1509 lpNextKey->class = NULL;
1510 lpNextKey->flags|=REG_OPTION_TAINTED;
1511 *retkey = currenthandle;
1512 *lpDispos = REG_CREATED_NEW_KEY;
1514 return SHELL_ERROR_SUCCESS;
1517 /* RegCreateKeyW [ADVAPI32.132] */
1518 DWORD RegCreateKey32W(
1525 dprintf_reg(stddeb,"RegCreateKey32W(%lx,%s,%p)\n",
1526 (LONG)hkey,W2C(lpszSubKey,0),retkey
1528 ret=RegCreateKeyEx32W(
1529 hkey, /* key handle */
1530 lpszSubKey, /* subkey name */
1531 0, /* reserved = 0 */
1532 NULL, /* lpszClass? FIXME: ? */
1533 REG_OPTION_NON_VOLATILE, /* options */
1534 KEY_ALL_ACCESS, /* desired access attribs */
1535 NULL, /* lpsecurity attributes */
1536 retkey, /* lpretkey */
1537 &junk /* disposition value */
1542 /* RegCreateKeyExA [ADVAPI32.130] */
1543 DWORD RegCreateKeyEx32A(
1550 LPSECURITY_ATTRIBUTES lpSecAttribs,
1554 LPWSTR lpszSubKeyW,lpszClassW;
1557 dprintf_reg(stddeb,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1569 lpszSubKeyW=strdupA2W(lpszSubKey);
1573 lpszClassW=strdupA2W(lpszClass);
1576 ret=RegCreateKeyEx32W(
1594 /* RegCreateKeyA [ADVAPI32.129] */
1595 DWORD RegCreateKey32A(
1602 dprintf_reg(stddeb,"RegCreateKey32A(%lx,%s,%p)\n",
1603 (LONG)hkey,lpszSubKey,retkey
1605 return RegCreateKeyEx32A(
1606 hkey, /* key handle */
1607 lpszSubKey, /* subkey name */
1608 0, /* reserved = 0 */
1609 NULL, /* lpszClass? FIXME: ? */
1610 REG_OPTION_NON_VOLATILE,/* options */
1611 KEY_ALL_ACCESS, /* desired access attribs */
1612 NULL, /* lpsecurity attributes */
1613 retkey, /* lpretkey */
1614 &junk /* disposition value */
1618 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1619 DWORD RegCreateKey16(
1624 dprintf_reg(stddeb,"RegCreateKey16(%lx,%s,%p)\n",
1625 (LONG)hkey,lpszSubKey,retkey
1627 return RegCreateKey32A(hkey,lpszSubKey,retkey);
1631 * Query Value Functions
1632 * Win32 differs between keynames and valuenames.
1633 * multiple values may belong to one key, the special value
1634 * with name NULL is the default value used by the win31
1638 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1639 * RegQueryValue32W -> RegQueryValueEx32W
1642 /* RegQueryValueExW [ADVAPI32.158] */
1643 DWORD RegQueryValueEx32W(
1645 LPWSTR lpszValueName,
1646 LPDWORD lpdwReserved,
1654 dprintf_reg(stddeb,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%p)\n",
1655 hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,lpcbData
1658 lpkey = lookup_hkey(hkey);
1660 return SHELL_ERROR_BADKEY;
1661 if (lpszValueName==NULL) {
1662 for (i=0;i<lpkey->nrofvalues;i++)
1663 if (lpkey->values[i].name==NULL)
1666 for (i=0;i<lpkey->nrofvalues;i++)
1667 if (!strcmpW(lpszValueName,lpkey->values[i].name))
1670 if (i==lpkey->nrofvalues) {
1671 if (lpszValueName==NULL) {
1672 *(WCHAR*)lpbData = 0;
1675 return SHELL_ERROR_SUCCESS;
1677 return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
1680 *lpdwType = lpkey->values[i].type;
1681 if (lpbData==NULL) {
1683 return SHELL_ERROR_SUCCESS;
1684 *lpcbData = lpkey->values[i].len;
1685 return SHELL_ERROR_SUCCESS;
1687 if (*lpcbData<lpkey->values[i].len) {
1690 *lpcbData = lpkey->values[i].len;
1691 return ERROR_MORE_DATA;
1693 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
1694 *lpcbData = lpkey->values[i].len;
1695 return SHELL_ERROR_SUCCESS;
1698 /* RegQueryValueW [ADVAPI32.159] */
1699 DWORD RegQueryValue32W(
1708 dprintf_reg(stddeb,"RegQueryValue32W(%x,%s,%p,%p)\n->",
1709 hkey,W2C(lpszSubKey,0),lpszData,lpcbData
1712 /* only open subkey, if we really do descend */
1713 if (lpszSubKey && *lpszSubKey) {
1714 ret = RegOpenKey32W(hkey,lpszSubKey,&xhkey);
1715 if (ret!=ERROR_SUCCESS)
1721 ret = RegQueryValueEx32W(
1723 NULL, /* varname NULL -> compat */
1724 NULL, /* lpdwReserved, must be NULL */
1734 /* RegQueryValueExA [ADVAPI32.157] */
1735 DWORD RegQueryValueEx32A(
1737 LPSTR lpszValueName,
1738 LPDWORD lpdwReserved,
1743 LPWSTR lpszValueNameW;
1748 dprintf_reg(stddeb,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%p)\n->",
1749 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData
1753 buf = (LPBYTE)xmalloc((*lpcbData)*2);
1754 myxlen = *lpcbData*2;
1759 myxlen = *lpcbData*2;
1765 lpszValueNameW=strdupA2W(lpszValueName);
1767 lpszValueNameW=NULL;
1769 ret=RegQueryValueEx32W(
1778 if (ret==ERROR_SUCCESS) {
1780 if (UNICONVMASK & (1<<(*lpdwType))) {
1781 /* convert UNICODE to ASCII */
1782 strcpyWA(lpbData,(LPWSTR)buf);
1783 *lpcbData = myxlen/2;
1785 if (myxlen>*lpcbData)
1786 ret = ERROR_MORE_DATA;
1788 memcpy(lpbData,buf,myxlen);
1793 if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
1794 *lpcbData = myxlen/2;
1797 if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
1798 *lpcbData = myxlen/2;
1805 /* RegQueryValueEx [KERNEL.225] */
1806 DWORD RegQueryValueEx16(
1808 LPSTR lpszValueName,
1809 LPDWORD lpdwReserved,
1814 dprintf_reg(stddeb,"RegQueryValueEx16(%x,%s,%p,%p,%p,%p)\n",
1815 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData
1817 return RegQueryValueEx32A(
1827 /* RegQueryValueA [ADVAPI32.156] */
1828 DWORD RegQueryValue32A(
1837 dprintf_reg(stddeb,"RegQueryValue32A(%x,%s,%p,%p)\n",
1838 hkey,lpszSubKey,lpszData,lpcbData
1841 /* only open subkey, if we really do descend */
1842 if (lpszSubKey && *lpszSubKey) {
1843 ret = RegOpenKey16(hkey,lpszSubKey,&xhkey);
1844 if (ret!=ERROR_SUCCESS)
1850 ret = RegQueryValueEx32A(
1852 NULL, /* lpszValueName NULL -> compat */
1853 NULL, /* lpdwReserved, must be NULL */
1863 /* RegQueryValue [SHELL.6] [KERNEL.224] */
1864 DWORD RegQueryValue16(
1870 dprintf_reg(stddeb,"RegQueryValue16(%x,%s,%p,%p)\n",
1871 hkey,lpszSubKey,lpszData,lpcbData
1873 return RegQueryValue32A(hkey,lpszSubKey,lpszData,lpcbData);
1877 * Setting values of Registry keys
1880 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
1881 * RegSetValue32W -> RegSetValueEx32W
1884 /* RegSetValueExW [ADVAPI32.170] */
1885 DWORD RegSetValueEx32W(
1887 LPWSTR lpszValueName,
1896 dprintf_reg(stddeb,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
1897 hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData
1899 /* we no longer care about the lpbData type here... */
1900 lpkey = lookup_hkey(hkey);
1902 return SHELL_ERROR_BADKEY;
1904 lpkey->flags |= REG_OPTION_TAINTED;
1906 if (lpszValueName==NULL) {
1907 for (i=0;i<lpkey->nrofvalues;i++)
1908 if (lpkey->values[i].name==NULL)
1911 for (i=0;i<lpkey->nrofvalues;i++)
1912 if (!strcmpW(lpszValueName,lpkey->values[i].name))
1915 if (i==lpkey->nrofvalues) {
1916 lpkey->values = (LPKEYVALUE)xrealloc(
1918 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
1920 lpkey->nrofvalues++;
1921 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
1923 if (lpkey->values[i].name==NULL)
1925 lpkey->values[i].name = strdupW(lpszValueName);
1927 lpkey->values[i].name = NULL;
1928 lpkey->values[i].len = cbData;
1929 lpkey->values[i].type = dwType;
1930 if (lpkey->values[i].data !=NULL)
1931 free(lpkey->values[i].data);
1932 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
1933 lpkey->values[i].lastmodified = time(NULL);
1934 memcpy(lpkey->values[i].data,lpbData,cbData);
1935 return SHELL_ERROR_SUCCESS;
1938 /* RegSetValueExA [ADVAPI32.169] */
1939 DWORD RegSetValueEx32A(
1941 LPSTR lpszValueName,
1948 LPWSTR lpszValueNameW;
1951 dprintf_reg(stddeb,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
1952 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
1954 if ((1<<dwType) & UNICONVMASK) {
1955 buf=(LPBYTE)strdupA2W(lpbData);
1956 cbData=2*strlen(lpbData)+2;
1960 lpszValueNameW = strdupA2W(lpszValueName);
1962 lpszValueNameW = NULL;
1963 ret=RegSetValueEx32W(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
1965 free(lpszValueNameW);
1971 /* RegSetValueEx [KERNEL.226] */
1972 DWORD RegSetValueEx16(
1974 LPSTR lpszValueName,
1980 dprintf_reg(stddeb,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
1981 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
1983 return RegSetValueEx32A(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData);
1986 /* RegSetValueW [ADVAPI32.171] */
1987 DWORD RegSetValue32W(
1997 dprintf_reg(stddeb,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
1998 hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
2000 if (lpszSubKey && *lpszSubKey) {
2001 ret=RegCreateKey32W(hkey,lpszSubKey,&xhkey);
2002 if (ret!=ERROR_SUCCESS)
2006 if (dwType!=REG_SZ) {
2007 fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
2010 if (cbData!=2*strlenW(lpszData)+2) {
2011 dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2012 cbData,W2C(lpszData,0),2*strlenW(lpszData)+2
2014 cbData=2*strlenW(lpszData)+2;
2016 ret=RegSetValueEx32W(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2022 /* RegSetValueA [ADVAPI32.168] */
2023 DWORD RegSetValue32A(
2033 dprintf_reg(stddeb,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2034 hkey,lpszSubKey,dwType,lpszData,cbData
2036 if (lpszSubKey && *lpszSubKey) {
2037 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
2038 if (ret!=ERROR_SUCCESS)
2043 if (dwType!=REG_SZ) {
2044 dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType);
2047 if (cbData!=strlen(lpszData)+1)
2048 cbData=strlen(lpszData)+1;
2049 ret=RegSetValueEx32A(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2055 /* RegSetValue [KERNEL.221] [SHELL.5] */
2056 DWORD RegSetValue16(
2064 dprintf_reg(stddeb,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2065 hkey,lpszSubKey,dwType,lpszData,cbData
2067 ret=RegSetValue32A(hkey,lpszSubKey,dwType,lpszData,cbData);
2075 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2076 * RegEnumKey32W -> RegEnumKeyEx32W
2079 /* RegEnumKeyExW [ADVAPI32.139] */
2080 DWORD RegEnumKeyEx32W(
2085 LPDWORD lpdwReserved,
2090 LPKEYSTRUCT lpkey,lpxkey;
2092 dprintf_reg(stddeb,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2093 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2095 lpkey=lookup_hkey(hkey);
2097 return SHELL_ERROR_BADKEY;
2098 if (!lpkey->nextsub)
2099 return ERROR_NO_MORE_ITEMS;
2100 lpxkey=lpkey->nextsub;
2101 while (iSubkey && lpxkey) {
2103 lpxkey=lpxkey->next;
2105 if (iSubkey || !lpxkey)
2106 return ERROR_NO_MORE_ITEMS;
2107 if (2*strlenW(lpxkey->keyname)+2>*lpcchName)
2108 return ERROR_MORE_DATA;
2109 memcpy(lpszName,lpxkey->keyname,strlenW(lpxkey->keyname)*2+2);
2111 /* what should we write into it? */
2115 return ERROR_SUCCESS;
2119 /* RegEnumKeyW [ADVAPI32.140] */
2120 DWORD RegEnumKey32W(
2128 dprintf_reg(stddeb,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2129 hkey,iSubkey,lpszName,lpcchName
2131 return RegEnumKeyEx32W(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
2133 /* RegEnumKeyExA [ADVAPI32.138] */
2134 DWORD RegEnumKeyEx32A(
2139 LPDWORD lpdwReserved,
2144 DWORD ret,lpcchNameW,lpcchClassW;
2145 LPWSTR lpszNameW,lpszClassW;
2148 dprintf_reg(stddeb,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2149 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2152 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
2153 lpcchNameW = *lpcchName*2;
2159 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
2160 lpcchClassW = *lpcchClass*2;
2165 ret=RegEnumKeyEx32W(
2175 if (ret==ERROR_SUCCESS) {
2176 strcpyWA(lpszName,lpszNameW);
2177 *lpcchName=strlen(lpszName);
2179 strcpyWA(lpszClass,lpszClassW);
2180 *lpcchClass=strlen(lpszClass);
2190 /* RegEnumKeyA [ADVAPI32.137] */
2191 DWORD RegEnumKey32A(
2199 dprintf_reg(stddeb,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2200 hkey,iSubkey,lpszName,lpcchName
2202 return RegEnumKeyEx32A(
2214 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2221 dprintf_reg(stddeb,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2222 hkey,iSubkey,lpszName,lpcchName
2224 return RegEnumKey32A(hkey,iSubkey,lpszName,lpcchName);
2228 * Enumerate Registry Values
2231 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2234 /* RegEnumValueW [ADVAPI32.142] */
2235 DWORD RegEnumValue32W(
2240 LPDWORD lpdReserved,
2248 dprintf_reg(stddeb,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2249 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2251 lpkey = lookup_hkey(hkey);
2253 return SHELL_ERROR_BADKEY;
2254 if (lpkey->nrofvalues<=iValue)
2255 return ERROR_NO_MORE_ITEMS;
2256 val = lpkey->values+iValue;
2259 if (strlenW(val->name)*2+2>*lpcchValue) {
2260 *lpcchValue = strlenW(val->name)*2+2;
2261 return ERROR_MORE_DATA;
2263 memcpy(lpszValue,val->name,2*strlenW(val->name)+2);
2264 *lpcchValue=strlenW(val->name)*2+2;
2266 /* how to handle NULL value? */
2270 *lpdwType=val->type;
2272 if (val->len>*lpcbData)
2273 return ERROR_MORE_DATA;
2274 memcpy(lpbData,val->data,val->len);
2275 *lpcbData = val->len;
2277 return SHELL_ERROR_SUCCESS;
2280 /* RegEnumValueA [ADVAPI32.141] */
2281 DWORD RegEnumValue32A(
2286 LPDWORD lpdReserved,
2293 DWORD ret,lpcbDataW;
2295 dprintf_reg(stddeb,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2296 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2299 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
2301 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
2302 lpcbDataW = *lpcbData*2;
2305 ret=RegEnumValue32W(
2316 if (ret==ERROR_SUCCESS) {
2317 strcpyWA(lpszValue,lpszValueW);
2319 if ((1<<*lpdwType) & UNICONVMASK) {
2320 strcpyWA(lpbData,(LPWSTR)lpbDataW);
2322 if (lpcbDataW > *lpcbData)
2323 ret = ERROR_MORE_DATA;
2325 memcpy(lpbData,lpbDataW,lpcbDataW);
2327 *lpcbData = lpcbDataW;
2337 /* RegEnumValue [KERNEL.223] */
2338 DWORD RegEnumValue16(
2343 LPDWORD lpdReserved,
2348 dprintf_reg(stddeb,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2349 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2351 return RegEnumValue32A(
2364 * Close registry key
2366 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2367 DWORD RegCloseKey(HKEY hkey) {
2368 dprintf_reg(stddeb,"RegCloseKey(%x)\n",hkey);
2369 remove_handle(hkey);
2370 return ERROR_SUCCESS;
2373 * Delete registry key
2376 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2378 /* RegDeleteKeyW [ADVAPI32.134] */
2379 DWORD RegDeleteKey32W(HKEY hkey,LPWSTR lpszSubKey) {
2380 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2384 dprintf_reg(stddeb,"RegDeleteKey32W(%x,%s)\n",
2385 hkey,W2C(lpszSubKey,0)
2387 lpNextKey = lookup_hkey(hkey);
2389 return SHELL_ERROR_BADKEY;
2390 /* we need to know the previous key in the hier. */
2391 if (!lpszSubKey || !*lpszSubKey)
2392 return SHELL_ERROR_BADKEY;
2393 split_keypath(lpszSubKey,&wps,&wpc);
2397 lpxkey=lpNextKey->nextsub;
2399 if (!strcmpW(wps[i],lpxkey->keyname))
2401 lpxkey=lpxkey->next;
2405 /* not found is success */
2406 return SHELL_ERROR_SUCCESS;
2411 lpxkey = lpNextKey->nextsub;
2412 lplpPrevKey = &(lpNextKey->nextsub);
2414 if (!strcmpW(wps[i],lpxkey->keyname))
2416 lplpPrevKey = &(lpxkey->next);
2417 lpxkey = lpxkey->next;
2420 return SHELL_ERROR_SUCCESS;
2421 if (lpxkey->nextsub)
2422 return SHELL_ERROR_CANTWRITE;
2423 *lplpPrevKey = lpxkey->next;
2424 free(lpxkey->keyname);
2426 free(lpxkey->class);
2428 free(lpxkey->values);
2431 return SHELL_ERROR_SUCCESS;
2434 /* RegDeleteKeyA [ADVAPI32.133] */
2435 DWORD RegDeleteKey32A(HKEY hkey,LPCSTR lpszSubKey) {
2439 dprintf_reg(stddeb,"RegDeleteKey32A(%x,%s)\n",
2442 lpszSubKeyW=strdupA2W(lpszSubKey);
2443 ret=RegDeleteKey32W(hkey,lpszSubKeyW);
2448 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2449 DWORD RegDeleteKey16(HKEY hkey,LPCSTR lpszSubKey) {
2450 dprintf_reg(stddeb,"RegDeleteKey16(%x,%s)\n",
2453 return RegDeleteKey32A(hkey,lpszSubKey);
2457 * Delete registry value
2460 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2462 /* RegDeleteValueW [ADVAPI32.136] */
2463 DWORD RegDeleteValue32W(HKEY hkey,LPWSTR lpszValue) {
2468 dprintf_reg(stddeb,"RegDeleteValue32W(%x,%s)\n",
2469 hkey,W2C(lpszValue,0)
2471 lpkey=lookup_hkey(hkey);
2473 return SHELL_ERROR_BADKEY;
2475 for (i=0;i<lpkey->nrofvalues;i++)
2476 if (!strcmpW(lpkey->values[i].name,lpszValue))
2479 for (i=0;i<lpkey->nrofvalues;i++)
2480 if (lpkey->values[i].name==NULL)
2483 if (i==lpkey->nrofvalues)
2484 return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */
2485 val = lpkey->values+i;
2486 if (val->name) free(val->name);
2487 if (val->data) free(val->data);
2491 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
2493 lpkey->values = (LPKEYVALUE)xrealloc(
2495 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
2497 lpkey->nrofvalues--;
2498 return SHELL_ERROR_SUCCESS;
2501 /* RegDeleteValueA [ADVAPI32.135] */
2502 DWORD RegDeleteValue32A(HKEY hkey,LPSTR lpszValue) {
2506 dprintf_reg( stddeb, "RegDeleteValue32A(%x,%s)\n", hkey,lpszValue );
2508 lpszValueW=strdupA2W(lpszValue);
2511 ret=RegDeleteValue32W(hkey,lpszValueW);
2517 /* RegDeleteValue [KERNEL.222] */
2518 DWORD RegDeleteValue16(HKEY hkey,LPSTR lpszValue) {
2519 dprintf_reg( stddeb,"RegDeleteValue16(%x,%s)\n", hkey,lpszValue );
2520 return RegDeleteValue32A(hkey,lpszValue);
2523 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2524 DWORD RegFlushKey(HKEY hkey) {
2525 dprintf_reg(stddeb,"RegFlushKey(%x), STUB.\n",hkey);
2526 return SHELL_ERROR_SUCCESS;
2529 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2531 /* RegQueryInfoKeyW [ADVAPI32.153] */
2532 DWORD RegQueryInfoKey32W(
2536 LPDWORD lpdwReserved,
2538 LPDWORD lpcchMaxSubkey,
2539 LPDWORD lpcchMaxClass,
2541 LPDWORD lpcchMaxValueName,
2542 LPDWORD lpccbMaxValueData,
2543 LPDWORD lpcbSecurityDescriptor,
2546 LPKEYSTRUCT lpkey,lpxkey;
2547 int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata;
2550 dprintf_reg(stddeb,"RegQueryInfoKey32W(%x,......)\n",hkey);
2551 lpkey=lookup_hkey(hkey);
2553 return SHELL_ERROR_BADKEY;
2556 if (strlenW(lpkey->class)*2+2>*lpcchClass) {
2557 *lpcchClass=strlenW(lpkey->class)*2;
2558 return ERROR_MORE_DATA;
2560 *lpcchClass=strlenW(lpkey->class)*2;
2561 memcpy(lpszClass,lpkey->class,strlenW(lpkey->class));
2568 *lpcchClass = strlenW(lpkey->class)*2;
2570 lpxkey=lpkey->nextsub;
2571 nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
2574 if (strlenW(lpxkey->keyname)>maxsubkey)
2575 maxsubkey=strlenW(lpxkey->keyname);
2576 if (lpxkey->class && strlenW(lpxkey->class)>maxclass)
2577 maxclass=strlenW(lpxkey->class);
2578 if (lpxkey->nrofvalues>maxvalues)
2579 maxvalues=lpxkey->nrofvalues;
2580 for (i=0;i<lpxkey->nrofvalues;i++) {
2581 LPKEYVALUE val=lpxkey->values+i;
2583 if (val->name && strlenW(val->name)>maxvname)
2584 maxvname=strlenW(val->name);
2585 if (val->len>maxvdata)
2588 lpxkey=lpxkey->next;
2590 if (!maxclass) maxclass = 1;
2591 if (!maxvname) maxvname = 1;
2593 *lpcSubKeys = nrofkeys;
2595 *lpcchMaxSubkey = maxsubkey*2;
2597 *lpcchMaxClass = maxclass*2;
2599 *lpcValues = maxvalues;
2600 if (lpcchMaxValueName)
2601 *lpcchMaxValueName= maxvname;
2602 if (lpccbMaxValueData)
2603 *lpccbMaxValueData= maxvdata;
2604 return SHELL_ERROR_SUCCESS;
2607 /* RegQueryInfoKeyA [ADVAPI32.152] */
2608 DWORD RegQueryInfoKey32A(
2612 LPDWORD lpdwReserved,
2614 LPDWORD lpcchMaxSubkey,
2615 LPDWORD lpcchMaxClass,
2617 LPDWORD lpcchMaxValueName,
2618 LPDWORD lpccbMaxValueData,
2619 LPDWORD lpcbSecurityDescriptor,
2625 dprintf_reg(stddeb,"RegQueryInfoKey32A(%x,......)\n",hkey);
2628 lpszClassW = (LPWSTR)xmalloc(*lpcchClass);
2632 ret=RegQueryInfoKey32W(
2643 lpcbSecurityDescriptor,
2646 if (ret==ERROR_SUCCESS)
2647 strcpyWA(lpszClass,lpszClassW);
2654 if (lpcchMaxValueName)
2655 *lpcchMaxValueName/=2;