diff --git a/dlls/wbemprox/Makefile.in b/dlls/wbemprox/Makefile.in index e610049037f..b04bb644d19 100644 --- a/dlls/wbemprox/Makefile.in +++ b/dlls/wbemprox/Makefile.in @@ -6,6 +6,7 @@ C_SRCS = \ class.c \ main.c \ query.c \ + reg.c \ services.c \ table.c \ wbemlocator.c diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c index ccb6d53e782..d8af7693a0e 100644 --- a/dlls/wbemprox/builtin.c +++ b/dlls/wbemprox/builtin.c @@ -69,8 +69,6 @@ static const WCHAR class_serviceW[] = {'W','i','n','3','2','_','S','e','r','v','i','c','e',0}; static const WCHAR class_sounddeviceW[] = {'W','i','n','3','2','_','S','o','u','n','d','D','e','v','i','c','e',0}; -static const WCHAR class_stdregprovW[] = - {'S','t','d','R','e','g','P','r','o','v',0}; static const WCHAR class_videocontrollerW[] = {'W','i','n','3','2','_','V','i','d','e','o','C','o','n','t','r','o','l','l','e','r',0}; @@ -191,22 +189,6 @@ static const WCHAR prop_varianttypeW[] = static const WCHAR prop_versionW[] = {'V','e','r','s','i','o','n',0}; -static const WCHAR method_enumkeyW[] = - {'E','n','u','m','K','e','y',0}; -static const WCHAR method_enumvaluesW[] = - {'E','n','u','m','V','a','l','u','e','s',0}; - -static const WCHAR param_defkeyW[] = - {'h','D','e','f','K','e','y',0}; -static const WCHAR param_namesW[] = - {'N','a','m','e','s',0}; -static const WCHAR param_returnvalueW[] = - {'R','e','t','u','r','n','V','a','l','u','e',0}; -static const WCHAR param_subkeynameW[] = - {'s','S','u','b','K','e','y','N','a','m','e',0}; -static const WCHAR param_typesW[] = - {'T','y','p','e','s',0}; - /* column definitions must be kept in sync with record structures below */ static const struct column col_baseboard[] = { @@ -321,8 +303,8 @@ static const struct column col_sounddevice[] = }; static const struct column col_stdregprov[] = { - { method_enumkeyW, CIM_OBJECT|COL_FLAG_METHOD }, - { method_enumvaluesW, CIM_OBJECT|COL_FLAG_METHOD } + { method_enumkeyW, CIM_FLAG_ARRAY|COL_FLAG_METHOD }, + { method_enumvaluesW, CIM_FLAG_ARRAY|COL_FLAG_METHOD } }; static const struct column col_videocontroller[] = { @@ -512,17 +494,6 @@ struct record_videocontroller }; #include "poppack.h" -static HRESULT reg_enumkey( IWbemClassObject *in, IWbemClassObject **out ) -{ - FIXME("\n"); - return E_NOTIMPL; -} -static HRESULT reg_enumvalues( IWbemClassObject *in, IWbemClassObject **out ) -{ - FIXME("\n"); - return E_NOTIMPL; -} - static const struct record_baseboard data_baseboard[] = { { baseboard_manufacturerW, baseboard_serialnumberW, baseboard_tagW } diff --git a/dlls/wbemprox/class.c b/dlls/wbemprox/class.c index a2d70682c00..dc03371a5ca 100644 --- a/dlls/wbemprox/class.c +++ b/dlls/wbemprox/class.c @@ -804,8 +804,8 @@ static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *metho return struprW( ret ); } -static HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir, - IWbemClassObject **sig ) +HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir, + IWbemClassObject **sig ) { static const WCHAR selectW[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', diff --git a/dlls/wbemprox/query.c b/dlls/wbemprox/query.c index b48d75dc359..29026c90073 100644 --- a/dlls/wbemprox/query.c +++ b/dlls/wbemprox/query.c @@ -602,7 +602,7 @@ SAFEARRAY *to_safearray( const struct array *array, CIMTYPE type ) return ret; } -static void set_variant( VARTYPE type, LONGLONG val, void *val_ptr, VARIANT *ret ) +void set_variant( VARTYPE type, LONGLONG val, void *val_ptr, VARIANT *ret ) { if (type & VT_ARRAY) { diff --git a/dlls/wbemprox/reg.c b/dlls/wbemprox/reg.c new file mode 100644 index 00000000000..00f41c5190e --- /dev/null +++ b/dlls/wbemprox/reg.c @@ -0,0 +1,268 @@ +/* + * 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 "config.h" +#include + +#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 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 enumkey( 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 = sizeof(buf)/sizeof(buf[0]); + 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 = ERROR_OUTOFMEMORY; + break; + } + i++; + } + if (hr == S_OK && !res) hr = to_bstr_array( strings, i, names ); + set_variant( VT_UI4, res, NULL, retval ); + RegCloseKey( hkey ); + heap_free( strings ); + return hr; +} + +HRESULT reg_enumkey( IWbemClassObject *in, IWbemClassObject **out ) +{ + VARIANT defkey, subkey, names, retval; + IWbemClassObject *sig; + 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; + } + hr = IWbemClassObject_SpawnInstance( sig, 0, out ); + if (hr != S_OK) + { + VariantClear( &subkey ); + IWbemClassObject_Release( sig ); + return hr; + } + VariantInit( &names ); + hr = enumkey( (HKEY)V_I4(&defkey), V_BSTR(&subkey), &names, &retval ); + if (hr != S_OK) goto done; + if (!V_UI4( &retval )) + { + hr = IWbemClassObject_Put( *out, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY ); + if (hr != S_OK) goto done; + } + hr = IWbemClassObject_Put( *out, param_returnvalueW, 0, &retval, CIM_UINT32 ); + +done: + VariantClear( &names ); + VariantClear( &subkey ); + IWbemClassObject_Release( sig ); + if (hr != S_OK) IWbemClassObject_Release( *out ); + return hr; +} + +static HRESULT enumvalues( 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 = ERROR_OUTOFMEMORY; + break; + } + i++; + } + if (hr == S_OK && !res) + { + hr = to_bstr_array( value_names, i, names ); + 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_enumvalues( IWbemClassObject *in, IWbemClassObject **out ) +{ + VARIANT defkey, subkey, names, types, retval; + IWbemClassObject *sig; + 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; + } + hr = IWbemClassObject_SpawnInstance( sig, 0, out ); + if (hr != S_OK) + { + VariantClear( &subkey ); + IWbemClassObject_Release( sig ); + return hr; + } + VariantInit( &names ); + VariantInit( &types ); + hr = enumvalues( (HKEY)V_I4(&defkey), V_BSTR(&subkey), &names, &types, &retval ); + if (hr != S_OK) goto done; + if (!V_UI4( &retval )) + { + hr = IWbemClassObject_Put( *out, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY ); + if (hr != S_OK) goto done; + hr = IWbemClassObject_Put( *out, param_typesW, 0, &types, CIM_SINT32|CIM_FLAG_ARRAY ); + if (hr != S_OK) goto done; + } + hr = IWbemClassObject_Put( *out, param_returnvalueW, 0, &retval, CIM_UINT32 ); + +done: + VariantClear( &types ); + VariantClear( &names ); + VariantClear( &subkey ); + IWbemClassObject_Release( sig ); + if (hr != S_OK) IWbemClassObject_Release( *out ); + return hr; +} diff --git a/dlls/wbemprox/wbemprox_private.h b/dlls/wbemprox/wbemprox_private.h index f2dff0217dd..9f3debca62e 100644 --- a/dlls/wbemprox/wbemprox_private.h +++ b/dlls/wbemprox/wbemprox_private.h @@ -186,6 +186,9 @@ HRESULT get_properties( const struct view *, SAFEARRAY ** ) DECLSPEC_HIDDEN; HRESULT get_object( const WCHAR *, IWbemClassObject ** ) DECLSPEC_HIDDEN; BSTR get_method_name( const WCHAR *, UINT ) DECLSPEC_HIDDEN; BSTR get_property_name( const WCHAR *, UINT ) DECLSPEC_HIDDEN; +void set_variant( VARTYPE, LONGLONG, void *, VARIANT * ) DECLSPEC_HIDDEN; +HRESULT create_signature( const WCHAR *, const WCHAR *, enum param_direction, + IWbemClassObject ** ) DECLSPEC_HIDDEN; HRESULT WbemLocator_create(IUnknown *, LPVOID *) DECLSPEC_HIDDEN; HRESULT WbemServices_create(IUnknown *, const WCHAR *, LPVOID *) DECLSPEC_HIDDEN; @@ -193,6 +196,9 @@ HRESULT create_class_object(const WCHAR *, IEnumWbemClassObject *, UINT, struct record *, IWbemClassObject **) DECLSPEC_HIDDEN; HRESULT EnumWbemClassObject_create(IUnknown *, struct query *, LPVOID *) DECLSPEC_HIDDEN; +HRESULT reg_enumkey(IWbemClassObject *, IWbemClassObject **) DECLSPEC_HIDDEN; +HRESULT reg_enumvalues(IWbemClassObject *, IWbemClassObject **) DECLSPEC_HIDDEN; + static void *heap_alloc( size_t len ) __WINE_ALLOC_SIZE(1); static inline void *heap_alloc( size_t len ) { @@ -223,3 +229,14 @@ static inline WCHAR *heap_strdupW( const WCHAR *src ) if ((dst = heap_alloc( (strlenW( src ) + 1) * sizeof(WCHAR) ))) strcpyW( dst, src ); return dst; } + +static const WCHAR class_stdregprovW[] = {'S','t','d','R','e','g','P','r','o','v',0}; + +static const WCHAR method_enumkeyW[] = {'E','n','u','m','K','e','y',0}; +static const WCHAR method_enumvaluesW[] = {'E','n','u','m','V','a','l','u','e','s',0}; + +static const WCHAR param_defkeyW[] = {'h','D','e','f','K','e','y',0}; +static const WCHAR param_namesW[] = {'s','N','a','m','e','s',0}; +static const WCHAR param_returnvalueW[] = {'R','e','t','u','r','n','V','a','l','u','e',0}; +static const WCHAR param_subkeynameW[] = {'s','S','u','b','K','e','y','N','a','m','e',0}; +static const WCHAR param_typesW[] = {'T','y','p','e','s',0};