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.
227 void SHELL_StartupRegistry();
232 HKEY cl_r_hkey,c_u_hkey;
233 #define ADD_ROOT_KEY(xx) \
234 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
235 memset(xx,'\0',sizeof(KEYSTRUCT));\
236 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
238 ADD_ROOT_KEY(key_local_machine);
239 if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
240 fprintf(stderr,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
243 key_classes_root = lookup_hkey(cl_r_hkey);
245 ADD_ROOT_KEY(key_users);
248 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
249 * (later, when a win32 registry editing tool becomes avail.)
251 while (pwd=getpwent()) {
252 if (pwd->pw_name == NULL)
254 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
255 RegCloseKey(c_u_hkey);
258 pwd=getpwuid(getuid());
259 if (pwd && pwd->pw_name) {
260 RegCreateKey16(HKEY_USERS,pwd->pw_name,&c_u_hkey);
261 key_current_user = lookup_hkey(c_u_hkey);
263 ADD_ROOT_KEY(key_current_user);
265 ADD_ROOT_KEY(key_performance_data);
266 ADD_ROOT_KEY(key_current_config);
267 ADD_ROOT_KEY(key_dyn_data);
269 SHELL_StartupRegistry();
274 SHELL_StartupRegistry() {
277 char buf[200],cpubuf[200];
279 RegCreateKey16(HKEY_DYN_DATA,"\\PerfStats\\StatData",&xhkey);
281 RegCreateKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey);
283 F=fopen("/proc/cpuinfo","r");
286 while (NULL!=fgets(buf,200,F)) {
287 if (sscanf(buf,"processor\t: %d",&x)) {
292 RegCreateKey16(hkey,buf,&xhkey);
294 if (sscanf(buf,"cpu\t\t: %s",cpubuf)) {
295 sprintf(buf,"CPU %s",cpubuf);
297 RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,buf,strlen(buf));
307 RegCreateKey16(hkey,"0",&xhkey);
308 RegSetValueEx32A(xhkey,"Identifier",0,REG_SZ,"CPU 386",strlen("CPU 386"));
310 RegOpenKey16(HKEY_LOCAL_MACHINE,"\\HARDWARE\\DESCRIPTION\\System",&hkey);
311 RegSetValueEx32A(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
313 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
317 * string RegisteredOwner
318 * string RegisteredOrganization
321 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
326 if (-1!=gethostname(buf,200)) {
327 RegCreateKey16(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&xhkey);
328 RegSetValueEx16(xhkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
332 /************************ SAVE Registry Function ****************************/
334 #define REGISTRY_SAVE_VERSION 0x00000001
336 /* Registry saveformat:
337 * If you change it, increase above number by 1, which will flush
338 * old registry database files.
341 * "WINE REGISTRY Version %d"
345 * valuename=lastmodified,type,data
349 * keyname,valuename,stringdata:
350 * the usual ascii characters from 0x00-0xff (well, not 0x00)
351 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
352 * ( "=\\\t" escaped in \uXXXX form.)
356 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
358 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
359 * SaveOnlyUpdatedKeys=yes
362 _save_check_tainted(LPKEYSTRUCT lpkey) {
367 if (lpkey->flags & REG_OPTION_TAINTED)
372 if (_save_check_tainted(lpkey->nextsub)) {
373 lpkey->flags |= REG_OPTION_TAINTED;
382 _save_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
395 if (escapeeq && *s=='=')
398 fputc(*s,F); /* if \\ than put it twice. */
400 fprintf(F,"\\u%04x",*((unsigned short*)s));
408 _savesubkey(FILE *F,LPKEYSTRUCT lpkey,int level,int all) {
414 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
415 (all || (lpxkey->flags & REG_OPTION_TAINTED))
417 for (tabs=level;tabs--;)
419 _save_USTRING(F,lpxkey->keyname,1);
421 for (i=0;i<lpxkey->nrofvalues;i++) {
422 LPKEYVALUE val=lpxkey->values+i;
424 for (tabs=level+1;tabs--;)
426 _save_USTRING(F,val->name,0);
428 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
429 if ((1<<val->type) & UNICONVMASK)
430 _save_USTRING(F,(LPWSTR)val->data,0);
432 for (j=0;j<val->len;j++)
433 fprintf(F,"%02x",*((unsigned char*)val->data+j));
436 /* descend recursively */
437 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
446 _savesubreg(FILE *F,LPKEYSTRUCT lpkey,int all) {
447 fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
448 _save_check_tainted(lpkey->nextsub);
449 return _savesubkey(F,lpkey->nextsub,0,all);
453 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
458 fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
463 if (!_savesubreg(F,lpkey,all)) {
466 fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
473 SHELL_SaveRegistry() {
481 if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) {
487 if ( (ERROR_SUCCESS!=RegQueryValueEx32A(
499 if (lstrcmpi32A(buf,"yes"))
501 pwd=getpwuid(getuid());
502 if (pwd!=NULL && pwd->pw_dir!=NULL) {
503 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2);
504 strcpy(fn,pwd->pw_dir);
505 strcat(fn,WINE_PREFIX);
506 /* create the directory. don't care about errorcodes. */
507 mkdir(fn,0755); /* drwxr-xr-x */
508 strcat(fn,"/"SAVE_CURRENT_USER);
509 _savereg(key_current_user,fn,all);
511 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
512 strcpy(fn,pwd->pw_dir);
513 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
514 _savereg(key_local_machine,fn,all);
517 fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
520 /************************ LOAD Registry Function ****************************/
523 _find_or_add_key(LPKEYSTRUCT lpkey,LPWSTR keyname) {
524 LPKEYSTRUCT lpxkey,*lplpkey;
526 lplpkey= &(lpkey->nextsub);
529 if (!lstrcmp32W(lpxkey->keyname,keyname))
531 lplpkey = &(lpxkey->next);
535 *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
537 memset(lpxkey,'\0',sizeof(KEYSTRUCT));
538 lpxkey->keyname = keyname;
546 LPKEYSTRUCT lpkey,LPWSTR name,DWORD type,LPBYTE data,DWORD len,
552 for (i=0;i<lpkey->nrofvalues;i++) {
558 if ( val->name!=NULL &&
559 !lstrcmp32W(val->name,name)
564 if (i==lpkey->nrofvalues) {
565 lpkey->values = xrealloc(
567 (++lpkey->nrofvalues)*sizeof(KEYVALUE)
570 memset(val,'\0',sizeof(KEYVALUE));
576 if (val->lastmodified<lastmodified) {
577 val->lastmodified=lastmodified;
588 /* reads a line including dynamically enlarging the readbuffer and throwing
592 _wine_read_line(FILE *F,char **buf,int *len) {
601 s=fgets(curread,mylen,F);
604 if (NULL==(s=strchr(curread,'\n'))) {
605 /* buffer wasn't large enough */
606 curoff = strlen(*buf);
607 *buf = xrealloc(*buf,*len*2);
608 curread = *buf + curoff;
609 mylen = *len; /* we filled up the buffer and
610 * got new '*len' bytes to fill
618 /* throw away comments */
619 if (**buf=='#' || **buf==';') {
624 if (s) /* got end of line */
630 /* converts a char* into a UNICODE string (up to a special char)
631 * and returns the position exactly after that string
634 _wine_read_USTRING(char *buf,LPWSTR *str) {
638 /* read up to "=" or "\0" or "\n" */
641 /* empty string is the win3.1 default value(NULL)*/
645 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
647 while (*s && (*s!='\n') && (*s!='=')) {
649 *ws++=*((unsigned char*)s++);
658 fprintf(stderr,"_wine_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
666 memcpy(xbuf,s,4);xbuf[4]='\0';
667 if (!sscanf(xbuf,"%x",&wc))
668 fprintf(stderr,"_wine_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf);
670 *ws++ =(unsigned short)wc;
676 *str = strdupW(*str);
683 FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen,int optflag
690 lpkey->flags |= optflag;
692 /* good. we already got a line here ... so parse it */
702 fprintf(stderr,"_load_subkey:Got a subhierarchy without resp. key?\n");
705 _wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag);
708 /* let the caller handle this line */
709 if (i<level || **buf=='\0')
712 /* it can be: a value or a keyname. Parse the name first */
713 s=_wine_read_USTRING(s,&name);
715 /* switch() default: hack to avoid gotos */
719 lpxkey=_find_or_add_key(lpkey,name);
722 int len,lastmodified,type;
725 fprintf(stderr,"_wine_load_subkey:unexpected character: %c\n",*s);
729 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
730 fprintf(stderr,"_wine_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf);
736 if ((1<<type) & UNICONVMASK) {
737 s=_wine_read_USTRING(s,(LPWSTR*)&data);
739 len = lstrlen32W((LPWSTR)data)*2+2;
744 data = (LPBYTE)xmalloc(len+1);
745 for (i=0;i<len;i++) {
747 if (*s>='0' && *s<='9')
749 if (*s>='a' && *s<='f')
751 if (*s>='A' && *s<='F')
754 if (*s>='0' && *s<='9')
756 if (*s>='a' && *s<='f')
758 if (*s>='A' && *s<='F')
763 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
766 /* read the next line */
767 if (!_wine_read_line(F,buf,buflen))
774 _wine_loadsubreg(FILE *F,LPKEYSTRUCT lpkey,int optflag) {
779 buf=xmalloc(10);buflen=10;
780 if (!_wine_read_line(F,&buf,&buflen)) {
784 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
788 if (ver!=REGISTRY_SAVE_VERSION) {
789 dprintf_reg(stddeb,__FILE__":_wine_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
793 if (!_wine_read_line(F,&buf,&buflen)) {
797 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
806 _wine_loadreg(LPKEYSTRUCT lpkey,char *fn,int optflag) {
811 dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n",
816 if (!_wine_loadsubreg(F,lpkey,optflag)) {
825 _copy_registry(LPKEYSTRUCT from,LPKEYSTRUCT to) {
832 lpxkey = _find_or_add_key(to,strdupW(from->keyname));
834 for (j=0;j<from->nrofvalues;j++) {
838 valfrom = from->values+j;
840 if (name) name=strdupW(name);
841 data=(LPBYTE)malloc(valfrom->len);
842 memcpy(data,valfrom->data,valfrom->len);
850 valfrom->lastmodified
853 _copy_registry(from,lpxkey);
858 /* WINDOWS 95 REGISTRY LOADER */
860 * Structure of a win95 registry database.
864 * 8 : DWORD offset_of_RGDB_part
865 * 0C..1F: ? (someone fill in please)
870 * 4..0x1B: ? (fill in)
871 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
873 * Disk Key Entry Structure:
874 * 00: DWORD - unknown
875 * 04: DWORD - unknown
876 * 08: DWORD - unknown, but usually 0xFFFFFFFF on win95 systems
877 * 0C: DWORD - disk address of PreviousLevel Key.
878 * 10: DWORD - disk address of Next Sublevel Key.
879 * 14: DWORD - disk address of Next Key (on same level).
880 * DKEP>18: WORD - Nr, Low Significant part.
881 * 1A: WORD - Nr, High Significant part.
883 * The disk address always points to the nr part of the previous key entry
884 * of the referenced key. Don't ask me why, or even if I got this correct
885 * from staring at 1kg of hexdumps. (DKEP)
887 * The number of the entry is the low byte of the Low Significant Part ored
888 * with 0x100 * (low byte of the High Significant part)
889 * (C expression : nr = (nrLS & 0xFF) | ((nrHS &0xFF)<<8))
891 * There are two minor corrections to the position of that structure.
892 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
893 * the DKE reread from there.
894 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
895 * (FIXME: slightly better explanation needed here)
899 * 04: DWORD offset to next RGDB section (perhaps WORD)
904 * 00: DWORD nextkeyoffset - offset to the next disk key structure
905 * 08: WORD nrLS - low significant part of NR
906 * 0A: WORD nrHS - high significant part of NR
907 * 0C: DWORD bytesused - bytes used in this structure.
908 * 10: WORD name_len - length of name in bytes. without \0
909 * 12: WORD nr_of_values - number of values.
910 * 14: char name[name_len] - name string. No \0.
911 * 14+name_len: disk values
912 * nextkeyoffset: ... next disk key
915 * 00: DWORD type - value type (hmm, could be WORD too)
916 * 04: DWORD - unknown, usually 0
917 * 08: WORD namelen - length of Name. 0 means name=NULL
918 * 0C: WORD datalen - length of Data.
919 * 10: char name[namelen] - name, no \0
920 * 10+namelen: BYTE data[datalen] - data, without \0 if string
921 * 10+namelen+datalen: next values or disk key
923 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
924 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
925 * structure) and reading another RGDB_section.
926 * repeat until end of file.
928 * FIXME: this description needs some serious help, yes.
931 struct _w95keyvalue {
933 unsigned short datalen;
943 struct _w95keyvalue *values;
944 unsigned long dkeaddr;
949 struct _w95key *prevlvl;
950 struct _w95key *nextsub;
951 struct _w95key *next;
954 /* fast lookup table dkeaddr->nr */
956 unsigned long dkeaddr;
962 _w95_walk_tree(LPKEYSTRUCT lpkey,struct _w95key *key) {
968 if (key->name == NULL) {
969 fprintf(stderr,"_w95_walk_tree:Please report: key with dkeaddr %lx not loaded, skipping hierarchy\n",
974 lpxkey=_find_or_add_key(lpkey,strdupA2W(key->name));
976 if (key->nrofvals<0) {
977 /* shouldn't happen */
978 fprintf(stderr,"key %s already processed!\n",key->name);
982 for (i=0;i<key->nrofvals;i++) {
986 name = strdupA2W(key->values[i].name);
987 if (!*name) name = NULL;
988 free(key->values[i].name);
990 len = key->values[i].datalen;
991 data = key->values[i].data;
992 if ((1<<key->values[i].type) & UNICONVMASK) {
993 data = (BYTE*)strdupA2W(data);
994 len = lstrlen32W((LPWSTR)data)*2+2;
995 free(key->values[i].data);
1000 key->values[i].type,
1003 key->values[i].lastmodified
1010 key->nrofvals=-key->nrofvals-1;
1011 _w95_walk_tree(lpxkey,key->nextsub);
1016 /* small helper function to adjust address offset (dkeaddrs) */
1017 static unsigned long
1018 _w95_adj_da(unsigned long dkeaddr) {
1019 if ((dkeaddr&0xFFF)<0x018) {
1022 diff=0x1C-(dkeaddr&0xFFF);
1023 return dkeaddr+diff;
1025 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1026 /* readjust to 0x000,
1027 * but ONLY if we are >0x1000 already
1029 if (dkeaddr & ~0xFFF)
1030 return dkeaddr & ~0xFFF;
1036 _w95dkecomp(struct _w95nr2da *a,struct _w95nr2da *b){return a->dkeaddr-b->dkeaddr;}
1038 static struct _w95key*
1039 _w95dkelookup(unsigned long dkeaddr,int n,struct _w95nr2da *nr2da,struct _w95key *keys) {
1042 if (dkeaddr == 0xFFFFFFFF)
1046 dkeaddr=_w95_adj_da(dkeaddr+0x1c);
1047 off = (dkeaddr-0x3c)/0x1c;
1049 if (nr2da[(i+off)%n].dkeaddr == dkeaddr)
1050 return keys+nr2da[(i+off)%n].nr;
1051 /* 0x3C happens often, just report unusual values */
1053 dprintf_reg(stddeb,"search hasn't found dkeaddr %lx?\n",dkeaddr);
1057 extern time_t FileTimeToUnixTime(FILETIME*);
1060 _w95_loadreg(char* fn,LPKEYSTRUCT lpkey) {
1061 /* Disk Key Entry structure (RGKN part) */
1065 unsigned long x3;/*usually 0xFFFFFFFF */
1066 unsigned long prevlvl;
1067 unsigned long nextsub;
1069 unsigned short nrLS;
1070 unsigned short nrMS;
1072 /* Disk Key Header structure (RGDB part) */
1074 unsigned long nextkeyoff;
1075 unsigned short nrLS;
1076 unsigned short nrMS;
1077 unsigned long bytesused;
1078 unsigned short keynamelen;
1079 unsigned short values;
1082 /* disk key values or nothing */
1084 /* Disk Key Value structure */
1088 unsigned short valnamelen;
1089 unsigned short valdatalen;
1090 /* valname, valdata */
1092 struct _w95nr2da *nr2da;
1097 unsigned long nr,pos,i,where,version,rgdbsection,end,off_next_rgdb;
1098 struct _w95key *keys;
1100 unsigned char *data,*curdata,*nextrgdb;
1102 BY_HANDLE_FILE_INFORMATION hfdinfo;
1104 dprintf_reg(stddeb,"Loading Win95 registry database '%s'\n",fn);
1105 hfd=OpenFile(fn,&ofs,OF_READ);
1106 if (hfd==HFILE_ERROR)
1109 if (4!=_lread32(hfd,magic,4))
1111 if (strcmp(magic,"CREG")) {
1112 fprintf(stddeb,"%s is not a w95 registry.\n",fn);
1115 if (4!=_lread32(hfd,&version,4))
1117 if (4!=_lread32(hfd,&rgdbsection,4))
1119 if (-1==_llseek(hfd,0x20,SEEK_SET))
1121 if (4!=_lread32(hfd,magic,4))
1123 if (strcmp(magic,"RGKN")) {
1124 dprintf_reg(stddeb,"second IFF header not RGKN, but %s\n",magic);
1128 /* STEP 1: Keylink structures */
1129 if (-1==_llseek(hfd,0x40,SEEK_SET))
1134 nrofdkes = (end-where)/sizeof(struct dke)+100;
1135 data = (char*)xmalloc(end-where);
1136 if ((end-where)!=_lread32(hfd,data,end-where))
1140 keys = (struct _w95key*)xmalloc(nrofdkes * sizeof(struct _w95key));
1141 memset(keys,'\0',nrofdkes*sizeof(struct _w95key));
1142 nr2da= (struct _w95nr2da*)xmalloc(nrofdkes * sizeof(struct _w95nr2da));
1143 memset(nr2da,'\0',nrofdkes*sizeof(struct _w95nr2da));
1145 for (i=0;i<nrofdkes;i++) {
1147 unsigned long dkeaddr;
1149 pos=curdata-data+0x40;
1150 memcpy(&dke,curdata,sizeof(dke));
1151 curdata+=sizeof(dke);
1152 nr = dke.nrLS + (dke.nrMS<<8);
1154 if ((dkeaddr&0xFFF)<0x018) {
1157 diff=0x1C-(dkeaddr&0xFFF);
1159 curdata+=diff-sizeof(dke);
1160 memcpy(&dke,curdata,sizeof(dke));
1161 nr = dke.nrLS + (dke.nrMS<<8);
1162 curdata+=sizeof(dke);
1164 if (((dkeaddr+0x1C)&0xFFF)<0x1C) {
1165 /* readjust to 0x000,
1166 * but ONLY if we are >0x1000 already
1168 if (dkeaddr & ~0xFFF)
1169 dkeaddr = dkeaddr & ~0xFFF;
1172 /* 0xFFFFFFFF happens often, just report unusual values */
1174 dprintf_reg(stddeb,"nr %ld exceeds nrofdkes %d, skipping.\n",nr,nrofdkes);
1177 if (keys[nr].dkeaddr) {
1180 for (x=sizeof(dke);x--;)
1181 if (((char*)&dke)[x])
1184 break; /* finished reading if we got only 0 */
1186 if ( (dke.next!=(long)keys[nr].next) ||
1187 (dke.nextsub!=(long)keys[nr].nextsub) ||
1188 (dke.prevlvl!=(long)keys[nr].prevlvl)
1190 dprintf_reg(stddeb,"key doubled? nr=%ld,key->dkeaddr=%lx,dkeaddr=%lx\n",nr,keys[nr].dkeaddr,dkeaddr);
1195 nr2da[i].dkeaddr = dkeaddr;
1197 keys[nr].dkeaddr = dkeaddr;
1198 keys[nr].x1 = dke.x1;
1199 keys[nr].x2 = dke.x2;
1200 keys[nr].x3 = dke.x3;
1201 keys[nr].prevlvl= (struct _w95key*)dke.prevlvl;
1202 keys[nr].nextsub= (struct _w95key*)dke.nextsub;
1203 keys[nr].next = (struct _w95key*)dke.next;
1207 qsort(nr2da,nrofdkes,sizeof(nr2da[0]),
1208 (int(*)(const void *,const void*))_w95dkecomp);
1210 /* STEP 2: keydata & values */
1211 if (!GetFileInformationByHandle(hfd,&hfdinfo))
1213 end = hfdinfo.nFileSizeLow;
1214 lastmodified = FileTimeToUnixTime(&(hfdinfo.ftLastWriteTime));
1216 if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
1218 data = (char*)xmalloc(end-rgdbsection);
1219 if ((end-rgdbsection)!=_lread32(hfd,data,end-rgdbsection))
1223 memcpy(magic,curdata,4);
1224 memcpy(&off_next_rgdb,curdata+4,4);
1225 nextrgdb = curdata+off_next_rgdb;
1226 if (strcmp(magic,"RGDB")) {
1227 dprintf_reg(stddeb,"third IFF header not RGDB, but %s\n",magic);
1234 struct _w95key *key,xkey;
1237 if (curdata>=nextrgdb) {
1239 if (!strncmp(curdata,"RGDB",4)) {
1240 memcpy(&off_next_rgdb,curdata+4,4);
1241 nextrgdb = curdata+off_next_rgdb;
1244 dprintf_reg(stddeb,"at end of RGDB section, but no next header (%x of %lx). Breaking.\n",curdata-data,end-rgdbsection);
1248 #define XREAD(whereto,len) \
1249 if ((curdata-data+len)<end) {\
1250 memcpy(whereto,curdata,len);\
1255 XREAD(&dkh,sizeof(dkh));
1256 nr = dkh.nrLS + (dkh.nrMS<<8);
1257 if ((nr>nrofdkes) || (dkh.nrLS == 0xFFFF)) {
1258 if (dkh.nrLS == 0xFFFF) {
1259 /* skip over key using nextkeyoff */
1260 curdata+=dkh.nextkeyoff-sizeof(struct dkh);
1263 dprintf_reg(stddeb,"haven't found nr %ld.\n",nr);
1265 memset(key,'\0',sizeof(xkey));
1269 dprintf_reg(stddeb,"key with nr=%ld has no dkeaddr?\n",nr);
1271 key->nrofvals = dkh.values;
1272 key->name = (char*)xmalloc(dkh.keynamelen+1);
1274 XREAD(key->name,dkh.keynamelen);
1275 key->name[dkh.keynamelen]=0;
1276 if (key->nrofvals) {
1277 key->values = (struct _w95keyvalue*)xmalloc(
1278 sizeof(struct _w95keyvalue)*key->nrofvals
1280 for (i=0;i<key->nrofvals;i++) {
1283 XREAD(&dkv,sizeof(dkv));
1284 key->values[i].type = dkv.type;
1285 key->values[i].name = (char*)xmalloc(
1288 key->values[i].datalen = dkv.valdatalen;
1289 key->values[i].data = (unsigned char*)xmalloc(
1292 key->values[i].x1 = dkv.x1;
1293 XREAD(key->values[i].name,dkv.valnamelen);
1294 XREAD(key->values[i].data,dkv.valdatalen);
1295 key->values[i].data[dkv.valdatalen]=0;
1296 key->values[i].name[dkv.valnamelen]=0;
1297 key->values[i].lastmodified=lastmodified;
1300 if (bytesread != dkh.nextkeyoff) {
1301 if (dkh.bytesused != bytesread)
1303 "read has difference in read bytes (%d) and nextoffset (%ld) (bytesused=%ld)\n",bytesread,dkh.nextkeyoff,
1306 curdata += dkh.nextkeyoff-bytesread;
1308 key->prevlvl = _w95dkelookup((long)key->prevlvl,nrofdkes,nr2da,keys);
1309 key->nextsub = _w95dkelookup((long)key->nextsub,nrofdkes,nr2da,keys);
1310 key->next = _w95dkelookup((long)key->next,nrofdkes,nr2da,keys);
1315 _w95_walk_tree(lpkey,keys);
1320 SHELL_LoadRegistry() {
1327 if (key_classes_root==NULL)
1330 /* Load windows 95 entries */
1331 _w95_loadreg("C:\\system.1st", key_local_machine);
1332 _w95_loadreg("system.dat", key_local_machine);
1333 _w95_loadreg("user.dat", key_users);
1335 /* FIXME: win3.1 reg.dat loader still missing */
1337 /* the global user default is loaded under HKEY_USERS\\.Default */
1338 RegCreateKey16(HKEY_USERS,".Default",&hkey);
1339 lpkey = lookup_hkey(hkey);
1340 _wine_loadreg(lpkey,SAVE_USERS_DEFAULT,0);
1342 /* HKEY_USERS\\.Default is copied to HKEY_CURRENT_USER */
1343 _copy_registry(lpkey,key_current_user);
1346 /* the global machine defaults */
1347 _wine_loadreg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT,0);
1349 /* load the user saved registries */
1351 /* FIXME: use getenv("HOME") or getpwuid(getuid())->pw_dir ?? */
1353 pwd=getpwuid(getuid());
1354 if (pwd!=NULL && pwd->pw_dir!=NULL) {
1355 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
1356 strcpy(fn,pwd->pw_dir);
1357 strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
1358 _wine_loadreg(key_current_user,fn,REG_OPTION_TAINTED);
1360 fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
1361 strcpy(fn,pwd->pw_dir);
1362 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1363 _wine_loadreg(key_local_machine,fn,REG_OPTION_TAINTED);
1366 fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
1367 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) {
1368 DWORD junk,type,len;
1372 if (( RegQueryValueEx32A(
1379 )!=ERROR_SUCCESS) ||
1382 RegSetValueEx32A(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
1388 /********************* API FUNCTIONS ***************************************/
1392 * All functions are stubs to RegOpenKeyEx32W where all the
1395 * FIXME: security,options,desiredaccess,...
1398 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
1399 * RegOpenKey32W -> RegOpenKeyEx32W
1402 /* RegOpenKeyExW [ADVAPI32.150] */
1403 DWORD RegOpenKeyEx32W(
1410 LPKEYSTRUCT lpNextKey,lpxkey;
1413 dprintf_reg(stddeb,"RegOpenKeyEx32W(%lx,%s,%ld,%lx,%p)\n",
1414 (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey
1417 lpNextKey = lookup_hkey(hkey);
1419 return SHELL_ERROR_BADKEY;
1420 if (!lpszSubKey || !*lpszSubKey) {
1421 add_handle(++currenthandle,lpNextKey,samDesired);
1422 *retkey=currenthandle;
1423 return SHELL_ERROR_SUCCESS;
1425 split_keypath(lpszSubKey,&wps,&wpc);
1427 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1430 lpxkey=lpNextKey->nextsub;
1432 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1434 lpxkey=lpxkey->next;
1438 return SHELL_ERROR_BADKEY;
1443 add_handle(++currenthandle,lpxkey,samDesired);
1444 *retkey = currenthandle;
1446 return SHELL_ERROR_SUCCESS;
1449 /* RegOpenKeyW [ADVAPI32.151] */
1450 DWORD RegOpenKey32W(
1455 dprintf_reg(stddeb,"RegOpenKey32W(%lx,%s,%p)\n",
1456 (LONG)hkey,W2C(lpszSubKey,0),retkey
1458 return RegOpenKeyEx32W(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1462 /* RegOpenKeyExA [ADVAPI32.149] */
1463 DWORD RegOpenKeyEx32A(
1473 dprintf_reg(stddeb,"RegOpenKeyEx32A(%lx,%s,%ld,%lx,%p)\n",
1474 (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey
1477 lpszSubKeyW=strdupA2W(lpszSubKey);
1480 ret=RegOpenKeyEx32W(hkey,lpszSubKeyW,dwReserved,samDesired,retkey);
1486 /* RegOpenKeyA [ADVAPI32.148] */
1487 DWORD RegOpenKey32A(
1492 dprintf_reg(stddeb,"RegOpenKey32A(%lx,%s,%p)\n",
1493 (LONG)hkey,lpszSubKey,retkey
1495 return RegOpenKeyEx32A(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
1498 /* RegOpenKey [SHELL.1] [KERNEL.217] */
1504 dprintf_reg(stddeb,"RegOpenKey16(%lx,%s,%p)\n",
1505 (LONG)hkey,lpszSubKey,retkey
1507 return RegOpenKey32A(hkey,lpszSubKey,retkey);
1513 * All those functions convert their respective
1514 * arguments and call RegCreateKeyExW at the end.
1516 * FIXME: no security,no access attrib,no optionhandling yet.
1519 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKeyEx32A \
1520 * RegCreateKey32W -> RegCreateKeyEx32W
1523 /* RegCreateKeyExW [ADVAPI32.131] */
1524 DWORD RegCreateKeyEx32W(
1531 LPSECURITY_ATTRIBUTES lpSecAttribs,
1535 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
1539 /*FIXME: handle security/access/whatever */
1540 dprintf_reg(stddeb,"RegCreateKeyEx32W(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1552 lpNextKey = lookup_hkey(hkey);
1554 return SHELL_ERROR_BADKEY;
1555 if (!lpszSubKey || !*lpszSubKey) {
1556 add_handle(++currenthandle,lpNextKey,samDesired);
1557 *retkey=currenthandle;
1558 lpNextKey->flags|=REG_OPTION_TAINTED;
1559 return SHELL_ERROR_SUCCESS;
1561 split_keypath(lpszSubKey,&wps,&wpc);
1563 while ((i<wpc) && (wps[i][0]=='\0')) i++;
1566 lpxkey=lpNextKey->nextsub;
1568 if (!lstrcmp32W(wps[i],lpxkey->keyname))
1570 lpxkey=lpxkey->next;
1578 add_handle(++currenthandle,lpxkey,samDesired);
1579 lpxkey->flags |= REG_OPTION_TAINTED;
1580 *retkey = currenthandle;
1582 *lpDispos = REG_OPENED_EXISTING_KEY;
1584 return SHELL_ERROR_SUCCESS;
1586 /* good. now the hard part */
1588 lplpPrevKey = &(lpNextKey->nextsub);
1589 lpxkey = *lplpPrevKey;
1591 lplpPrevKey = &(lpxkey->next);
1592 lpxkey = *lplpPrevKey;
1594 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
1595 if (!*lplpPrevKey) {
1597 return SHELL_ERROR_OUTOFMEMORY;
1599 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
1600 (*lplpPrevKey)->keyname = strdupW(wps[i]);
1601 (*lplpPrevKey)->next = NULL;
1602 (*lplpPrevKey)->nextsub = NULL;
1603 (*lplpPrevKey)->values = NULL;
1604 (*lplpPrevKey)->nrofvalues = 0;
1605 (*lplpPrevKey)->flags = REG_OPTION_TAINTED;
1607 (*lplpPrevKey)->class = strdupW(lpszClass);
1609 (*lplpPrevKey)->class = NULL;
1610 lpNextKey = *lplpPrevKey;
1613 add_handle(++currenthandle,lpNextKey,samDesired);
1615 /*FIXME: flag handling correct? */
1616 lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
1618 lpNextKey->class = strdupW(lpszClass);
1620 lpNextKey->class = NULL;
1621 *retkey = currenthandle;
1623 *lpDispos = REG_CREATED_NEW_KEY;
1625 return SHELL_ERROR_SUCCESS;
1628 /* RegCreateKeyW [ADVAPI32.132] */
1629 DWORD RegCreateKey32W(
1636 dprintf_reg(stddeb,"RegCreateKey32W(%lx,%s,%p)\n",
1637 (LONG)hkey,W2C(lpszSubKey,0),retkey
1639 ret=RegCreateKeyEx32W(
1640 hkey, /* key handle */
1641 lpszSubKey, /* subkey name */
1642 0, /* reserved = 0 */
1643 NULL, /* lpszClass? FIXME: ? */
1644 REG_OPTION_NON_VOLATILE, /* options */
1645 KEY_ALL_ACCESS, /* desired access attribs */
1646 NULL, /* lpsecurity attributes */
1647 retkey, /* lpretkey */
1648 &junk /* disposition value */
1653 /* RegCreateKeyExA [ADVAPI32.130] */
1654 DWORD RegCreateKeyEx32A(
1661 LPSECURITY_ATTRIBUTES lpSecAttribs,
1665 LPWSTR lpszSubKeyW,lpszClassW;
1668 dprintf_reg(stddeb,"RegCreateKeyEx32A(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
1680 lpszSubKeyW=strdupA2W(lpszSubKey);
1684 lpszClassW=strdupA2W(lpszClass);
1687 ret=RegCreateKeyEx32W(
1705 /* RegCreateKeyA [ADVAPI32.129] */
1706 DWORD RegCreateKey32A(
1713 dprintf_reg(stddeb,"RegCreateKey32A(%lx,%s,%p)\n",
1714 (LONG)hkey,lpszSubKey,retkey
1716 return RegCreateKeyEx32A(
1717 hkey, /* key handle */
1718 lpszSubKey, /* subkey name */
1719 0, /* reserved = 0 */
1720 NULL, /* lpszClass? FIXME: ? */
1721 REG_OPTION_NON_VOLATILE,/* options */
1722 KEY_ALL_ACCESS, /* desired access attribs */
1723 NULL, /* lpsecurity attributes */
1724 retkey, /* lpretkey */
1725 &junk /* disposition value */
1729 /* RegCreateKey [SHELL.2] [KERNEL.218] */
1730 DWORD RegCreateKey16(
1735 dprintf_reg(stddeb,"RegCreateKey16(%lx,%s,%p)\n",
1736 (LONG)hkey,lpszSubKey,retkey
1738 return RegCreateKey32A(hkey,lpszSubKey,retkey);
1742 * Query Value Functions
1743 * Win32 differs between keynames and valuenames.
1744 * multiple values may belong to one key, the special value
1745 * with name NULL is the default value used by the win31
1749 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
1750 * RegQueryValue32W -> RegQueryValueEx32W
1753 /* RegQueryValueExW [ADVAPI32.158] */
1754 DWORD RegQueryValueEx32W(
1756 LPWSTR lpszValueName,
1757 LPDWORD lpdwReserved,
1765 dprintf_reg(stddeb,"RegQueryValueEx32W(%x,%s,%p,%p,%p,%ld)\n",
1766 hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,
1767 lpcbData?*lpcbData:0
1770 lpkey = lookup_hkey(hkey);
1772 return SHELL_ERROR_BADKEY;
1773 if (lpszValueName==NULL) {
1774 for (i=0;i<lpkey->nrofvalues;i++)
1775 if (lpkey->values[i].name==NULL)
1778 for (i=0;i<lpkey->nrofvalues;i++)
1779 if ( lpkey->values[i].name &&
1780 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
1784 if (i==lpkey->nrofvalues) {
1785 if (lpszValueName==NULL) {
1787 *(WCHAR*)lpbData = 0;
1792 return SHELL_ERROR_SUCCESS;
1794 return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
1797 *lpdwType = lpkey->values[i].type;
1798 if (lpbData==NULL) {
1800 return SHELL_ERROR_SUCCESS;
1801 *lpcbData = lpkey->values[i].len;
1802 return SHELL_ERROR_SUCCESS;
1804 if (*lpcbData<lpkey->values[i].len) {
1807 *lpcbData = lpkey->values[i].len;
1808 return ERROR_MORE_DATA;
1810 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
1811 *lpcbData = lpkey->values[i].len;
1812 return SHELL_ERROR_SUCCESS;
1815 /* RegQueryValueW [ADVAPI32.159] */
1816 DWORD RegQueryValue32W(
1825 dprintf_reg(stddeb,"RegQueryValue32W(%x,%s,%p,%ld)\n->",
1826 hkey,W2C(lpszSubKey,0),lpszData,
1827 lpcbData?*lpcbData:0
1830 /* only open subkey, if we really do descend */
1831 if (lpszSubKey && *lpszSubKey) {
1832 ret = RegOpenKey32W(hkey,lpszSubKey,&xhkey);
1833 if (ret!=ERROR_SUCCESS)
1839 ret = RegQueryValueEx32W(
1841 NULL, /* varname NULL -> compat */
1842 NULL, /* lpdwReserved, must be NULL */
1852 /* RegQueryValueExA [ADVAPI32.157] */
1853 DWORD RegQueryValueEx32A(
1855 LPSTR lpszValueName,
1856 LPDWORD lpdwReserved,
1861 LPWSTR lpszValueNameW;
1867 dprintf_reg(stddeb,"RegQueryValueEx32A(%x,%s,%p,%p,%p,%ld)\n->",
1868 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
1869 lpcbData?*lpcbData:0
1873 buf = (LPBYTE)xmalloc((*lpcbData)*2);
1874 myxlen = *lpcbData*2;
1879 myxlen = *lpcbData*2;
1885 lpszValueNameW=strdupA2W(lpszValueName);
1887 lpszValueNameW=NULL;
1891 ret=RegQueryValueEx32W(
1901 if (ret==ERROR_SUCCESS) {
1903 if (UNICONVMASK & (1<<(type))) {
1904 /* convert UNICODE to ASCII */
1905 strcpyWA(lpbData,(LPWSTR)buf);
1906 *lpcbData = myxlen/2;
1908 if (myxlen>*lpcbData)
1909 ret = ERROR_MORE_DATA;
1911 memcpy(lpbData,buf,myxlen);
1916 if ((UNICONVMASK & (1<<(type))) && lpcbData)
1917 *lpcbData = myxlen/2;
1920 if ((UNICONVMASK & (1<<(type))) && lpcbData)
1921 *lpcbData = myxlen/2;
1928 /* RegQueryValueEx [KERNEL.225] */
1929 DWORD RegQueryValueEx16(
1931 LPSTR lpszValueName,
1932 LPDWORD lpdwReserved,
1937 dprintf_reg(stddeb,"RegQueryValueEx16(%x,%s,%p,%p,%p,%ld)\n",
1938 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,
1939 lpcbData?*lpcbData:0
1941 return RegQueryValueEx32A(
1951 /* RegQueryValueA [ADVAPI32.156] */
1952 DWORD RegQueryValue32A(
1961 dprintf_reg(stddeb,"RegQueryValue32A(%x,%s,%p,%ld)\n",
1962 hkey,lpszSubKey,lpszData,
1963 lpcbData?*lpcbData:0
1966 /* only open subkey, if we really do descend */
1967 if (lpszSubKey && *lpszSubKey) {
1968 ret = RegOpenKey16(hkey,lpszSubKey,&xhkey);
1969 if (ret!=ERROR_SUCCESS)
1975 ret = RegQueryValueEx32A(
1977 NULL, /* lpszValueName NULL -> compat */
1978 NULL, /* lpdwReserved, must be NULL */
1988 /* RegQueryValue [SHELL.6] [KERNEL.224] */
1989 DWORD RegQueryValue16(
1995 dprintf_reg(stddeb,"RegQueryValue16(%x,%s,%p,%ld)\n",
1996 hkey,lpszSubKey,lpszData,lpcbData?*lpcbData:0
1998 /* HACK: the 16bit RegQueryValue doesn't handle selectorblocks
1999 * anyway, so we just mask out the high 16 bit.
2000 * (this (not so much incidently;) hopefully fixes Aldus FH4)
2003 *lpcbData &= 0xFFFF;
2004 return RegQueryValue32A(hkey,lpszSubKey,lpszData,lpcbData);
2008 * Setting values of Registry keys
2011 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
2012 * RegSetValue32W -> RegSetValueEx32W
2015 /* RegSetValueExW [ADVAPI32.170] */
2016 DWORD RegSetValueEx32W(
2018 LPWSTR lpszValueName,
2027 dprintf_reg(stddeb,"RegSetValueEx32W(%x,%s,%ld,%ld,%p,%ld)\n",
2028 hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData
2030 /* we no longer care about the lpbData type here... */
2031 lpkey = lookup_hkey(hkey);
2033 return SHELL_ERROR_BADKEY;
2035 lpkey->flags |= REG_OPTION_TAINTED;
2037 if (lpszValueName==NULL) {
2038 for (i=0;i<lpkey->nrofvalues;i++)
2039 if (lpkey->values[i].name==NULL)
2042 for (i=0;i<lpkey->nrofvalues;i++)
2043 if ( lpkey->values[i].name &&
2044 !lstrcmp32W(lpszValueName,lpkey->values[i].name)
2048 if (i==lpkey->nrofvalues) {
2049 lpkey->values = (LPKEYVALUE)xrealloc(
2051 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
2053 lpkey->nrofvalues++;
2054 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
2056 if (lpkey->values[i].name==NULL)
2058 lpkey->values[i].name = strdupW(lpszValueName);
2060 lpkey->values[i].name = NULL;
2061 lpkey->values[i].len = cbData;
2062 lpkey->values[i].type = dwType;
2063 if (lpkey->values[i].data !=NULL)
2064 free(lpkey->values[i].data);
2065 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
2066 lpkey->values[i].lastmodified = time(NULL);
2067 memcpy(lpkey->values[i].data,lpbData,cbData);
2068 return SHELL_ERROR_SUCCESS;
2071 /* RegSetValueExA [ADVAPI32.169] */
2072 DWORD RegSetValueEx32A(
2074 LPSTR lpszValueName,
2081 LPWSTR lpszValueNameW;
2084 dprintf_reg(stddeb,"RegSetValueEx32A(%x,%s,%ld,%ld,%p,%ld)\n->",
2085 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2087 if ((1<<dwType) & UNICONVMASK) {
2088 buf=(LPBYTE)strdupA2W(lpbData);
2089 cbData=2*strlen(lpbData)+2;
2093 lpszValueNameW = strdupA2W(lpszValueName);
2095 lpszValueNameW = NULL;
2096 ret=RegSetValueEx32W(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
2098 free(lpszValueNameW);
2104 /* RegSetValueEx [KERNEL.226] */
2105 DWORD RegSetValueEx16(
2107 LPSTR lpszValueName,
2113 dprintf_reg(stddeb,"RegSetValueEx16(%x,%s,%ld,%ld,%p,%ld)\n->",
2114 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
2116 return RegSetValueEx32A(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData);
2119 /* RegSetValueW [ADVAPI32.171] */
2120 DWORD RegSetValue32W(
2130 dprintf_reg(stddeb,"RegSetValue32W(%x,%s,%ld,%s,%ld)\n->",
2131 hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
2133 if (lpszSubKey && *lpszSubKey) {
2134 ret=RegCreateKey32W(hkey,lpszSubKey,&xhkey);
2135 if (ret!=ERROR_SUCCESS)
2139 if (dwType!=REG_SZ) {
2140 fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
2143 if (cbData!=2*lstrlen32W(lpszData)+2) {
2144 dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
2145 cbData,W2C(lpszData,0),2*lstrlen32W(lpszData)+2
2147 cbData=2*lstrlen32W(lpszData)+2;
2149 ret=RegSetValueEx32W(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2155 /* RegSetValueA [ADVAPI32.168] */
2156 DWORD RegSetValue32A(
2166 dprintf_reg(stddeb,"RegSetValue32A(%x,%s,%ld,%s,%ld)\n->",
2167 hkey,lpszSubKey,dwType,lpszData,cbData
2169 if (lpszSubKey && *lpszSubKey) {
2170 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
2171 if (ret!=ERROR_SUCCESS)
2176 if (dwType!=REG_SZ) {
2177 dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType);
2180 if (cbData!=strlen(lpszData)+1)
2181 cbData=strlen(lpszData)+1;
2182 ret=RegSetValueEx32A(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
2188 /* RegSetValue [KERNEL.221] [SHELL.5] */
2189 DWORD RegSetValue16(
2197 dprintf_reg(stddeb,"RegSetValue16(%x,%s,%ld,%s,%ld)\n->",
2198 hkey,lpszSubKey,dwType,lpszData,cbData
2200 ret=RegSetValue32A(hkey,lpszSubKey,dwType,lpszData,cbData);
2208 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
2209 * RegEnumKey32W -> RegEnumKeyEx32W
2212 /* RegEnumKeyExW [ADVAPI32.139] */
2213 DWORD RegEnumKeyEx32W(
2218 LPDWORD lpdwReserved,
2223 LPKEYSTRUCT lpkey,lpxkey;
2225 dprintf_reg(stddeb,"RegEnumKeyEx32W(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
2226 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2228 lpkey=lookup_hkey(hkey);
2230 return SHELL_ERROR_BADKEY;
2231 if (!lpkey->nextsub)
2232 return ERROR_NO_MORE_ITEMS;
2233 lpxkey=lpkey->nextsub;
2234 while (iSubkey && lpxkey) {
2236 lpxkey=lpxkey->next;
2238 if (iSubkey || !lpxkey)
2239 return ERROR_NO_MORE_ITEMS;
2240 if (2*lstrlen32W(lpxkey->keyname)+2>*lpcchName)
2241 return ERROR_MORE_DATA;
2242 memcpy(lpszName,lpxkey->keyname,lstrlen32W(lpxkey->keyname)*2+2);
2244 /* what should we write into it? */
2248 return ERROR_SUCCESS;
2252 /* RegEnumKeyW [ADVAPI32.140] */
2253 DWORD RegEnumKey32W(
2261 dprintf_reg(stddeb,"RegEnumKey32W(%x,%ld,%p,%ld)\n->",
2262 hkey,iSubkey,lpszName,lpcchName
2264 return RegEnumKeyEx32W(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
2266 /* RegEnumKeyExA [ADVAPI32.138] */
2267 DWORD RegEnumKeyEx32A(
2272 LPDWORD lpdwReserved,
2277 DWORD ret,lpcchNameW,lpcchClassW;
2278 LPWSTR lpszNameW,lpszClassW;
2281 dprintf_reg(stddeb,"RegEnumKeyEx32A(%x,%ld,%p,%ld,%p,%p,%p,%p)\n->",
2282 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
2285 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
2286 lpcchNameW = *lpcchName*2;
2292 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
2293 lpcchClassW = *lpcchClass*2;
2298 ret=RegEnumKeyEx32W(
2308 if (ret==ERROR_SUCCESS) {
2309 strcpyWA(lpszName,lpszNameW);
2310 *lpcchName=strlen(lpszName);
2312 strcpyWA(lpszClass,lpszClassW);
2313 *lpcchClass=strlen(lpszClass);
2323 /* RegEnumKeyA [ADVAPI32.137] */
2324 DWORD RegEnumKey32A(
2332 dprintf_reg(stddeb,"RegEnumKey32A(%x,%ld,%p,%ld)\n->",
2333 hkey,iSubkey,lpszName,lpcchName
2335 return RegEnumKeyEx32A(
2347 /* RegEnumKey [SHELL.7] [KERNEL.216] */
2354 dprintf_reg(stddeb,"RegEnumKey16(%x,%ld,%p,%ld)\n->",
2355 hkey,iSubkey,lpszName,lpcchName
2357 return RegEnumKey32A(hkey,iSubkey,lpszName,lpcchName);
2361 * Enumerate Registry Values
2364 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
2367 /* RegEnumValueW [ADVAPI32.142] */
2368 DWORD RegEnumValue32W(
2373 LPDWORD lpdReserved,
2381 dprintf_reg(stddeb,"RegEnumValue32W(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2382 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2384 lpkey = lookup_hkey(hkey);
2386 return SHELL_ERROR_BADKEY;
2387 if (lpkey->nrofvalues<=iValue)
2388 return ERROR_NO_MORE_ITEMS;
2389 val = lpkey->values+iValue;
2392 if (lstrlen32W(val->name)*2+2>*lpcchValue) {
2393 *lpcchValue = lstrlen32W(val->name)*2+2;
2394 return ERROR_MORE_DATA;
2396 memcpy(lpszValue,val->name,2*lstrlen32W(val->name)+2);
2397 *lpcchValue=lstrlen32W(val->name)*2+2;
2399 /* how to handle NULL value? */
2403 *lpdwType=val->type;
2405 if (val->len>*lpcbData)
2406 return ERROR_MORE_DATA;
2407 memcpy(lpbData,val->data,val->len);
2408 *lpcbData = val->len;
2410 return SHELL_ERROR_SUCCESS;
2413 /* RegEnumValueA [ADVAPI32.141] */
2414 DWORD RegEnumValue32A(
2419 LPDWORD lpdReserved,
2426 DWORD ret,lpcbDataW;
2428 dprintf_reg(stddeb,"RegEnumValue32A(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2429 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2432 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
2434 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
2435 lpcbDataW = *lpcbData*2;
2438 ret=RegEnumValue32W(
2449 if (ret==ERROR_SUCCESS) {
2450 strcpyWA(lpszValue,lpszValueW);
2452 if ((1<<*lpdwType) & UNICONVMASK) {
2453 strcpyWA(lpbData,(LPWSTR)lpbDataW);
2455 if (lpcbDataW > *lpcbData)
2456 ret = ERROR_MORE_DATA;
2458 memcpy(lpbData,lpbDataW,lpcbDataW);
2460 *lpcbData = lpcbDataW;
2470 /* RegEnumValue [KERNEL.223] */
2471 DWORD RegEnumValue16(
2476 LPDWORD lpdReserved,
2481 dprintf_reg(stddeb,"RegEnumValue(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
2482 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
2484 return RegEnumValue32A(
2497 * Close registry key
2499 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
2500 DWORD RegCloseKey(HKEY hkey) {
2501 dprintf_reg(stddeb,"RegCloseKey(%x)\n",hkey);
2502 remove_handle(hkey);
2503 return ERROR_SUCCESS;
2506 * Delete registry key
2509 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
2511 /* RegDeleteKeyW [ADVAPI32.134] */
2512 DWORD RegDeleteKey32W(HKEY hkey,LPWSTR lpszSubKey) {
2513 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2517 dprintf_reg(stddeb,"RegDeleteKey32W(%x,%s)\n",
2518 hkey,W2C(lpszSubKey,0)
2520 lpNextKey = lookup_hkey(hkey);
2522 return SHELL_ERROR_BADKEY;
2523 /* we need to know the previous key in the hier. */
2524 if (!lpszSubKey || !*lpszSubKey)
2525 return SHELL_ERROR_BADKEY;
2526 split_keypath(lpszSubKey,&wps,&wpc);
2530 lpxkey=lpNextKey->nextsub;
2532 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2534 lpxkey=lpxkey->next;
2538 /* not found is success */
2539 return SHELL_ERROR_SUCCESS;
2544 lpxkey = lpNextKey->nextsub;
2545 lplpPrevKey = &(lpNextKey->nextsub);
2547 if (!lstrcmp32W(wps[i],lpxkey->keyname))
2549 lplpPrevKey = &(lpxkey->next);
2550 lpxkey = lpxkey->next;
2553 return SHELL_ERROR_SUCCESS;
2554 if (lpxkey->nextsub)
2555 return SHELL_ERROR_CANTWRITE;
2556 *lplpPrevKey = lpxkey->next;
2557 free(lpxkey->keyname);
2559 free(lpxkey->class);
2561 free(lpxkey->values);
2564 return SHELL_ERROR_SUCCESS;
2567 /* RegDeleteKeyA [ADVAPI32.133] */
2568 DWORD RegDeleteKey32A(HKEY hkey,LPCSTR lpszSubKey) {
2572 dprintf_reg(stddeb,"RegDeleteKey32A(%x,%s)\n",
2575 lpszSubKeyW=strdupA2W(lpszSubKey);
2576 ret=RegDeleteKey32W(hkey,lpszSubKeyW);
2581 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
2582 DWORD RegDeleteKey16(HKEY hkey,LPCSTR lpszSubKey) {
2583 dprintf_reg(stddeb,"RegDeleteKey16(%x,%s)\n",
2586 return RegDeleteKey32A(hkey,lpszSubKey);
2590 * Delete registry value
2593 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
2595 /* RegDeleteValueW [ADVAPI32.136] */
2596 DWORD RegDeleteValue32W(HKEY hkey,LPWSTR lpszValue) {
2601 dprintf_reg(stddeb,"RegDeleteValue32W(%x,%s)\n",
2602 hkey,W2C(lpszValue,0)
2604 lpkey=lookup_hkey(hkey);
2606 return SHELL_ERROR_BADKEY;
2608 for (i=0;i<lpkey->nrofvalues;i++)
2609 if ( lpkey->values[i].name &&
2610 !lstrcmp32W(lpkey->values[i].name,lpszValue)
2614 for (i=0;i<lpkey->nrofvalues;i++)
2615 if (lpkey->values[i].name==NULL)
2618 if (i==lpkey->nrofvalues)
2619 return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */
2620 val = lpkey->values+i;
2621 if (val->name) free(val->name);
2622 if (val->data) free(val->data);
2626 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
2628 lpkey->values = (LPKEYVALUE)xrealloc(
2630 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
2632 lpkey->nrofvalues--;
2633 return SHELL_ERROR_SUCCESS;
2636 /* RegDeleteValueA [ADVAPI32.135] */
2637 DWORD RegDeleteValue32A(HKEY hkey,LPSTR lpszValue) {
2641 dprintf_reg( stddeb, "RegDeleteValue32A(%x,%s)\n", hkey,lpszValue );
2643 lpszValueW=strdupA2W(lpszValue);
2646 ret=RegDeleteValue32W(hkey,lpszValueW);
2652 /* RegDeleteValue [KERNEL.222] */
2653 DWORD RegDeleteValue16(HKEY hkey,LPSTR lpszValue) {
2654 dprintf_reg( stddeb,"RegDeleteValue16(%x,%s)\n", hkey,lpszValue );
2655 return RegDeleteValue32A(hkey,lpszValue);
2658 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
2659 DWORD RegFlushKey(HKEY hkey) {
2660 dprintf_reg(stddeb,"RegFlushKey(%x), STUB.\n",hkey);
2661 return SHELL_ERROR_SUCCESS;
2664 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
2666 /* RegQueryInfoKeyW [ADVAPI32.153] */
2667 DWORD RegQueryInfoKey32W(
2671 LPDWORD lpdwReserved,
2673 LPDWORD lpcchMaxSubkey,
2674 LPDWORD lpcchMaxClass,
2676 LPDWORD lpcchMaxValueName,
2677 LPDWORD lpccbMaxValueData,
2678 LPDWORD lpcbSecurityDescriptor,
2681 LPKEYSTRUCT lpkey,lpxkey;
2682 int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata;
2685 dprintf_reg(stddeb,"RegQueryInfoKey32W(%x,......)\n",hkey);
2686 lpkey=lookup_hkey(hkey);
2688 return SHELL_ERROR_BADKEY;
2691 if (lstrlen32W(lpkey->class)*2+2>*lpcchClass) {
2692 *lpcchClass=lstrlen32W(lpkey->class)*2;
2693 return ERROR_MORE_DATA;
2695 *lpcchClass=lstrlen32W(lpkey->class)*2;
2696 memcpy(lpszClass,lpkey->class,lstrlen32W(lpkey->class));
2703 *lpcchClass = lstrlen32W(lpkey->class)*2;
2705 lpxkey=lpkey->nextsub;
2706 nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
2709 if (lstrlen32W(lpxkey->keyname)>maxsubkey)
2710 maxsubkey=lstrlen32W(lpxkey->keyname);
2711 if (lpxkey->class && lstrlen32W(lpxkey->class)>maxclass)
2712 maxclass=lstrlen32W(lpxkey->class);
2713 if (lpxkey->nrofvalues>maxvalues)
2714 maxvalues=lpxkey->nrofvalues;
2715 for (i=0;i<lpxkey->nrofvalues;i++) {
2716 LPKEYVALUE val=lpxkey->values+i;
2718 if (val->name && lstrlen32W(val->name)>maxvname)
2719 maxvname=lstrlen32W(val->name);
2720 if (val->len>maxvdata)
2723 lpxkey=lpxkey->next;
2725 if (!maxclass) maxclass = 1;
2726 if (!maxvname) maxvname = 1;
2728 *lpcSubKeys = nrofkeys;
2730 *lpcchMaxSubkey = maxsubkey*2;
2732 *lpcchMaxClass = maxclass*2;
2734 *lpcValues = maxvalues;
2735 if (lpcchMaxValueName)
2736 *lpcchMaxValueName= maxvname;
2737 if (lpccbMaxValueData)
2738 *lpccbMaxValueData= maxvdata;
2739 return SHELL_ERROR_SUCCESS;
2742 /* RegQueryInfoKeyA [ADVAPI32.152] */
2743 DWORD RegQueryInfoKey32A(
2747 LPDWORD lpdwReserved,
2749 LPDWORD lpcchMaxSubkey,
2750 LPDWORD lpcchMaxClass,
2752 LPDWORD lpcchMaxValueName,
2753 LPDWORD lpccbMaxValueData,
2754 LPDWORD lpcbSecurityDescriptor,
2760 dprintf_reg(stddeb,"RegQueryInfoKey32A(%x,......)\n",hkey);
2763 lpszClassW = (LPWSTR)xmalloc(*lpcchClass);
2767 ret=RegQueryInfoKey32W(
2778 lpcbSecurityDescriptor,
2781 if (ret==ERROR_SUCCESS)
2782 strcpyWA(lpszClass,lpszClassW);
2789 if (lpcchMaxValueName)
2790 *lpcchMaxValueName/=2;