wshom.ocx: Implement RegRead().
This commit is contained in:
parent
797bd65f62
commit
41c44f9185
|
@ -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)
|
||||
{
|
||||
FIXME("(%s %p): stub\n", debugstr_w(Name), out_Value);
|
||||
return E_NOTIMPL;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue