/* * Registry Functions * * Copyright 1996 Marcus Meissner */ #include #include #include #include #include #include #include #include #include #include #include #include "windows.h" #include "win.h" #include "winerror.h" #include "string32.h" #include "stddebug.h" #include "debug.h" #include "xmalloc.h" #include "winreg.h" /* FIXME: following defines should be configured global ... */ /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */ #define WINE_PREFIX "/.wine" #define SAVE_CURRENT_USER_DEFAULT "/usr/local/etc/wine.userreg" /* relative in ~user/.wine/ */ #define SAVE_CURRENT_USER "user.reg" #define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg" /* relative in ~user/.wine/ */ #define SAVE_LOCAL_MACHINE "system.reg" static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */ static KEYSTRUCT *key_current_user=NULL; /* user specific values */ static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */ static KEYSTRUCT *key_users=NULL; /* all users? */ /* dynamic, not saved */ static KEYSTRUCT *key_performance_data=NULL; static KEYSTRUCT *key_current_config=NULL; static KEYSTRUCT *key_dyn_data=NULL; /* what valuetypes do we need to convert? */ #define UNICONVMASK ((1<"; if (sub!=0 && sub!=1) return ""; if (unicodedebug[sub]) free(unicodedebug[sub]); unicodedebug[sub] = strdupW2A(x); return unicodedebug[sub]; } static LPKEYSTRUCT lookup_hkey(HKEY hkey) { switch (hkey) { case 0x00000000: case 0x00000001: case HKEY_CLASSES_ROOT: return key_classes_root; case HKEY_CURRENT_USER: return key_current_user; case HKEY_LOCAL_MACHINE: return key_local_machine; case HKEY_USERS: return key_users; case HKEY_PERFORMANCE_DATA: return key_performance_data; case HKEY_DYN_DATA: return key_dyn_data; case HKEY_CURRENT_CONFIG: return key_current_config; default: dprintf_reg(stddeb,"lookup_hkey(%lx), special key!\n", (LONG)hkey ); return get_handle(hkey); } /*NOTREACHED*/ } /* * splits the unicode string 'wp' into an array of strings. * the array is allocated by this function. * the number of components will be stored in 'wpc' * Free the array using FREE_KEY_PATH */ static void split_keypath(LPCWSTR wp,LPWSTR **wpv,int *wpc) { int i,j,len; LPWSTR ws; ws = strdupW(wp); *wpc = 1; for (i=0;ws[i];i++) { if (ws[i]=='\\') { ws[i]=0; (*wpc)++; } } len = i; *wpv = (LPWSTR*)xmalloc(sizeof(LPWSTR)*(*wpc+2)); (*wpv)[0]= ws; j = 1; for (i=1;ikeyname= strdupA2W(""); ADD_ROOT_KEY(key_local_machine); if (RegCreateKey(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) { fprintf(stderr,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n"); exit(1); } key_classes_root = lookup_hkey(cl_r_hkey); ADD_ROOT_KEY(key_users); #if 0 /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg * (later, when a win32 registry editing tool becomes avail.) */ while (pwd=getpwent()) { if (pwd->pw_name == NULL) continue; RegCreateKey(HKEY_USERS,pwd->pw_name,&c_u_hkey); RegCloseKey(c_u_hkey); } #endif pwd=getpwuid(getuid()); if (pwd && pwd->pw_name) { RegCreateKey(HKEY_USERS,pwd->pw_name,&c_u_hkey); key_current_user = lookup_hkey(c_u_hkey); } else { ADD_ROOT_KEY(key_current_user); } ADD_ROOT_KEY(key_performance_data); ADD_ROOT_KEY(key_current_config); ADD_ROOT_KEY(key_dyn_data); #undef ADD_ROOT_KEY } /************************ SAVE Registry Function ****************************/ #define REGISTRY_SAVE_VERSION 0x00000001 /* Registry saveformat: * If you change it, increase above number by 1, which will flush * old registry database files. * * Global: * "WINE REGISTRY Version %d" * subkeys.... * Subkeys: * keyname * valuename=lastmodified,type,data * ... * subkeys * ... * keyname,valuename,stringdata: * the usual ascii characters from 0x00-0xff (well, not 0x00) * and \uXXXX as UNICODE value XXXX with XXXX>0xff * ( "=\\\t" escaped in \uXXXX form.) * type,lastmodified: * int * * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags. */ static void _write_USTRING(FILE *F,LPWSTR wstr,int escapeeq) { LPWSTR s; int doescape; if (wstr==NULL) { /* FIXME: NULL equals empty string... I hope * the empty string isn't a valid valuename */ return; } s=wstr; while (*s) { doescape=0; if (*s>0xff) doescape = 1; if (*s=='\n') doescape = 1; if (escapeeq && *s=='=') doescape = 1; if (*s=='\\') fputc(*s,F); /* if \\ than put it twice. */ if (doescape) fprintf(F,"\\u%04x",*((unsigned short*)s)); else fputc(*s,F); s++; } } static int _do_save_subkey(FILE *F,LPKEYSTRUCT lpkey,int level) { LPKEYSTRUCT lpxkey; int i,tabs,j; lpxkey = lpkey; while (lpxkey) { if (!(lpxkey->flags & REG_OPTION_VOLATILE)) { for (tabs=level;tabs--;) fputc('\t',F); _write_USTRING(F,lpxkey->keyname,1); fputs("\n",F); for (i=0;inrofvalues;i++) { LPKEYVALUE val=lpxkey->values+i; for (tabs=level+1;tabs--;) fputc('\t',F); _write_USTRING(F,val->name,0); fputc('=',F); fprintf(F,"%ld,%ld,",val->type,val->lastmodified); if ((1<type) & UNICONVMASK) _write_USTRING(F,(LPWSTR)val->data,0); else for (j=0;jlen;j++) fprintf(F,"%02x",*((unsigned char*)val->data+j)); fputs("\n",F); } /* descend recursively */ if (!_do_save_subkey(F,lpxkey->nextsub,level+1)) return 0; } lpxkey=lpxkey->next; } return 1; } static int _do_savesubreg(FILE *F,LPKEYSTRUCT lpkey) { fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION); return _do_save_subkey(F,lpkey->nextsub,0); } static void _SaveSubReg(LPKEYSTRUCT lpkey,char *fn) { FILE *F; F=fopen(fn,"w"); if (F==NULL) { fprintf(stddeb,__FILE__":_SaveSubReg:Couldn't open %s for writing: %s\n", fn,strerror(errno) ); return; } if (!_do_savesubreg(F,lpkey)) { fclose(F); unlink(fn); fprintf(stddeb,__FILE__":_SaveSubReg:Failed to save keys, perhaps no more diskspace for %s?\n",fn); return; } fclose(F); } void SHELL_SaveRegistry() { char *fn; struct passwd *pwd; pwd=getpwuid(getuid()); if (pwd!=NULL && pwd->pw_dir!=NULL) { fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2); strcpy(fn,pwd->pw_dir); strcat(fn,WINE_PREFIX); /* create the directory. don't care about errorcodes. */ mkdir(fn,0755); /* drwxr-xr-x */ strcat(fn,"/"SAVE_CURRENT_USER); _SaveSubReg(key_current_user,fn); free(fn); fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2); strcpy(fn,pwd->pw_dir); strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE); _SaveSubReg(key_local_machine,fn); free(fn); } else { fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid()); } } /************************ LOAD Registry Function ****************************/ /* reads a line including dynamically enlarging the readbuffer and throwing * away comments */ static int _read_line(FILE *F,char **buf,int *len) { char *s,*curread; int mylen,curoff; curread = *buf; mylen = *len; **buf = '\0'; while (1) { while (1) { s=fgets(curread,mylen,F); if (s==NULL) return 0; /* EOF */ if (NULL==(s=strchr(curread,'\n'))) { /* buffer wasn't large enough */ curoff = strlen(*buf); *buf = xrealloc(*buf,*len*2); curread = *buf + curoff; mylen = *len; /* we filled up the buffer and * got new '*len' bytes to fill */ *len = *len * 2; } else { *s='\0'; break; } } /* throw away comments */ if (**buf=='#' || **buf==';') { curread = *buf; mylen = *len; continue; } if (s) /* got end of line */ break; } return 1; } /* converts a char* into a UNICODE string (up to a special char) * and returns the position exactly after that string */ static char* _read_USTRING(char *buf,LPWSTR *str) { char *s; LPWSTR ws; /* read up to "=" or "\0" or "\n" */ s = buf; if (*s == '=') { /* empty string is the win3.1 default value(NULL)*/ *str = NULL; return s; } *str = (LPWSTR)xmalloc(2*strlen(buf)+2); ws = *str; while (*s && (*s!='\n') && (*s!='=')) { if (*s!='\\') *ws++=*((unsigned char*)s++); else { s++; if (*s=='\\') { *ws+='\\'; s++; continue; } if (*s!='u') { fprintf(stderr,"_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf); *ws++='\\'; *ws++=*s++; } else { char xbuf[5]; int wc; s++; memcpy(xbuf,s,4);xbuf[4]='\0'; if (!sscanf(xbuf,"%x",&wc)) fprintf(stderr,"_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf); s+=4; *ws++ =(unsigned short)wc; } } } *ws = 0; ws = *str; *str = strdupW(*str); free(ws); return s; } static int _do_load_subkey(FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen) { LPKEYSTRUCT lpxkey,*lplpkey; int i; char *s; LPWSTR name; /* good. we already got a line here ... so parse it */ lpxkey = NULL; while (1) { i=0;s=*buf; while (*s=='\t') { s++; i++; } if (i>level) { if (lpxkey==NULL) { fprintf(stderr,"_do_load_subkey:Got a subhierarchy without resp. key?\n"); return 0; } _do_load_subkey(F,lpxkey,level+1,buf,buflen); continue; } /* let the caller handle this line */ if (inextsub); lpxkey = *lplpkey; while (lpxkey) { if (!strcmpW(lpxkey->keyname,name)) break; lplpkey = &(lpxkey->next); lpxkey = *lplpkey; } if (lpxkey==NULL) { /* we have no key with that name yet. allocate * it. */ *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT)); lpxkey = *lplpkey; memset(lpxkey,'\0',sizeof(KEYSTRUCT)); lpxkey->keyname = name; } else { /* already got it. we just remember it in * 'lpxkey' */ free(name); } } else { LPKEYVALUE val=NULL; LPBYTE data; int len,lastmodified,type; if (*s!='=') { fprintf(stderr,"_do_load_subkey:unexpected character: %c\n",*s); break; } /* good. this looks like a value to me */ s++; for (i=0;inrofvalues;i++) { val=lpkey->values+i; if (name==NULL) { if (val->name==NULL) break; } else { if ( val->name!=NULL && !strcmpW(val->name,name) ) break; } } if (i==lpkey->nrofvalues) { lpkey->values = xrealloc( lpkey->values, (++lpkey->nrofvalues)*sizeof(KEYVALUE) ); val=lpkey->values+i; memset(val,'\0',sizeof(KEYVALUE)); val->name = name; } else { /* value already exists, free name */ free(name); } if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) { fprintf(stderr,"_do_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf); break; } /* skip the 2 , */ s=strchr(s,',');s++; s=strchr(s,',');s++; if ((1<='0' && *s<='9') data[i]=(*s-'0')<<4; if (*s>='a' && *s<='f') data[i]=(*s-'a')<<4; if (*s>='A' && *s<='F') data[i]=(*s-'A')<<4; s++; if (*s>='0' && *s<='9') data[i]|=*s-'0'; if (*s>='a' && *s<='f') data[i]|=*s-'a'; if (*s>='A' && *s<='F') data[i]|=*s-'A'; s++; } } if (val->lastmodifiedlastmodified=lastmodified; val->type = type; val->len = len; if (val->data) free(val->data); val->data = data; } else { free(data); } } } /* read the next line */ if (!_read_line(F,buf,buflen)) return 1; } return 1; } static int _do_loadsubreg(FILE *F,LPKEYSTRUCT lpkey) { int ver; char *buf; int buflen; buf=xmalloc(10);buflen=10; if (!_read_line(F,&buf,&buflen)) { free(buf); return 0; } if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) { free(buf); return 0; } if (ver!=REGISTRY_SAVE_VERSION) { dprintf_reg(stddeb,__FILE__":_do_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf); free(buf); return 0; } if (!_read_line(F,&buf,&buflen)) { free(buf); return 0; } if (!_do_load_subkey(F,lpkey,0,&buf,&buflen)) { free(buf); /* FIXME: memory leak on failure to read registry ... * But this won't happen very often. */ lpkey->nextsub=NULL; return 0; } free(buf); return 1; } static void _LoadSubReg(LPKEYSTRUCT lpkey,char *fn) { FILE *F; F=fopen(fn,"rb"); if (F==NULL) { dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n", fn,strerror(errno) ); return; } if (!_do_loadsubreg(F,lpkey)) { fclose(F); unlink(fn); return; } fclose(F); } void SHELL_LoadRegistry() { char *fn; struct passwd *pwd; if (key_classes_root==NULL) SHELL_Init(); /* load the machine-wide defaults first */ _LoadSubReg(key_current_user,SAVE_CURRENT_USER_DEFAULT); _LoadSubReg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT); /* load the user saved registry. overwriting only newer entries */ pwd=getpwuid(getuid()); if (pwd!=NULL && pwd->pw_dir!=NULL) { fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2); strcpy(fn,pwd->pw_dir); strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER); _LoadSubReg(key_current_user,fn); free(fn); fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2); strcpy(fn,pwd->pw_dir); strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE); _LoadSubReg(key_local_machine,fn); free(fn); } else { fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid()); } /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg * (later, when a win32 registry editing tool becomes avail.) */ } /********************* API FUNCTIONS ***************************************/ /* * Open Keys. * * All functions are stubs to RegOpenKeyExW where all the * magic happens. * * FIXME: security,options,desiredaccess,... * * Callpath: * RegOpenKey -> RegOpenKeyA -> RegOpenKeyExA \ * RegOpenKeyW -> RegOpenKeyExW */ /* RegOpenKeyExW [ADVAPI32.150] */ WINAPI DWORD RegOpenKeyExW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwReserved, REGSAM samDesired, LPHKEY retkey ) { LPKEYSTRUCT lpNextKey,lpxkey; LPWSTR *wps; int wpc,i; dprintf_reg(stddeb,"RegOpenKeyExW(%lx,%s,%ld,%lx,%p)\n", (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey ); lpNextKey = lookup_hkey(hkey); if (!lpNextKey) return SHELL_ERROR_BADKEY; if (!lpszSubKey || !*lpszSubKey) { add_handle(++currenthandle,lpNextKey,samDesired); *retkey=currenthandle; return SHELL_ERROR_SUCCESS; } split_keypath(lpszSubKey,&wps,&wpc); i = 0; while ((inextsub; while (lpxkey) { if (!strcmpW(wps[i],lpxkey->keyname)) break; lpxkey=lpxkey->next; } if (!lpxkey) { FREE_KEY_PATH; return SHELL_ERROR_BADKEY; } i++; lpNextKey = lpxkey; } add_handle(++currenthandle,lpxkey,samDesired); *retkey = currenthandle; FREE_KEY_PATH; return SHELL_ERROR_SUCCESS; } /* RegOpenKeyW [ADVAPI32.151] */ WINAPI DWORD RegOpenKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey ) { dprintf_reg(stddeb,"RegOpenKeyW(%lx,%s,%p)\n", (LONG)hkey,W2C(lpszSubKey,0),retkey ); return RegOpenKeyExW(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey); } /* RegOpenKeyExA [ADVAPI32.149] */ WINAPI DWORD RegOpenKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved, REGSAM samDesired, LPHKEY retkey ) { LPWSTR lpszSubKeyW; DWORD ret; dprintf_reg(stddeb,"RegOpenKeyExA(%lx,%s,%ld,%lx,%p)\n", (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey ); if (lpszSubKey) lpszSubKeyW=strdupA2W(lpszSubKey); else lpszSubKeyW=NULL; ret=RegOpenKeyExW(hkey,lpszSubKeyW,dwReserved,samDesired,retkey); if (lpszSubKeyW) free(lpszSubKeyW); return ret; } /* RegOpenKeyA [ADVAPI32.148] */ WINAPI DWORD RegOpenKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) { dprintf_reg(stddeb,"RegOpenKeyA(%lx,%s,%p)\n", (LONG)hkey,lpszSubKey,retkey ); return RegOpenKeyExA(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey); } /* RegOpenKey [SHELL.1] [KERNEL.217] */ WINAPI DWORD RegOpenKey( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) { dprintf_reg(stddeb,"RegOpenKey(%lx,%s,%p)\n", (LONG)hkey,lpszSubKey,retkey ); return RegOpenKeyA(hkey,lpszSubKey,retkey); } /* * Create keys * * All those functions convert their respective * arguments and call RegCreateKeyExW at the end. * * FIXME: no security,no access attrib,no optionhandling yet. * * Callpath: * RegCreateKey -> RegCreateKeyA -> RegCreateKeyExA \ * RegCreateKeyW -> RegCreateKeyExW */ /* RegCreateKeyExW [ADVAPI32.131] */ WINAPI DWORD RegCreateKeyExW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwReserved, LPWSTR lpszClass, DWORD fdwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecAttribs, LPHKEY retkey, LPDWORD lpDispos ) { LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey; LPWSTR *wps; int wpc,i; /*FIXME: handle security/access/whatever */ dprintf_reg(stddeb,"RegCreateKeyExW(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", (LONG)hkey, W2C(lpszSubKey,0), dwReserved, W2C(lpszClass,1), fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos ); lpNextKey = lookup_hkey(hkey); if (!lpNextKey) return SHELL_ERROR_BADKEY; if (!lpszSubKey || !*lpszSubKey) { add_handle(++currenthandle,lpNextKey,samDesired); *retkey=currenthandle; return SHELL_ERROR_SUCCESS; } split_keypath(lpszSubKey,&wps,&wpc); i = 0; while ((inextsub; while (lpxkey) { if (!strcmpW(wps[i],lpxkey->keyname)) break; lpxkey=lpxkey->next; } if (!lpxkey) break; i++; lpNextKey = lpxkey; } if (lpxkey) { add_handle(++currenthandle,lpxkey,samDesired); *retkey = currenthandle; *lpDispos = REG_OPENED_EXISTING_KEY; FREE_KEY_PATH; return SHELL_ERROR_SUCCESS; } /* good. now the hard part */ while (inextsub); lpxkey = *lplpPrevKey; while (lpxkey) { lplpPrevKey = &(lpxkey->next); lpxkey = *lplpPrevKey; } *lplpPrevKey=malloc(sizeof(KEYSTRUCT)); if (!*lplpPrevKey) { FREE_KEY_PATH; return SHELL_ERROR_OUTOFMEMORY; } memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT)); (*lplpPrevKey)->keyname = strdupW(wps[i]); (*lplpPrevKey)->next = NULL; (*lplpPrevKey)->nextsub = NULL; (*lplpPrevKey)->values = NULL; (*lplpPrevKey)->nrofvalues = 0; if (lpszClass) (*lplpPrevKey)->class = strdupW(lpszClass); else (*lplpPrevKey)->class = NULL; lpNextKey = *lplpPrevKey; i++; } add_handle(++currenthandle,lpNextKey,samDesired); /*FIXME: flag handling correct? */ lpNextKey->flags= fdwOptions; if (lpszClass) lpNextKey->class = strdupW(lpszClass); else lpNextKey->class = NULL; *retkey = currenthandle; *lpDispos = REG_CREATED_NEW_KEY; FREE_KEY_PATH; return SHELL_ERROR_SUCCESS; } /* RegCreateKeyW [ADVAPI32.132] */ WINAPI DWORD RegCreateKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey ) { DWORD junk,ret; dprintf_reg(stddeb,"RegCreateKeyW(%lx,%s,%p)\n", (LONG)hkey,W2C(lpszSubKey,0),retkey ); ret=RegCreateKeyExW( hkey, /* key handle */ lpszSubKey, /* subkey name */ 0, /* reserved = 0 */ NULL, /* lpszClass? FIXME: ? */ REG_OPTION_NON_VOLATILE, /* options */ KEY_ALL_ACCESS, /* desired access attribs */ NULL, /* lpsecurity attributes */ retkey, /* lpretkey */ &junk /* disposition value */ ); return ret; } /* RegCreateKeyExA [ADVAPI32.130] */ WINAPI DWORD RegCreateKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved, LPSTR lpszClass, DWORD fdwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecAttribs, LPHKEY retkey, LPDWORD lpDispos ) { LPWSTR lpszSubKeyW,lpszClassW; DWORD ret; dprintf_reg(stddeb,"RegCreateKeyExA(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", (LONG)hkey, lpszSubKey, dwReserved, lpszClass, fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos ); if (lpszSubKey) lpszSubKeyW=strdupA2W(lpszSubKey); else lpszSubKeyW=NULL; if (lpszClass) lpszClassW=strdupA2W(lpszClass); else lpszClassW=NULL; ret=RegCreateKeyExW( hkey, lpszSubKeyW, dwReserved, lpszClassW, fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos ); if (lpszSubKeyW) free(lpszSubKeyW); if (lpszClassW) free(lpszClassW); return ret; } /* RegCreateKeyA [ADVAPI32.129] */ WINAPI DWORD RegCreateKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) { DWORD junk; dprintf_reg(stddeb,"RegCreateKeyA(%lx,%s,%p)\n", (LONG)hkey,lpszSubKey,retkey ); return RegCreateKeyExA( hkey, /* key handle */ lpszSubKey, /* subkey name */ 0, /* reserved = 0 */ NULL, /* lpszClass? FIXME: ? */ REG_OPTION_NON_VOLATILE,/* options */ KEY_ALL_ACCESS, /* desired access attribs */ NULL, /* lpsecurity attributes */ retkey, /* lpretkey */ &junk /* disposition value */ ); } /* RegCreateKey [SHELL.2] [KERNEL.218] */ WINAPI DWORD RegCreateKey( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) { dprintf_reg(stddeb,"RegCreateKey(%lx,%s,%p)\n", (LONG)hkey,lpszSubKey,retkey ); return RegCreateKeyA(hkey,lpszSubKey,retkey); } /* * Query Value Functions * Win32 differs between keynames and valuenames. * multiple values may belong to one key, the special value * with name NULL is the default value used by the win31 * compat functions. * * Callpath: * RegQueryValue -> RegQueryValueA -> RegQueryValueExA \ * RegQueryValueW -> RegQueryValueExW */ /* RegQueryValueExW [ADVAPI32.158] */ WINAPI DWORD RegQueryValueExW( HKEY hkey, LPWSTR lpszValueName, LPDWORD lpdwReserved, LPDWORD lpdwType, LPBYTE lpbData, LPDWORD lpcbData ) { LPKEYSTRUCT lpkey; int i; dprintf_reg(stddeb,"RegQueryValueExW(%lx,%s,%p,%p,%p,%p)\n", hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,lpcbData ); lpkey = lookup_hkey(hkey); if (!lpkey) return SHELL_ERROR_BADKEY; if (lpszValueName==NULL) { for (i=0;inrofvalues;i++) if (lpkey->values[i].name==NULL) break; } else { for (i=0;inrofvalues;i++) if (!strcmpW(lpszValueName,lpkey->values[i].name)) break; } if (i==lpkey->nrofvalues) { if (lpszValueName==NULL) { *(WCHAR*)lpbData = 0; *lpcbData = 2; *lpdwType = REG_SZ; return SHELL_ERROR_SUCCESS; } return SHELL_ERROR_BADKEY;/*FIXME: correct return? */ } if (lpdwType) *lpdwType = lpkey->values[i].type; if (lpbData==NULL) { if (lpcbData==NULL) return SHELL_ERROR_SUCCESS; *lpcbData = lpkey->values[i].len; return SHELL_ERROR_SUCCESS; } if (*lpcbDatavalues[i].len) { *(WCHAR*)lpbData = 0; *lpcbData = lpkey->values[i].len; return ERROR_MORE_DATA; } memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len); *lpcbData = lpkey->values[i].len; return SHELL_ERROR_SUCCESS; } /* RegQueryValueW [ADVAPI32.159] */ WINAPI DWORD RegQueryValueW( HKEY hkey, LPWSTR lpszSubKey, LPWSTR lpszData, LPDWORD lpcbData ) { HKEY xhkey; DWORD ret,lpdwType; dprintf_reg(stddeb,"RegQueryValueW(%lx,%s,%p,%p)\n->", hkey,W2C(lpszSubKey,0),lpszData,lpcbData ); /* only open subkey, if we really do descend */ if (lpszSubKey && *lpszSubKey) { ret = RegOpenKeyW(hkey,lpszSubKey,&xhkey); if (ret!=ERROR_SUCCESS) return ret; } else xhkey = hkey; lpdwType = REG_SZ; ret = RegQueryValueExW( xhkey, NULL, /* varname NULL -> compat */ NULL, /* lpdwReserved, must be NULL */ &lpdwType, (LPBYTE)lpszData, lpcbData ); if (xhkey!=hkey) RegCloseKey(xhkey); return ret; } /* RegQueryValueExA [ADVAPI32.157] */ WINAPI DWORD RegQueryValueExA( HKEY hkey, LPSTR lpszValueName, LPDWORD lpdwReserved, LPDWORD lpdwType, LPBYTE lpbData, LPDWORD lpcbData ) { LPWSTR lpszValueNameW; LPBYTE buf; DWORD ret,myxlen; DWORD *mylen; dprintf_reg(stddeb,"RegQueryValueExA(%lx,%s,%p,%p,%p,%p)\n->", hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData ); if (lpbData) { /* double buffer */ buf = (LPBYTE)xmalloc((*lpcbData)*2); myxlen = *lpcbData*2; mylen = &myxlen; } else { buf=NULL; if (lpcbData) { myxlen = *lpcbData*2; mylen = &myxlen; } mylen = NULL; } if (lpszValueName) lpszValueNameW=strdupA2W(lpszValueName); else lpszValueNameW=NULL; ret=RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, buf, mylen ); if (ret==ERROR_SUCCESS) { if (buf) { if (UNICONVMASK & (1<<(*lpdwType))) { /* convert UNICODE to ASCII */ strcpyWA(lpbData,(LPWSTR)buf); *lpcbData = myxlen/2; } else { if (myxlen>*lpcbData) ret = ERROR_MORE_DATA; else memcpy(lpbData,buf,myxlen); *lpcbData = myxlen; } } else { if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData) *lpcbData = myxlen/2; } } else { if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData) *lpcbData = myxlen/2; } if (buf) free(buf); return ret; } /* RegQueryValueEx [KERNEL.225] */ WINAPI DWORD RegQueryValueEx( HKEY hkey, LPSTR lpszValueName, LPDWORD lpdwReserved, LPDWORD lpdwType, LPBYTE lpbData, LPDWORD lpcbData ) { dprintf_reg(stddeb,"RegQueryValueEx(%lx,%s,%p,%p,%p,%p)\n", hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData ); return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType, lpbData, lpcbData ); } /* RegQueryValueA [ADVAPI32.156] */ WINAPI DWORD RegQueryValueA( HKEY hkey, LPSTR lpszSubKey, LPSTR lpszData, LPDWORD lpcbData ) { HKEY xhkey; DWORD ret,lpdwType; dprintf_reg(stddeb,"RegQueryValueA(%lx,%s,%p,%p)\n", hkey,lpszSubKey,lpszData,lpcbData ); /* only open subkey, if we really do descend */ if (lpszSubKey && *lpszSubKey) { ret = RegOpenKey(hkey,lpszSubKey,&xhkey); if (ret!=ERROR_SUCCESS) return ret; } else xhkey = hkey; lpdwType = REG_SZ; ret = RegQueryValueExA( xhkey, NULL, /* lpszValueName NULL -> compat */ NULL, /* lpdwReserved, must be NULL */ &lpdwType, (LPBYTE)lpszData, lpcbData ); if (xhkey!=hkey) RegCloseKey(xhkey); return ret; } /* RegQueryValue [SHELL.6] [KERNEL.224] */ WINAPI DWORD RegQueryValue( HKEY hkey, LPSTR lpszSubKey, LPSTR lpszData, LPDWORD lpcbData ) { dprintf_reg(stddeb,"RegQueryValueA(%lx,%s,%p,%p)\n", hkey,lpszSubKey,lpszData,lpcbData ); return RegQueryValueA(hkey,lpszSubKey,lpszData,lpcbData); } /* * Setting values of Registry keys * * Callpath: * RegSetValue -> RegSetValueA -> RegSetValueExA \ * RegSetValueW -> RegSetValueExW */ /* RegSetValueExW [ADVAPI32.170] */ WINAPI DWORD RegSetValueExW( HKEY hkey, LPWSTR lpszValueName, DWORD dwReserved, DWORD dwType, LPBYTE lpbData, DWORD cbData ) { LPKEYSTRUCT lpkey; int i; dprintf_reg(stddeb,"RegSetValueExW(%lx,%s,%ld,%ld,%p,%ld)\n", hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData ); /* we no longer care about the lpbData dwType here... */ lpkey = lookup_hkey(hkey); if (!lpkey) return SHELL_ERROR_BADKEY; if (lpszValueName==NULL) { for (i=0;inrofvalues;i++) if (lpkey->values[i].name==NULL) break; } else { for (i=0;inrofvalues;i++) if (!strcmpW(lpszValueName,lpkey->values[i].name)) break; } if (i==lpkey->nrofvalues) { lpkey->values = (LPKEYVALUE)xrealloc( lpkey->values, (lpkey->nrofvalues+1)*sizeof(KEYVALUE) ); lpkey->nrofvalues++; memset(lpkey->values+i,'\0',sizeof(KEYVALUE)); } if (lpkey->values[i].name==NULL) if (lpszValueName) lpkey->values[i].name = strdupW(lpszValueName); else lpkey->values[i].name = NULL; lpkey->values[i].len = cbData; lpkey->values[i].type = dwType; if (lpkey->values[i].data !=NULL) free(lpkey->values[i].data); lpkey->values[i].data = (LPBYTE)xmalloc(cbData); lpkey->values[i].lastmodified = time(NULL); memcpy(lpkey->values[i].data,lpbData,cbData); return SHELL_ERROR_SUCCESS; } /* RegSetValueExA [ADVAPI32.169] */ WINAPI DWORD RegSetValueExA( HKEY hkey, LPSTR lpszValueName, DWORD dwReserved, DWORD dwType, LPBYTE lpbData, DWORD cbData ) { LPBYTE buf; LPWSTR lpszValueNameW; DWORD ret; dprintf_reg(stddeb,"RegSetValueExA(%lx,%s,%ld,%ld,%p,%ld)\n->", hkey,lpszValueName,dwReserved,dwType,lpbData,cbData ); if ((1<", hkey,lpszValueName,dwReserved,dwType,lpbData,cbData ); return RegSetValueExA(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData); } /* RegSetValueW [ADVAPI32.171] */ WINAPI DWORD RegSetValueW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwType, LPCWSTR lpszData, DWORD cbData ) { HKEY xhkey; DWORD ret; dprintf_reg(stddeb,"RegSetValueW(%lx,%s,%ld,%s,%ld)\n->", hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData ); if (lpszSubKey && *lpszSubKey) { ret=RegCreateKeyW(hkey,lpszSubKey,&xhkey); if (ret!=ERROR_SUCCESS) return ret; } else xhkey=hkey; if (dwType!=REG_SZ) { fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType); dwType=REG_SZ; } if (cbData!=2*strlenW(lpszData)+2) { dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n", cbData,W2C(lpszData,0),2*strlenW(lpszData)+2 ); cbData=2*strlenW(lpszData)+2; } ret=RegSetValueExW(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData); if (hkey!=xhkey) RegCloseKey(xhkey); return ret; } /* RegSetValueA [ADVAPI32.168] */ WINAPI DWORD RegSetValueA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType, LPCSTR lpszData, DWORD cbData ) { DWORD ret; HKEY xhkey; dprintf_reg(stddeb,"RegSetValueA(%lx,%s,%ld,%s,%ld)\n->", hkey,lpszSubKey,dwType,lpszData,cbData ); if (lpszSubKey && *lpszSubKey) { ret=RegCreateKey(hkey,lpszSubKey,&xhkey); if (ret!=ERROR_SUCCESS) return ret; } else xhkey=hkey; if (dwType!=REG_SZ) { dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType); dwType=REG_SZ; } if (cbData!=strlen(lpszData)+1) cbData=strlen(lpszData)+1; ret=RegSetValueExA(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData); if (xhkey!=hkey) RegCloseKey(xhkey); return ret; } /* RegSetValue [KERNEL.221] [SHELL.5] */ WINAPI DWORD RegSetValue( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType, LPCSTR lpszData, DWORD cbData ) { DWORD ret; dprintf_reg(stddeb,"RegSetValue(%lx,%s,%ld,%s,%ld)\n->", hkey,lpszSubKey,dwType,lpszData,cbData ); ret=RegSetValueA(hkey,lpszSubKey,dwType,lpszData,cbData); return ret; } /* * Key Enumeration * * Callpath: * RegEnumKey -> RegEnumKeyA -> RegEnumKeyExA \ * RegEnumKeyW -> RegEnumKeyExW */ /* RegEnumKeyExW [ADVAPI32.139] */ WINAPI DWORD RegEnumKeyExW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName, LPDWORD lpcchName, LPDWORD lpdwReserved, LPWSTR lpszClass, LPDWORD lpcchClass, FILETIME *ft ) { LPKEYSTRUCT lpkey,lpxkey; dprintf_reg(stddeb,"RegEnumKeyExW(%lx,%ld,%p,%ld,%p,%p,%p,%p)\n", hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft ); lpkey=lookup_hkey(hkey); if (!lpkey) return SHELL_ERROR_BADKEY; if (!lpkey->nextsub) return ERROR_NO_MORE_ITEMS; lpxkey=lpkey->nextsub; while (iSubkey && lpxkey) { iSubkey--; lpxkey=lpxkey->next; } if (iSubkey || !lpxkey) return ERROR_NO_MORE_ITEMS; if (2*strlenW(lpxkey->keyname)+2>*lpcchName) return ERROR_MORE_DATA; memcpy(lpszName,lpxkey->keyname,strlenW(lpxkey->keyname)*2+2); if (lpszClass) { /* what should we write into it? */ *lpszClass = 0; *lpcchClass = 2; } return ERROR_SUCCESS; } /* RegEnumKeyW [ADVAPI32.140] */ WINAPI DWORD RegEnumKeyW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName, DWORD lpcchName ) { FILETIME ft; dprintf_reg(stddeb,"RegEnumKeyW(%lx,%ld,%p,%ld)\n->", hkey,iSubkey,lpszName,lpcchName ); return RegEnumKeyExW(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft); } /* RegEnumKeyExA [ADVAPI32.138] */ WINAPI DWORD RegEnumKeyExA( HKEY hkey, DWORD iSubkey, LPSTR lpszName, LPDWORD lpcchName, LPDWORD lpdwReserved, LPSTR lpszClass, LPDWORD lpcchClass, FILETIME *ft ) { DWORD ret,lpcchNameW,lpcchClassW; LPWSTR lpszNameW,lpszClassW; dprintf_reg(stddeb,"RegEnumKeyExA(%lx,%ld,%p,%ld,%p,%p,%p,%p)\n->", hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft ); if (lpszName) { lpszNameW = (LPWSTR)xmalloc(*lpcchName*2); lpcchNameW = *lpcchName*2; } else { lpszNameW = NULL; lpcchNameW = 0; } if (lpszClass) { lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2); lpcchClassW = *lpcchClass*2; } else { lpszClassW =0; lpcchClassW=0; } ret=RegEnumKeyExW( hkey, iSubkey, lpszNameW, &lpcchNameW, lpdwReserved, lpszClassW, &lpcchClassW, ft ); if (ret==ERROR_SUCCESS) { strcpyWA(lpszName,lpszNameW); *lpcchName=strlen(lpszName); if (lpszClassW) { strcpyWA(lpszClass,lpszClassW); *lpcchClass=strlen(lpszClass); } } if (lpszNameW) free(lpszNameW); if (lpszClassW) free(lpszClassW); return ret; } /* RegEnumKeyA [ADVAPI32.137] */ WINAPI DWORD RegEnumKeyA( HKEY hkey, DWORD iSubkey, LPSTR lpszName, DWORD lpcchName ) { FILETIME ft; dprintf_reg(stddeb,"RegEnumKeyA(%lx,%ld,%p,%ld)\n->", hkey,iSubkey,lpszName,lpcchName ); return RegEnumKeyExA( hkey, iSubkey, lpszName, &lpcchName, NULL, NULL, NULL, &ft ); } /* RegEnumKey [SHELL.7] [KERNEL.216] */ WINAPI DWORD RegEnumKey( HKEY hkey, DWORD iSubkey, LPSTR lpszName, DWORD lpcchName ) { dprintf_reg(stddeb,"RegEnumKey(%lx,%ld,%p,%ld)\n->", hkey,iSubkey,lpszName,lpcchName ); return RegEnumKeyA(hkey,iSubkey,lpszName,lpcchName); } /* * Enumerate Registry Values * * Callpath: * RegEnumValue -> RegEnumValueA -> RegEnumValueW */ /* RegEnumValueW [ADVAPI32.142] */ WINAPI DWORD RegEnumValueW( HKEY hkey, DWORD iValue, LPWSTR lpszValue, LPDWORD lpcchValue, LPDWORD lpdReserved, LPDWORD lpdwType, LPBYTE lpbData, LPDWORD lpcbData ) { LPKEYSTRUCT lpkey; LPKEYVALUE val; dprintf_reg(stddeb,"RegEnumValueW(%ld,%ld,%p,%p,%p,%p,%p,%p)\n", hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData ); lpkey = lookup_hkey(hkey); if (!lpkey) return SHELL_ERROR_BADKEY; if (lpkey->nrofvalues<=iValue) return ERROR_NO_MORE_ITEMS; val = lpkey->values+iValue; if (val->name) { if (strlenW(val->name)*2+2>*lpcchValue) { *lpcchValue = strlenW(val->name)*2+2; return ERROR_MORE_DATA; } memcpy(lpszValue,val->name,2*strlenW(val->name)+2); *lpcchValue=strlenW(val->name)*2+2; } else { /* how to handle NULL value? */ *lpszValue = 0; *lpcchValue = 2; } *lpdwType=val->type; if (lpbData) { if (val->len>*lpcbData) return ERROR_MORE_DATA; memcpy(lpbData,val->data,val->len); *lpcbData = val->len; } return SHELL_ERROR_SUCCESS; } /* RegEnumValueA [ADVAPI32.141] */ WINAPI DWORD RegEnumValueA( HKEY hkey, DWORD iValue, LPSTR lpszValue, LPDWORD lpcchValue, LPDWORD lpdReserved, LPDWORD lpdwType, LPBYTE lpbData, LPDWORD lpcbData ) { LPWSTR lpszValueW; LPBYTE lpbDataW; DWORD ret,lpcbDataW; dprintf_reg(stddeb,"RegEnumValueA(%ld,%ld,%p,%p,%p,%p,%p,%p)\n", hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData ); lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2); if (lpbData) { lpbDataW = (LPBYTE)xmalloc(*lpcbData*2); lpcbDataW = *lpcbData*2; } else lpbDataW = NULL; ret=RegEnumValueW( hkey, iValue, lpszValueW, lpcchValue, lpdReserved, lpdwType, lpbDataW, &lpcbDataW ); if (ret==ERROR_SUCCESS) { strcpyWA(lpszValue,lpszValueW); if (lpbData) { if ((1<<*lpdwType) & UNICONVMASK) { strcpyWA(lpbData,(LPWSTR)lpbDataW); } else { if (lpcbDataW > *lpcbData) ret = ERROR_MORE_DATA; else memcpy(lpbData,lpbDataW,lpcbDataW); } *lpcbData = lpcbDataW; } } if (lpbDataW) free(lpbDataW); if (lpszValueW) free(lpszValueW); return ret; } /* RegEnumValue [KERNEL.223] */ WINAPI DWORD RegEnumValue( HKEY hkey, DWORD iValue, LPSTR lpszValue, LPDWORD lpcchValue, LPDWORD lpdReserved, LPDWORD lpdwType, LPBYTE lpbData, LPDWORD lpcbData ) { dprintf_reg(stddeb,"RegEnumValue(%ld,%ld,%p,%p,%p,%p,%p,%p)\n", hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData ); return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, lpdReserved, lpdwType, lpbData, lpcbData ); } /* * Close registry key */ /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */ WINAPI DWORD RegCloseKey(HKEY hkey) { dprintf_reg(stddeb,"RegCloseKey(%ld)\n",hkey); remove_handle(hkey); return ERROR_SUCCESS; } /* * Delete registry key * * Callpath: * RegDeleteKey -> RegDeleteKeyA -> RegDeleteKeyW */ /* RegDeleteKeyW [ADVAPI32.134] */ WINAPI DWORD RegDeleteKeyW(HKEY hkey,LPWSTR lpszSubKey) { LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey; LPWSTR *wps; int wpc,i; dprintf_reg(stddeb,"RegDeleteKeyW(%ld,%s)\n", hkey,W2C(lpszSubKey,0) ); lpNextKey = lookup_hkey(hkey); if (!lpNextKey) return SHELL_ERROR_BADKEY; /* we need to know the previous key in the hier. */ if (!lpszSubKey || !*lpszSubKey) return SHELL_ERROR_BADKEY; split_keypath(lpszSubKey,&wps,&wpc); i = 0; lpxkey = lpNextKey; while (inextsub; while (lpxkey) { if (!strcmpW(wps[i],lpxkey->keyname)) break; lpxkey=lpxkey->next; } if (!lpxkey) { FREE_KEY_PATH; /* not found is success */ return SHELL_ERROR_SUCCESS; } i++; lpNextKey = lpxkey; } lpxkey = lpNextKey->nextsub; lplpPrevKey = &(lpNextKey->nextsub); while (lpxkey) { if (!strcmpW(wps[i],lpxkey->keyname)) break; lplpPrevKey = &(lpxkey->next); lpxkey = lpxkey->next; } if (!lpxkey) return SHELL_ERROR_SUCCESS; if (lpxkey->nextsub) return SHELL_ERROR_CANTWRITE; *lplpPrevKey = lpxkey->next; free(lpxkey->keyname); if (lpxkey->class) free(lpxkey->class); if (lpxkey->values) free(lpxkey->values); free(lpxkey); FREE_KEY_PATH; return SHELL_ERROR_SUCCESS; } /* RegDeleteKeyA [ADVAPI32.133] */ WINAPI DWORD RegDeleteKeyA(HKEY hkey,LPCSTR lpszSubKey) { LPWSTR lpszSubKeyW; DWORD ret; dprintf_reg(stddeb,"RegDeleteKeyA(%ld,%s)\n", hkey,lpszSubKey ); lpszSubKeyW=strdupA2W(lpszSubKey); ret=RegDeleteKeyW(hkey,lpszSubKeyW); free(lpszSubKeyW); return ret; } /* RegDeleteKey [SHELL.4] [KERNEL.219] */ WINAPI DWORD RegDeleteKey(HKEY hkey,LPCSTR lpszSubKey) { dprintf_reg(stddeb,"RegDeleteKey(%ld,%s)\n", hkey,lpszSubKey ); return RegDeleteKeyA(hkey,lpszSubKey); } /* * Delete registry value * * Callpath: * RegDeleteValue -> RegDeleteValueA -> RegDeleteValueW */ /* RegDeleteValueW [ADVAPI32.136] */ WINAPI DWORD RegDeleteValueW(HKEY hkey,LPWSTR lpszValue) { DWORD i; LPKEYSTRUCT lpkey; LPKEYVALUE val; dprintf_reg(stddeb,"RegDeleteValueW(%ld,%s)\n", hkey,W2C(lpszValue,0) ); lpkey=lookup_hkey(hkey); if (!lpkey) return SHELL_ERROR_BADKEY; if (lpszValue) { for (i=0;inrofvalues;i++) if (!strcmpW(lpkey->values[i].name,lpszValue)) break; } else { for (i=0;inrofvalues;i++) if (lpkey->values[i].name==NULL) break; } if (i==lpkey->nrofvalues) return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */ val = lpkey->values+i; if (val->name) free(val->name); if (val->data) free(val->data); memcpy( lpkey->values+i, lpkey->values+i+1, sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1) ); lpkey->values = (LPKEYVALUE)xrealloc( lpkey->values, (lpkey->nrofvalues-1)*sizeof(KEYVALUE) ); lpkey->nrofvalues--; return SHELL_ERROR_SUCCESS; } /* RegDeleteValueA [ADVAPI32.135] */ WINAPI DWORD RegDeleteValueA(HKEY hkey,LPSTR lpszValue) { LPWSTR lpszValueW; DWORD ret; dprintf_reg(stddeb,"RegDeleteValueA(%ld,%s)\n", hkey,lpszValue ); if (lpszValue) lpszValueW=strdupA2W(lpszValue); else lpszValueW=NULL; ret=RegDeleteValueW(hkey,lpszValueW); if (lpszValueW) free(lpszValueW); return ret; } /* RegDeleteValue [KERNEL.222] */ WINAPI DWORD RegDeleteValue(HKEY hkey,LPSTR lpszValue) { dprintf_reg(stddeb,"RegDeleteValue(%ld,%s)\n", hkey,lpszValue ); return RegDeleteValueA(hkey,lpszValue); } /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */ WINAPI DWORD RegFlushKey(HKEY hkey) { dprintf_reg(stddeb,"RegFlushKey(%ld), STUB.\n",hkey); return SHELL_ERROR_SUCCESS; } /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */ /* RegQueryInfoKeyW [ADVAPI32.153] */ WINAPI DWORD RegQueryInfoKeyW( HKEY hkey, LPWSTR lpszClass, LPDWORD lpcchClass, LPDWORD lpdwReserved, LPDWORD lpcSubKeys, LPDWORD lpcchMaxSubkey, LPDWORD lpcchMaxClass, LPDWORD lpcValues, LPDWORD lpcchMaxValueName, LPDWORD lpccbMaxValueData, LPDWORD lpcbSecurityDescriptor, FILETIME *ft ) { LPKEYSTRUCT lpkey,lpxkey; int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata; int i; dprintf_reg(stddeb,"RegQueryInfoKeyW(%lx,......)\n",hkey); lpkey=lookup_hkey(hkey); if (!lpkey) return SHELL_ERROR_BADKEY; if (lpszClass) { if (lpkey->class) { if (strlenW(lpkey->class)*2+2>*lpcchClass) { *lpcchClass=strlenW(lpkey->class)*2; return ERROR_MORE_DATA; } *lpcchClass=strlenW(lpkey->class)*2; memcpy(lpszClass,lpkey->class,strlenW(lpkey->class)); } else { *lpszClass = 0; *lpcchClass = 0; } } else { if (lpcchClass) *lpcchClass = strlenW(lpkey->class)*2; } lpxkey=lpkey->nextsub; nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0; while (lpxkey) { nrofkeys++; if (strlenW(lpxkey->keyname)>maxsubkey) maxsubkey=strlenW(lpxkey->keyname); if (lpxkey->class && strlenW(lpxkey->class)>maxclass) maxclass=strlenW(lpxkey->class); if (lpxkey->nrofvalues>maxvalues) maxvalues=lpxkey->nrofvalues; for (i=0;inrofvalues;i++) { LPKEYVALUE val=lpxkey->values+i; if (val->name && strlenW(val->name)>maxvname) maxvname=strlenW(val->name); if (val->len>maxvdata) maxvdata=val->len; } lpxkey=lpxkey->next; } if (!maxclass) maxclass = 1; if (!maxvname) maxvname = 1; if (lpcSubKeys) *lpcSubKeys = nrofkeys; if (lpcchMaxSubkey) *lpcchMaxSubkey = maxsubkey*2; if (lpcchMaxClass) *lpcchMaxClass = maxclass*2; if (lpcValues) *lpcValues = maxvalues; if (lpcchMaxValueName) *lpcchMaxValueName= maxvname; if (lpccbMaxValueData) *lpccbMaxValueData= maxvdata; return SHELL_ERROR_SUCCESS; } /* RegQueryInfoKeyA [ADVAPI32.152] */ WINAPI DWORD RegQueryInfoKeyA( HKEY hkey, LPSTR lpszClass, LPDWORD lpcchClass, LPDWORD lpdwReserved, LPDWORD lpcSubKeys, LPDWORD lpcchMaxSubkey, LPDWORD lpcchMaxClass, LPDWORD lpcValues, LPDWORD lpcchMaxValueName, LPDWORD lpccbMaxValueData, LPDWORD lpcbSecurityDescriptor, FILETIME *ft ) { LPWSTR lpszClassW; DWORD ret; dprintf_reg(stddeb,"RegQueryInfoKeyA(%lx,......)\n",hkey); if (lpszClass) { *lpcchClass*= 2; lpszClassW = (LPWSTR)xmalloc(*lpcchClass); } else lpszClassW = NULL; ret=RegQueryInfoKeyW( hkey, lpszClassW, lpcchClass, lpdwReserved, lpcSubKeys, lpcchMaxSubkey, lpcchMaxClass, lpcValues, lpcchMaxValueName, lpccbMaxValueData, lpcbSecurityDescriptor, ft ); if (ret==ERROR_SUCCESS) strcpyWA(lpszClass,lpszClassW); if (lpcchClass) *lpcchClass/=2; if (lpcchMaxSubkey) *lpcchMaxSubkey/=2; if (lpcchMaxClass) *lpcchMaxClass/=2; if (lpcchMaxValueName) *lpcchMaxValueName/=2; if (lpszClassW) free(lpszClassW); return ret; }