wine/misc/registry.c

1886 lines
39 KiB
C
Raw Normal View History

Release 960331 Sun Mar 31 13:54:46 1996 Alexandre Julliard <julliard@lrc.epfl.ch> * [tools/build.c] Changed BuildSpec32Files() to generate assembly instead of C code. Unified -spec16 and -spec32 options; DLL type is now determined by the 'type' declaration in the .spec file. New -stdcall option to build all stdcall assembly relays. * [if1632/relay.c] [if1632/relay32.c] [include/dlls.h] Started to unify 16- and 32-bit builtin DLLs. * [loader/module.c] Added MODULE_GetWndProcEntry32() to mirror MODULE_GetWndProcEntry16(). * [loader/pe_image.c] [loader/resource.c] All modules now have a NE signature, and can be distinguished by the NE_FFLAGS_WIN32 flag. * [windows/alias.c] Aliases for built-in window procedures are now all created at startup in ALIAS_Init(). Fri Mar 29 14:56:39 1996 Greg Kreider <kreider@natlab.research.philips.com> * [controls/combo.c] Limit rectangle to clear to size of item when painting combo, not default. Only draw items in list when there is enough room for them. * [controls/listbox.c] Get the measure of every item that's added and store in the item's data structure. Scroll listbox if mouse near edge of box. Only draw items in list when there is enough room. Fri Mar 29 12:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu> * [windows/defwnd.c] [windows/dialog.c] [windows/mdi.c] [windows/nonclient.c] [controls/menu.c] Various changes for better keyboard handling. * [windows/event.c] [windows/message.c] [misc/keyboard.c] Proper keyboard message ordering, working GetKeyState() (finally!), improvements in ToAscii(). * [windows/win.c] [windows/message.c] Small improvements in WIN_FindWinToRepaint. * [windows/win.c] [windows/painting.c] [windows/nonclient.c] Put update region in WM_NCPAINT wParam. * [loader/task.c] Kill task timers when task is deleted, switch timers to the new queue in SetTaskQueue(). * [loader/signal.c] [miscemu/dosmem.c] Added SIGALRM signal handler to increment BIOS clock. * [windows/win.c] [windows/winpos.c] [windows/mdi.c] Fixed ChildWindowFromPoint(), WM_PARENTNOTIFY and its handling by MDI client. * [windows/winpos.c] Improvements in handling of owned popups. "Floating" toolboxes work better now. Thu Mar 28 12:38:29 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de> * [misc/registry.c] New file, registry rewrite including win32 extensions - Unicode - multiple valus per key - different datatypes for values - multiple rootkeys - saving and loading in different registries. * [include/winreg.h] New file, definitions and structs for registry. * [include/winerror.h] Some new error defines added... there are more, someone please check a (real-)windows winerror.h. * [if1632/shell.spec] [if1632/advapi32.spec] [if1632/kernel.spec] Registry specs added. * [if1632/relay.c] Switch internal SHELL.DLL to default 'used'. * [win32/string32.c] [include/string32.h] Some new functions added. char should be unsigned char when converting to 16bit ints. * [misc/shell.c] [include/shell.h] [win32/advapi.c] Removed old registry functions. Tue Mar 26 15:01:46 1996 Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl> * [include/bitmaps/ocr_ibeam] Fixed the position of the hotspot. * [objects/text.c] Fixed a few bugs in TEXT_TabbedTextOut(). * [windows/event.c] Fixed the order of the bits in the KeyStateTable. 0x80 is the up/down-bit. 0x01 is the toggle bit. * [loader/resource.c] [windows/mdi.c] [controls/edit.c] Fixed the calls to GetKeyState(). Tue Mar 26 08:43:15 1996 Robert Pouliot <krynos@qbc.clic.net> * [resources/sysres_Fr.rc] [resources/TODO] Updated FIND_TEXT and REPLACE_TEXT to work like the English version. Mon Mar 25 17:38:59 1996 Tristan Tarrant <tst@dcs.ed.ac.uk> * [resources/sysres_it.rc] Added support for Italian [It] language.
1996-03-31 16:40:13 +00:00
/*
* 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;
}