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