From 4588bb117094f71de5ac9601fbc758ad6a8c9b30 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 18 Feb 2015 08:39:25 +0300 Subject: [PATCH] wshom.ocx: Implement RegWrite(). --- dlls/wshom.ocx/Makefile.in | 2 +- dlls/wshom.ocx/shell.c | 156 +++++++++++++++++++++++++++++++++++-------- dlls/wshom.ocx/tests/wshom.c | 81 +++++++++++++++++++++- 3 files changed, 210 insertions(+), 29 deletions(-) diff --git a/dlls/wshom.ocx/Makefile.in b/dlls/wshom.ocx/Makefile.in index 891812ea7a7..18e1b96210b 100644 --- a/dlls/wshom.ocx/Makefile.in +++ b/dlls/wshom.ocx/Makefile.in @@ -1,5 +1,5 @@ MODULE = wshom.ocx -IMPORTS = uuid oleaut32 ole32 shell32 +IMPORTS = uuid oleaut32 ole32 shell32 advapi32 C_SRCS = \ shell.c \ diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c index 9bc39cbd9f7..02849676470 100644 --- a/dlls/wshom.ocx/shell.c +++ b/dlls/wshom.ocx/shell.c @@ -1035,12 +1035,46 @@ static HKEY get_root_key(const WCHAR *path) return NULL; } +/* Caller is responsible to free 'subkey' if 'value' is not NULL */ +static HRESULT split_reg_path(const WCHAR *path, WCHAR **subkey, WCHAR **value) +{ + *value = NULL; + + /* at least one separator should be present */ + *subkey = strchrW(path, '\\'); + if (!*subkey) + return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + + /* default value or not */ + if ((*subkey)[strlenW(*subkey)-1] == '\\') { + (*subkey)++; + *value = NULL; + } + else { + *value = strrchrW(*subkey, '\\'); + if (*value - *subkey > 1) { + unsigned int len = *value - *subkey - 1; + WCHAR *ret; + + ret = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); + if (!ret) + return E_OUTOFMEMORY; + + memcpy(ret, *subkey + 1, len*sizeof(WCHAR)); + ret[len] = 0; + *subkey = ret; + } + (*value)++; + } + + return S_OK; +} + 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; + WCHAR *subkey, *val; + HRESULT hr; HKEY root; TRACE("(%s %p)\n", debugstr_w(name), value); @@ -1052,28 +1086,13 @@ static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR name, VARIANT *v 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++; - } + hr = split_reg_path(name, &subkey, &val); + if (FAILED(hr)) + return hr; type = REG_NONE; datalen = 0; - ret = RegGetValueW(root, keyname, val, RRF_RT_ANY, &type, NULL, &datalen); + ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, NULL, &datalen); if (ret == ERROR_SUCCESS) { void *data; @@ -1083,7 +1102,7 @@ static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR name, VARIANT *v goto fail; } - ret = RegGetValueW(root, keyname, val, RRF_RT_ANY, &type, data, &datalen); + ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, data, &datalen); if (ret) { HeapFree(GetProcessHeap(), 0, data); hr = HRESULT_FROM_WIN32(ret); @@ -1183,14 +1202,97 @@ static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR name, VARIANT *v hr = HRESULT_FROM_WIN32(ret); fail: - SysFreeString(subkey); + if (val) + HeapFree(GetProcessHeap(), 0, subkey); return hr; } -static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR Name, VARIANT *Value, VARIANT *Type) +static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR name, VARIANT *value, VARIANT *type) { - FIXME("(%s %s %s): stub\n", debugstr_w(Name), debugstr_variant(Value), debugstr_variant(Type)); - return E_NOTIMPL; + static const WCHAR regexpandszW[] = {'R','E','G','_','E','X','P','A','N','D','_','S','Z',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}; + + DWORD regtype, data_len; + WCHAR *subkey, *val; + const BYTE *data; + HRESULT hr; + HKEY root; + VARIANT v; + LONG ret; + + TRACE("(%s %s %s)\n", debugstr_w(name), debugstr_variant(value), debugstr_variant(type)); + + if (!name || !value || !type) + return E_POINTER; + + root = get_root_key(name); + if (!root) + return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + + /* value type */ + if (is_optional_argument(type)) + regtype = REG_SZ; + else { + if (V_VT(type) != VT_BSTR) + return E_INVALIDARG; + + if (!strcmpW(V_BSTR(type), regszW)) + regtype = REG_SZ; + else if (!strcmpW(V_BSTR(type), regdwordW)) + regtype = REG_DWORD; + else if (!strcmpW(V_BSTR(type), regexpandszW)) + regtype = REG_EXPAND_SZ; + else if (!strcmpW(V_BSTR(type), regbinaryW)) + regtype = REG_BINARY; + else { + FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type))); + return E_FAIL; + } + } + + /* it's always a string or a DWORD */ + VariantInit(&v); + switch (regtype) + { + case REG_SZ: + case REG_EXPAND_SZ: + hr = VariantChangeType(&v, value, 0, VT_BSTR); + if (hr == S_OK) { + data = (BYTE*)V_BSTR(&v); + data_len = SysStringByteLen(V_BSTR(&v)) + sizeof(WCHAR); + } + break; + case REG_DWORD: + case REG_BINARY: + hr = VariantChangeType(&v, value, 0, VT_I4); + data = (BYTE*)&V_I4(&v); + data_len = sizeof(DWORD); + break; + default: + FIXME("unexpected regtype %d\n", regtype); + return E_FAIL; + }; + + if (FAILED(hr)) { + FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype, hr); + return hr; + } + + hr = split_reg_path(name, &subkey, &val); + if (FAILED(hr)) + goto fail; + + ret = RegSetKeyValueW(root, subkey, val, regtype, data, data_len); + if (ret) + hr = HRESULT_FROM_WIN32(ret); + +fail: + VariantClear(&v); + if (val) + HeapFree(GetProcessHeap(), 0, subkey); + return hr; } static HRESULT WINAPI WshShell3_RegDelete(IWshShell3 *iface, BSTR Name) diff --git a/dlls/wshom.ocx/tests/wshom.c b/dlls/wshom.ocx/tests/wshom.c index 1521b2b9004..a836f106d1c 100644 --- a/dlls/wshom.ocx/tests/wshom.c +++ b/dlls/wshom.ocx/tests/wshom.c @@ -240,10 +240,10 @@ static void test_registry(void) 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]; + DWORD dwvalue, type; VARIANT value, v; IWshShell3 *sh3; VARTYPE vartype; - DWORD dwvalue; LONG bound; HRESULT hr; BSTR name; @@ -255,6 +255,7 @@ static void test_registry(void) &IID_IWshShell3, (void**)&sh3); ok(hr == S_OK, "got 0x%08x\n", hr); + /* RegRead() */ V_VT(&value) = VT_I2; hr = IWshShell3_RegRead(sh3, NULL, &value); ok(hr == E_POINTER, "got 0x%08x\n", hr); @@ -389,6 +390,84 @@ static void test_registry(void) SysFreeString(name); delete_key(root); + + /* RegWrite() */ + ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &root); + ok(ret == 0, "got %d\n", ret); + + hr = IWshShell3_RegWrite(sh3, NULL, NULL, NULL); + ok(hr == E_POINTER, "got 0x%08x\n", hr); + + lstrcpyW(pathW, keypathW); + lstrcatW(pathW, regszW); + name = SysAllocString(pathW); + + hr = IWshShell3_RegWrite(sh3, name, NULL, NULL); + ok(hr == E_POINTER, "got 0x%08x\n", hr); + + VariantInit(&value); + hr = IWshShell3_RegWrite(sh3, name, &value, NULL); + ok(hr == E_POINTER, "got 0x%08x\n", hr); + + hr = IWshShell3_RegWrite(sh3, name, &value, &value); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + + /* type is optional */ + V_VT(&v) = VT_ERROR; + V_ERROR(&v) = DISP_E_PARAMNOTFOUND; + hr = IWshShell3_RegWrite(sh3, name, &value, &v); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* default type is REG_SZ */ + V_VT(&value) = VT_I4; + V_I4(&value) = 12; + hr = IWshShell3_RegWrite(sh3, name, &value, &v); + ok(hr == S_OK, "got 0x%08x\n", hr); + + type = REG_NONE; + ret = RegGetValueA(root, NULL, "regsz", RRF_RT_ANY, &type, NULL, NULL); + ok(ret == ERROR_SUCCESS, "got %d\n", ret); + ok(type == REG_SZ, "got %d\n", type); + + ret = RegDeleteValueA(root, "regsz"); + ok(ret == ERROR_SUCCESS, "got %d\n", ret); + V_VT(&value) = VT_BSTR; + V_BSTR(&value) = SysAllocString(regszW); + hr = IWshShell3_RegWrite(sh3, name, &value, &v); + ok(hr == S_OK, "got 0x%08x\n", hr); + VariantClear(&value); + + type = REG_NONE; + ret = RegGetValueA(root, NULL, "regsz", RRF_RT_ANY, &type, NULL, NULL); + ok(ret == ERROR_SUCCESS, "got %d\n", ret); + ok(type == REG_SZ, "got %d\n", type); + + ret = RegDeleteValueA(root, "regsz"); + ok(ret == ERROR_SUCCESS, "got %d\n", ret); + V_VT(&value) = VT_R4; + V_R4(&value) = 1.2; + hr = IWshShell3_RegWrite(sh3, name, &value, &v); + ok(hr == S_OK, "got 0x%08x\n", hr); + VariantClear(&value); + + type = REG_NONE; + ret = RegGetValueA(root, NULL, "regsz", RRF_RT_ANY, &type, NULL, NULL); + ok(ret == ERROR_SUCCESS, "got %d\n", ret); + ok(type == REG_SZ, "got %d\n", type); + + ret = RegDeleteValueA(root, "regsz"); + ok(ret == ERROR_SUCCESS, "got %d\n", ret); + V_VT(&value) = VT_R4; + V_R4(&value) = 1.2; + V_VT(&v) = VT_I2; + V_I2(&v) = 1; + hr = IWshShell3_RegWrite(sh3, name, &value, &v); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + VariantClear(&value); + + SysFreeString(name); + + delete_key(root); IWshShell3_Release(sh3); } -- 2.11.4.GIT