445 lines
13 KiB
C
445 lines
13 KiB
C
/*
|
|
* StdRegProv implementation
|
|
*
|
|
* Copyright 2012 Hans Leidekker for CodeWeavers
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#define COBJMACROS
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "wbemcli.h"
|
|
|
|
#include "wine/debug.h"
|
|
#include "wbemprox_private.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
|
|
|
|
static HRESULT to_bstr_array( BSTR *strings, DWORD count, VARIANT *var )
|
|
{
|
|
SAFEARRAY *sa;
|
|
HRESULT hr;
|
|
LONG i;
|
|
|
|
if (!(sa = SafeArrayCreateVector( VT_BSTR, 0, count ))) return E_OUTOFMEMORY;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if ((hr = SafeArrayPutElement( sa, &i, strings[i] )) != S_OK)
|
|
{
|
|
SafeArrayDestroy( sa );
|
|
return hr;
|
|
}
|
|
}
|
|
set_variant( VT_BSTR|VT_ARRAY, 0, sa, var );
|
|
return S_OK;
|
|
}
|
|
|
|
static void free_bstr_array( BSTR *strings, DWORD count )
|
|
{
|
|
while (count--)
|
|
SysFreeString( *(strings++) );
|
|
}
|
|
|
|
static HRESULT to_i4_array( DWORD *values, DWORD count, VARIANT *var )
|
|
{
|
|
SAFEARRAY *sa;
|
|
HRESULT hr;
|
|
LONG i;
|
|
|
|
if (!(sa = SafeArrayCreateVector( VT_I4, 0, count ))) return E_OUTOFMEMORY;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if ((hr = SafeArrayPutElement( sa, &i, &values[i] )) != S_OK)
|
|
{
|
|
SafeArrayDestroy( sa );
|
|
return hr;
|
|
}
|
|
}
|
|
set_variant( VT_I4|VT_ARRAY, 0, sa, var );
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT create_key( HKEY root, const WCHAR *subkey, VARIANT *retval )
|
|
{
|
|
LONG res;
|
|
HKEY hkey;
|
|
|
|
TRACE("%p, %s\n", root, debugstr_w(subkey));
|
|
|
|
res = RegCreateKeyExW( root, subkey, 0, NULL, 0, 0, NULL, &hkey, NULL );
|
|
set_variant( VT_UI4, res, NULL, retval );
|
|
if (!res)
|
|
{
|
|
RegCloseKey( hkey );
|
|
return S_OK;
|
|
}
|
|
return HRESULT_FROM_WIN32( res );
|
|
}
|
|
|
|
HRESULT reg_create_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
|
|
{
|
|
VARIANT defkey, subkey, retval;
|
|
IWbemClassObject *sig, *out_params = NULL;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", in, out);
|
|
|
|
hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
|
|
hr = create_signature( class_stdregprovW, method_createkeyW, PARAM_OUT, &sig );
|
|
if (hr != S_OK)
|
|
{
|
|
VariantClear( &subkey );
|
|
return hr;
|
|
}
|
|
if (out)
|
|
{
|
|
hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
|
|
if (hr != S_OK)
|
|
{
|
|
VariantClear( &subkey );
|
|
IWbemClassObject_Release( sig );
|
|
return hr;
|
|
}
|
|
}
|
|
hr = create_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &retval );
|
|
if (hr == S_OK && out_params)
|
|
hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
|
|
|
|
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 HRESULT enum_key( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *retval )
|
|
{
|
|
HKEY hkey;
|
|
HRESULT hr = S_OK;
|
|
WCHAR buf[256];
|
|
BSTR *strings, *tmp;
|
|
DWORD count = 2, len = ARRAY_SIZE( buf );
|
|
LONG res, i = 0;
|
|
|
|
TRACE("%p, %s\n", root, debugstr_w(subkey));
|
|
|
|
if (!(strings = heap_alloc( count * sizeof(BSTR) ))) return E_OUTOFMEMORY;
|
|
if ((res = RegOpenKeyExW( root, subkey, 0, KEY_ENUMERATE_SUB_KEYS, &hkey )))
|
|
{
|
|
set_variant( VT_UI4, res, NULL, retval );
|
|
heap_free( strings );
|
|
return S_OK;
|
|
}
|
|
for (;;)
|
|
{
|
|
if (i >= count)
|
|
{
|
|
count *= 2;
|
|
if (!(tmp = heap_realloc( strings, count * sizeof(BSTR) )))
|
|
{
|
|
RegCloseKey( hkey );
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
strings = tmp;
|
|
}
|
|
if ((res = RegEnumKeyW( hkey, i, buf, len )) == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
if (i) res = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
if (res) break;
|
|
if (!(strings[i] = SysAllocString( buf )))
|
|
{
|
|
for (i--; i >= 0; i--) SysFreeString( strings[i] );
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if (hr == S_OK && !res)
|
|
{
|
|
hr = to_bstr_array( strings, i, names );
|
|
free_bstr_array( strings, i );
|
|
}
|
|
set_variant( VT_UI4, res, NULL, retval );
|
|
RegCloseKey( hkey );
|
|
heap_free( strings );
|
|
return hr;
|
|
}
|
|
|
|
HRESULT reg_enum_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
|
|
{
|
|
VARIANT defkey, subkey, names, retval;
|
|
IWbemClassObject *sig, *out_params = NULL;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", in, out);
|
|
|
|
hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
|
|
hr = create_signature( class_stdregprovW, method_enumkeyW, PARAM_OUT, &sig );
|
|
if (hr != S_OK)
|
|
{
|
|
VariantClear( &subkey );
|
|
return hr;
|
|
}
|
|
if (out)
|
|
{
|
|
hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
|
|
if (hr != S_OK)
|
|
{
|
|
VariantClear( &subkey );
|
|
IWbemClassObject_Release( sig );
|
|
return hr;
|
|
}
|
|
}
|
|
VariantInit( &names );
|
|
hr = enum_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &retval );
|
|
if (hr != S_OK) goto done;
|
|
if (out_params)
|
|
{
|
|
if (!V_UI4( &retval ))
|
|
{
|
|
hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
|
|
if (hr != S_OK) goto done;
|
|
}
|
|
hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
|
|
}
|
|
|
|
done:
|
|
VariantClear( &names );
|
|
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 HRESULT enum_values( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *types, VARIANT *retval )
|
|
{
|
|
HKEY hkey = NULL;
|
|
HRESULT hr = S_OK;
|
|
BSTR *value_names = NULL;
|
|
DWORD count, buflen, len, *value_types = NULL;
|
|
LONG res, i = 0;
|
|
WCHAR *buf = NULL;
|
|
|
|
TRACE("%p, %s\n", root, debugstr_w(subkey));
|
|
|
|
if ((res = RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE, &hkey ))) goto done;
|
|
if ((res = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, &buflen, NULL, NULL, NULL )))
|
|
goto done;
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
if (!(buf = heap_alloc( (buflen + 1) * sizeof(WCHAR) ))) goto done;
|
|
if (!(value_names = heap_alloc( count * sizeof(BSTR) ))) goto done;
|
|
if (!(value_types = heap_alloc( count * sizeof(DWORD) ))) goto done;
|
|
|
|
hr = S_OK;
|
|
for (;;)
|
|
{
|
|
len = buflen + 1;
|
|
res = RegEnumValueW( hkey, i, buf, &len, NULL, &value_types[i], NULL, NULL );
|
|
if (res == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
if (i) res = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
if (res) break;
|
|
if (!(value_names[i] = SysAllocString( buf )))
|
|
{
|
|
for (i--; i >= 0; i--) SysFreeString( value_names[i] );
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if (hr == S_OK && !res)
|
|
{
|
|
hr = to_bstr_array( value_names, i, names );
|
|
free_bstr_array( value_names, i );
|
|
if (hr == S_OK) hr = to_i4_array( value_types, i, types );
|
|
}
|
|
|
|
done:
|
|
set_variant( VT_UI4, res, NULL, retval );
|
|
RegCloseKey( hkey );
|
|
heap_free( value_names );
|
|
heap_free( value_types );
|
|
heap_free( buf );
|
|
return hr;
|
|
}
|
|
|
|
HRESULT reg_enum_values( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
|
|
{
|
|
VARIANT defkey, subkey, names, types, retval;
|
|
IWbemClassObject *sig, *out_params = NULL;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", in, out);
|
|
|
|
hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
|
|
hr = create_signature( class_stdregprovW, method_enumvaluesW, PARAM_OUT, &sig );
|
|
if (hr != S_OK)
|
|
{
|
|
VariantClear( &subkey );
|
|
return hr;
|
|
}
|
|
if (out)
|
|
{
|
|
hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
|
|
if (hr != S_OK)
|
|
{
|
|
VariantClear( &subkey );
|
|
IWbemClassObject_Release( sig );
|
|
return hr;
|
|
}
|
|
}
|
|
VariantInit( &names );
|
|
VariantInit( &types );
|
|
hr = enum_values( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &types, &retval );
|
|
if (hr != S_OK) goto done;
|
|
if (out_params)
|
|
{
|
|
if (!V_UI4( &retval ))
|
|
{
|
|
hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
|
|
if (hr != S_OK) goto done;
|
|
hr = IWbemClassObject_Put( out_params, param_typesW, 0, &types, CIM_SINT32|CIM_FLAG_ARRAY );
|
|
if (hr != S_OK) goto done;
|
|
}
|
|
hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
|
|
}
|
|
|
|
done:
|
|
VariantClear( &types );
|
|
VariantClear( &names );
|
|
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 HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value, VARIANT *retval )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR str = NULL;
|
|
DWORD size;
|
|
LONG res;
|
|
|
|
TRACE("%p, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name));
|
|
|
|
if ((res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, NULL, &size ))) goto done;
|
|
if (!(str = SysAllocStringLen( NULL, size / sizeof(WCHAR) - 1 )))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
if (!(res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, str, &size )))
|
|
set_variant( VT_BSTR, 0, str, value );
|
|
|
|
done:
|
|
set_variant( VT_UI4, res, NULL, retval );
|
|
if (res) SysFreeString( str );
|
|
return hr;
|
|
}
|
|
|
|
HRESULT reg_get_stringvalue( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
|
|
{
|
|
VARIANT defkey, subkey, name, value, retval;
|
|
IWbemClassObject *sig, *out_params = NULL;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", in, out);
|
|
|
|
hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
hr = IWbemClassObject_Get( in, param_valuenameW, 0, &name, NULL, NULL );
|
|
if (hr != S_OK) return hr;
|
|
|
|
hr = create_signature( class_stdregprovW, method_getstringvalueW, 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_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, &retval );
|
|
if (hr != S_OK) goto done;
|
|
if (out_params)
|
|
{
|
|
if (!V_UI4( &retval ))
|
|
{
|
|
hr = IWbemClassObject_Put( out_params, param_valueW, 0, &value, CIM_STRING );
|
|
if (hr != S_OK) goto done;
|
|
}
|
|
hr = IWbemClassObject_Put( out_params, param_returnvalueW, 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;
|
|
}
|