wshom.ocx: Implement RegWrite().
This commit is contained in:
parent
129862f369
commit
4588bb1170
|
@ -1,5 +1,5 @@
|
|||
MODULE = wshom.ocx
|
||||
IMPORTS = uuid oleaut32 ole32 shell32
|
||||
IMPORTS = uuid oleaut32 ole32 shell32 advapi32
|
||||
|
||||
C_SRCS = \
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
@ -388,6 +389,84 @@ static void test_registry(void)
|
|||
VariantClear(&value);
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue