Release 1.5.29.
[wine] / dlls / 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 "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 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
34
35 static HRESULT to_bstr_array( BSTR *strings, DWORD count, VARIANT *var )
36 {
37     SAFEARRAY *sa;
38     HRESULT hr;
39     LONG i;
40
41     if (!(sa = SafeArrayCreateVector( VT_BSTR, 0, count ))) return E_OUTOFMEMORY;
42     for (i = 0; i < count; i++)
43     {
44         if ((hr = SafeArrayPutElement( sa, &i, strings[i] )) != S_OK)
45         {
46             SafeArrayDestroy( sa );
47             return hr;
48         }
49     }
50     set_variant( VT_BSTR|VT_ARRAY, 0, sa, var );
51     return S_OK;
52 }
53
54 static HRESULT to_i4_array( DWORD *values, DWORD count, VARIANT *var )
55 {
56     SAFEARRAY *sa;
57     HRESULT hr;
58     LONG i;
59
60     if (!(sa = SafeArrayCreateVector( VT_I4, 0, count ))) return E_OUTOFMEMORY;
61     for (i = 0; i < count; i++)
62     {
63         if ((hr = SafeArrayPutElement( sa, &i, &values[i] )) != S_OK)
64         {
65             SafeArrayDestroy( sa );
66             return hr;
67         }
68     }
69     set_variant( VT_I4|VT_ARRAY, 0, sa, var );
70     return S_OK;
71 }
72
73 static HRESULT enum_key( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *retval )
74 {
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;
81
82     TRACE("%p, %s\n", root, debugstr_w(subkey));
83
84     if (!(strings = heap_alloc( count * sizeof(BSTR) ))) return E_OUTOFMEMORY;
85     if ((res = RegOpenKeyExW( root, subkey, 0, KEY_ENUMERATE_SUB_KEYS, &hkey )))
86     {
87         set_variant( VT_UI4, res, NULL, retval );
88         heap_free( strings );
89         return S_OK;
90     }
91     for (;;)
92     {
93         if (i >= count)
94         {
95             count *= 2;
96             if (!(tmp = heap_realloc( strings, count * sizeof(BSTR) )))
97             {
98                 RegCloseKey( hkey );
99                 return E_OUTOFMEMORY;
100             }
101             strings = tmp;
102         }
103         if ((res = RegEnumKeyW( hkey, i, buf, len )) == ERROR_NO_MORE_ITEMS)
104         {
105             if (i) res = ERROR_SUCCESS;
106             break;
107         }
108         if (res) break;
109         if (!(strings[i] = SysAllocString( buf )))
110         {
111             for (i--; i >= 0; i--) SysFreeString( strings[i] );
112             hr = ERROR_OUTOFMEMORY;
113             break;
114         }
115         i++;
116     }
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;
122 }
123
124 HRESULT reg_enum_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
125 {
126     VARIANT defkey, subkey, names, retval;
127     IWbemClassObject *sig;
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     hr = IWbemClassObject_SpawnInstance( sig, 0, out );
144     if (hr != S_OK)
145     {
146         VariantClear( &subkey );
147         IWbemClassObject_Release( sig );
148         return hr;
149     }
150     VariantInit( &names );
151     hr = enum_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &retval );
152     if (hr != S_OK) goto done;
153     if (!V_UI4( &retval ))
154     {
155         hr = IWbemClassObject_Put( *out, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
156         if (hr != S_OK) goto done;
157     }
158     hr = IWbemClassObject_Put( *out, param_returnvalueW, 0, &retval, CIM_UINT32 );
159
160 done:
161     VariantClear( &names );
162     VariantClear( &subkey );
163     IWbemClassObject_Release( sig );
164     if (hr != S_OK) IWbemClassObject_Release( *out );
165     return hr;
166 }
167
168 static HRESULT enum_values( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *types, VARIANT *retval )
169 {
170     HKEY hkey = NULL;
171     HRESULT hr = S_OK;
172     BSTR *value_names = NULL;
173     DWORD count, buflen, len, *value_types = NULL;
174     LONG res, i = 0;
175     WCHAR *buf = NULL;
176
177     TRACE("%p, %s\n", root, debugstr_w(subkey));
178
179     if ((res = RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE, &hkey ))) goto done;
180     if ((res = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, &buflen, NULL, NULL, NULL )))
181         goto done;
182
183     hr = E_OUTOFMEMORY;
184     if (!(buf = heap_alloc( (buflen + 1) * sizeof(WCHAR) ))) goto done;
185     if (!(value_names = heap_alloc( count * sizeof(BSTR) ))) goto done;
186     if (!(value_types = heap_alloc( count * sizeof(DWORD) ))) goto done;
187
188     hr = S_OK;
189     for (;;)
190     {
191         len = buflen + 1;
192         res = RegEnumValueW( hkey, i, buf, &len, NULL, &value_types[i], NULL, NULL );
193         if (res == ERROR_NO_MORE_ITEMS)
194         {
195             if (i) res = ERROR_SUCCESS;
196             break;
197         }
198         if (res) break;
199         if (!(value_names[i] = SysAllocString( buf )))
200         {
201             for (i--; i >= 0; i--) SysFreeString( value_names[i] );
202             hr = ERROR_OUTOFMEMORY;
203             break;
204         }
205         i++;
206     }
207     if (hr == S_OK && !res)
208     {
209         hr = to_bstr_array( value_names, i, names );
210         if (hr == S_OK) hr = to_i4_array( value_types, i, types );
211     }
212
213 done:
214     set_variant( VT_UI4, res, NULL, retval );
215     RegCloseKey( hkey );
216     heap_free( value_names );
217     heap_free( value_types );
218     heap_free( buf );
219     return hr;
220 }
221
222 HRESULT reg_enum_values( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
223 {
224     VARIANT defkey, subkey, names, types, retval;
225     IWbemClassObject *sig;
226     HRESULT hr;
227
228     TRACE("%p, %p\n", in, out);
229
230     hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
231     if (hr != S_OK) return hr;
232     hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
233     if (hr != S_OK) return hr;
234
235     hr = create_signature( class_stdregprovW, method_enumvaluesW, PARAM_OUT, &sig );
236     if (hr != S_OK)
237     {
238         VariantClear( &subkey );
239         return hr;
240     }
241     hr = IWbemClassObject_SpawnInstance( sig, 0, out );
242     if (hr != S_OK)
243     {
244         VariantClear( &subkey );
245         IWbemClassObject_Release( sig );
246         return hr;
247     }
248     VariantInit( &names );
249     VariantInit( &types );
250     hr = enum_values( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &types, &retval );
251     if (hr != S_OK) goto done;
252     if (!V_UI4( &retval ))
253     {
254         hr = IWbemClassObject_Put( *out, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
255         if (hr != S_OK) goto done;
256         hr = IWbemClassObject_Put( *out, param_typesW, 0, &types, CIM_SINT32|CIM_FLAG_ARRAY );
257         if (hr != S_OK) goto done;
258     }
259     hr = IWbemClassObject_Put( *out, param_returnvalueW, 0, &retval, CIM_UINT32 );
260
261 done:
262     VariantClear( &types );
263     VariantClear( &names );
264     VariantClear( &subkey );
265     IWbemClassObject_Release( sig );
266     if (hr != S_OK) IWbemClassObject_Release( *out );
267     return hr;
268 }
269
270 static HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value, VARIANT *retval )
271 {
272     HRESULT hr = S_OK;
273     WCHAR *buf = NULL;
274     DWORD size;
275     LONG res;
276
277     TRACE("%p, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name));
278
279     if ((res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, NULL, &size ))) goto done;
280     if (!(buf = heap_alloc( size )))
281     {
282         hr = E_OUTOFMEMORY;
283         goto done;
284     }
285     if (!(res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, buf, &size )))
286         set_variant( VT_BSTR, 0, buf, value );
287
288 done:
289     set_variant( VT_UI4, res, NULL, retval );
290     heap_free( buf );
291     return hr;
292 }
293
294 HRESULT reg_get_stringvalue( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out )
295 {
296     VARIANT defkey, subkey, name, value, retval;
297     IWbemClassObject *sig;
298     HRESULT hr;
299
300     TRACE("%p, %p\n", in, out);
301
302     hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL );
303     if (hr != S_OK) return hr;
304     hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL );
305     if (hr != S_OK) return hr;
306     hr = IWbemClassObject_Get( in, param_valuenameW, 0, &name, NULL, NULL );
307     if (hr != S_OK) return hr;
308
309     hr = create_signature( class_stdregprovW, method_getstringvalueW, PARAM_OUT, &sig );
310     if (hr != S_OK)
311     {
312         VariantClear( &name );
313         VariantClear( &subkey );
314         return hr;
315     }
316     hr = IWbemClassObject_SpawnInstance( sig, 0, out );
317     if (hr != S_OK)
318     {
319         VariantClear( &name );
320         VariantClear( &subkey );
321         IWbemClassObject_Release( sig );
322         return hr;
323     }
324     VariantInit( &value );
325     hr = get_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, &retval );
326     if (hr != S_OK) goto done;
327     if (!V_UI4( &retval ))
328     {
329         hr = IWbemClassObject_Put( *out, param_valueW, 0, &value, CIM_STRING );
330         if (hr != S_OK) goto done;
331     }
332     hr = IWbemClassObject_Put( *out, param_returnvalueW, 0, &retval, CIM_UINT32 );
333
334 done:
335     VariantClear( &name );
336     VariantClear( &subkey );
337     IWbemClassObject_Release( sig );
338     if (hr != S_OK) IWbemClassObject_Release( *out );
339     return hr;
340 }