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