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