[WBEMPROX] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / wbemprox / reg.c
1 /*
2 * StdRegProv implementation
3 *
4 * Copyright 2012 Hans Leidekker for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define COBJMACROS
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wbemcli.h"
28
29 #include "wine/debug.h"
30 #include "wbemprox_private.h"
31
32 #ifdef __REACTOS__
33 #include <winreg.h>
34 #endif
35
36 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
37
38 static HRESULT to_bstr_array( BSTR *strings, DWORD count, VARIANT *var )
39 {
40 SAFEARRAY *sa;
41 HRESULT hr;
42 LONG i;
43
44 if (!(sa = SafeArrayCreateVector( VT_BSTR, 0, count ))) return E_OUTOFMEMORY;
45 for (i = 0; i < count; i++)
46 {
47 if ((hr = SafeArrayPutElement( sa, &i, strings[i] )) != S_OK)
48 {
49 SafeArrayDestroy( sa );
50 return hr;
51 }
52 }
53 set_variant( VT_BSTR|VT_ARRAY, 0, sa, var );
54 return S_OK;
55 }
56
57 static void free_bstr_array( BSTR *strings, DWORD count )
58 {
59 while (count--)
60 SysFreeString( *(strings++) );
61 }
62
63 static HRESULT to_i4_array( DWORD *values, DWORD count, VARIANT *var )
64 {
65 SAFEARRAY *sa;
66 HRESULT hr;
67 LONG i;
68
69 if (!(sa = SafeArrayCreateVector( VT_I4, 0, count ))) return E_OUTOFMEMORY;
70 for (i = 0; i < count; i++)
71 {
72 if ((hr = SafeArrayPutElement( sa, &i, &values[i] )) != S_OK)
73 {
74 SafeArrayDestroy( sa );
75 return hr;
76 }
77 }
78 set_variant( VT_I4|VT_ARRAY, 0, sa, var );
79 return S_OK;
80 }
81
82 static HRESULT create_key( HKEY root, const WCHAR *subkey, VARIANT *retval )
83 {
84 LONG res;
85 HKEY hkey;
86
87 TRACE("%p, %s\n", root, debugstr_w(subkey));
88
89 res = RegCreateKeyExW( root, subkey, 0, NULL, 0, 0, NULL, &hkey, NULL );
90 set_variant( VT_UI4, res, NULL, retval );
91 if (!res)
92 {
93 RegCloseKey( hkey );
94 return S_OK;
95 }
96 return HRESULT_FROM_WIN32( res );
97 }
98
99 HRESULT reg_create_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
100 {
101 VARIANT defkey, subkey, retval;
102 IWbemClassObject *sig, *out_params = NULL;
103 HRESULT hr;
104
105 TRACE("%p, %p\n", in, out);
106
107 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
108 if (hr != S_OK) return hr;
109 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
110 if (hr != S_OK) return hr;
111
112 hr = create_signature( class_stdregprovW, method_createkeyW, PARAM_OUT, &sig );
113 if (hr != S_OK)
114 {
115 VariantClear( &subkey );
116 return hr;
117 }
118 if (out)
119 {
120 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
121 if (hr != S_OK)
122 {
123 VariantClear( &subkey );
124 IWbemClassObject_Release( sig );
125 return hr;
126 }
127 }
128 hr = create_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &retval );
129 if (hr == S_OK && out_params)
130 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
131
132 VariantClear( &subkey );
133 IWbemClassObject_Release( sig );
134 if (hr == S_OK && out)
135 {
136 *out = out_params;
137 IWbemClassObject_AddRef( out_params );
138 }
139 if (out_params) IWbemClassObject_Release( out_params );
140 return hr;
141 }
142
143 static HRESULT enum_key( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *retval )
144 {
145 HKEY hkey;
146 HRESULT hr = S_OK;
147 WCHAR buf[256];
148 BSTR *strings, *tmp;
149 DWORD count = 2, len = ARRAY_SIZE( buf );
150 LONG res, i = 0;
151
152 TRACE("%p, %s\n", root, debugstr_w(subkey));
153
154 if (!(strings = heap_alloc( count * sizeof(BSTR) ))) return E_OUTOFMEMORY;
155 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_ENUMERATE_SUB_KEYS, &hkey )))
156 {
157 set_variant( VT_UI4, res, NULL, retval );
158 heap_free( strings );
159 return S_OK;
160 }
161 for (;;)
162 {
163 if (i >= count)
164 {
165 count *= 2;
166 if (!(tmp = heap_realloc( strings, count * sizeof(BSTR) )))
167 {
168 RegCloseKey( hkey );
169 return E_OUTOFMEMORY;
170 }
171 strings = tmp;
172 }
173 if ((res = RegEnumKeyW( hkey, i, buf, len )) == ERROR_NO_MORE_ITEMS)
174 {
175 if (i) res = ERROR_SUCCESS;
176 break;
177 }
178 if (res) break;
179 if (!(strings[i] = SysAllocString( buf )))
180 {
181 for (i--; i >= 0; i--) SysFreeString( strings[i] );
182 hr = E_OUTOFMEMORY;
183 break;
184 }
185 i++;
186 }
187 if (hr == S_OK && !res)
188 {
189 hr = to_bstr_array( strings, i, names );
190 free_bstr_array( strings, i );
191 }
192 set_variant( VT_UI4, res, NULL, retval );
193 RegCloseKey( hkey );
194 heap_free( strings );
195 return hr;
196 }
197
198 HRESULT reg_enum_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
199 {
200 VARIANT defkey, subkey, names, retval;
201 IWbemClassObject *sig, *out_params = NULL;
202 HRESULT hr;
203
204 TRACE("%p, %p\n", in, out);
205
206 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
207 if (hr != S_OK) return hr;
208 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
209 if (hr != S_OK) return hr;
210
211 hr = create_signature( class_stdregprovW, method_enumkeyW, PARAM_OUT, &sig );
212 if (hr != S_OK)
213 {
214 VariantClear( &subkey );
215 return hr;
216 }
217 if (out)
218 {
219 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
220 if (hr != S_OK)
221 {
222 VariantClear( &subkey );
223 IWbemClassObject_Release( sig );
224 return hr;
225 }
226 }
227 VariantInit( &names );
228 hr = enum_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &retval );
229 if (hr != S_OK) goto done;
230 if (out_params)
231 {
232 if (!V_UI4( &retval ))
233 {
234 hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
235 if (hr != S_OK) goto done;
236 }
237 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
238 }
239
240 done:
241 VariantClear( &names );
242 VariantClear( &subkey );
243 IWbemClassObject_Release( sig );
244 if (hr == S_OK && out)
245 {
246 *out = out_params;
247 IWbemClassObject_AddRef( out_params );
248 }
249 if (out_params) IWbemClassObject_Release( out_params );
250 return hr;
251 }
252
253 static HRESULT enum_values( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *types, VARIANT *retval )
254 {
255 HKEY hkey = NULL;
256 HRESULT hr = S_OK;
257 BSTR *value_names = NULL;
258 DWORD count, buflen, len, *value_types = NULL;
259 LONG res, i = 0;
260 WCHAR *buf = NULL;
261
262 TRACE("%p, %s\n", root, debugstr_w(subkey));
263
264 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE, &hkey ))) goto done;
265 if ((res = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, &buflen, NULL, NULL, NULL )))
266 goto done;
267
268 hr = E_OUTOFMEMORY;
269 if (!(buf = heap_alloc( (buflen + 1) * sizeof(WCHAR) ))) goto done;
270 if (!(value_names = heap_alloc( count * sizeof(BSTR) ))) goto done;
271 if (!(value_types = heap_alloc( count * sizeof(DWORD) ))) goto done;
272
273 hr = S_OK;
274 for (;;)
275 {
276 len = buflen + 1;
277 res = RegEnumValueW( hkey, i, buf, &len, NULL, &value_types[i], NULL, NULL );
278 if (res == ERROR_NO_MORE_ITEMS)
279 {
280 if (i) res = ERROR_SUCCESS;
281 break;
282 }
283 if (res) break;
284 if (!(value_names[i] = SysAllocString( buf )))
285 {
286 for (i--; i >= 0; i--) SysFreeString( value_names[i] );
287 hr = E_OUTOFMEMORY;
288 break;
289 }
290 i++;
291 }
292 if (hr == S_OK && !res)
293 {
294 hr = to_bstr_array( value_names, i, names );
295 free_bstr_array( value_names, i );
296 if (hr == S_OK) hr = to_i4_array( value_types, i, types );
297 }
298
299 done:
300 set_variant( VT_UI4, res, NULL, retval );
301 RegCloseKey( hkey );
302 heap_free( value_names );
303 heap_free( value_types );
304 heap_free( buf );
305 return hr;
306 }
307
308 HRESULT reg_enum_values( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
309 {
310 VARIANT defkey, subkey, names, types, retval;
311 IWbemClassObject *sig, *out_params = NULL;
312 HRESULT hr;
313
314 TRACE("%p, %p\n", in, out);
315
316 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
317 if (hr != S_OK) return hr;
318 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
319 if (hr != S_OK) return hr;
320
321 hr = create_signature( class_stdregprovW, method_enumvaluesW, PARAM_OUT, &sig );
322 if (hr != S_OK)
323 {
324 VariantClear( &subkey );
325 return hr;
326 }
327 if (out)
328 {
329 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
330 if (hr != S_OK)
331 {
332 VariantClear( &subkey );
333 IWbemClassObject_Release( sig );
334 return hr;
335 }
336 }
337 VariantInit( &names );
338 VariantInit( &types );
339 hr = enum_values( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &types, &retval );
340 if (hr != S_OK) goto done;
341 if (out_params)
342 {
343 if (!V_UI4( &retval ))
344 {
345 hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
346 if (hr != S_OK) goto done;
347 hr = IWbemClassObject_Put( out_params, param_typesW, 0, &types, CIM_SINT32|CIM_FLAG_ARRAY );
348 if (hr != S_OK) goto done;
349 }
350 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
351 }
352
353 done:
354 VariantClear( &types );
355 VariantClear( &names );
356 VariantClear( &subkey );
357 IWbemClassObject_Release( sig );
358 if (hr == S_OK && out)
359 {
360 *out = out_params;
361 IWbemClassObject_AddRef( out_params );
362 }
363 if (out_params) IWbemClassObject_Release( out_params );
364 return hr;
365 }
366
367 static HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value, VARIANT *retval )
368 {
369 HRESULT hr = S_OK;
370 BSTR str = NULL;
371 DWORD size;
372 LONG res;
373
374 TRACE("%p, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name));
375
376 if ((res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, NULL, &size ))) goto done;
377 if (!(str = SysAllocStringLen( NULL, size / sizeof(WCHAR) - 1 )))
378 {
379 hr = E_OUTOFMEMORY;
380 goto done;
381 }
382 if (!(res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, str, &size )))
383 set_variant( VT_BSTR, 0, str, value );
384
385 done:
386 set_variant( VT_UI4, res, NULL, retval );
387 if (res) SysFreeString( str );
388 return hr;
389 }
390
391 HRESULT reg_get_stringvalue( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
392 {
393 VARIANT defkey, subkey, name, value, retval;
394 IWbemClassObject *sig, *out_params = NULL;
395 HRESULT hr;
396
397 TRACE("%p, %p\n", in, out);
398
399 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
400 if (hr != S_OK) return hr;
401 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
402 if (hr != S_OK) return hr;
403 hr = IWbemClassObject_Get( in, param_valuenameW, 0, &name, NULL, NULL );
404 if (hr != S_OK) return hr;
405
406 hr = create_signature( class_stdregprovW, method_getstringvalueW, PARAM_OUT, &sig );
407 if (hr != S_OK)
408 {
409 VariantClear( &name );
410 VariantClear( &subkey );
411 return hr;
412 }
413 if (out)
414 {
415 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
416 if (hr != S_OK)
417 {
418 VariantClear( &name );
419 VariantClear( &subkey );
420 IWbemClassObject_Release( sig );
421 return hr;
422 }
423 }
424 VariantInit( &value );
425 hr = get_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, &retval );
426 if (hr != S_OK) goto done;
427 if (out_params)
428 {
429 if (!V_UI4( &retval ))
430 {
431 hr = IWbemClassObject_Put( out_params, param_valueW, 0, &value, CIM_STRING );
432 if (hr != S_OK) goto done;
433 }
434 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 );
435 }
436
437 done:
438 VariantClear( &name );
439 VariantClear( &subkey );
440 IWbemClassObject_Release( sig );
441 if (hr == S_OK && out)
442 {
443 *out = out_params;
444 IWbemClassObject_AddRef( out_params );
445 }
446 if (out_params) IWbemClassObject_Release( out_params );
447 return hr;
448 }