| /* |
| * Registry Functions |
| * |
| * Copyright 1996 Marcus Meissner |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <ctype.h> |
| #include "windows.h" |
| #include "win.h" |
| #include "winerror.h" |
| #include "string32.h" |
| #include "kernel32.h" /* LPSECURITY_ATTRIBUTES */ |
| #include "stddebug.h" |
| #include "debug.h" |
| #include "xmalloc.h" |
| #include "winreg.h" |
| |
| #define SAVE_CLASSES_ROOT "/tmp/reg.classes_root" |
| #define SAVE_CURRENT_USER "/tmp/reg.current_user" |
| #define SAVE_LOCAL_MACHINE "/tmp/reg.local_machine" |
| #define SAVE_USERS "/tmp/reg.users" |
| |
| static KEYSTRUCT *key_classes_root=NULL; /* windows 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<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ)) |
| |
| #define strdupA2W(x) STRING32_DupAnsiToUni(x) |
| #define strdupW2A(x) STRING32_DupUniToAnsi(x) |
| #define strdupW(x) STRING32_strdupW(x) |
| #define strcmpW(a,b) STRING32_lstrcmpW(a,b) |
| #define strcmpniW(a,b) STRING32_lstrcmpniW(a,b) |
| #define strchrW(a,c) STRING32_lstrchrW(a,c) |
| #define strlenW(a) STRING32_UniLen(a) |
| #define strcpyWA(a,b) STRING32_UniToAnsi(a,b) |
| |
| static struct openhandle { |
| LPKEYSTRUCT lpkey; |
| HKEY hkey; |
| REGSAM accessmask; |
| } *openhandles=NULL; |
| static int nrofopenhandles=0; |
| static int currenthandle=1; |
| |
| static void |
| add_handle(HKEY hkey,LPKEYSTRUCT lpkey,REGSAM accessmask) { |
| int i; |
| |
| for (i=0;i<nrofopenhandles;i++) { |
| if (openhandles[i].lpkey==lpkey) { |
| dprintf_reg(stddeb,"add_handle:Tried to add %p twice!\n",lpkey); |
| } |
| if (openhandles[i].hkey==hkey) { |
| dprintf_reg(stddeb,"add_handle:Tried to add %lx twice!\n",(LONG)hkey); |
| } |
| } |
| openhandles=xrealloc( openhandles, |
| sizeof(struct openhandle)*(nrofopenhandles+1) |
| ); |
| openhandles[i].lpkey = lpkey; |
| openhandles[i].hkey = hkey; |
| openhandles[i].accessmask= accessmask; |
| nrofopenhandles++; |
| } |
| |
| static LPKEYSTRUCT |
| get_handle(hkey) { |
| int i; |
| |
| for (i=0;i<nrofopenhandles;i++) |
| if (openhandles[i].hkey==hkey) |
| return openhandles[i].lpkey; |
| dprintf_reg(stddeb,"get_handle:Didn't find handle %lx?\n",(LONG)hkey); |
| return NULL; |
| } |
| |
| static void |
| remove_handle(HKEY hkey) { |
| int i; |
| |
| for (i=0;i<nrofopenhandles;i++) |
| if (openhandles[i].hkey==hkey) |
| break; |
| if (i==nrofopenhandles) { |
| dprintf_reg(stddeb,"remove_handle:Didn't find handle %lx?\n",hkey); |
| return; |
| } |
| memcpy( openhandles+i, |
| openhandles+i+1, |
| sizeof(struct openhandle)*(nrofopenhandles-i-1) |
| ); |
| openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1)); |
| nrofopenhandles--; |
| return; |
| } |
| |
| |
| /* debug function, converts a unicode into a static memory area |
| * (sub for using two static strings, in case we need them in a single call) |
| */ |
| LPSTR |
| W2C(LPCWSTR x,int sub) { |
| static LPSTR unicodedebug[2]={NULL,NULL}; |
| if (x==NULL) |
| return "<NULL>"; |
| if (sub!=0 && sub!=1) |
| return "<W2C:bad sub>"; |
| 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;i<len;i++) |
| if (ws[i-1]==0) |
| (*wpv)[j++]=ws+i; |
| (*wpv)[j]=NULL; |
| } |
| #define FREE_KEY_PATH free(wps[0]);free(wps); |
| |
| /** |
| * Shell initialisation, allocates keys. |
| * FIXME:should set default values too |
| */ |
| void |
| SHELL_Init() { |
| #define ADD_ROOT_KEY(xx) \ |
| xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\ |
| memset(xx,'\0',sizeof(KEYSTRUCT));\ |
| xx->keyname= strdupA2W("<should_not_appear_anywhere>"); |
| |
| ADD_ROOT_KEY(key_classes_root); |
| ADD_ROOT_KEY(key_current_user); |
| ADD_ROOT_KEY(key_local_machine); |
| ADD_ROOT_KEY(key_users); |
| 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: |
| * DWORD version |
| * DWORD nrofkeys |
| * KEY keys[nrofkeys] |
| * |
| * KEY: |
| * USTRING name |
| * USTRING class |
| * DWORD nrofvalues |
| * VALUE vals[nrofvalues] |
| * DWORD nrofsubkeys |
| * KEY keys[nrofsubkeys] |
| * |
| * Value: |
| * USTRING name |
| * DWORD type |
| * DWORD len |
| * BYTE data[len] |
| * |
| * USTRING: |
| * DWORD len (len==0 means data=NULL) |
| * BYTE data[len] |
| * |
| * |
| * All _write_XXX and _read_XXX functions return !0 on sucess. |
| */ |
| |
| |
| static int |
| _write_DWORD(FILE *F,DWORD dw) { |
| return fwrite(&dw,sizeof(dw),1,F); |
| } |
| |
| static int |
| _write_USTRING(FILE *F,LPWSTR str) { |
| int len; |
| |
| if (str==NULL) { |
| if (!_write_DWORD(F,0)) |
| return 0; |
| } else { |
| len=strlenW(str)*2+2; |
| |
| if (!_write_DWORD(F,len)) |
| return 0; |
| if (!fwrite(str,len,1,F)) |
| return 0; |
| } |
| return 1; |
| } |
| |
| |
| static int |
| _do_save_subkey(FILE *F,LPKEYSTRUCT lpkey) { |
| LPKEYSTRUCT lpxkey; |
| int nrofkeys; |
| int i; |
| |
| nrofkeys= 0; |
| lpxkey = lpkey; |
| while (lpxkey) { |
| if (!(lpxkey->flags & REG_OPTION_VOLATILE)) |
| nrofkeys++; |
| lpxkey = lpxkey->next; |
| } |
| if (!_write_DWORD(F,nrofkeys)) |
| return 0; |
| |
| lpxkey = lpkey; |
| while (lpxkey) { |
| if (!(lpxkey->flags & REG_OPTION_VOLATILE)) { |
| if (!_write_USTRING(F,lpxkey->keyname)) |
| return 0; |
| if (!_write_USTRING(F,lpxkey->class)) |
| return 0; |
| if (!_write_DWORD(F,lpxkey->nrofvalues)) |
| return 0; |
| for (i=0;i<lpxkey->nrofvalues;i++) { |
| LPKEYVALUE val=lpxkey->values+i; |
| |
| if (!_write_USTRING(F,val->name)) |
| return 0; |
| if (!_write_DWORD(F,val->type)) |
| return 0; |
| if (!_write_DWORD(F,val->len)) |
| return 0; |
| if (!fwrite(val->data,val->len,1,F)) |
| return 0; |
| } |
| /* descend recursively */ |
| if (!_do_save_subkey(F,lpxkey->nextsub)) |
| return 0; |
| } |
| lpxkey=lpxkey->next; |
| } |
| return 1; |
| } |
| |
| static int |
| _do_savesubreg(FILE *F,LPKEYSTRUCT lpkey) { |
| if (!_write_DWORD(F,REGISTRY_SAVE_VERSION)) |
| return 0; |
| return _do_save_subkey(F,lpkey->nextsub); |
| } |
| |
| static void |
| _SaveSubReg(LPKEYSTRUCT lpkey,char *fn) { |
| FILE *F; |
| |
| F=fopen(fn,"wb"); |
| 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() { |
| _SaveSubReg(key_classes_root,SAVE_CLASSES_ROOT); |
| _SaveSubReg(key_current_user,SAVE_CURRENT_USER); |
| _SaveSubReg(key_local_machine,SAVE_LOCAL_MACHINE); |
| _SaveSubReg(key_users,SAVE_USERS); |
| } |
| |
| /************************ LOAD Registry Function ****************************/ |
| |
| /* FIXME: |
| * Currently overwrites any old registry data (leaks it away) |
| * should better be a merge, or ? |
| */ |
| |
| static int |
| _read_DWORD(FILE *F,DWORD *dw) { |
| return fread(dw,sizeof(DWORD),1,F); |
| } |
| |
| static int |
| _read_USTRING(FILE *F,LPWSTR *str) { |
| DWORD len; |
| |
| if (!_read_DWORD(F,&len)) |
| return 0; |
| if (len==0) { |
| *str=NULL; |
| return 1; |
| } |
| *str=xmalloc(len); |
| return fread(*str,len,1,F); |
| } |
| |
| static int |
| _do_load_subkey(FILE *F,LPKEYSTRUCT lpkey) { |
| DWORD howmuch; |
| LPKEYSTRUCT *lplpkey,lpxkey; |
| int i; |
| |
| if (!_read_DWORD(F,&howmuch)) |
| return 0; |
| |
| /* no subkeys? */ |
| if (howmuch==0) |
| return 1; |
| |
| lplpkey = &(lpkey->nextsub); |
| while (howmuch--) { |
| *lplpkey= (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT)); |
| memset(*lplpkey,'\0',sizeof(KEYSTRUCT)); |
| lpxkey = *lplpkey; |
| if (!_read_USTRING(F,&(lpxkey->keyname))) |
| return 0; |
| if (!_read_USTRING(F,&(lpxkey->class))) |
| return 0; |
| if (!_read_DWORD(F,&(lpxkey->nrofvalues))) |
| return 0; |
| if (lpxkey->nrofvalues) { |
| lpxkey->values = (LPKEYVALUE)xmalloc( |
| lpxkey->nrofvalues*sizeof(KEYVALUE) |
| ); |
| for (i=0;i<lpxkey->nrofvalues;i++) { |
| LPKEYVALUE val=lpxkey->values+i; |
| |
| memset(val,'\0',sizeof(KEYVALUE)); |
| if (!_read_USTRING(F,&(val->name))) |
| return 0; |
| if (!_read_DWORD(F,&(val->type))) |
| return 0; |
| if (!_read_DWORD(F,&(val->len))) |
| return 0; |
| val->data = (LPBYTE)xmalloc(val->len); |
| if (!fread(val->data,val->len,1,F)) |
| return 0; |
| } |
| } |
| if (!_do_load_subkey(F,*lplpkey)) |
| return 0; |
| lplpkey = &(lpxkey->next); |
| } |
| return 1; |
| } |
| |
| static int |
| _do_loadsubreg(FILE *F,LPKEYSTRUCT lpkey) { |
| DWORD ver; |
| |
| if (!_read_DWORD(F,&ver)) |
| return 0; |
| if (ver!=REGISTRY_SAVE_VERSION) { |
| dprintf_reg(stddeb,__FILE__":_do_loadsubreg:Old format (%lx) registry found, ignoring it.\n",ver); |
| return 0; |
| } |
| if (!_do_load_subkey(F,lpkey)) { |
| /* FIXME: memory leak on failure to read registry ... |
| * But this won't happen very often. |
| */ |
| lpkey->nextsub=NULL; |
| return 0; |
| } |
| 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); |
| } |
| fclose(F); |
| } |
| |
| void |
| SHELL_LoadRegistry() { |
| if (key_classes_root==NULL) |
| SHELL_Init(); |
| _LoadSubReg(key_classes_root,SAVE_CLASSES_ROOT); |
| _LoadSubReg(key_current_user,SAVE_CURRENT_USER); |
| _LoadSubReg(key_local_machine,SAVE_LOCAL_MACHINE); |
| _LoadSubReg(key_users,SAVE_USERS); |
| } |
| |
| /********************* 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; |
| lpxkey = lpNextKey; |
| while (i<wpc) { |
| lpxkey=lpNextKey->nextsub; |
| 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; |
| lpxkey = lpNextKey; |
| while (i<wpc) { |
| lpxkey=lpNextKey->nextsub; |
| 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 (i<wpc) { |
| lplpPrevKey = &(lpNextKey->nextsub); |
| 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;i<lpkey->nrofvalues;i++) |
| if (lpkey->values[i].name==NULL) |
| break; |
| } else { |
| for (i=0;i<lpkey->nrofvalues;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 (*lpcbData<lpkey->values[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;i<lpkey->nrofvalues;i++) |
| if (lpkey->values[i].name==NULL) |
| break; |
| } else { |
| for (i=0;i<lpkey->nrofvalues;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); |
| 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<<dwType) & UNICONVMASK) { |
| buf=(LPBYTE)strdupA2W(lpbData); |
| cbData=2*strlen(lpbData)+2; |
| } else |
| buf=lpbData; |
| if (lpszValueName) |
| lpszValueNameW = strdupA2W(lpszValueName); |
| else |
| lpszValueNameW = NULL; |
| ret=RegSetValueExW(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData); |
| if (lpszValueNameW) |
| free(lpszValueNameW); |
| if (buf!=lpbData) |
| free(buf); |
| return ret; |
| } |
| |
| /* RegSetValueEx [KERNEL.226] */ |
| WINAPI DWORD |
| RegSetValueEx( |
| HKEY hkey, |
| LPSTR lpszValueName, |
| DWORD dwReserved, |
| DWORD dwType, |
| LPBYTE lpbData, |
| DWORD cbData |
| ) { |
| dprintf_reg(stddeb,"RegSetValueEx(%lx,%s,%ld,%ld,%p,%ld)\n->", |
| 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 (i<wpc-1) { |
| lpxkey=lpNextKey->nextsub; |
| 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;i<lpkey->nrofvalues;i++) |
| if (!strcmpW(lpkey->values[i].name,lpszValue)) |
| break; |
| } else { |
| for (i=0;i<lpkey->nrofvalues;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;i<lpxkey->nrofvalues;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; |
| } |