ntdll: Validate blocks in the heap pending free request list.
[wine.git] / dlls / wbemprox / reg.c
blob81ed914ae2f358e04d579b7916e942e1b5840e31
1 /*
2 * StdRegProv implementation
4 * Copyright 2012 Hans Leidekker for CodeWeavers
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.
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.
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
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wbemcli.h"
29 #include "wine/debug.h"
30 #include "wbemprox_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
34 static HRESULT to_bstr_array( BSTR *strings, DWORD count, VARIANT *var )
36 SAFEARRAY *sa;
37 HRESULT hr;
38 LONG i;
40 if (!(sa = SafeArrayCreateVector( VT_BSTR, 0, count ))) return E_OUTOFMEMORY;
41 for (i = 0; i < count; i++)
43 if ((hr = SafeArrayPutElement( sa, &i, strings[i] )) != S_OK)
45 SafeArrayDestroy( sa );
46 return hr;
49 set_variant( VT_BSTR|VT_ARRAY, 0, sa, var );
50 return S_OK;
53 static void free_bstr_array( BSTR *strings, DWORD count )
55 while (count--)
56 SysFreeString( *(strings++) );
59 static HRESULT to_i4_array( DWORD *values, DWORD count, VARIANT *var )
61 SAFEARRAY *sa;
62 HRESULT hr;
63 LONG i;
65 if (!(sa = SafeArrayCreateVector( VT_I4, 0, count ))) return E_OUTOFMEMORY;
66 for (i = 0; i < count; i++)
68 if ((hr = SafeArrayPutElement( sa, &i, &values[i] )) != S_OK)
70 SafeArrayDestroy( sa );
71 return hr;
74 set_variant( VT_I4|VT_ARRAY, 0, sa, var );
75 return S_OK;
78 static unsigned int reg_get_access_mask( IWbemContext *context )
80 VARIANT value;
82 if (!context) return 0;
84 V_VT( &value ) = VT_EMPTY;
85 if (FAILED(IWbemContext_GetValue( context, L"__ProviderArchitecture", 0, &value )))
86 return 0;
88 if (FAILED(VariantChangeType( &value, &value, 0, VT_I4 )))
90 VariantClear( &value );
91 return 0;
94 if (V_I4( &value ) == 32)
95 return KEY_WOW64_32KEY;
96 else if (V_I4( &value ) == 64)
97 return KEY_WOW64_64KEY;
99 return 0;
102 static HRESULT create_key( HKEY root, const WCHAR *subkey, IWbemContext *context, VARIANT *retval )
104 LONG res;
105 HKEY hkey;
107 TRACE("%p, %s\n", root, debugstr_w(subkey));
109 res = RegCreateKeyExW( root, subkey, 0, NULL, 0, reg_get_access_mask( context ), NULL, &hkey, NULL );
110 set_variant( VT_UI4, res, NULL, retval );
111 if (!res)
113 RegCloseKey( hkey );
114 return S_OK;
116 return HRESULT_FROM_WIN32( res );
119 HRESULT reg_create_key( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
121 VARIANT defkey, subkey, retval;
122 IWbemClassObject *sig, *out_params = NULL;
123 HRESULT hr;
125 TRACE("%p, %p, %p, %p\n", obj, context, in, out);
127 hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL );
128 if (hr != S_OK) return hr;
129 hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL );
130 if (hr != S_OK) return hr;
132 hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"CreateKey", PARAM_OUT, &sig );
133 if (hr != S_OK)
135 VariantClear( &subkey );
136 return hr;
138 if (out)
140 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
141 if (hr != S_OK)
143 VariantClear( &subkey );
144 IWbemClassObject_Release( sig );
145 return hr;
148 hr = create_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), context, &retval );
149 if (hr == S_OK && out_params)
150 hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
152 VariantClear( &subkey );
153 IWbemClassObject_Release( sig );
154 if (hr == S_OK && out)
156 *out = out_params;
157 IWbemClassObject_AddRef( out_params );
159 if (out_params) IWbemClassObject_Release( out_params );
160 return hr;
163 static HRESULT enum_key( HKEY root, const WCHAR *subkey, VARIANT *names, IWbemContext *context, VARIANT *retval )
165 HKEY hkey;
166 HRESULT hr = S_OK;
167 WCHAR buf[256];
168 BSTR *strings, *tmp;
169 DWORD count = 2, len = ARRAY_SIZE( buf );
170 LONG res, i = 0;
172 TRACE("%p, %s\n", root, debugstr_w(subkey));
174 if (!(strings = malloc( count * sizeof(BSTR) ))) return E_OUTOFMEMORY;
175 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_ENUMERATE_SUB_KEYS | reg_get_access_mask( context ), &hkey )))
177 set_variant( VT_UI4, res, NULL, retval );
178 free( strings );
179 return S_OK;
181 for (;;)
183 if (i >= count)
185 count *= 2;
186 if (!(tmp = realloc( strings, count * sizeof(BSTR) )))
188 RegCloseKey( hkey );
189 return E_OUTOFMEMORY;
191 strings = tmp;
193 if ((res = RegEnumKeyW( hkey, i, buf, len )) == ERROR_NO_MORE_ITEMS)
195 if (i) res = ERROR_SUCCESS;
196 break;
198 if (res) break;
199 if (!(strings[i] = SysAllocString( buf )))
201 for (i--; i >= 0; i--) SysFreeString( strings[i] );
202 hr = E_OUTOFMEMORY;
203 break;
205 i++;
207 if (hr == S_OK && !res)
209 hr = to_bstr_array( strings, i, names );
210 free_bstr_array( strings, i );
212 set_variant( VT_UI4, res, NULL, retval );
213 RegCloseKey( hkey );
214 free( strings );
215 return hr;
218 HRESULT reg_enum_key( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
220 VARIANT defkey, subkey, names, retval;
221 IWbemClassObject *sig, *out_params = NULL;
222 HRESULT hr;
224 TRACE("%p, %p, %p, %p\n", obj, context, in, out);
226 hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL );
227 if (hr != S_OK) return hr;
228 hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL );
229 if (hr != S_OK) return hr;
231 hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"EnumKey", PARAM_OUT, &sig );
232 if (hr != S_OK)
234 VariantClear( &subkey );
235 return hr;
237 if (out)
239 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
240 if (hr != S_OK)
242 VariantClear( &subkey );
243 IWbemClassObject_Release( sig );
244 return hr;
247 VariantInit( &names );
248 hr = enum_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, context, &retval );
249 if (hr != S_OK) goto done;
250 if (out_params)
252 if (!V_UI4( &retval ))
254 hr = IWbemClassObject_Put( out_params, L"sNames", 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
255 if (hr != S_OK) goto done;
257 hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
260 done:
261 VariantClear( &names );
262 VariantClear( &subkey );
263 IWbemClassObject_Release( sig );
264 if (hr == S_OK && out)
266 *out = out_params;
267 IWbemClassObject_AddRef( out_params );
269 if (out_params) IWbemClassObject_Release( out_params );
270 return hr;
273 static HRESULT enum_values( HKEY root, const WCHAR *subkey, VARIANT *names, VARIANT *types, IWbemContext *context,
274 VARIANT *retval )
276 HKEY hkey = NULL;
277 HRESULT hr = S_OK;
278 BSTR *value_names = NULL;
279 DWORD count, buflen, len, *value_types = NULL;
280 LONG res, i = 0;
281 WCHAR *buf = NULL;
283 TRACE("%p, %s\n", root, debugstr_w(subkey));
285 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_QUERY_VALUE | reg_get_access_mask( context ), &hkey ))) goto done;
286 if ((res = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, &buflen, NULL, NULL, NULL )))
287 goto done;
289 hr = E_OUTOFMEMORY;
290 if (!(buf = malloc( (buflen + 1) * sizeof(WCHAR) ))) goto done;
291 if (!(value_names = malloc( count * sizeof(BSTR) ))) goto done;
292 if (!(value_types = malloc( count * sizeof(DWORD) ))) goto done;
294 hr = S_OK;
295 for (;;)
297 len = buflen + 1;
298 res = RegEnumValueW( hkey, i, buf, &len, NULL, &value_types[i], NULL, NULL );
299 if (res == ERROR_NO_MORE_ITEMS)
301 if (i) res = ERROR_SUCCESS;
302 break;
304 if (res) break;
305 if (!(value_names[i] = SysAllocString( buf )))
307 for (i--; i >= 0; i--) SysFreeString( value_names[i] );
308 hr = E_OUTOFMEMORY;
309 break;
311 i++;
313 if (hr == S_OK && !res)
315 hr = to_bstr_array( value_names, i, names );
316 free_bstr_array( value_names, i );
317 if (hr == S_OK) hr = to_i4_array( value_types, i, types );
320 done:
321 set_variant( VT_UI4, res, NULL, retval );
322 RegCloseKey( hkey );
323 free( value_names );
324 free( value_types );
325 free( buf );
326 return hr;
329 HRESULT reg_enum_values( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
331 VARIANT defkey, subkey, names, types, retval;
332 IWbemClassObject *sig, *out_params = NULL;
333 HRESULT hr;
335 TRACE("%p, %p, %p, %p\n", obj, context, in, out);
337 hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL );
338 if (hr != S_OK) return hr;
339 hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL );
340 if (hr != S_OK) return hr;
342 hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"EnumValues", PARAM_OUT, &sig );
343 if (hr != S_OK)
345 VariantClear( &subkey );
346 return hr;
348 if (out)
350 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
351 if (hr != S_OK)
353 VariantClear( &subkey );
354 IWbemClassObject_Release( sig );
355 return hr;
358 VariantInit( &names );
359 VariantInit( &types );
360 hr = enum_values( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), &names, &types, context, &retval );
361 if (hr != S_OK) goto done;
362 if (out_params)
364 if (!V_UI4( &retval ))
366 hr = IWbemClassObject_Put( out_params, L"sNames", 0, &names, CIM_STRING|CIM_FLAG_ARRAY );
367 if (hr != S_OK) goto done;
368 hr = IWbemClassObject_Put( out_params, L"Types", 0, &types, CIM_SINT32|CIM_FLAG_ARRAY );
369 if (hr != S_OK) goto done;
371 hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
374 done:
375 VariantClear( &types );
376 VariantClear( &names );
377 VariantClear( &subkey );
378 IWbemClassObject_Release( sig );
379 if (hr == S_OK && out)
381 *out = out_params;
382 IWbemClassObject_AddRef( out_params );
384 if (out_params) IWbemClassObject_Release( out_params );
385 return hr;
388 static HRESULT get_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, VARIANT *value,
389 IWbemContext *context, VARIANT *retval )
391 DWORD size, mask, flags = RRF_RT_REG_SZ;
392 HRESULT hr = S_OK;
393 BSTR str = NULL;
394 LONG res;
396 TRACE("%p, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name));
398 mask = reg_get_access_mask( context );
400 if (mask & KEY_WOW64_64KEY)
401 flags |= RRF_SUBKEY_WOW6464KEY;
402 else if (mask & KEY_WOW64_32KEY)
403 flags |= RRF_SUBKEY_WOW6432KEY;
405 if ((res = RegGetValueW( root, subkey, name, flags, NULL, NULL, &size ))) goto done;
406 if (!(str = SysAllocStringLen( NULL, size / sizeof(WCHAR) - 1 )))
408 hr = E_OUTOFMEMORY;
409 goto done;
411 if (!(res = RegGetValueW( root, subkey, name, flags, NULL, str, &size )))
412 set_variant( VT_BSTR, 0, str, value );
414 done:
415 set_variant( VT_UI4, res, NULL, retval );
416 if (res) SysFreeString( str );
417 return hr;
420 HRESULT reg_get_stringvalue( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
422 VARIANT defkey, subkey, name, value, retval;
423 IWbemClassObject *sig, *out_params = NULL;
424 HRESULT hr;
426 TRACE("%p, %p, %p, %p\n", obj, context, in, out);
428 hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL );
429 if (hr != S_OK) return hr;
430 hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL );
431 if (hr != S_OK) return hr;
432 hr = IWbemClassObject_Get( in, L"sValueName", 0, &name, NULL, NULL );
433 if (hr != S_OK)
435 VariantClear( &subkey );
436 return hr;
439 hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"GetStringValue", PARAM_OUT, &sig );
440 if (hr != S_OK)
442 VariantClear( &name );
443 VariantClear( &subkey );
444 return hr;
446 if (out)
448 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
449 if (hr != S_OK)
451 VariantClear( &name );
452 VariantClear( &subkey );
453 IWbemClassObject_Release( sig );
454 return hr;
457 VariantInit( &value );
458 hr = get_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), &value, context, &retval );
459 if (hr != S_OK) goto done;
460 if (out_params)
462 if (!V_UI4( &retval ))
464 hr = IWbemClassObject_Put( out_params, L"sValue", 0, &value, CIM_STRING );
465 if (hr != S_OK) goto done;
467 hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
470 done:
471 VariantClear( &name );
472 VariantClear( &subkey );
473 IWbemClassObject_Release( sig );
474 if (hr == S_OK && out)
476 *out = out_params;
477 IWbemClassObject_AddRef( out_params );
479 if (out_params) IWbemClassObject_Release( out_params );
480 return hr;
483 static void set_stringvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, const WCHAR *value,
484 IWbemContext *context, VARIANT *retval )
486 HKEY hkey;
487 LONG res;
489 TRACE("%p, %s, %s, %s\n", root, debugstr_w(subkey), debugstr_w(name), debugstr_w(value));
491 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_SET_VALUE | reg_get_access_mask( context ), &hkey )))
493 set_variant( VT_UI4, res, NULL, retval );
494 return;
497 res = RegSetKeyValueW( hkey, NULL, name, REG_SZ, value, (lstrlenW( value ) + 1) * sizeof(*value) );
498 set_variant( VT_UI4, res, NULL, retval );
499 RegCloseKey( hkey );
502 HRESULT reg_set_stringvalue( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
504 VARIANT defkey, subkey, name, value, retval;
505 IWbemClassObject *sig, *out_params = NULL;
506 HRESULT hr;
508 TRACE("%p, %p, %p, %p\n", obj, context, in, out);
510 hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL );
511 if (hr != S_OK) return hr;
512 hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL );
513 if (hr != S_OK) return hr;
514 hr = IWbemClassObject_Get( in, L"sValueName", 0, &name, NULL, NULL );
515 if (hr != S_OK)
517 VariantClear( &subkey );
518 return hr;
520 hr = IWbemClassObject_Get( in, L"sValue", 0, &value, NULL, NULL );
521 if (hr != S_OK)
523 VariantClear( &name );
524 VariantClear( &subkey );
525 return hr;
528 hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"SetStringValue", PARAM_OUT, &sig );
529 if (hr != S_OK)
531 VariantClear( &name );
532 VariantClear( &subkey );
533 VariantClear( &value );
534 return hr;
536 if (out)
538 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
539 if (hr != S_OK)
541 VariantClear( &name );
542 VariantClear( &subkey );
543 VariantClear( &value );
544 IWbemClassObject_Release( sig );
545 return hr;
549 set_stringvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), V_BSTR(&value), context, &retval );
550 if (out_params)
551 hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
553 VariantClear( &name );
554 VariantClear( &subkey );
555 VariantClear( &value );
556 IWbemClassObject_Release( sig );
557 if (hr == S_OK && out)
559 *out = out_params;
560 IWbemClassObject_AddRef( out_params );
562 if (out_params) IWbemClassObject_Release( out_params );
563 return hr;
566 static void set_dwordvalue( HKEY root, const WCHAR *subkey, const WCHAR *name, DWORD value, IWbemContext *context,
567 VARIANT *retval )
569 HKEY hkey;
570 LONG res;
572 TRACE( "%p, %s, %s, %#lx\n", root, debugstr_w(subkey), debugstr_w(name), value );
574 if ((res = RegOpenKeyExW( root, subkey, 0, KEY_SET_VALUE | reg_get_access_mask( context ), &hkey )))
576 set_variant( VT_UI4, res, NULL, retval );
577 return;
580 res = RegSetKeyValueW( hkey, NULL, name, REG_DWORD, &value, sizeof(value) );
581 set_variant( VT_UI4, res, NULL, retval );
582 RegCloseKey( hkey );
585 HRESULT reg_set_dwordvalue( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
587 VARIANT defkey, subkey, name, value, retval;
588 IWbemClassObject *sig, *out_params = NULL;
589 HRESULT hr;
591 TRACE("%p, %p, %p, %p\n", obj, context, in, out);
593 hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL );
594 if (hr != S_OK) return hr;
595 hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL );
596 if (hr != S_OK) return hr;
597 hr = IWbemClassObject_Get( in, L"sValueName", 0, &name, NULL, NULL );
598 if (hr != S_OK)
600 VariantClear( &subkey );
601 return hr;
603 hr = IWbemClassObject_Get( in, L"uValue", 0, &value, NULL, NULL );
604 if (hr != S_OK)
606 VariantClear( &name );
607 VariantClear( &subkey );
608 return hr;
611 hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"SetDWORDValue", PARAM_OUT, &sig );
612 if (hr != S_OK)
614 VariantClear( &name );
615 VariantClear( &subkey );
616 return hr;
618 if (out)
620 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
621 if (hr != S_OK)
623 VariantClear( &name );
624 VariantClear( &subkey );
625 IWbemClassObject_Release( sig );
626 return hr;
629 set_dwordvalue( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), V_BSTR(&name), V_UI4(&value), context, &retval );
630 if (out_params)
631 hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
633 VariantClear( &name );
634 VariantClear( &subkey );
635 IWbemClassObject_Release( sig );
636 if (hr == S_OK && out)
638 *out = out_params;
639 IWbemClassObject_AddRef( out_params );
641 if (out_params) IWbemClassObject_Release( out_params );
642 return hr;
645 static void delete_key( HKEY root, const WCHAR *subkey, IWbemContext *context, VARIANT *retval )
647 LONG res;
649 TRACE("%p, %s\n", root, debugstr_w(subkey));
651 res = RegDeleteKeyExW( root, subkey, reg_get_access_mask( context ), 0 );
652 set_variant( VT_UI4, res, NULL, retval );
655 HRESULT reg_delete_key( IWbemClassObject *obj, IWbemContext *context, IWbemClassObject *in, IWbemClassObject **out )
657 VARIANT defkey, subkey, retval;
658 IWbemClassObject *sig, *out_params = NULL;
659 HRESULT hr;
661 TRACE("%p, %p, %p, %p\n", obj, context, in, out);
663 hr = IWbemClassObject_Get( in, L"hDefKey", 0, &defkey, NULL, NULL );
664 if (hr != S_OK) return hr;
665 hr = IWbemClassObject_Get( in, L"sSubKeyName", 0, &subkey, NULL, NULL );
666 if (hr != S_OK) return hr;
668 hr = create_signature( WBEMPROX_NAMESPACE_CIMV2, L"StdRegProv", L"DeleteKey", PARAM_OUT, &sig );
669 if (hr != S_OK)
671 VariantClear( &subkey );
672 return hr;
674 if (out)
676 hr = IWbemClassObject_SpawnInstance( sig, 0, &out_params );
677 if (hr != S_OK)
679 VariantClear( &subkey );
680 IWbemClassObject_Release( sig );
681 return hr;
684 delete_key( (HKEY)(INT_PTR)V_I4(&defkey), V_BSTR(&subkey), context, &retval );
685 if (out_params)
686 hr = IWbemClassObject_Put( out_params, L"ReturnValue", 0, &retval, CIM_UINT32 );
688 VariantClear( &subkey );
689 IWbemClassObject_Release( sig );
690 if (hr == S_OK && out)
692 *out = out_params;
693 IWbemClassObject_AddRef( out_params );
695 if (out_params) IWbemClassObject_Release( out_params );
696 return hr;