xref: /reactos/dll/win32/wbemprox/reg.c (revision 465745b6)
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 }
449