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