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 #ifdef __REACTOS__ 34 #include <winreg.h> 35 #endif 36 37 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox); 38 39 static HRESULT to_bstr_array( BSTR *strings, DWORD count, VARIANT *var ) 40 { 41 SAFEARRAY *sa; 42 HRESULT hr; 43 LONG i; 44 45 if (!(sa = SafeArrayCreateVector( VT_BSTR, 0, count ))) return E_OUTOFMEMORY; 46 for (i = 0; i < count; i++) 47 { 48 if ((hr = SafeArrayPutElement( sa, &i, strings[i] )) != S_OK) 49 { 50 SafeArrayDestroy( sa ); 51 return hr; 52 } 53 } 54 set_variant( VT_BSTR|VT_ARRAY, 0, sa, var ); 55 return S_OK; 56 } 57 58 static void free_bstr_array( BSTR *strings, DWORD count ) 59 { 60 while (count--) 61 SysFreeString( *(strings++) ); 62 } 63 64 static HRESULT to_i4_array( DWORD *values, DWORD count, VARIANT *var ) 65 { 66 SAFEARRAY *sa; 67 HRESULT hr; 68 LONG i; 69 70 if (!(sa = SafeArrayCreateVector( VT_I4, 0, count ))) return E_OUTOFMEMORY; 71 for (i = 0; i < count; i++) 72 { 73 if ((hr = SafeArrayPutElement( sa, &i, &values[i] )) != S_OK) 74 { 75 SafeArrayDestroy( sa ); 76 return hr; 77 } 78 } 79 set_variant( VT_I4|VT_ARRAY, 0, sa, var ); 80 return S_OK; 81 } 82 83 static HRESULT create_key( HKEY root, const WCHAR *subkey, VARIANT *retval ) 84 { 85 LONG res; 86 HKEY hkey; 87 88 TRACE("%p, %s\n", root, debugstr_w(subkey)); 89 90 res = RegCreateKeyExW( root, subkey, 0, NULL, 0, 0, NULL, &hkey, NULL ); 91 set_variant( VT_UI4, res, NULL, retval ); 92 if (!res) 93 { 94 RegCloseKey( hkey ); 95 return S_OK; 96 } 97 return HRESULT_FROM_WIN32( res ); 98 } 99 100 HRESULT reg_create_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out ) 101 { 102 VARIANT defkey, subkey, retval; 103 IWbemClassObject *sig, *out_params = NULL; 104 HRESULT hr; 105 106 TRACE("%p, %p\n", in, out); 107 108 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL ); 109 if (hr != S_OK) return hr; 110 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL ); 111 if (hr != S_OK) return hr; 112 113 hr = create_signature( class_stdregprovW, method_createkeyW, PARAM_OUT, &sig ); 114 if (hr != S_OK) 115 { 116 VariantClear( &subkey ); 117 return hr; 118 } 119 if (out) 120 { 121 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params ); 122 if (hr != S_OK) 123 { 124 VariantClear( &subkey ); 125 IWbemClassObject_Release( sig ); 126 return hr; 127 } 128 } 129 hr = create_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &retval ); 130 if (hr == S_OK && out_params) 131 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 ); 132 133 VariantClear( &subkey ); 134 IWbemClassObject_Release( sig ); 135 if (hr == S_OK && out) 136 { 137 *out = out_params; 138 IWbemClassObject_AddRef( out_params ); 139 } 140 if (out_params) IWbemClassObject_Release( out_params ); 141 return hr; 142 } 143 144 static HRESULT enum_key( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *retval ) 145 { 146 HKEY hkey; 147 HRESULT hr = S_OK; 148 WCHAR buf[256]; 149 BSTR *strings, *tmp; 150 DWORD count = 2, len = ARRAY_SIZE( buf ); 151 LONG res, i = 0; 152 153 TRACE("%p, %s\n", root, debugstr_w(subkey)); 154 155 if (!(strings = heap_alloc( count * sizeof(BSTR) ))) return E_OUTOFMEMORY; 156 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_ENUMERATE_SUB_KEYS, &hkey ))) 157 { 158 set_variant( VT_UI4, res, NULL, retval ); 159 heap_free( strings ); 160 return S_OK; 161 } 162 for (;;) 163 { 164 if (i >= count) 165 { 166 count *= 2; 167 if (!(tmp = heap_realloc( strings, count * sizeof(BSTR) ))) 168 { 169 RegCloseKey( hkey ); 170 return E_OUTOFMEMORY; 171 } 172 strings = tmp; 173 } 174 if ((res = RegEnumKeyW( hkey, i, buf, len )) == ERROR_NO_MORE_ITEMS) 175 { 176 if (i) res = ERROR_SUCCESS; 177 break; 178 } 179 if (res) break; 180 if (!(strings[i] = SysAllocString( buf ))) 181 { 182 for (i--; i >= 0; i--) SysFreeString( strings[i] ); 183 hr = E_OUTOFMEMORY; 184 break; 185 } 186 i++; 187 } 188 if (hr == S_OK && !res) 189 { 190 hr = to_bstr_array( strings, i, names ); 191 free_bstr_array( strings, i ); 192 } 193 set_variant( VT_UI4, res, NULL, retval ); 194 RegCloseKey( hkey ); 195 heap_free( strings ); 196 return hr; 197 } 198 199 HRESULT reg_enum_key( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out ) 200 { 201 VARIANT defkey, subkey, names, retval; 202 IWbemClassObject *sig, *out_params = NULL; 203 HRESULT hr; 204 205 TRACE("%p, %p\n", in, out); 206 207 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL ); 208 if (hr != S_OK) return hr; 209 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL ); 210 if (hr != S_OK) return hr; 211 212 hr = create_signature( class_stdregprovW, method_enumkeyW, PARAM_OUT, &sig ); 213 if (hr != S_OK) 214 { 215 VariantClear( &subkey ); 216 return hr; 217 } 218 if (out) 219 { 220 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params ); 221 if (hr != S_OK) 222 { 223 VariantClear( &subkey ); 224 IWbemClassObject_Release( sig ); 225 return hr; 226 } 227 } 228 VariantInit( &names ); 229 hr = enum_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &retval ); 230 if (hr != S_OK) goto done; 231 if (out_params) 232 { 233 if (!V_UI4( &retval )) 234 { 235 hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY ); 236 if (hr != S_OK) goto done; 237 } 238 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 ); 239 } 240 241 done: 242 VariantClear( &names ); 243 VariantClear( &subkey ); 244 IWbemClassObject_Release( sig ); 245 if (hr == S_OK && out) 246 { 247 *out = out_params; 248 IWbemClassObject_AddRef( out_params ); 249 } 250 if (out_params) IWbemClassObject_Release( out_params ); 251 return hr; 252 } 253 254 static HRESULT enum_values( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *types, VARIANT *retval ) 255 { 256 HKEY hkey = NULL; 257 HRESULT hr = S_OK; 258 BSTR *value_names = NULL; 259 DWORD count, buflen, len, *value_types = NULL; 260 LONG res, i = 0; 261 WCHAR *buf = NULL; 262 263 TRACE("%p, %s\n", root, debugstr_w(subkey)); 264 265 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE, &hkey ))) goto done; 266 if ((res = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, &buflen, NULL, NULL, NULL ))) 267 goto done; 268 269 hr = E_OUTOFMEMORY; 270 if (!(buf = heap_alloc( (buflen + 1) * sizeof(WCHAR) ))) goto done; 271 if (!(value_names = heap_alloc( count * sizeof(BSTR) ))) goto done; 272 if (!(value_types = heap_alloc( count * sizeof(DWORD) ))) goto done; 273 274 hr = S_OK; 275 for (;;) 276 { 277 len = buflen + 1; 278 res = RegEnumValueW( hkey, i, buf, &len, NULL, &value_types[i], NULL, NULL ); 279 if (res == ERROR_NO_MORE_ITEMS) 280 { 281 if (i) res = ERROR_SUCCESS; 282 break; 283 } 284 if (res) break; 285 if (!(value_names[i] = SysAllocString( buf ))) 286 { 287 for (i--; i >= 0; i--) SysFreeString( value_names[i] ); 288 hr = E_OUTOFMEMORY; 289 break; 290 } 291 i++; 292 } 293 if (hr == S_OK && !res) 294 { 295 hr = to_bstr_array( value_names, i, names ); 296 free_bstr_array( value_names, i ); 297 if (hr == S_OK) hr = to_i4_array( value_types, i, types ); 298 } 299 300 done: 301 set_variant( VT_UI4, res, NULL, retval ); 302 RegCloseKey( hkey ); 303 heap_free( value_names ); 304 heap_free( value_types ); 305 heap_free( buf ); 306 return hr; 307 } 308 309 HRESULT reg_enum_values( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out ) 310 { 311 VARIANT defkey, subkey, names, types, retval; 312 IWbemClassObject *sig, *out_params = NULL; 313 HRESULT hr; 314 315 TRACE("%p, %p\n", in, out); 316 317 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL ); 318 if (hr != S_OK) return hr; 319 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL ); 320 if (hr != S_OK) return hr; 321 322 hr = create_signature( class_stdregprovW, method_enumvaluesW, PARAM_OUT, &sig ); 323 if (hr != S_OK) 324 { 325 VariantClear( &subkey ); 326 return hr; 327 } 328 if (out) 329 { 330 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params ); 331 if (hr != S_OK) 332 { 333 VariantClear( &subkey ); 334 IWbemClassObject_Release( sig ); 335 return hr; 336 } 337 } 338 VariantInit( &names ); 339 VariantInit( &types ); 340 hr = enum_values( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &types, &retval ); 341 if (hr != S_OK) goto done; 342 if (out_params) 343 { 344 if (!V_UI4( &retval )) 345 { 346 hr = IWbemClassObject_Put( out_params, param_namesW, 0, &names, CIM_STRING|CIM_FLAG_ARRAY ); 347 if (hr != S_OK) goto done; 348 hr = IWbemClassObject_Put( out_params, param_typesW, 0, &types, CIM_SINT32|CIM_FLAG_ARRAY ); 349 if (hr != S_OK) goto done; 350 } 351 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 ); 352 } 353 354 done: 355 VariantClear( &types ); 356 VariantClear( &names ); 357 VariantClear( &subkey ); 358 IWbemClassObject_Release( sig ); 359 if (hr == S_OK && out) 360 { 361 *out = out_params; 362 IWbemClassObject_AddRef( out_params ); 363 } 364 if (out_params) IWbemClassObject_Release( out_params ); 365 return hr; 366 } 367 368 static HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value, VARIANT *retval ) 369 { 370 HRESULT hr = S_OK; 371 BSTR str = NULL; 372 DWORD size; 373 LONG res; 374 375 TRACE("%p, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name)); 376 377 if ((res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, NULL, &size ))) goto done; 378 if (!(str = SysAllocStringLen( NULL, size / sizeof(WCHAR) - 1 ))) 379 { 380 hr = E_OUTOFMEMORY; 381 goto done; 382 } 383 if (!(res = RegGetValueW( root, subkey, name, RRF_RT_REG_SZ, NULL, str, &size ))) 384 set_variant( VT_BSTR, 0, str, value ); 385 386 done: 387 set_variant( VT_UI4, res, NULL, retval ); 388 if (res) SysFreeString( str ); 389 return hr; 390 } 391 392 HRESULT reg_get_stringvalue( IWbemClassObject *obj, IWbemClassObject *in, IWbemClassObject **out ) 393 { 394 VARIANT defkey, subkey, name, value, retval; 395 IWbemClassObject *sig, *out_params = NULL; 396 HRESULT hr; 397 398 TRACE("%p, %p\n", in, out); 399 400 hr = IWbemClassObject_Get( in, param_defkeyW, 0, &defkey, NULL, NULL ); 401 if (hr != S_OK) return hr; 402 hr = IWbemClassObject_Get( in, param_subkeynameW, 0, &subkey, NULL, NULL ); 403 if (hr != S_OK) return hr; 404 hr = IWbemClassObject_Get( in, param_valuenameW, 0, &name, NULL, NULL ); 405 if (hr != S_OK) return hr; 406 407 hr = create_signature( class_stdregprovW, method_getstringvalueW, PARAM_OUT, &sig ); 408 if (hr != S_OK) 409 { 410 VariantClear( &name ); 411 VariantClear( &subkey ); 412 return hr; 413 } 414 if (out) 415 { 416 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params ); 417 if (hr != S_OK) 418 { 419 VariantClear( &name ); 420 VariantClear( &subkey ); 421 IWbemClassObject_Release( sig ); 422 return hr; 423 } 424 } 425 VariantInit( &value ); 426 hr = get_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, &retval ); 427 if (hr != S_OK) goto done; 428 if (out_params) 429 { 430 if (!V_UI4( &retval )) 431 { 432 hr = IWbemClassObject_Put( out_params, param_valueW, 0, &value, CIM_STRING ); 433 if (hr != S_OK) goto done; 434 } 435 hr = IWbemClassObject_Put( out_params, param_returnvalueW, 0, &retval, CIM_UINT32 ); 436 } 437 438 done: 439 VariantClear( &name ); 440 VariantClear( &subkey ); 441 IWbemClassObject_Release( sig ); 442 if (hr == S_OK && out) 443 { 444 *out = out_params; 445 IWbemClassObject_AddRef( out_params ); 446 } 447 if (out_params) IWbemClassObject_Release( out_params ); 448 return hr; 449 } 450