4 * Copyright 1996 Marcus Meissner
14 #include <sys/types.h>
15 #include <sys/fcntl.h>
29 #define MAKE_DWORD(x,y) ((DWORD)MAKELONG(x,y))
31 /* FIXME: following defines should be configured global ... */
33 /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
34 #define WINE_PREFIX "/.wine"
35 #define SAVE_USERS_DEFAULT "/usr/local/etc/wine.userreg"
36 #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
38 /* relative in ~user/.wine/ : */
39 #define SAVE_CURRENT_USER "user.reg"
40 #define SAVE_LOCAL_MACHINE "system.reg"
42 #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
43 #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
45 /* one value of a key */
46 typedef struct tagKEYVALUE
48 LPWSTR name; /* name of value (UNICODE) or NULL for win31 */
49 DWORD type; /* type of value */
50 DWORD len; /* length of data */
51 DWORD lastmodified; /* time of seconds since 1.1.1970 */
52 LPBYTE data; /* content, may be strings, binaries, etc. */
53 } KEYVALUE,*LPKEYVALUE;
56 typedef struct tagKEYSTRUCT
58 LPWSTR keyname; /* name of THIS key (UNICODE) */
59 DWORD flags; /* flags. */
62 DWORD nrofvalues; /* nr of values in THIS key */
63 LPKEYVALUE values; /* values in THIS key */
64 /* key management pointers */
65 struct tagKEYSTRUCT *next; /* next key on same hierarchy */
66 struct tagKEYSTRUCT *nextsub; /* keys that hang below THIS key */
67 } KEYSTRUCT, *LPKEYSTRUCT;
70 static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */
71 static KEYSTRUCT *key_current_user=NULL; /* user specific values */
72 static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
73 static KEYSTRUCT *key_users=NULL; /* all users? */
75 /* dynamic, not saved */
76 static KEYSTRUCT *key_performance_data=NULL;
77 static KEYSTRUCT *key_current_config=NULL;
78 static KEYSTRUCT *key_dyn_data=NULL;
80 /* what valuetypes do we need to convert? */
81 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
83 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
84 #define strdupW2A(x) STRING32_DupUniToAnsi(x)
85 #define strdupW(x) STRING32_strdupW(x)
86 #define strcmpniW(a,b) STRING32_lstrcmpniW(a,b)
87 #define strchrW(a,c) STRING32_lstrchrW(a,c)
88 #define strcpyWA(a,b) STRING32_UniToAnsi(a,b)
90 static struct openhandle {
95 static int nrofopenhandles=0;
96 static int currenthandle=1;
99 add_handle(HKEY hkey,LPKEYSTRUCT lpkey,REGSAM accessmask) {
102 for (i=0;i<nrofopenhandles;i++) {
103 if (openhandles[i].lpkey==lpkey) {
104 dprintf_reg(stddeb,"add_handle:Tried to add %p twice!\n",lpkey);
106 if (openhandles[i].hkey==hkey) {
107 dprintf_reg(stddeb,"add_handle:Tried to add %lx twice!\n",(LONG)hkey);
110 openhandles=xrealloc( openhandles,
111 sizeof(struct openhandle)*(nrofopenhandles+1)
113 openhandles[i].lpkey = lpkey;
114 openhandles[i].hkey = hkey;
115 openhandles[i].accessmask= accessmask;
120 get_handle(HKEY hkey) {
123 for (i=0;i<nrofopenhandles;i++)
124 if (openhandles[i].hkey==hkey)
125 return openhandles[i].lpkey;
126 dprintf_reg(stddeb,"get_handle:Didn't find handle %lx?\n",(LONG)hkey);
131 remove_handle(HKEY hkey) {
134 for (i=0;i<nrofopenhandles;i++)
135 if (openhandles[i].hkey==hkey)
137 if (i==nrofopenhandles) {
138 dprintf_reg(stddeb,"remove_handle:Didn't find handle %08x?\n",hkey);
141 memcpy( openhandles+i,
143 sizeof(struct openhandle)*(nrofopenhandles-i-1)
145 openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
151 /* debug function, converts a unicode into a static memory area
152 * (sub for using two static strings, in case we need them in a single call)
155 W2C(LPCWSTR x,int sub) {
156 static LPSTR unicodedebug[2]={NULL,NULL};
159 if (sub!=0 && sub!=1)
160 return "<W2C:bad sub>";
161 if (unicodedebug[sub]) free(unicodedebug[sub]);
162 unicodedebug[sub] = strdupW2A(x);
163 return unicodedebug[sub];
167 lookup_hkey(HKEY hkey) {
171 case HKEY_CLASSES_ROOT:
172 return key_classes_root;
173 case HKEY_CURRENT_USER:
174 return key_current_user;
175 case HKEY_LOCAL_MACHINE:
176 return key_local_machine;
179 case HKEY_PERFORMANCE_DATA:
180 return key_performance_data;
183 case HKEY_CURRENT_CONFIG:
184 return key_current_config;
186 dprintf_reg(stddeb,"lookup_hkey(%lx), special key!\n",
189 return get_handle(hkey);
195 * splits the unicode string 'wp' into an array of strings.
196 * the array is allocated by this function.
197 * the number of components will be stored in 'wpc'
198 * Free the array using FREE_KEY_PATH
201 split_keypath(LPCWSTR wp,LPWSTR **wpv,int *wpc) {
207 for (i=0;ws[i];i++) {
214 *wpv = (LPWSTR*)xmalloc(sizeof(LPWSTR)*(*wpc+2));
222 #define FREE_KEY_PATH free(wps[0]);free(wps);
225 * Shell initialisation, allocates keys.
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");
242 key_classes_root = lookup_hkey(cl_r_hkey);
244 ADD_ROOT_KEY(key_users);
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)
253 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
254 RegCloseKey(c_u_hkey);
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);
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);
270 /************************ SAVE Registry Function ****************************/
272 #define REGISTRY_SAVE_VERSION 0x00000001
274 /* Registry saveformat:
275 * If you change it, increase above number by 1, which will flush
276 * old registry database files.
279 * "WINE REGISTRY Version %d"
283 * valuename=lastmodified,type,data
287 * keyname,valuename,stringdata:
288 * the usual ascii characters from 0x00-0xff (well, not 0x00)
289 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
290 * ( "=\\\t" escaped in \uXXXX form.)
294 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
296 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
297 * SaveOnlyUpdatedKeys=yes
300 _save_check_tainted(LPKEYSTRUCT lpkey) {
305 if (lpkey->flags & REG_OPTION_TAINTED)
310 if (_save_check_tainted(lpkey->nextsub)) {
311 lpkey->flags |= REG_OPTION_TAINTED;
320 _save_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
333 if (escapeeq && *s=='=')
336 fputc(*s,F); /* if \\ than put it twice. */
338 fprintf(F,"\\u%04x",*((unsigned short*)s));
346 _savesubkey(FILE *F,LPKEYSTRUCT lpkey,int level,int all) {
352 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
353 (all || (lpxkey->flags & REG_OPTION_TAINTED))
355 for (tabs=level;tabs--;)
357 _save_USTRING(F,lpxkey->keyname,1);
359 for (i=0;i<lpxkey->nrofvalues;i++) {
360 LPKEYVALUE val=lpxkey->values+i;
362 for (tabs=level+1;tabs--;)
364 _save_USTRING(F,val->name,0);
366 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
367 if ((1<<val->type) & UNICONVMASK)
368 _save_USTRING(F,(LPWSTR)val->data,0);
370 for (j=0;j<val->len;j++)
371 fprintf(F,"%02x",*((unsigned char*)val->data+j));
374 /* descend recursively */
375 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
384 _savesubreg(FILE *F,LPKEYSTRUCT lpkey,int all) {
385 fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
386 _save_check_tainted(lpkey->nextsub);
387 return _savesubkey(F,lpkey->nextsub,0,all);
391 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
396 fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
401 if (!_savesubreg(F,lpkey,all)) {
404 fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
411 SHELL_SaveRegistry() {
419 if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) {
425 if ( (ERROR_SUCCESS!=RegQueryValueEx32A(
437 if (lstrcmpi32A(buf,"yes"))
439 pwd=getpwuid(getuid());
440 if (pwd!=NULL && pwd->pw_dir!=NULL) {
441 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2);
442 strcpy(fn,pwd->pw_dir);
443 strcat(fn,WINE_PREFIX);
444 /* create the directory. don't care about errorcodes. */
445 mkdir(fn,0755); /* drwxr-xr-x */
446 strcat(fn,"/"SAVE_CURRENT_USER);
447 _savereg(key_current_user,fn,all);
449 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
450 strcpy(fn,pwd->pw_dir);
451 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
452 _savereg(key_local_machine,fn,all);
455 fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
458 /************************ LOAD Registry Function ****************************/
461 _find_or_add_key(LPKEYSTRUCT lpkey,LPWSTR keyname) {
462 LPKEYSTRUCT lpxkey,*lplpkey;
464 lplpkey= &(lpkey->nextsub);
467 if (!lstrcmp32W(lpxkey->keyname,keyname))
469 lplpkey = &(lpxkey->next);
473 *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
475 memset(lpxkey,'\0',sizeof(KEYSTRUCT));
476 lpxkey->keyname = keyname;
484 LPKEYSTRUCT lpkey,LPWSTR name,DWORD type,LPBYTE data,DWORD len,
490 for (i=0;i<lpkey->nrofvalues;i++) {
496 if ( val->name!=NULL &&
497 !lstrcmp32W(val->name,name)
502 if (i==lpkey->nrofvalues) {
503 lpkey->values = xrealloc(
505 (++lpkey->nrofvalues)*sizeof(KEYVALUE)
508 memset(val,'\0',sizeof(KEYVALUE));
514 if (val->lastmodified<lastmodified) {
515 val->lastmodified=lastmodified;
526 /* reads a line including dynamically enlarging the readbuffer and throwing
530 _wine_read_line(FILE *F,char **buf,int *len) {
539 s=fgets(curread,mylen,F);
542 if (NULL==(s=strchr(curread,'\n'))) {
543 /* buffer wasn't large enough */
544 curoff = strlen(*buf);
545 *buf = xrealloc(*buf,*len*2);
546 curread = *buf + curoff;
547 mylen = *len; /* we filled up the buffer and
548 * got new '*len' bytes to fill
556 /* throw away comments */
557 if (**buf=='#' || **buf==';') {
562 if (s) /* got end of line */
568 /* converts a char* into a UNICODE string (up to a special char)
569 * and returns the position exactly after that string
572 _wine_read_USTRING(char *buf,LPWSTR *str) {
576 /* read up to "=" or "\0" or "\n" */
579 /* empty string is the win3.1 default value(NULL)*/
583 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
585 while (*s && (*s!='\n') && (*s!='=')) {
587 *ws++=*((unsigned char*)s++);
596 fprintf(stderr,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
604 memcpy(xbuf,s,4);xbuf[4]='\0';
605 if (!sscanf(xbuf,"%x",&wc))
606 fprintf(stderr,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf);
608 *ws++ =(unsigned short)wc;
614 *str = strdupW(*str);
621 FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen,int optflag
628 lpkey->flags |= optflag;
630 /* good. we already got a line here ... so parse it */
640 fprintf(stderr,"_load_subkey:Got a subhierarchy without resp. key?\n");
643 _wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag);
646 /* let the caller handle this line */
647 if (i<level || **buf=='\0')
650 /* it can be: a value or a keyname. Parse the name first */
651 s=_wine_read_USTRING(s,&name);
653 /* switch() default: hack to avoid gotos */
657 lpxkey=_find_or_add_key(lpkey,name);
660 int len,lastmodified,type;
663 fprintf(stderr,"_wine_load_subkey:unexpected character: %c\n",*s);
667 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
668 fprintf(stderr,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf);
674 if ((1<<type) & UNICONVMASK) {
675 s=_wine_read_USTRING(s,(LPWSTR*)&data);
677 len = lstrlen32W((LPWSTR)data)*2+2;
682 data = (LPBYTE)xmalloc(len+1);
683 for (i=0;i<len;i++) {
685 if (*s>='0' && *s<='9')
687 if (*s>='a' && *s<='f')
689 if (*s>='A' && *s<='F')
692 if (*s>='0' && *s<='9')
694 if (*s>='a' && *s<='f')
696 if (*s>='A' && *s<='F')
701 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
704 /* read the next line */
705 if (!_wine_read_line(F,buf,buflen))
712 _wine_loadsubreg(FILE *F,LPKEYSTRUCT lpkey,int optflag) {
717 buf=xmalloc(10);buflen=10;
718 if (!_wine_read_line(F,&buf,&buflen)) {
722 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
726 if (ver!=REGISTRY_SAVE_VERSION) {
727 dprintf_reg(stddeb,__FILE__":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
731 if (!_wine_read_line(F,&buf,&buflen)) {
735 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
744 _wine_loadreg(LPKEYSTRUCT lpkey,char *fn,int optflag) {
749 dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n",
754 if (!_wine_loadsubreg(F,lpkey,optflag)) {
763 _copy_registry(LPKEYSTRUCT from,LPKEYSTRUCT to) {
770 lpxkey = _find_or_add_key(to,strdupW(from->keyname));
772 for (j=0;j<from->nrofvalues;j++) {
776 valfrom = from->values+j;
778 if (name) name=strdupW(name);
779 data=(LPBYTE)malloc(valfrom->len);
780 memcpy(data,valfrom->data,valfrom->len);
788 valfrom->lastmodified
791 _copy_registry(from,lpxkey);
796 /* WINDOWS 95 REGISTRY LOADER */
798 * Structure of a win95 registry database.
802 * 8 : DWORD offset_of_RGDB_part
803 * 0C..1F: ? (someone fill in please)
808 * 4..0x1B: ? (fill in)
809 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
811 * Disk Key Entry Structure:
812 * 00: DWORD - unknown
813 * 04: DWORD - unknown
814 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
815 * 0C: DWORD - disk address of PreviousLevel Key.
816 * 10: DWORD - disk address of Next Sublevel Key.
817 * 14: DWORD - disk address of Next Key (on same level).
818 * DKEP>18: WORD - Nr, Low Significant part.
819 * 1A: WORD - Nr, High Significant part.
821 * The disk address always points to the nr part of the previous key entry
822 * of the referenced key. Don't ask me why, or even if I got this correct
823 * from staring at 1kg of hexdumps. (DKEP)
825 * The number of the entry is the low byte of the Low Significant Part ored
826 * with 0x100 * (low byte of the High Significant part)
827 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
829 * There are two minor corrections to the position of that structure.
830 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
831 * the DKE reread from there.
832 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
833 * (FIXME: slightly better explanation needed here)
837 * 04: DWORD offset to next RGDB section (perhaps WORD)
842 * 00: DWORD nextkeyoffset - offset to the next disk key structure
843 * 08: WORD nrLS - low significant part of NR
844 * 0A: WORD nrHS - high significant part of NR
845 * 0C: DWORD bytesused - bytes used in this structure.
846 * 10: WORD name_len - length of name in bytes. without \0
847 * 12: WORD nr_of_values - number of values.
848 * 14: char name[name_len] - name string. No \0.
849 * 14+name_len: disk values
850 * nextkeyoffset: ... next disk key
853 * 00: DWORD type - value type (hmm, could be WORD too)
854 * 04: DWORD - unknown, usually 0
855 * 08: WORD namelen - length of Name. 0 means name=NULL
856 * 0C: WORD datalen - length of Data.
857 * 10: char name[namelen] - name, no \0
858 * 10+namelen: BYTE data[datalen] - data, without \0 if string
859 * 10+namelen+datalen: next values or disk key
861 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
862 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
863 * structure) and reading another RGDB_section.
864 * repeat until end of file.
866 * FIXME: this description needs some serious help, yes.
869 struct _w95keyvalue {
871 unsigned short datalen;
881 struct _w95keyvalue *values;
882 unsigned long dkeaddr;
887 struct _w95key *prevlvl;
888 struct _w95key *nextsub;
889 struct _w95key *next;
892 /* fast lookup table dkeaddr->nr */
894 unsigned long dkeaddr;
900 _w95_walk_tree(LPKEYSTRUCT lpkey,struct _w95key *key) {
906 if (key->name == NULL) {
907 fprintf(stderr,"_w95_walk_tree:Please report: key with dkeaddr %lx not loaded, skipping hierarchy\n",
912 lpxkey=_find_or_add_key(lpkey,strdupA2W(key->name));
914 if (key->nrofvals<0) {
915 /* shouldn't happen */
916 fprintf(stderr,"key %s already processed!\n",key->name);
920 for (i=0;i<key->nrofvals;i++) {
924 name = strdupA2W(key->values[i].name);
925 if (!*name) name = NULL;
926 free(key->values[i].name);
928 len = key->values[i].datalen;
929 data = key->values[i].data;
930 if ((1<<key->values[i].type) & UNICONVMASK) {
931 data = (BYTE*)strdupA2W(data);
932 len = lstrlen32W((LPWSTR)data)*2+2;
933 free(key->values[i].data);
941 key->values[i].lastmodified
948 key->nrofvals=-key->nrofvals-1;
949 _w95_walk_tree(lpxkey,key->nextsub);
954 /* small helper function to adjust address offset (dkeaddrs) */
956 _w95_adj_da(unsigned long dkeaddr) {
957 if ((dkeaddr&0xFFF)<0x018) {
960 diff=0x1C-(dkeaddr&0xFFF);
963 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
964 /* readjust to 0x000,
965 * but ONLY if we are >0x1000 already
967 if (dkeaddr & ~0xFFF)
968 return dkeaddr & ~0xFFF;
974 _w95dkecomp(struct _w95nr2da *a,struct _w95nr2da *b){return a->dkeaddr-b->dkeaddr;}
976 static struct _w95key*
977 _w95dkelookup(unsigned long dkeaddr,int n,struct _w95nr2da *nr2da,struct _w95key *keys) {
980 if (dkeaddr == 0xFFFFFFFF)
984 dkeaddr=_w95_adj_da(dkeaddr+0x1c);
985 off = (dkeaddr-0x3c)/0x1c;
987 if (nr2da[(i+off)%n].dkeaddr == dkeaddr)
988 return keys+nr2da[(i+off)%n].nr;
989 /* 0x3C happens often, just report unusual values */
991 dprintf_reg(stddeb,"search hasn't found dkeaddr %lx?\n",dkeaddr);
996 _w95_loadreg(char* fn,LPKEYSTRUCT lpkey) {
997 /* Disk Key Entry structure (RGKN part) */
1001 unsigned long x3;/*usually 0xFFFFFFFF */
1002 unsigned long prevlvl;
1003 unsigned long nextsub;
1005 unsigned short nrLS;
1006 unsigned short nrMS;
1008 /* Disk Key Header structure (RGDB part) */
1010 unsigned long nextkeyoff;
1011 unsigned short nrLS;
1012 unsigned short nrMS;
1013 unsigned long bytesused;
1014 unsigned short keynamelen;
1015 unsigned short values;
1018 /* disk key values or nothing */
1020 /* Disk Key Value structure */
1024 unsigned short valnamelen;
1025 unsigned short valdatalen;
1026 /* valname, valdata */
1028 struct _w95nr2da *nr2da;
1031 int fd,lastmodified;
1033 unsigned long nr,pos,i,where,version,rgdbsection,end,off_next_rgdb;
1034 struct _w95key *keys;
1036 unsigned char *data,*curdata,*nextrgdb;
1040 dprintf_reg(stddeb,"Loading Win95 registry database '%s'\n",fn);
1041 hfd=OpenFile(fn,&ofs,OF_READ);
1042 if (hfd==HFILE_ERROR)
1044 fd = FILE_GetUnixHandle(hfd);
1046 if (4!=read(fd,magic,4))
1048 if (strcmp(magic,"CREG")) {
1049 fprintf(stddeb,"%s is not a w95 registry.\n",fn);
1052 if (4!=read(fd,&version,4))
1054 if (4!=read(fd,&rgdbsection,4))
1056 if (-1==lseek(fd,0x20,SEEK_SET))
1058 if (4!=read(fd,magic,4))
1060 if (strcmp(magic,"RGKN")) {
1061 dprintf_reg(stddeb,"second IFF header not RGKN, but %s\n",magic);
1065 /* STEP 1: Keylink structures */
1066 if (-1==lseek(fd,0x40,SEEK_SET))
1071 nrofdkes = (end-where)/sizeof(struct dke)+100;
1072 data = (char*)xmalloc(end-where);
1073 if ((end-where)!=read(fd,data,end-where))
1077 keys = (struct _w95key*)xmalloc(nrofdkes * sizeof(struct _w95key));
1078 memset(keys,'\0',nrofdkes*sizeof(struct _w95key));
1079 nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
1080 memset(nr2da,'\0',nrofdkes*sizeof(struct _w95nr2da));
1082 for (i=0;i<nrofdkes;i++) {
1084 unsigned long dkeaddr;
1086 pos=curdata-data+0x40;
1087 memcpy(&dke,curdata,sizeof(dke));
1088 curdata+=sizeof(dke);
1089 nr = dke.nrLS + (dke.nrMS<<8);
1091 if ((dkeaddr&0xFFF)<0x018) {
1094 diff=0x1C-(dkeaddr&0xFFF);
1096 curdata+=diff-sizeof(dke);
1097 memcpy(&dke,curdata,sizeof(dke));
1098 nr = dke.nrLS + (dke.nrMS<<8);
1099 curdata+=sizeof(dke);
1101 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1102 /* readjust to 0x000,
1103 * but ONLY if we are >0x1000 already
1105 if (dkeaddr & ~0xFFF)
1106 dkeaddr = dkeaddr & ~0xFFF;
1109 /* 0xFFFFFFFF happens often, just report unusual values */
1111 dprintf_reg(stddeb,"nr %ld exceeds nrofdkes %d, skipping.\n",nr,nrofdkes);
1114 if (keys[nr].dkeaddr) {
1117 for (x=sizeof(dke);x--;)
1118 if (((char*)&dke)[x])
1121 break; /* finished reading if we got only 0 */
1123 if ( (dke.next!=(long)keys[nr].next) ||
1124 (dke.nextsub!=(long)keys[nr].nextsub) ||
1125 (dke.prevlvl!=(long)keys[nr].prevlvl)
1127 dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[nr].dkeaddr,dkeaddr);
1132 nr2da[i].dkeaddr = dkeaddr;
1134 keys[nr].dkeaddr = dkeaddr;
1135 keys[nr].x1 = dke.x1;
1136 keys[nr].x2 = dke.x2;
1137 keys[nr].x3 = dke.x3;
1138 keys[nr].prevlvl= (struct _w95key*)dke.prevlvl;
1139 keys[nr].nextsub= (struct _w95key*)dke.nextsub;
1140 keys[nr].next = (struct _w95key*)dke.next;
1144 qsort(nr2da,nrofdkes,sizeof(nr2da[0]),_w95dkecomp);
1146 /* STEP 2: keydata & values */
1147 if (-1==fstat(fd,&stbuf))
1149 end = stbuf.st_size;
1150 lastmodified = stbuf.st_mtime;
1152 if (-1==lseek(fd,rgdbsection,SEEK_SET))
1154 data = (char*)xmalloc(end-rgdbsection);
1155 if ((end-rgdbsection)!=read(fd,data,end-rgdbsection))
1159 memcpy(magic,curdata,4);
1160 memcpy(&off_next_rgdb,curdata+4,4);
1161 nextrgdb = curdata+off_next_rgdb;
1162 if (strcmp(magic,"RGDB")) {
1163 dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
1170 struct _w95key *key,xkey;
1173 if (curdata>=nextrgdb) {
1175 if (!strncmp(curdata,"RGDB",4)) {
1176 memcpy(&off_next_rgdb,curdata+4,4);
1177 nextrgdb = curdata+off_next_rgdb;
1180 dprintf_reg(stddeb,"at end of RGDB section, but no next header (%x of %lx). Breaking.\n",curdata-data,end-rgdbsection);
1184 #define XREAD(whereto,len) \
1185 if ((curdata-data+len)<end) {\
1186 memcpy(whereto,curdata,len);\
1191 XREAD(&dkh,sizeof(dkh));
1192 nr = dkh.nrLS + (dkh.nrMS<<8);
1193 if ((nr>nrofdkes) || (dkh.nrLS == 0xFFFF)) {
1194 if (dkh.nrLS == 0xFFFF) {
1195 /* skip over key using nextkeyoff */
1196 curdata+=dkh.nextkeyoff-sizeof(struct dkh);
1199 dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
1201 memset(key,'\0',sizeof(xkey));
1205 dprintf_reg(stddeb,"key with nr=%ld has no dkeaddr?\n",nr);
1207 key->nrofvals = dkh.values;
1208 key->name = (char*)xmalloc(dkh.keynamelen+1);
1210 XREAD(key->name,dkh.keynamelen);
1211 key->name[dkh.keynamelen]=0;
1212 if (key->nrofvals) {
1213 key->values = (struct _w95keyvalue*)xmalloc(
1214 sizeof(struct _w95keyvalue)*key->nrofvals
1216 for (i=0;i<key->nrofvals;i++) {
1219 XREAD(&dkv,sizeof(dkv));
1220 key->values[i].type = dkv.type;
1221 key->values[i].name = (char*)xmalloc(
1224 key->values[i].datalen = dkv.valdatalen;
1225 key->values[i].data = (unsigned char*)xmalloc(
1228 key->values[i].x1 = dkv.x1;
1229 XREAD(key->values[i].name,dkv.valnamelen);
1230 XREAD(key->values[i].data,dkv.valdatalen);
1231 key->values[i].data[dkv.valdatalen]=0;
1232 key->values[i].name[dkv.valnamelen]=0;
1233 key->values[i].lastmodified=lastmodified;
1236 if (bytesread != dkh.nextkeyoff) {
1237 if (dkh.bytesused != bytesread)
1239 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread,dkh.nextkeyoff,
1242 curdata += dkh.nextkeyoff-bytesread;
1244 key->prevlvl = _w95dkelookup((long)key->prevlvl,nrofdkes,nr2da,keys);
1245 key->nextsub = _w95dkelookup((long)key->nextsub,nrofdkes,nr2da,keys);
1246 key->next = _w95dkelookup((long)key->next,nrofdkes,nr2da,keys);
1251 _w95_walk_tree(lpkey,keys);
1256 SHELL_LoadRegistry() {
1263 if (key_classes_root==NULL)
1266 /* Load windows 95 entries */
1267 _w95_loadreg("C:\\system.1st", key_local_machine);
1268 _w95_loadreg("system.dat", key_local_machine);
1269 _w95_loadreg("user.dat", key_users);
1271 /* FIXME: win3.1 reg.dat loader still missing */
1273 /* the global user default is loaded under HKEY_USERS\\.Default */
1274 RegCreateKey16(HKEY_USERS,".Default",&hkey);
1275 lpkey = lookup_hkey(hkey);
1276 _wine_loadreg(lpkey,SAVE_USERS_DEFAULT,0);
1278 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1279 _copy_registry(lpkey,key_current_user);
1282 /* the global machine defaults */
1283 _wine_loadreg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT,0);
1285 /* load the user saved registries */
1287 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1289 pwd=getpwuid(getuid());
1290 if (pwd!=NULL && pwd->pw_dir!=NULL) {
1291 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
1292 strcpy(fn,pwd->pw_dir);
1293 strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
1294 _wine_loadreg(key_current_user,fn,REG_OPTION_TAINTED);
1296 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
1297 strcpy(fn,pwd->pw_dir);
1298 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1299 _wine_loadreg(key_local_machine,fn,REG_OPTION_TAINTED);
1302 fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1303 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) {
1304 DWORD junk,type,len;
1308 if (( RegQueryValueEx32A(
1315 )!=ERROR_SUCCESS) ||
1318 RegSetValueEx32A(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1324 /********************* API FUNCTIONS ***************************************/
1328 * All functions are stubs to RegOpenKeyEx32W where all the
1331 * FIXME: security,options,desiredaccess,...
1334 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1335 * RegOpenKey32W -> RegOpenKeyEx32W
1338 /* RegOpenKeyExW [ADVAPI32.150] */
1339 DWORD RegOpenKeyEx32W(
1346 LPKEYSTRUCT lpNextKey,lpxkey;
1349 dprintf_reg(stddeb,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1350 (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey
1353 lpNextKey = lookup_hkey(hkey);
1355 return SHELL_ERROR_BADKEY;
1356 if (!lpszSubKey || !*lpszSubKey) {
1357 add_handle(++currenthandle,lpNextKey,samDesired);
1358 *retkey=currenthandle;
1359 return SHELL_ERROR_SUCCESS;
1361 split_keypath(lpszSubKey,&wps,&wpc);
1363 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1366 lpxkey=lpNextKey->nextsub;
1368 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1370 lpxkey=lpxkey->next;
1374 return SHELL_ERROR_BADKEY;
1379 add_handle(++currenthandle,lpxkey,samDesired);
1380 *retkey = currenthandle;
1382 return SHELL_ERROR_SUCCESS;
1385 /* RegOpenKeyW [ADVAPI32.151] */
1386 DWORD RegOpenKey32W(
1391 dprintf_reg(stddeb,"RegOpenKey32W(%lx,%s,%p)\n",
1392 (LONG)hkey,W2C(lpszSubKey,0),retkey
1394 return RegOpenKeyEx32W(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1398 /* RegOpenKeyExA [ADVAPI32.149] */
1399 DWORD RegOpenKeyEx32A(
1409 dprintf_reg(stddeb,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1410 (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey
1413 lpszSubKeyW=strdupA2W(lpszSubKey);
1416 ret=RegOpenKeyEx32W(hkey,lpszSubKeyW,dwReserved,samDesired,retkey);
1422 /* RegOpenKeyA [ADVAPI32.148] */
1423 DWORD RegOpenKey32A(
1428 dprintf_reg(stddeb,"RegOpenKey32A(%lx,%s,%p)\n",
1429 (LONG)hkey,lpszSubKey,retkey
1431 return RegOpenKeyEx32A(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1434 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1440 dprintf_reg(stddeb,"RegOpenKey16(%lx,%s,%p)\n",
1441 (LONG)hkey,lpszSubKey,retkey
1443 return RegOpenKey32A(hkey,lpszSubKey,retkey);
1449 * All those functions convert their respective
1450 * arguments and call RegCreateKeyExW at the end.
1452 * FIXME: no security,no access attrib,no optionhandling yet.
1455 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1456 * RegCreateKey32W -> RegCreateKeyEx32W
1459 /* RegCreateKeyExW [ADVAPI32.131] */
1460 DWORD RegCreateKeyEx32W(
1467 LPSECURITY_ATTRIBUTES lpSecAttribs,
1471 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
1475 /*FIXME: handle security/access/whatever */
1476 dprintf_reg(stddeb,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1488 lpNextKey = lookup_hkey(hkey);
1490 return SHELL_ERROR_BADKEY;
1491 if (!lpszSubKey || !*lpszSubKey) {
1492 add_handle(++currenthandle,lpNextKey,samDesired);
1493 *retkey=currenthandle;
1494 return SHELL_ERROR_SUCCESS;
1496 split_keypath(lpszSubKey,&wps,&wpc);
1498 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1501 lpxkey=lpNextKey->nextsub;
1503 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1505 lpxkey=lpxkey->next;
1513 add_handle(++currenthandle,lpxkey,samDesired);
1514 *retkey = currenthandle;
1515 *lpDispos = REG_OPENED_EXISTING_KEY;
1517 return SHELL_ERROR_SUCCESS;
1519 /* good. now the hard part */
1521 lplpPrevKey = &(lpNextKey->nextsub);
1522 lpxkey = *lplpPrevKey;
1524 lplpPrevKey = &(lpxkey->next);
1525 lpxkey = *lplpPrevKey;
1527 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
1528 if (!*lplpPrevKey) {
1530 return SHELL_ERROR_OUTOFMEMORY;
1532 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
1533 (*lplpPrevKey)->keyname = strdupW(wps[i]);
1534 (*lplpPrevKey)->next = NULL;
1535 (*lplpPrevKey)->nextsub = NULL;
1536 (*lplpPrevKey)->values = NULL;
1537 (*lplpPrevKey)->nrofvalues = 0;
1539 (*lplpPrevKey)->class = strdupW(lpszClass);
1541 (*lplpPrevKey)->class = NULL;
1542 lpNextKey = *lplpPrevKey;
1545 add_handle(++currenthandle,lpNextKey,samDesired);
1547 /*FIXME: flag handling correct? */
1548 lpNextKey->flags= fdwOptions;
1550 lpNextKey->class = strdupW(lpszClass);
1552 lpNextKey->class = NULL;
1553 lpNextKey->flags|=REG_OPTION_TAINTED;
1554 *retkey = currenthandle;
1555 *lpDispos = REG_CREATED_NEW_KEY;
1557 return SHELL_ERROR_SUCCESS;
1560 /* RegCreateKeyW [ADVAPI32.132] */
1561 DWORD RegCreateKey32W(
1568 dprintf_reg(stddeb,"RegCreateKey32W(%lx,%s,%p)\n",
1569 (LONG)hkey,W2C(lpszSubKey,0),retkey
1571 ret=RegCreateKeyEx32W(
1572 hkey, /* key handle */
1573 lpszSubKey, /* subkey name */
1574 0, /* reserved = 0 */
1575 NULL, /* lpszClass? FIXME: ? */
1576 REG_OPTION_NON_VOLATILE, /* options */
1577 KEY_ALL_ACCESS, /* desired access attribs */
1578 NULL, /* lpsecurity attributes */
1579 retkey, /* lpretkey */
1580 &junk /* disposition value */
1585 /* RegCreateKeyExA [ADVAPI32.130] */
1586 DWORD RegCreateKeyEx32A(
1593 LPSECURITY_ATTRIBUTES lpSecAttribs,
1597 LPWSTR lpszSubKeyW,lpszClassW;
1600 dprintf_reg(stddeb,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1612 lpszSubKeyW=strdupA2W(lpszSubKey);
1616 lpszClassW=strdupA2W(lpszClass);
1619 ret=RegCreateKeyEx32W(
1637 /* RegCreateKeyA [ADVAPI32.129] */
1638 DWORD RegCreateKey32A(
1645 dprintf_reg(stddeb,"RegCreateKey32A(%lx,%s,%p)\n",
1646 (LONG)hkey,lpszSubKey,retkey
1648 return RegCreateKeyEx32A(
1649 hkey, /* key handle */
1650 lpszSubKey, /* subkey name */
1651 0, /* reserved = 0 */
1652 NULL, /* lpszClass? FIXME: ? */
1653 REG_OPTION_NON_VOLATILE,/* options */
1654 KEY_ALL_ACCESS, /* desired access attribs */
1655 NULL, /* lpsecurity attributes */
1656 retkey, /* lpretkey */
1657 &junk /* disposition value */
1661 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1662 DWORD RegCreateKey16(
1667 dprintf_reg(stddeb,"RegCreateKey16(%lx,%s,%p)\n",
1668 (LONG)hkey,lpszSubKey,retkey
1670 return RegCreateKey32A(hkey,lpszSubKey,retkey);
1674 * Query Value Functions
1675 * Win32 differs between keynames and valuenames.
1676 * multiple values may belong to one key, the special value
1677 * with name NULL is the default value used by the win31
1681 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1682 * RegQueryValue32W -> RegQueryValueEx32W
1685 /* RegQueryValueExW [ADVAPI32.158] */
1686 DWORD RegQueryValueEx32W(
1688 LPWSTR lpszValueName,
1689 LPDWORD lpdwReserved,
1697 dprintf_reg(stddeb,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%ld)\n",
1698 hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,
1699 lpcbData?*lpcbData:0
1702 lpkey = lookup_hkey(hkey);
1704 return SHELL_ERROR_BADKEY;
1705 if (lpszValueName==NULL) {
1706 for (i=0;i<lpkey->nrofvalues;i++)
1707 if (lpkey->values[i].name==NULL)
1710 for (i=0;i<lpkey->nrofvalues;i++)
1711 if ( lpkey->values[i].name &&
1712 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
1716 if (i==lpkey->nrofvalues) {
1717 if (lpszValueName==NULL) {
1719 *(WCHAR*)lpbData = 0;
1724 return SHELL_ERROR_SUCCESS;
1726 return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
1729 *lpdwType = lpkey->values[i].type;
1730 if (lpbData==NULL) {
1732 return SHELL_ERROR_SUCCESS;
1733 *lpcbData = lpkey->values[i].len;
1734 return SHELL_ERROR_SUCCESS;
1736 if (*lpcbData<lpkey->values[i].len) {
1739 *lpcbData = lpkey->values[i].len;
1740 return ERROR_MORE_DATA;
1742 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
1743 *lpcbData = lpkey->values[i].len;
1744 return SHELL_ERROR_SUCCESS;
1747 /* RegQueryValueW [ADVAPI32.159] */
1748 DWORD RegQueryValue32W(
1757 dprintf_reg(stddeb,"RegQueryValue32W(%x,%s,%p,%ld)\n->",
1758 hkey,W2C(lpszSubKey,0),lpszData,
1759 lpcbData?*lpcbData:0
1762 /* only open subkey, if we really do descend */
1763 if (lpszSubKey && *lpszSubKey) {
1764 ret = RegOpenKey32W(hkey,lpszSubKey,&xhkey);
1765 if (ret!=ERROR_SUCCESS)
1771 ret = RegQueryValueEx32W(
1773 NULL, /* varname NULL -> compat */
1774 NULL, /* lpdwReserved, must be NULL */
1784 /* RegQueryValueExA [ADVAPI32.157] */
1785 DWORD RegQueryValueEx32A(
1787 LPSTR lpszValueName,
1788 LPDWORD lpdwReserved,
1793 LPWSTR lpszValueNameW;
1799 dprintf_reg(stddeb,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%ld)\n->",
1800 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
1801 lpcbData?*lpcbData:0
1805 buf = (LPBYTE)xmalloc((*lpcbData)*2);
1806 myxlen = *lpcbData*2;
1811 myxlen = *lpcbData*2;
1817 lpszValueNameW=strdupA2W(lpszValueName);
1819 lpszValueNameW=NULL;
1823 ret=RegQueryValueEx32W(
1833 if (ret==ERROR_SUCCESS) {
1835 if (UNICONVMASK & (1<<(type))) {
1836 /* convert UNICODE to ASCII */
1837 strcpyWA(lpbData,(LPWSTR)buf);
1838 *lpcbData = myxlen/2;
1840 if (myxlen>*lpcbData)
1841 ret = ERROR_MORE_DATA;
1843 memcpy(lpbData,buf,myxlen);
1848 if ((UNICONVMASK & (1<<(type))) && lpcbData)
1849 *lpcbData = myxlen/2;
1852 if ((UNICONVMASK & (1<<(type))) && lpcbData)
1853 *lpcbData = myxlen/2;
1860 /* RegQueryValueEx [KERNEL.225] */
1861 DWORD RegQueryValueEx16(
1863 LPSTR lpszValueName,
1864 LPDWORD lpdwReserved,
1869 dprintf_reg(stddeb,"RegQueryValueEx16(%x,%s,%p,%p,%p,%ld)\n",
1870 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
1871 lpcbData?*lpcbData:0
1873 return RegQueryValueEx32A(
1883 /* RegQueryValueA [ADVAPI32.156] */
1884 DWORD RegQueryValue32A(
1893 dprintf_reg(stddeb,"RegQueryValue32A(%x,%s,%p,%ld)\n",
1894 hkey,lpszSubKey,lpszData,
1895 lpcbData?*lpcbData:0
1898 /* only open subkey, if we really do descend */
1899 if (lpszSubKey && *lpszSubKey) {
1900 ret = RegOpenKey16(hkey,lpszSubKey,&xhkey);
1901 if (ret!=ERROR_SUCCESS)
1907 ret = RegQueryValueEx32A(
1909 NULL, /* lpszValueName NULL -> compat */
1910 NULL, /* lpdwReserved, must be NULL */
1920 /* RegQueryValue [SHELL.6] [KERNEL.224] */
1921 DWORD RegQueryValue16(
1927 dprintf_reg(stddeb,"RegQueryValue16(%x,%s,%p,%ld)\n",
1928 hkey,lpszSubKey,lpszData,lpcbData?*lpcbData:0
1930 /* HACK: the 16bit RegQueryValue doesn't handle selectorblocks
1931 * anyway, so we just mask out the high 16 bit.
1932 * (this (not so much incidently;) hopefully fixes Aldus FH4)
1935 *lpcbData &= 0xFFFF;
1936 return RegQueryValue32A(hkey,lpszSubKey,lpszData,lpcbData);
1940 * Setting values of Registry keys
1943 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
1944 * RegSetValue32W -> RegSetValueEx32W
1947 /* RegSetValueExW [ADVAPI32.170] */
1948 DWORD RegSetValueEx32W(
1950 LPWSTR lpszValueName,
1959 dprintf_reg(stddeb,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
1960 hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData
1962 /* we no longer care about the lpbData type here... */
1963 lpkey = lookup_hkey(hkey);
1965 return SHELL_ERROR_BADKEY;
1967 lpkey->flags |= REG_OPTION_TAINTED;
1969 if (lpszValueName==NULL) {
1970 for (i=0;i<lpkey->nrofvalues;i++)
1971 if (lpkey->values[i].name==NULL)
1974 for (i=0;i<lpkey->nrofvalues;i++)
1975 if ( lpkey->values[i].name &&
1976 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
1980 if (i==lpkey->nrofvalues) {
1981 lpkey->values = (LPKEYVALUE)xrealloc(
1983 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
1985 lpkey->nrofvalues++;
1986 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
1988 if (lpkey->values[i].name==NULL)
1990 lpkey->values[i].name = strdupW(lpszValueName);
1992 lpkey->values[i].name = NULL;
1993 lpkey->values[i].len = cbData;
1994 lpkey->values[i].type = dwType;
1995 if (lpkey->values[i].data !=NULL)
1996 free(lpkey->values[i].data);
1997 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
1998 lpkey->values[i].lastmodified = time(NULL);
1999 memcpy(lpkey->values[i].data,lpbData,cbData);
2000 return SHELL_ERROR_SUCCESS;
2003 /* RegSetValueExA [ADVAPI32.169] */
2004 DWORD RegSetValueEx32A(
2006 LPSTR lpszValueName,
2013 LPWSTR lpszValueNameW;
2016 dprintf_reg(stddeb,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
2017 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2019 if ((1<<dwType) & UNICONVMASK) {
2020 buf=(LPBYTE)strdupA2W(lpbData);
2021 cbData=2*strlen(lpbData)+2;
2025 lpszValueNameW = strdupA2W(lpszValueName);
2027 lpszValueNameW = NULL;
2028 ret=RegSetValueEx32W(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
2030 free(lpszValueNameW);
2036 /* RegSetValueEx [KERNEL.226] */
2037 DWORD RegSetValueEx16(
2039 LPSTR lpszValueName,
2045 dprintf_reg(stddeb,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2046 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2048 return RegSetValueEx32A(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData);
2051 /* RegSetValueW [ADVAPI32.171] */
2052 DWORD RegSetValue32W(
2062 dprintf_reg(stddeb,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2063 hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
2065 if (lpszSubKey && *lpszSubKey) {
2066 ret=RegCreateKey32W(hkey,lpszSubKey,&xhkey);
2067 if (ret!=ERROR_SUCCESS)
2071 if (dwType!=REG_SZ) {
2072 fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
2075 if (cbData!=2*lstrlen32W(lpszData)+2) {
2076 dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2077 cbData,W2C(lpszData,0),2*lstrlen32W(lpszData)+2
2079 cbData=2*lstrlen32W(lpszData)+2;
2081 ret=RegSetValueEx32W(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2087 /* RegSetValueA [ADVAPI32.168] */
2088 DWORD RegSetValue32A(
2098 dprintf_reg(stddeb,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2099 hkey,lpszSubKey,dwType,lpszData,cbData
2101 if (lpszSubKey && *lpszSubKey) {
2102 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
2103 if (ret!=ERROR_SUCCESS)
2108 if (dwType!=REG_SZ) {
2109 dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType);
2112 if (cbData!=strlen(lpszData)+1)
2113 cbData=strlen(lpszData)+1;
2114 ret=RegSetValueEx32A(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2120 /* RegSetValue [KERNEL.221] [SHELL.5] */
2121 DWORD RegSetValue16(
2129 dprintf_reg(stddeb,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2130 hkey,lpszSubKey,dwType,lpszData,cbData
2132 ret=RegSetValue32A(hkey,lpszSubKey,dwType,lpszData,cbData);
2140 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2141 * RegEnumKey32W -> RegEnumKeyEx32W
2144 /* RegEnumKeyExW [ADVAPI32.139] */
2145 DWORD RegEnumKeyEx32W(
2150 LPDWORD lpdwReserved,
2155 LPKEYSTRUCT lpkey,lpxkey;
2157 dprintf_reg(stddeb,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2158 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2160 lpkey=lookup_hkey(hkey);
2162 return SHELL_ERROR_BADKEY;
2163 if (!lpkey->nextsub)
2164 return ERROR_NO_MORE_ITEMS;
2165 lpxkey=lpkey->nextsub;
2166 while (iSubkey && lpxkey) {
2168 lpxkey=lpxkey->next;
2170 if (iSubkey || !lpxkey)
2171 return ERROR_NO_MORE_ITEMS;
2172 if (2*lstrlen32W(lpxkey->keyname)+2>*lpcchName)
2173 return ERROR_MORE_DATA;
2174 memcpy(lpszName,lpxkey->keyname,lstrlen32W(lpxkey->keyname)*2+2);
2176 /* what should we write into it? */
2180 return ERROR_SUCCESS;
2184 /* RegEnumKeyW [ADVAPI32.140] */
2185 DWORD RegEnumKey32W(
2193 dprintf_reg(stddeb,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2194 hkey,iSubkey,lpszName,lpcchName
2196 return RegEnumKeyEx32W(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
2198 /* RegEnumKeyExA [ADVAPI32.138] */
2199 DWORD RegEnumKeyEx32A(
2204 LPDWORD lpdwReserved,
2209 DWORD ret,lpcchNameW,lpcchClassW;
2210 LPWSTR lpszNameW,lpszClassW;
2213 dprintf_reg(stddeb,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2214 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2217 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
2218 lpcchNameW = *lpcchName*2;
2224 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
2225 lpcchClassW = *lpcchClass*2;
2230 ret=RegEnumKeyEx32W(
2240 if (ret==ERROR_SUCCESS) {
2241 strcpyWA(lpszName,lpszNameW);
2242 *lpcchName=strlen(lpszName);
2244 strcpyWA(lpszClass,lpszClassW);
2245 *lpcchClass=strlen(lpszClass);
2255 /* RegEnumKeyA [ADVAPI32.137] */
2256 DWORD RegEnumKey32A(
2264 dprintf_reg(stddeb,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2265 hkey,iSubkey,lpszName,lpcchName
2267 return RegEnumKeyEx32A(
2279 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2286 dprintf_reg(stddeb,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2287 hkey,iSubkey,lpszName,lpcchName
2289 return RegEnumKey32A(hkey,iSubkey,lpszName,lpcchName);
2293 * Enumerate Registry Values
2296 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2299 /* RegEnumValueW [ADVAPI32.142] */
2300 DWORD RegEnumValue32W(
2305 LPDWORD lpdReserved,
2313 dprintf_reg(stddeb,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2314 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2316 lpkey = lookup_hkey(hkey);
2318 return SHELL_ERROR_BADKEY;
2319 if (lpkey->nrofvalues<=iValue)
2320 return ERROR_NO_MORE_ITEMS;
2321 val = lpkey->values+iValue;
2324 if (lstrlen32W(val->name)*2+2>*lpcchValue) {
2325 *lpcchValue = lstrlen32W(val->name)*2+2;
2326 return ERROR_MORE_DATA;
2328 memcpy(lpszValue,val->name,2*lstrlen32W(val->name)+2);
2329 *lpcchValue=lstrlen32W(val->name)*2+2;
2331 /* how to handle NULL value? */
2335 *lpdwType=val->type;
2337 if (val->len>*lpcbData)
2338 return ERROR_MORE_DATA;
2339 memcpy(lpbData,val->data,val->len);
2340 *lpcbData = val->len;
2342 return SHELL_ERROR_SUCCESS;
2345 /* RegEnumValueA [ADVAPI32.141] */
2346 DWORD RegEnumValue32A(
2351 LPDWORD lpdReserved,
2358 DWORD ret,lpcbDataW;
2360 dprintf_reg(stddeb,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2361 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2364 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
2366 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
2367 lpcbDataW = *lpcbData*2;
2370 ret=RegEnumValue32W(
2381 if (ret==ERROR_SUCCESS) {
2382 strcpyWA(lpszValue,lpszValueW);
2384 if ((1<<*lpdwType) & UNICONVMASK) {
2385 strcpyWA(lpbData,(LPWSTR)lpbDataW);
2387 if (lpcbDataW > *lpcbData)
2388 ret = ERROR_MORE_DATA;
2390 memcpy(lpbData,lpbDataW,lpcbDataW);
2392 *lpcbData = lpcbDataW;
2402 /* RegEnumValue [KERNEL.223] */
2403 DWORD RegEnumValue16(
2408 LPDWORD lpdReserved,
2413 dprintf_reg(stddeb,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2414 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2416 return RegEnumValue32A(
2429 * Close registry key
2431 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2432 DWORD RegCloseKey(HKEY hkey) {
2433 dprintf_reg(stddeb,"RegCloseKey(%x)\n",hkey);
2434 remove_handle(hkey);
2435 return ERROR_SUCCESS;
2438 * Delete registry key
2441 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2443 /* RegDeleteKeyW [ADVAPI32.134] */
2444 DWORD RegDeleteKey32W(HKEY hkey,LPWSTR lpszSubKey) {
2445 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2449 dprintf_reg(stddeb,"RegDeleteKey32W(%x,%s)\n",
2450 hkey,W2C(lpszSubKey,0)
2452 lpNextKey = lookup_hkey(hkey);
2454 return SHELL_ERROR_BADKEY;
2455 /* we need to know the previous key in the hier. */
2456 if (!lpszSubKey || !*lpszSubKey)
2457 return SHELL_ERROR_BADKEY;
2458 split_keypath(lpszSubKey,&wps,&wpc);
2462 lpxkey=lpNextKey->nextsub;
2464 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2466 lpxkey=lpxkey->next;
2470 /* not found is success */
2471 return SHELL_ERROR_SUCCESS;
2476 lpxkey = lpNextKey->nextsub;
2477 lplpPrevKey = &(lpNextKey->nextsub);
2479 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2481 lplpPrevKey = &(lpxkey->next);
2482 lpxkey = lpxkey->next;
2485 return SHELL_ERROR_SUCCESS;
2486 if (lpxkey->nextsub)
2487 return SHELL_ERROR_CANTWRITE;
2488 *lplpPrevKey = lpxkey->next;
2489 free(lpxkey->keyname);
2491 free(lpxkey->class);
2493 free(lpxkey->values);
2496 return SHELL_ERROR_SUCCESS;
2499 /* RegDeleteKeyA [ADVAPI32.133] */
2500 DWORD RegDeleteKey32A(HKEY hkey,LPCSTR lpszSubKey) {
2504 dprintf_reg(stddeb,"RegDeleteKey32A(%x,%s)\n",
2507 lpszSubKeyW=strdupA2W(lpszSubKey);
2508 ret=RegDeleteKey32W(hkey,lpszSubKeyW);
2513 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2514 DWORD RegDeleteKey16(HKEY hkey,LPCSTR lpszSubKey) {
2515 dprintf_reg(stddeb,"RegDeleteKey16(%x,%s)\n",
2518 return RegDeleteKey32A(hkey,lpszSubKey);
2522 * Delete registry value
2525 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2527 /* RegDeleteValueW [ADVAPI32.136] */
2528 DWORD RegDeleteValue32W(HKEY hkey,LPWSTR lpszValue) {
2533 dprintf_reg(stddeb,"RegDeleteValue32W(%x,%s)\n",
2534 hkey,W2C(lpszValue,0)
2536 lpkey=lookup_hkey(hkey);
2538 return SHELL_ERROR_BADKEY;
2540 for (i=0;i<lpkey->nrofvalues;i++)
2541 if ( lpkey->values[i].name &&
2542 !lstrcmp32W(lpkey->values[i].name,lpszValue)
2546 for (i=0;i<lpkey->nrofvalues;i++)
2547 if (lpkey->values[i].name==NULL)
2550 if (i==lpkey->nrofvalues)
2551 return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */
2552 val = lpkey->values+i;
2553 if (val->name) free(val->name);
2554 if (val->data) free(val->data);
2558 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
2560 lpkey->values = (LPKEYVALUE)xrealloc(
2562 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
2564 lpkey->nrofvalues--;
2565 return SHELL_ERROR_SUCCESS;
2568 /* RegDeleteValueA [ADVAPI32.135] */
2569 DWORD RegDeleteValue32A(HKEY hkey,LPSTR lpszValue) {
2573 dprintf_reg( stddeb, "RegDeleteValue32A(%x,%s)\n", hkey,lpszValue );
2575 lpszValueW=strdupA2W(lpszValue);
2578 ret=RegDeleteValue32W(hkey,lpszValueW);
2584 /* RegDeleteValue [KERNEL.222] */
2585 DWORD RegDeleteValue16(HKEY hkey,LPSTR lpszValue) {
2586 dprintf_reg( stddeb,"RegDeleteValue16(%x,%s)\n", hkey,lpszValue );
2587 return RegDeleteValue32A(hkey,lpszValue);
2590 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2591 DWORD RegFlushKey(HKEY hkey) {
2592 dprintf_reg(stddeb,"RegFlushKey(%x), STUB.\n",hkey);
2593 return SHELL_ERROR_SUCCESS;
2596 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2598 /* RegQueryInfoKeyW [ADVAPI32.153] */
2599 DWORD RegQueryInfoKey32W(
2603 LPDWORD lpdwReserved,
2605 LPDWORD lpcchMaxSubkey,
2606 LPDWORD lpcchMaxClass,
2608 LPDWORD lpcchMaxValueName,
2609 LPDWORD lpccbMaxValueData,
2610 LPDWORD lpcbSecurityDescriptor,
2613 LPKEYSTRUCT lpkey,lpxkey;
2614 int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata;
2617 dprintf_reg(stddeb,"RegQueryInfoKey32W(%x,......)\n",hkey);
2618 lpkey=lookup_hkey(hkey);
2620 return SHELL_ERROR_BADKEY;
2623 if (lstrlen32W(lpkey->class)*2+2>*lpcchClass) {
2624 *lpcchClass=lstrlen32W(lpkey->class)*2;
2625 return ERROR_MORE_DATA;
2627 *lpcchClass=lstrlen32W(lpkey->class)*2;
2628 memcpy(lpszClass,lpkey->class,lstrlen32W(lpkey->class));
2635 *lpcchClass = lstrlen32W(lpkey->class)*2;
2637 lpxkey=lpkey->nextsub;
2638 nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
2641 if (lstrlen32W(lpxkey->keyname)>maxsubkey)
2642 maxsubkey=lstrlen32W(lpxkey->keyname);
2643 if (lpxkey->class && lstrlen32W(lpxkey->class)>maxclass)
2644 maxclass=lstrlen32W(lpxkey->class);
2645 if (lpxkey->nrofvalues>maxvalues)
2646 maxvalues=lpxkey->nrofvalues;
2647 for (i=0;i<lpxkey->nrofvalues;i++) {
2648 LPKEYVALUE val=lpxkey->values+i;
2650 if (val->name && lstrlen32W(val->name)>maxvname)
2651 maxvname=lstrlen32W(val->name);
2652 if (val->len>maxvdata)
2655 lpxkey=lpxkey->next;
2657 if (!maxclass) maxclass = 1;
2658 if (!maxvname) maxvname = 1;
2660 *lpcSubKeys = nrofkeys;
2662 *lpcchMaxSubkey = maxsubkey*2;
2664 *lpcchMaxClass = maxclass*2;
2666 *lpcValues = maxvalues;
2667 if (lpcchMaxValueName)
2668 *lpcchMaxValueName= maxvname;
2669 if (lpccbMaxValueData)
2670 *lpccbMaxValueData= maxvdata;
2671 return SHELL_ERROR_SUCCESS;
2674 /* RegQueryInfoKeyA [ADVAPI32.152] */
2675 DWORD RegQueryInfoKey32A(
2679 LPDWORD lpdwReserved,
2681 LPDWORD lpcchMaxSubkey,
2682 LPDWORD lpcchMaxClass,
2684 LPDWORD lpcchMaxValueName,
2685 LPDWORD lpccbMaxValueData,
2686 LPDWORD lpcbSecurityDescriptor,
2692 dprintf_reg(stddeb,"RegQueryInfoKey32A(%x,......)\n",hkey);
2695 lpszClassW = (LPWSTR)xmalloc(*lpcchClass);
2699 ret=RegQueryInfoKey32W(
2710 lpcbSecurityDescriptor,
2713 if (ret==ERROR_SUCCESS)
2714 strcpyWA(lpszClass,lpszClassW);
2721 if (lpcchMaxValueName)
2722 *lpcchMaxValueName/=2;