From: Hans Leidekker hans@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52878 --- dlls/wbemprox/builtin.c | 8 ++ dlls/wbemprox/reg.c | 124 ++++++++++++++++++++++++++++--- dlls/wbemprox/tests/query.c | 43 +++++++++++ dlls/wbemprox/wbemprox_private.h | 1 + 4 files changed, 166 insertions(+), 10 deletions(-)
diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c index a2c21a2a6de..54a66c2aa8a 100644 --- a/dlls/wbemprox/builtin.c +++ b/dlls/wbemprox/builtin.c @@ -422,6 +422,7 @@ static const struct column col_stdregprov[] = { L"CreateKey", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, { L"EnumKey", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, { L"EnumValues", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, + { L"GetBinaryValue", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, { L"GetStringValue", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, { L"SetStringValue", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, { L"SetDWORDValue", CIM_FLAG_ARRAY|COL_FLAG_METHOD }, @@ -871,6 +872,7 @@ struct record_stdregprov class_method *createkey; class_method *enumkey; class_method *enumvalues; + class_method *getbinaryvalue; class_method *getstringvalue; class_method *setstringvalue; class_method *setdwordvalue; @@ -980,6 +982,11 @@ static const struct record_param data_param[] = { L"StdRegProv", L"EnumValues", -1, L"ReturnValue", CIM_UINT32 }, { L"StdRegProv", L"EnumValues", -1, L"sNames", CIM_STRING|CIM_FLAG_ARRAY }, { L"StdRegProv", L"EnumValues", -1, L"Types", CIM_SINT32|CIM_FLAG_ARRAY }, + { L"StdRegProv", L"GetBinaryValue", 1, L"hDefKey", CIM_SINT32, 0x80000002 }, + { L"StdRegProv", L"GetBinaryValue", 1, L"sSubKeyName", CIM_STRING }, + { L"StdRegProv", L"GetBinaryValue", 1, L"sValueName", CIM_STRING }, + { L"StdRegProv", L"GetBinaryValue", -1, L"ReturnValue", CIM_UINT32 }, + { L"StdRegProv", L"GetBinaryValue", -1, L"uValue", CIM_UINT8|CIM_FLAG_ARRAY }, { L"StdRegProv", L"GetStringValue", 1, L"hDefKey", CIM_SINT32, 0x80000002 }, { L"StdRegProv", L"GetStringValue", 1, L"sSubKeyName", CIM_STRING }, { L"StdRegProv", L"GetStringValue", 1, L"sValueName", CIM_STRING }, @@ -1047,6 +1054,7 @@ static const struct record_stdregprov data_stdregprov[] = reg_create_key, reg_enum_key, reg_enum_values, + reg_get_binaryvalue, reg_get_stringvalue, reg_set_stringvalue, reg_set_dwordvalue, diff --git a/dlls/wbemprox/reg.c b/dlls/wbemprox/reg.c index 81ed914ae2f..4092cd90886 100644 --- a/dlls/wbemprox/reg.c +++ b/dlls/wbemprox/reg.c @@ -271,7 +271,7 @@ done: }
static HRESULT enum_values( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *types, IWbemContext *context, - VARIANT *retval ) + VARIANT *retval ) { HKEY hkey = NULL; HRESULT hr = S_OK; @@ -386,7 +386,7 @@ done: }
static HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value, - IWbemContext *context, VARIANT *retval ) + IWbemContext *context, VARIANT *retval ) { DWORD size, mask, flags = RRF_RT_REG_SZ; HRESULT hr = S_OK; @@ -403,13 +403,8 @@ static HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *nam flags |= RRF_SUBKEY_WOW6432KEY;
if ((res = RegGetValueW( root, subkey, name, flags, NULL, NULL, &size ))) goto done; - if (!(str = SysAllocStringLen( NULL, size / sizeof(WCHAR) - 1 ))) - { - hr = E_OUTOFMEMORY; - goto done; - } - if (!(res = RegGetValueW( root, subkey, name, flags, NULL, str, &size ))) - set_variant( VT_BSTR, 0, str, value ); + if (!(str = SysAllocStringLen( NULL, size / sizeof(WCHAR) - 1 ))) return E_OUTOFMEMORY; + if (!(res = RegGetValueW( root, subkey, name, flags, NULL, str, &size ))) set_variant( VT_BSTR, 0, str, value );
done: set_variant( VT_UI4, res, NULL, retval ); @@ -480,8 +475,117 @@ done: return hr; }
+static HRESULT to_ui1_array( BYTE *value, DWORD size, VARIANT *var ) +{ + SAFEARRAY *sa; + HRESULT hr; + LONG i; + + if (!(sa = SafeArrayCreateVector( VT_UI1, 0, size ))) return E_OUTOFMEMORY; + for (i = 0; i < size; i++) + { + if ((hr = SafeArrayPutElement( sa, &i, &value[i] )) != S_OK) + { + SafeArrayDestroy( sa ); + return hr; + } + } + set_variant( VT_UI1|VT_ARRAY, 0, sa, var ); + return S_OK; +} + +static HRESULT get_binaryvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value, + IWbemContext *context, VARIANT *retval ) +{ + DWORD size, mask, flags = RRF_RT_REG_BINARY; + HRESULT hr = S_OK; + BYTE *buf = NULL; + LONG res; + + TRACE("%p, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name)); + + mask = reg_get_access_mask( context ); + + if (mask & KEY_WOW64_64KEY) + flags |= RRF_SUBKEY_WOW6464KEY; + else if (mask & KEY_WOW64_32KEY) + flags |= RRF_SUBKEY_WOW6432KEY; + + if ((res = RegGetValueW( root, subkey, name, flags, NULL, NULL, &size ))) goto done; + if (!(buf = malloc( size ))) return E_OUTOFMEMORY; + if (!(res = RegGetValueW( root, subkey, name, flags, NULL, buf, &size ))) hr = to_ui1_array( buf, size, value ); + +done: + set_variant( VT_UI4, res, NULL, retval ); + free( buf ); + return hr; +} + +HRESULT reg_get_binaryvalue( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out ) +{ + VARIANT defkey, subkey, name, value, retval; + IWbemClassObject *sig, *out_params = NULL; + HRESULT hr; + + TRACE("%p, %p, %p, %p\n", obj, context, in, out); + + hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL ); + if (hr != S_OK) return hr; + hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL ); + if (hr != S_OK) return hr; + hr = IWbemClassObject_Get( in, L"sValueName", 0, &name, NULL, NULL ); + if (hr != S_OK) + { + VariantClear( &subkey ); + return hr; + } + + hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"GetBinaryValue", PARAM_OUT, &sig ); + if (hr != S_OK) + { + VariantClear( &name ); + VariantClear( &subkey ); + return hr; + } + if (out) + { + hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params ); + if (hr != S_OK) + { + VariantClear( &name ); + VariantClear( &subkey ); + IWbemClassObject_Release( sig ); + return hr; + } + } + VariantInit( &value ); + hr = get_binaryvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, context, &retval ); + if (hr != S_OK) goto done; + if (out_params) + { + if (!V_UI4( &retval )) + { + hr = IWbemClassObject_Put( out_params, L"uValue", 0, &value, CIM_UINT8|CIM_FLAG_ARRAY ); + if (hr != S_OK) goto done; + } + hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 ); + } + +done: + VariantClear( &name ); + VariantClear( &subkey ); + IWbemClassObject_Release( sig ); + if (hr == S_OK && out) + { + *out = out_params; + IWbemClassObject_AddRef( out_params ); + } + if (out_params) IWbemClassObject_Release( out_params ); + return hr; +} + static void set_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, const WCHAR *value, - IWbemContext *context, VARIANT *retval ) + IWbemContext *context, VARIANT *retval ) { HKEY hkey; LONG res; diff --git a/dlls/wbemprox/tests/query.c b/dlls/wbemprox/tests/query.c index f777c2a9c61..beceffe7e69 100644 --- a/dlls/wbemprox/tests/query.c +++ b/dlls/wbemprox/tests/query.c @@ -1042,6 +1042,49 @@ static void test_StdRegProv( IWbemServices *services ) IWbemClassObject_Release( out ); IWbemClassObject_Release( sig_in );
+ hr = IWbemClassObject_GetMethod( reg, L"GetBinaryValue", 0, &sig_in, NULL ); + ok( hr == S_OK, "failed to get GetStringValue method %#lx\n", hr ); + + hr = IWbemClassObject_SpawnInstance( sig_in, 0, &in ); + ok( hr == S_OK, "failed to spawn instance %#lx\n", hr ); + + V_VT( &defkey ) = VT_I4; + V_I4( &defkey ) = 0x80000001; + hr = IWbemClassObject_Put( in, L"hDefKey", 0, &defkey, 0 ); + ok( hr == S_OK, "failed to set root %#lx\n", hr ); + + V_VT( &subkey ) = VT_BSTR; + V_BSTR( &subkey ) = SysAllocString( L"Control Panel\Desktop" ); + hr = IWbemClassObject_Put( in, L"sSubKeyName", 0, &subkey, 0 ); + ok( hr == S_OK, "failed to set subkey %#lx\n", hr ); + + V_VT( &valuename ) = VT_BSTR; + V_BSTR( &valuename ) = SysAllocString( L"UserPreferencesMask" ); + hr = IWbemClassObject_Put( in, L"sValueName", 0, &valuename, 0 ); + ok( hr == S_OK, "failed to set value name %#lx\n", hr ); + + out = NULL; + method = SysAllocString( L"GetBinaryValue" ); + hr = IWbemServices_ExecMethod( services, class, method, 0, NULL, in, &out, NULL ); + ok( hr == S_OK, "failed to execute method %#lx\n", hr ); + SysFreeString( method ); + + type = 0xdeadbeef; + VariantInit( &retval ); + hr = IWbemClassObject_Get( out, L"ReturnValue", 0, &retval, &type, NULL ); + ok( hr == S_OK, "failed to get return value %#lx\n", hr ); + ok( V_VT( &retval ) == VT_I4, "unexpected variant type %#x\n", V_VT( &retval ) ); + ok( !V_I4( &retval ), "unexpected error %ld\n", V_I4( &retval ) ); + ok( type == CIM_UINT32, "unexpected type %#lx\n", type ); + + check_property( out, L"uValue", VT_UI1|VT_ARRAY, CIM_UINT8|CIM_FLAG_ARRAY ); + + VariantClear( &valuename ); + VariantClear( &subkey ); + IWbemClassObject_Release( in ); + IWbemClassObject_Release( out ); + IWbemClassObject_Release( sig_in ); + IWbemClassObject_Release( reg ); SysFreeString( class ); } diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h index 893fd922e19..328840e9dfe 100644 --- a/dlls/wbemprox/wbemprox_private.h +++ b/dlls/wbemprox/wbemprox_private.h @@ -259,6 +259,7 @@ HRESULT process_create(IWbemClassObject *obj, IWbemContext *context, IWbemClassO HRESULT reg_create_key(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN; HRESULT reg_enum_key(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN; HRESULT reg_enum_values(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN; +HRESULT reg_get_binaryvalue(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN; HRESULT reg_get_stringvalue(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN; HRESULT reg_set_stringvalue(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN; HRESULT reg_set_dwordvalue(IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out) DECLSPEC_HIDDEN;