wbemprox: Handle NULL out parameter to object methods.
[wine/multimedia.git] / dlls / wbemprox / reg.c
blob4bf249b74f836b07cc8ca0381575d102b516ab9e
1 /*
2 * StdRegProv implementation
4 * Copyright 2012 Hans Leidekker for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "config.h"
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wbemcli.h"
30 #include "wine/debug.h"
31 #include "wbemprox_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
35 static HRESULT to_bstr_array( BSTR *strings, DWORD count, VARIANT *var )
37 SAFEARRAY *sa;
38 HRESULT hr;
39 LONG i;
41 if (!(sa = SafeArrayCreateVector( VT_BSTR, 0, count ))) return E_OUTOFMEMORY;
42 for (i = 0; i < count; i++)
44 if ((hr = SafeArrayPutElement( sa, &i, strings[i] )) != S_OK)
46 SafeArrayDestroy( sa );
47 return hr;
50 set_variant( VT_BSTR|VT_ARRAY, 0, sa, var );
51 return S_OK;
54 static HRESULT to_i4_array( DWORD *values, DWORD count, VARIANT *var )
56 SAFEARRAY *sa;
57 HRESULT hr;
58 LONG i;
60 if (!(sa = SafeArrayCreateVector( VT_I4, 0, count ))) return E_OUTOFMEMORY;
61 for (i = 0; i < count; i++)
63 if ((hr = SafeArrayPutElement( sa, &i, &values[i] )) != S_OK)
65 SafeArrayDestroy( sa );
66 return hr;
69 set_variant( VT_I4|VT_ARRAY, 0, sa, var );
70 return S_OK;
73 static HRESULT enum_key( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *retval )
75 HKEY hkey;
76 HRESULT hr = S_OK;
77 WCHAR buf[256];
78 BSTR *strings, *tmp;
79 DWORD count = 2, len = sizeof(buf)/sizeof(buf[0]);
80 LONG res, i = 0;
82 TRACE("%p, %s\n", root, debugstr_w(subkey));
84 if (!(strings = heap_alloc( count * sizeof(BSTR) ))) return E_OUTOFMEMORY;
85 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_ENUMERATE_SUB_KEYS, &hkey )))
87 set_variant( VT_UI4, res, NULL, retval );
88 heap_free( strings );
89 return S_OK;
91 for (;;)
93 if (i >= count)
95 count *= 2;
96 if (!(tmp = heap_realloc( strings, count * sizeof(BSTR) )))
98 RegCloseKey( hkey );
99 return E_OUTOFMEMORY;
101 strings = tmp;
103 if ((res = RegEnumKeyW( hkey, i, buf, len )) == ERROR_NO_MORE_ITEMS)
105 if (i) res = ERROR_SUCCESS;
106 break;
108 if (res) break;
109 if (!(strings[i] = SysAllocString( buf )))
111 for (i--; i >= 0; i--) SysFreeString( strings[i] );
112 hr = ERROR_OUTOFMEMORY;
113 break;
115 i++;
117 if (hr == S_OK && !res) hr = to_bstr_array( strings, i, names );
118 set_variant( VT_UI4, res, NULL, retval );
119 RegCloseKey( hkey );
120 heap_free( strings );
121 return hr;
124 HRESULT reg_enum_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
126 VARIANT defkey, subkey, names, retval;
127 IWbemClassObject *sig, *out_params = NULL;
128 HRESULT hr;
130 TRACE("%p, %p\n", in, out);
132 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
133 if (hr != S_OK) return hr;
134 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
135 if (hr != S_OK) return hr;
137 hr = create_signature( class_stdregprovW, method_enumkeyW, PARAM_OUT, &sig );
138 if (hr != S_OK)
140 VariantClear( &subkey );
141 return hr;
143 if (out)
145 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
146 if (hr != S_OK)
148 VariantClear( &subkey );
149 IWbemClassObject_Release( sig );
150 return hr;
153 VariantInit( &names );
154 hr = enum_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &retval );
155 if (hr != S_OK) goto done;
156 if (out_params)
158 if (!V_UI4( &retval ))
160 hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
161 if (hr != S_OK) goto done;
163 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
166 done:
167 VariantClear( &names );
168 VariantClear( &subkey );
169 IWbemClassObject_Release( sig );
170 if (hr == S_OK && out)
172 *out = out_params;
173 IWbemClassObject_AddRef( out_params );
175 if (out_params) IWbemClassObject_Release( out_params );
176 return hr;
179 static HRESULT enum_values( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *types, VARIANT *retval )
181 HKEY hkey = NULL;
182 HRESULT hr = S_OK;
183 BSTR *value_names = NULL;
184 DWORD count, buflen, len, *value_types = NULL;
185 LONG res, i = 0;
186 WCHAR *buf = NULL;
188 TRACE("%p, %s\n", root, debugstr_w(subkey));
190 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE, &hkey ))) goto done;
191 if ((res = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, &buflen, NULL, NULL, NULL )))
192 goto done;
194 hr = E_OUTOFMEMORY;
195 if (!(buf = heap_alloc( (buflen + 1) * sizeof(WCHAR) ))) goto done;
196 if (!(value_names = heap_alloc( count * sizeof(BSTR) ))) goto done;
197 if (!(value_types = heap_alloc( count * sizeof(DWORD) ))) goto done;
199 hr = S_OK;
200 for (;;)
202 len = buflen + 1;
203 res = RegEnumValueW( hkey, i, buf, &len, NULL, &value_types[i], NULL, NULL );
204 if (res == ERROR_NO_MORE_ITEMS)
206 if (i) res = ERROR_SUCCESS;
207 break;
209 if (res) break;
210 if (!(value_names[i] = SysAllocString( buf )))
212 for (i--; i >= 0; i--) SysFreeString( value_names[i] );
213 hr = ERROR_OUTOFMEMORY;
214 break;
216 i++;
218 if (hr == S_OK && !res)
220 hr = to_bstr_array( value_names, i, names );
221 if (hr == S_OK) hr = to_i4_array( value_types, i, types );
224 done:
225 set_variant( VT_UI4, res, NULL, retval );
226 RegCloseKey( hkey );
227 heap_free( value_names );
228 heap_free( value_types );
229 heap_free( buf );
230 return hr;
233 HRESULT reg_enum_values( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
235 VARIANT defkey, subkey, names, types, retval;
236 IWbemClassObject *sig, *out_params = NULL;
237 HRESULT hr;
239 TRACE("%p, %p\n", in, out);
241 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
242 if (hr != S_OK) return hr;
243 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
244 if (hr != S_OK) return hr;
246 hr = create_signature( class_stdregprovW, method_enumvaluesW, PARAM_OUT, &sig );
247 if (hr != S_OK)
249 VariantClear( &subkey );
250 return hr;
252 if (out)
254 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
255 if (hr != S_OK)
257 VariantClear( &subkey );
258 IWbemClassObject_Release( sig );
259 return hr;
262 VariantInit( &names );
263 VariantInit( &types );
264 hr = enum_values( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &types, &retval );
265 if (hr != S_OK) goto done;
266 if (out_params)
268 if (!V_UI4( &retval ))
270 hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
271 if (hr != S_OK) goto done;
272 hr = IWbemClassObject_Put( out_params, param_typesW, 0, &types, CIM_SINT32|CIM_FLAG_ARRAY );
273 if (hr != S_OK) goto done;
275 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
278 done:
279 VariantClear( &types );
280 VariantClear( &names );
281 VariantClear( &subkey );
282 IWbemClassObject_Release( sig );
283 if (hr == S_OK && out)
285 *out = out_params;
286 IWbemClassObject_AddRef( out_params );
288 if (out_params) IWbemClassObject_Release( out_params );
289 return hr;
292 static HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value, VARIANT *retval )
294 HRESULT hr = S_OK;
295 BSTR str = NULL;
296 DWORD size;
297 LONG res;
299 TRACE("%p, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name));
301 if ((res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, NULL, &size ))) goto done;
302 if (!(str = SysAllocStringLen( NULL, size / sizeof(WCHAR) - 1 )))
304 hr = E_OUTOFMEMORY;
305 goto done;
307 if (!(res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, str, &size )))
308 set_variant( VT_BSTR, 0, str, value );
310 done:
311 set_variant( VT_UI4, res, NULL, retval );
312 if (res) SysFreeString( str );
313 return hr;
316 HRESULT reg_get_stringvalue( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
318 VARIANT defkey, subkey, name, value, retval;
319 IWbemClassObject *sig, *out_params = NULL;
320 HRESULT hr;
322 TRACE("%p, %p\n", in, out);
324 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
325 if (hr != S_OK) return hr;
326 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
327 if (hr != S_OK) return hr;
328 hr = IWbemClassObject_Get( in, param_valuenameW, 0, &name, NULL, NULL );
329 if (hr != S_OK) return hr;
331 hr = create_signature( class_stdregprovW, method_getstringvalueW, PARAM_OUT, &sig );
332 if (hr != S_OK)
334 VariantClear( &name );
335 VariantClear( &subkey );
336 return hr;
338 if (out)
340 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
341 if (hr != S_OK)
343 VariantClear( &name );
344 VariantClear( &subkey );
345 IWbemClassObject_Release( sig );
346 return hr;
349 VariantInit( &value );
350 hr = get_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, &retval );
351 if (hr != S_OK) goto done;
352 if (out_params)
354 if (!V_UI4( &retval ))
356 hr = IWbemClassObject_Put( out_params, param_valueW, 0, &value, CIM_STRING );
357 if (hr != S_OK) goto done;
359 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
362 done:
363 VariantClear( &name );
364 VariantClear( &subkey );
365 IWbemClassObject_Release( sig );
366 if (hr == S_OK && out)
368 *out = out_params;
369 IWbemClassObject_AddRef( out_params );
371 if (out_params) IWbemClassObject_Release( out_params );
372 return hr;