/* * 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 #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, 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 = create_signature( L"StdRegProv", L"CreateKey", 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, L"ReturnValue", 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, 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 = create_signature( L"StdRegProv", L"EnumKey", 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, L"sNames", 0, &names, CIM_STRING|CIM_FLAG_ARRAY ); if (hr != S_OK) goto done; } hr = IWbemClassObject_Put( out_params, L"ReturnValue", 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, 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 = create_signature( L"StdRegProv", L"EnumValues", 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, L"sNames", 0, &names, CIM_STRING|CIM_FLAG_ARRAY ); if (hr != S_OK) goto done; hr = IWbemClassObject_Put( out_params, L"Types", 0, &types, CIM_SINT32|CIM_FLAG_ARRAY ); if (hr != S_OK) goto done; } hr = IWbemClassObject_Put( out_params, L"ReturnValue", 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, 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) return hr; hr = create_signature( L"StdRegProv", L"GetStringValue", 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, L"sValue", 0, &value, CIM_STRING ); 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; }