Commit 41c44f91 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

wshom.ocx: Implement RegRead().

parent 797bd65f
......@@ -1010,10 +1010,181 @@ static HRESULT WINAPI WshShell3_ExpandEnvironmentStrings(IWshShell3 *iface, BSTR
}
}
static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR Name, VARIANT* out_Value)
static HKEY get_root_key(const WCHAR *path)
{
static const struct {
const WCHAR full[20];
const WCHAR abbrev[5];
HKEY hkey;
} rootkeys[] = {
{ {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, {'H','K','C','U',0}, HKEY_CURRENT_USER },
{ {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0}, {'H','K','L','M',0}, HKEY_LOCAL_MACHINE },
{ {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, {'H','K','C','R',0}, HKEY_CLASSES_ROOT },
{ {'H','K','E','Y','_','U','S','E','R','S',0}, {0}, HKEY_USERS },
{ {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, {0}, HKEY_CURRENT_CONFIG }
};
int i;
for (i = 0; i < sizeof(rootkeys)/sizeof(rootkeys[0]); i++) {
if (!strncmpW(path, rootkeys[i].full, strlenW(rootkeys[i].full)))
return rootkeys[i].hkey;
if (rootkeys[i].abbrev[0] && !strncmpW(path, rootkeys[i].abbrev, strlenW(rootkeys[i].abbrev)))
return rootkeys[i].hkey;
}
return NULL;
}
static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR name, VARIANT *value)
{
FIXME("(%s %p): stub\n", debugstr_w(Name), out_Value);
return E_NOTIMPL;
DWORD type, datalen, ret;
WCHAR *keyname, *val;
HRESULT hr = S_OK;
BSTR subkey = NULL;
HKEY root;
TRACE("(%s %p)\n", debugstr_w(name), value);
if (!name || !value)
return E_POINTER;
root = get_root_key(name);
if (!root)
return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
/* at least one separator should be present */
keyname = strchrW(name, '\\');
if (!keyname)
return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
/* default value or not */
if (keyname[strlenW(keyname)-1] == '\\') {
keyname++;
val = NULL;
}
else {
val = strrchrW(keyname, '\\');
if (val - keyname > 1) {
subkey = SysAllocStringLen(keyname+1, val-keyname-1);
keyname = subkey;
}
val++;
}
type = REG_NONE;
datalen = 0;
ret = RegGetValueW(root, keyname, val, RRF_RT_ANY, &type, NULL, &datalen);
if (ret == ERROR_SUCCESS) {
void *data;
data = HeapAlloc(GetProcessHeap(), 0, datalen);
if (!data) {
hr = E_OUTOFMEMORY;
goto fail;
}
ret = RegGetValueW(root, keyname, val, RRF_RT_ANY, &type, data, &datalen);
if (ret) {
HeapFree(GetProcessHeap(), 0, data);
hr = HRESULT_FROM_WIN32(ret);
goto fail;
}
switch (type) {
case REG_SZ:
case REG_EXPAND_SZ:
V_VT(value) = VT_BSTR;
V_BSTR(value) = SysAllocStringLen((WCHAR*)data, datalen - sizeof(WCHAR));
if (!V_BSTR(value))
hr = E_OUTOFMEMORY;
break;
case REG_DWORD:
V_VT(value) = VT_I4;
V_I4(value) = *(DWORD*)data;
break;
case REG_BINARY:
{
BYTE *ptr = (BYTE*)data;
SAFEARRAYBOUND bound;
unsigned int i;
SAFEARRAY *sa;
VARIANT *v;
bound.lLbound = 0;
bound.cElements = datalen;
sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
if (!sa)
break;
hr = SafeArrayAccessData(sa, (void**)&v);
if (FAILED(hr)) {
SafeArrayDestroy(sa);
break;
}
for (i = 0; i < datalen; i++) {
V_VT(&v[i]) = VT_UI1;
V_UI1(&v[i]) = ptr[i];
}
SafeArrayUnaccessData(sa);
V_VT(value) = VT_ARRAY|VT_VARIANT;
V_ARRAY(value) = sa;
break;
}
case REG_MULTI_SZ:
{
WCHAR *ptr = (WCHAR*)data;
SAFEARRAYBOUND bound;
SAFEARRAY *sa;
VARIANT *v;
/* get element count first */
bound.lLbound = 0;
bound.cElements = 0;
while (*ptr) {
bound.cElements++;
ptr += strlenW(ptr)+1;
}
sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
if (!sa)
break;
hr = SafeArrayAccessData(sa, (void**)&v);
if (FAILED(hr)) {
SafeArrayDestroy(sa);
break;
}
ptr = (WCHAR*)data;
while (*ptr) {
V_VT(v) = VT_BSTR;
V_BSTR(v) = SysAllocString(ptr);
ptr += strlenW(ptr)+1;
v++;
}
SafeArrayUnaccessData(sa);
V_VT(value) = VT_ARRAY|VT_VARIANT;
V_ARRAY(value) = sa;
break;
}
default:
FIXME("value type %d not supported\n", type);
hr = E_FAIL;
};
HeapFree(GetProcessHeap(), 0, data);
if (FAILED(hr))
VariantInit(value);
}
else
hr = HRESULT_FROM_WIN32(ret);
fail:
SysFreeString(subkey);
return hr;
}
static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR Name, VARIANT *Value, VARIANT *Type)
......
TESTDLL = wshom.ocx
IMPORTS = oleaut32 ole32
IMPORTS = oleaut32 ole32 advapi32
C_SRCS = \
wshom.c
......
......@@ -59,10 +59,7 @@ static void test_wshshell(void)
hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
&IID_IDispatch, (void**)&disp);
if(FAILED(hr)) {
win_skip("Could not create WshShell object: %08x\n", hr);
return;
}
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDispatch_QueryInterface(disp, &IID_IWshShell3, (void**)&shell);
EXPECT_HR(hr, S_OK);
......@@ -207,11 +204,211 @@ static void test_wshshell(void)
IUnknown_Release(shell);
}
/* delete key and all its subkeys */
static DWORD delete_key(HKEY hkey)
{
char name[MAX_PATH];
DWORD ret;
while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name)))) {
HKEY tmp;
if (!(ret = RegOpenKeyExA(hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp))) {
ret = delete_key(tmp);
RegCloseKey(tmp);
}
if (ret) break;
}
if (ret != ERROR_NO_MORE_ITEMS) return ret;
RegDeleteKeyA(hkey, "");
return 0;
}
static void test_registry(void)
{
static const WCHAR keypathW[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',
'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\',0};
static const WCHAR regszW[] = {'r','e','g','s','z',0};
static const WCHAR regdwordW[] = {'r','e','g','d','w','o','r','d',0};
static const WCHAR regbinaryW[] = {'r','e','g','b','i','n','a','r','y',0};
static const WCHAR regmultiszW[] = {'r','e','g','m','u','l','t','i','s','z',0};
static const WCHAR regsz1W[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\',
'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t','\\','r','e','g','s','z','1',0};
static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
static const WCHAR fooW[] = {'f','o','o',0};
static const WCHAR brokenW[] = {'H','K','E','Y','_','b','r','o','k','e','n','_','k','e','y',0};
static const WCHAR broken2W[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','a',0};
WCHAR pathW[MAX_PATH];
VARIANT value, v;
IWshShell3 *sh3;
VARTYPE vartype;
DWORD dwvalue;
LONG bound;
HRESULT hr;
BSTR name;
HKEY root;
LONG ret;
UINT dim;
hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
&IID_IWshShell3, (void**)&sh3);
ok(hr == S_OK, "got 0x%08x\n", hr);
V_VT(&value) = VT_I2;
hr = IWshShell3_RegRead(sh3, NULL, &value);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value));
name = SysAllocString(brokenW);
hr = IWshShell3_RegRead(sh3, name, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
V_VT(&value) = VT_I2;
hr = IWshShell3_RegRead(sh3, name, &value);
ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "got 0x%08x\n", hr);
ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value));
SysFreeString(name);
name = SysAllocString(broken2W);
V_VT(&value) = VT_I2;
hr = IWshShell3_RegRead(sh3, name, &value);
ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "got 0x%08x\n", hr);
ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value));
SysFreeString(name);
ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &root);
ok(ret == 0, "got %d\n", ret);
ret = RegSetValueExA(root, "regsz", 0, REG_SZ, (const BYTE*)"foobar", 7);
ok(ret == 0, "got %d\n", ret);
ret = RegSetValueExA(root, "regmultisz", 0, REG_MULTI_SZ, (const BYTE*)"foo\0bar\0", 9);
ok(ret == 0, "got %d\n", ret);
dwvalue = 10;
ret = RegSetValueExA(root, "regdword", 0, REG_DWORD, (const BYTE*)&dwvalue, sizeof(dwvalue));
ok(ret == 0, "got %d\n", ret);
dwvalue = 11;
ret = RegSetValueExA(root, "regbinary", 0, REG_BINARY, (const BYTE*)&dwvalue, sizeof(dwvalue));
ok(ret == 0, "got %d\n", ret);
/* REG_SZ */
lstrcpyW(pathW, keypathW);
lstrcatW(pathW, regszW);
name = SysAllocString(pathW);
VariantInit(&value);
hr = IWshShell3_RegRead(sh3, name, &value);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
ok(!lstrcmpW(V_BSTR(&value), foobarW), "got %s\n", wine_dbgstr_w(V_BSTR(&value)));
VariantClear(&value);
SysFreeString(name);
/* REG_DWORD */
lstrcpyW(pathW, keypathW);
lstrcatW(pathW, regdwordW);
name = SysAllocString(pathW);
VariantInit(&value);
hr = IWshShell3_RegRead(sh3, name, &value);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&value) == VT_I4, "got %d\n", V_VT(&value));
ok(V_I4(&value) == 10, "got %d\n", V_I4(&value));
SysFreeString(name);
/* REG_BINARY */
lstrcpyW(pathW, keypathW);
lstrcatW(pathW, regbinaryW);
name = SysAllocString(pathW);
VariantInit(&value);
hr = IWshShell3_RegRead(sh3, name, &value);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&value) == (VT_ARRAY|VT_VARIANT), "got 0x%x\n", V_VT(&value));
dim = SafeArrayGetDim(V_ARRAY(&value));
ok(dim == 1, "got %u\n", dim);
hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &bound);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(bound == 0, "got %u\n", bound);
hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &bound);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(bound == 3, "got %u\n", bound);
hr = SafeArrayGetVartype(V_ARRAY(&value), &vartype);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(vartype == VT_VARIANT, "got %d\n", vartype);
bound = 0;
hr = SafeArrayGetElement(V_ARRAY(&value), &bound, &v);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&v) == VT_UI1, "got %d\n", V_VT(&v));
ok(V_UI1(&v) == 11, "got %u\n", V_UI1(&v));
VariantClear(&v);
VariantClear(&value);
SysFreeString(name);
/* REG_MULTI_SZ */
lstrcpyW(pathW, keypathW);
lstrcatW(pathW, regmultiszW);
name = SysAllocString(pathW);
VariantInit(&value);
hr = IWshShell3_RegRead(sh3, name, &value);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&value) == (VT_ARRAY|VT_VARIANT), "got 0x%x\n", V_VT(&value));
dim = SafeArrayGetDim(V_ARRAY(&value));
ok(dim == 1, "got %u\n", dim);
hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &bound);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(bound == 0, "got %u\n", bound);
hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &bound);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(bound == 1, "got %u\n", bound);
hr = SafeArrayGetVartype(V_ARRAY(&value), &vartype);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(vartype == VT_VARIANT, "got %d\n", vartype);
bound = 0;
hr = SafeArrayGetElement(V_ARRAY(&value), &bound, &v);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
ok(!lstrcmpW(V_BSTR(&v), fooW), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
VariantClear(&v);
VariantClear(&value);
name = SysAllocString(regsz1W);
V_VT(&value) = VT_I2;
hr = IWshShell3_RegRead(sh3, name, &value);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
ok(V_VT(&value) == VT_I2, "got %d\n", V_VT(&value));
VariantClear(&value);
SysFreeString(name);
delete_key(root);
IWshShell3_Release(sh3);
}
START_TEST(wshom)
{
IUnknown *unk;
HRESULT hr;
CoInitialize(NULL);
hr = CoCreateInstance(&CLSID_WshShell, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
&IID_IUnknown, (void**)&unk);
if (FAILED(hr)) {
win_skip("Could not create WshShell object: %08x\n", hr);
return;
}
IUnknown_Release(unk);
test_wshshell();
test_registry();
CoUninitialize();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment