Commit d74e643f authored by Misha Koshelev's avatar Misha Koshelev Committed by Alexandre Julliard

msi: automation: Implement Installer::RegistryValue.

parent 627ca407
......@@ -25,6 +25,7 @@
#include "winbase.h"
#include "winerror.h"
#include "winuser.h"
#include "winreg.h"
#include "msidefs.h"
#include "msipriv.h"
#include "activscp.h"
......@@ -514,6 +515,35 @@ static const IProvideMultipleClassInfoVtbl AutomationObject_IProvideMultipleClas
* Individual Object Invocation Functions
*/
/* Helper function that copies a passed parameter instead of using VariantChangeType like the actual DispGetParam.
This function is only for VARIANT type parameters that have several types that cannot be properly discriminated
using DispGetParam/VariantChangeType. */
HRESULT WINAPI DispGetParam_CopyOnly(
DISPPARAMS *pdispparams, /* [in] Parameter list */
UINT *position, /* [in] Position of parameter to copy in pdispparams; on return will contain calculated position */
VARIANT *pvarResult) /* [out] Destination for resulting variant */
{
/* position is counted backwards */
UINT pos;
TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
*position, pdispparams->cArgs, pdispparams->cNamedArgs);
if (*position < pdispparams->cArgs) {
/* positional arg? */
pos = pdispparams->cArgs - *position - 1;
} else {
/* FIXME: is this how to handle named args? */
for (pos=0; pos<pdispparams->cNamedArgs; pos++)
if (pdispparams->rgdispidNamedArgs[pos] == *position) break;
if (pos==pdispparams->cNamedArgs)
return DISP_E_PARAMNOTFOUND;
}
*position = pos;
return VariantCopyInd(pvarResult,
&pdispparams->rgvarg[pos]);
}
static HRESULT WINAPI RecordImpl_Invoke(
AutomationObject* This,
DISPID dispIdMember,
......@@ -990,6 +1020,69 @@ static HRESULT WINAPI SessionImpl_Invoke(
return S_OK;
}
/* Fill the variant pointed to by pVarResult with the value & size returned by RegQueryValueEx as dictated by the
* registry value type. Used by Installer::RegistryValue. */
static void variant_from_registry_value(VARIANT *pVarResult, DWORD dwType, LPBYTE lpData, DWORD dwSize)
{
static const WCHAR szREG_BINARY[] = { '(','R','E','G','_','B','I','N','A','R','Y',')',0 };
static const WCHAR szREG_[] = { '(','R','E','G','_',']',0 };
WCHAR *szString = (WCHAR *)lpData;
LPWSTR szNewString = NULL;
DWORD dwNewSize = 0;
int idx;
switch (dwType)
{
/* Registry strings may not be null terminated so we must use SysAllocStringByteLen/Len */
case REG_MULTI_SZ: /* Multi SZ change internal null characters to newlines */
idx = (dwSize/sizeof(WCHAR))-1;
while (idx >= 0 && !szString[idx]) idx--;
for (; idx >= 0; idx--)
if (!szString[idx]) szString[idx] = '\n';
case REG_SZ:
V_VT(pVarResult) = VT_BSTR;
V_BSTR(pVarResult) = SysAllocStringByteLen((LPCSTR)szString, dwSize);
break;
case REG_EXPAND_SZ:
if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
else if (!(szNewString = msi_alloc(dwNewSize)))
ERR("Out of memory\n");
else if (!(dwNewSize = ExpandEnvironmentStringsW(szString, szNewString, dwNewSize)))
ERR("ExpandEnvironmentStrings returned error %d\n", GetLastError());
else
{
V_VT(pVarResult) = VT_BSTR;
V_BSTR(pVarResult) = SysAllocStringLen(szNewString, dwNewSize);
}
msi_free(szNewString);
break;
case REG_DWORD:
V_VT(pVarResult) = VT_I4;
V_I4(pVarResult) = *((DWORD *)lpData);
break;
case REG_QWORD:
V_VT(pVarResult) = VT_BSTR;
V_BSTR(pVarResult) = SysAllocString(szREG_); /* Weird string, don't know why native returns it */
break;
case REG_BINARY:
V_VT(pVarResult) = VT_BSTR;
V_BSTR(pVarResult) = SysAllocString(szREG_BINARY);
break;
case REG_NONE:
V_VT(pVarResult) = VT_EMPTY;
break;
default:
FIXME("Unhandled registry value type %d\n", dwType);
}
}
static HRESULT WINAPI InstallerImpl_Invoke(
AutomationObject* This,
DISPID dispIdMember,
......@@ -1004,11 +1097,12 @@ static HRESULT WINAPI InstallerImpl_Invoke(
MSIHANDLE msiHandle;
IDispatch *pDispatch = NULL;
UINT ret;
VARIANTARG varg0, varg1;
VARIANTARG varg0, varg1, varg2;
HRESULT hr;
VariantInit(&varg0);
VariantInit(&varg1);
VariantInit(&varg2);
switch (dispIdMember)
{
......@@ -1043,6 +1137,95 @@ static HRESULT WINAPI InstallerImpl_Invoke(
}
break;
case DISPID_INSTALLER_REGISTRYVALUE:
if (wFlags & DISPATCH_METHOD) {
HKEY hkey;
LPWSTR szString = NULL;
DWORD dwSize = 0, dwType;
UINT posValue = 2; /* Save valuePos so we can save puArgErr if we are unable to do our type conversions */
hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr);
if (FAILED(hr)) return hr;
hr = DispGetParam(pDispParams, 1, VT_BSTR, &varg1, puArgErr);
if (FAILED(hr)) return hr;
hr = DispGetParam_CopyOnly(pDispParams, &posValue, &varg2);
if (FAILED(hr))
{
VariantClear(&varg1);
return hr;
}
ret = RegOpenKeyW((HKEY)V_I4(&varg0), V_BSTR(&varg1), &hkey);
/* Third parameter can be VT_EMPTY, VT_I4, or VT_BSTR */
switch (V_VT(&varg2))
{
case VT_EMPTY: /* Return VT_BOOL as to whether or not registry key exists */
V_VT(pVarResult) = VT_BOOL;
V_BOOL(pVarResult) = (ret == ERROR_SUCCESS);
break;
case VT_BSTR: /* Return value of specified key if it exists */
if (ret == ERROR_SUCCESS &&
(ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL, NULL, NULL, &dwSize)) == ERROR_SUCCESS)
{
if (!(szString = msi_alloc(dwSize)))
ERR("Out of memory\n");
else if ((ret = RegQueryValueExW(hkey, V_BSTR(&varg2), NULL, &dwType, (LPBYTE)szString, &dwSize)) == ERROR_SUCCESS)
variant_from_registry_value(pVarResult, dwType, (LPBYTE)szString, dwSize);
}
if (ret != ERROR_SUCCESS)
{
msi_free(szString);
VariantClear(&varg2);
VariantClear(&varg1);
return DISP_E_BADINDEX;
}
break;
default: /* Try to make it into VT_I4, can use VariantChangeType for this */
hr = VariantChangeType(&varg2, &varg2, 0, VT_I4);
if (SUCCEEDED(hr) && ret != ERROR_SUCCESS) hr = DISP_E_BADINDEX; /* Conversion fine, but couldn't find key */
if (FAILED(hr))
{
if (hr == DISP_E_TYPEMISMATCH) *puArgErr = posValue;
VariantClear(&varg2); /* Unknown type, so let's clear it */
VariantClear(&varg1);
return hr;
}
/* Retrieve class name or maximum value name or subkey name size */
if (!V_I4(&varg2))
ret = RegQueryInfoKeyW(hkey, NULL, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
else if (V_I4(&varg2) > 0)
ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwSize, NULL, NULL, NULL);
else /* V_I4(&varg2) < 0 */
ret = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL);
if (ret == ERROR_SUCCESS)
{
if (!(szString = msi_alloc(++dwSize * sizeof(WCHAR))))
ERR("Out of memory\n");
else if (!V_I4(&varg2))
ret = RegQueryInfoKeyW(hkey, szString, &dwSize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
else if (V_I4(&varg2) > 0)
ret = RegEnumValueW(hkey, V_I4(&varg2)-1, szString, &dwSize, 0, 0, NULL, NULL);
else /* V_I4(&varg2) < 0 */
ret = RegEnumKeyW(hkey, -1 - V_I4(&varg2), szString, dwSize);
if (szString && ret == ERROR_SUCCESS)
{
V_VT(pVarResult) = VT_BSTR;
V_BSTR(pVarResult) = SysAllocString(szString);
}
}
}
msi_free(szString);
RegCloseKey(hkey);
}
break;
case DISPID_INSTALLER_PRODUCTSTATE:
if (wFlags & DISPATCH_PROPERTYGET) {
hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr);
......@@ -1096,6 +1279,7 @@ static HRESULT WINAPI InstallerImpl_Invoke(
return DISP_E_MEMBERNOTFOUND;
}
VariantClear(&varg2);
VariantClear(&varg1);
VariantClear(&varg0);
......
......@@ -63,6 +63,11 @@ library WindowsInstaller
Session* OpenPackage(
[in] VARIANT PackagePath,
[in, optional, defaultvalue(0)] long Options);
[id(DISPID_INSTALLER_REGISTRYVALUE), propget]
BSTR RegistryValue(
[in] VARIANT Root,
[in] BSTR Key,
[in, optional] VARIANT Value);
[id(DISPID_INSTALLER_PRODUCTSTATE), propget]
MsiInstallState ProductState(
[in] BSTR Product);
......
......@@ -17,6 +17,7 @@
*/
#define DISPID_INSTALLER_OPENPACKAGE 2
#define DISPID_INSTALLER_REGISTRYVALUE 11
#define DISPID_INSTALLER_PRODUCTSTATE 17
#define DISPID_INSTALLER_PRODUCTS 35
......
......@@ -325,7 +325,9 @@ static void test_dispid(void)
ok( get_dispid( pInstaller, "InstallProduct" ) == 8, "dispid wrong\n");
ok( get_dispid( pInstaller, "Version" ) == 9, "dispid wrong\n");
ok( get_dispid( pInstaller, "LastErrorRecord" ) == 10, "dispid wrong\n");
}
ok( get_dispid( pInstaller, "RegistryValue" ) == 11, "dispid wrong\n");
todo_wine {
ok( get_dispid( pInstaller, "Environment" ) == 12, "dispid wrong\n");
ok( get_dispid( pInstaller, "FileAttributes" ) == 13, "dispid wrong\n");
......@@ -1153,20 +1155,18 @@ static void test_Installer_RegistryValue(void)
if (!RegOpenKeyW( HKEY_CURRENT_USER, szKey, &hkey )) delete_key( hkey );
/* Does our key exist? Shouldn't; check with all three possible value parameter types */
todo_wine {
hr = Installer_RegistryValueE(HKEY_CURRENT_USER, szKey, &bRet);
ok(SUCCEEDED(hr), "Installer_RegistryValueE failed, hresult 0x%08x\n", hr);
if (SUCCEEDED(hr))
ok(!bRet, "Registry key expected to not exist, but Installer_RegistryValue claims it does\n");
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, NULL, szString);
ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 0, szString, VT_BSTR);
ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
}
hr = Installer_RegistryValueE(HKEY_CURRENT_USER, szKey, &bRet);
ok(SUCCEEDED(hr), "Installer_RegistryValueE failed, hresult 0x%08x\n", hr);
if (SUCCEEDED(hr))
ok(!bRet, "Registry key expected to not exist, but Installer_RegistryValue claims it does\n");
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, NULL, szString);
ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 0, szString, VT_BSTR);
ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
/* Create key */
ok(!RegCreateKeyW( HKEY_CURRENT_USER, szKey, &hkey ), "RegCreateKeyW failed\n");
......@@ -1192,92 +1192,91 @@ static void test_Installer_RegistryValue(void)
ok(!RegCreateKeyW( hkey, szEight, &hkey_sub ), "RegCreateKeyW failed\n");
todo_wine {
/* Does our key exist? It should, and make sure we retrieve the correct default value */
bRet = FALSE;
hr = Installer_RegistryValueE(HKEY_CURRENT_USER, szKey, &bRet);
ok(SUCCEEDED(hr), "Installer_RegistryValueE failed, hresult 0x%08x\n", hr);
if (SUCCEEDED(hr))
ok(bRet, "Registry key expected to exist, but Installer_RegistryValue claims it does not\n");
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, NULL, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Default registry value \"%s\" does not match expected \"%s\"\n", szString, szOne);
/* Ask for the value of a non-existent key */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szExpand, szString);
ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
/* Get values of keys */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szOne, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szOne);
VariantInit(&vararg);
V_VT(&vararg) = VT_BSTR;
V_BSTR(&vararg) = SysAllocString(szTwo);
hr = Installer_RegistryValue(HKEY_CURRENT_USER, szKey, vararg, &varresult, VT_I4);
ok(SUCCEEDED(hr), "Installer_RegistryValue failed, hresult 0x%08x\n", hr);
ok(V_I4(&varresult) == 305419896, "Registry value %d does not match expected value\n", V_I4(&varresult));
VariantClear(&varresult);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szThree, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szREG_BINARY);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szFour, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szFour);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szFive, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szFiveHi);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szSix, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szREG_);
VariantInit(&vararg);
V_VT(&vararg) = VT_BSTR;
V_BSTR(&vararg) = SysAllocString(szSeven);
hr = Installer_RegistryValue(HKEY_CURRENT_USER, szKey, vararg, &varresult, VT_EMPTY);
ok(SUCCEEDED(hr), "Installer_RegistryValue failed, hresult 0x%08x\n", hr);
/* Get string class name for the key */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 0, szString, VT_BSTR);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szBlank);
/* Get name of a value by positive number (RegEnumValue like), valid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 2, szString, VT_BSTR);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szTwo);
/* Get name of a value by positive number (RegEnumValue like), invalid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 10, szString, VT_EMPTY);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
/* Get name of a subkey by negative number (RegEnumValue like), valid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, -1, szString, VT_BSTR);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szEight);
/* Get name of a subkey by negative number (RegEnumValue like), invalid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, -10, szString, VT_EMPTY);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
}
/* Does our key exist? It should, and make sure we retrieve the correct default value */
bRet = FALSE;
hr = Installer_RegistryValueE(HKEY_CURRENT_USER, szKey, &bRet);
ok(SUCCEEDED(hr), "Installer_RegistryValueE failed, hresult 0x%08x\n", hr);
if (SUCCEEDED(hr))
ok(bRet, "Registry key expected to exist, but Installer_RegistryValue claims it does not\n");
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, NULL, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Default registry value \"%s\" does not match expected \"%s\"\n", szString, szOne);
/* Ask for the value of a non-existent key */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szExpand, szString);
ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
/* Get values of keys */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szOne, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szOne);
VariantInit(&vararg);
V_VT(&vararg) = VT_BSTR;
V_BSTR(&vararg) = SysAllocString(szTwo);
hr = Installer_RegistryValue(HKEY_CURRENT_USER, szKey, vararg, &varresult, VT_I4);
ok(SUCCEEDED(hr), "Installer_RegistryValue failed, hresult 0x%08x\n", hr);
ok(V_I4(&varresult) == 305419896, "Registry value %d does not match expected value\n", V_I4(&varresult));
VariantClear(&varresult);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szThree, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szREG_BINARY);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szFour, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szFour);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szFive, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szFiveHi);
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szSix, szString);
ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr);
ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szREG_);
VariantInit(&vararg);
V_VT(&vararg) = VT_BSTR;
V_BSTR(&vararg) = SysAllocString(szSeven);
hr = Installer_RegistryValue(HKEY_CURRENT_USER, szKey, vararg, &varresult, VT_EMPTY);
ok(SUCCEEDED(hr), "Installer_RegistryValue failed, hresult 0x%08x\n", hr);
/* Get string class name for the key */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 0, szString, VT_BSTR);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szBlank);
/* Get name of a value by positive number (RegEnumValue like), valid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 2, szString, VT_BSTR);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
/* RegEnumValue order seems different on wine */
todo_wine ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szTwo);
/* Get name of a value by positive number (RegEnumValue like), invalid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 10, szString, VT_EMPTY);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
/* Get name of a subkey by negative number (RegEnumValue like), valid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, -1, szString, VT_BSTR);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szEight);
/* Get name of a subkey by negative number (RegEnumValue like), invalid index */
memset(szString, 0, sizeof(szString));
hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, -10, szString, VT_EMPTY);
ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr);
/* clean up */
delete_key(hkey);
......
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