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