mirror of
https://github.com/reactos/wine.git
synced 2024-12-05 10:17:57 +00:00
8664b890b0
Fri Apr 5 15:22:55 1996 Alexandre Julliard <julliard@lrc.epfl.ch> * [controls/button.c] [controls/static.c] Changes to use WND * wherever possible. * [debugger/dbg.y] [debugger/debug.l] Added 'info module' and 'walk module' commands. * [if1632/Makefile.in] [if1632/relay.c] [tools/build.c] Added assembly code generation to call from Wine into 32-bit code. Changed all 'call32' references in 'callfrom16' to avoid confusion with Win32 routines. * [include/callback.h] Added prototypes for 32-bit callbacks. * [loader/module.c] [if1632/relay32.c] [tools/build.c] Unified 16- and 32-bit modules. The fake module for 32-bit DLLs is now generated by the build program. * [include/module.h] Added extra info to NE_MODULE for Win32 modules to point to the PE module data. * [include/pe_image.h] [loader/pe_image.c] [win32/resource.c] Removed the wine_files list. The PE data for a module can now be accessed with the NE_WIN32_MODULE macro. * [loader/signal.c] [miscemu/instr.c] Don't start the BIOS timer at startup, but only after an access to the 0x40 segment. * [memory/local.c] Changed LOCAL_Lock() to return a 32-bit pointer. * [misc/main.c] [include/dlls.h] Some built-in DLLs (like KERNEL) can no longer be disabled from the command-line. Thu Apr 4 19:54:39 1996 Keith Reynolds <keithr@sco.COM> * [*/*] A lot of small changes to support SCO OpenServer 5. Thu Apr 4 15:38:13 1996 Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl> * [controls/edit.c] Fixed GetKeyState() call to use 0x8000 convention. * [include/windows.h] Added undocumented messages EM_SCROLL and EM_GETTHUMB. Thu Apr 4 09:52:52 1996 John Harvey <john@division.co.uk> * [if1632/except.S] Modified code to assemble on unixware. Wed Apr 3 09:38:26 1996 Juergen Marquardt <marqu@lunar.advantest.de> * [objects/font.c] Implementation of a second font cache which will be updated dynamically. Mon Apr 1 16:47:40 1996 Robert Pouliot <krynos@qbc.clic.net> * [resources/sysres_Cz.rc] [resources/sysres_Da.rc] [resources/sysres_De.rc] [resources/sysres_Eo.rc] [resources/sysres_Es.rc] [resources/sysres_Fi.rc] [resources/sysres_No.rc] [resources/TODO] Updated FIND_TEXT and REPLACE_TEXT to work like the English version.
1887 lines
39 KiB
C
1887 lines
39 KiB
C
/*
|
|
* Registry Functions
|
|
*
|
|
* Copyright 1996 Marcus Meissner
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
#include <errno.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 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;
|
|
}
|