xref: /reactos/dll/win32/wbemdisp/locator.c (revision 84ccccab)
1 /*
2  * Copyright 2013 Hans Leidekker for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "wbemdisp_private.h"
20 
21 #include <wbemcli.h>
22 
23 static HRESULT EnumVARIANT_create( IEnumWbemClassObject *, IEnumVARIANT ** );
24 static HRESULT ISWbemSecurity_create( ISWbemSecurity ** );
25 
26 enum type_id
27 {
28     ISWbemLocator_tid,
29     ISWbemObject_tid,
30     ISWbemObjectSet_tid,
31     ISWbemProperty_tid,
32     ISWbemPropertySet_tid,
33     ISWbemServices_tid,
34     ISWbemSecurity_tid,
35     last_tid
36 };
37 
38 static ITypeLib *wbemdisp_typelib;
39 static ITypeInfo *wbemdisp_typeinfo[last_tid];
40 
41 static REFIID wbemdisp_tid_id[] =
42 {
43     &IID_ISWbemLocator,
44     &IID_ISWbemObject,
45     &IID_ISWbemObjectSet,
46     &IID_ISWbemProperty,
47     &IID_ISWbemPropertySet,
48     &IID_ISWbemServices,
49     &IID_ISWbemSecurity
50 };
51 
52 static HRESULT get_typeinfo( enum type_id tid, ITypeInfo **ret )
53 {
54     HRESULT hr;
55 
56     if (!wbemdisp_typelib)
57     {
58         ITypeLib *typelib;
59 
60         hr = LoadRegTypeLib( &LIBID_WbemScripting, 1, 2, LOCALE_SYSTEM_DEFAULT, &typelib );
61         if (FAILED( hr ))
62         {
63             ERR( "LoadRegTypeLib failed: %08x\n", hr );
64             return hr;
65         }
66         if (InterlockedCompareExchangePointer( (void **)&wbemdisp_typelib, typelib, NULL ))
67             ITypeLib_Release( typelib );
68     }
69     if (!wbemdisp_typeinfo[tid])
70     {
71         ITypeInfo *typeinfo;
72 
73         hr = ITypeLib_GetTypeInfoOfGuid( wbemdisp_typelib, wbemdisp_tid_id[tid], &typeinfo );
74         if (FAILED( hr ))
75         {
76             ERR( "GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(wbemdisp_tid_id[tid]), hr );
77             return hr;
78         }
79         if (InterlockedCompareExchangePointer( (void **)(wbemdisp_typeinfo + tid), typeinfo, NULL ))
80             ITypeInfo_Release( typeinfo );
81     }
82     *ret = wbemdisp_typeinfo[tid];
83     ITypeInfo_AddRef( *ret );
84     return S_OK;
85 }
86 
87 struct property
88 {
89     ISWbemProperty ISWbemProperty_iface;
90     LONG refs;
91     IWbemClassObject *object;
92     BSTR name;
93 };
94 
95 static inline struct property *impl_from_ISWbemProperty( ISWbemProperty *iface )
96 {
97     return CONTAINING_RECORD( iface, struct property, ISWbemProperty_iface );
98 }
99 
100 static ULONG WINAPI property_AddRef( ISWbemProperty *iface )
101 {
102     struct property *property = impl_from_ISWbemProperty( iface );
103     return InterlockedIncrement( &property->refs );
104 }
105 
106 static ULONG WINAPI property_Release( ISWbemProperty *iface )
107 {
108     struct property *property = impl_from_ISWbemProperty( iface );
109     LONG refs = InterlockedDecrement( &property->refs );
110     if (!refs)
111     {
112         TRACE( "destroying %p\n", property );
113         IWbemClassObject_Release( property->object );
114         SysFreeString( property->name );
115         heap_free( property );
116     }
117     return refs;
118 }
119 
120 static HRESULT WINAPI property_QueryInterface( ISWbemProperty *iface, REFIID riid, void **obj )
121 {
122     struct property *property = impl_from_ISWbemProperty( iface );
123 
124     TRACE( "%p %s %p\n", property, debugstr_guid(riid), obj );
125 
126     if (IsEqualGUID( riid, &IID_ISWbemProperty ) ||
127         IsEqualGUID( riid, &IID_IDispatch ) ||
128         IsEqualGUID( riid, &IID_IUnknown ))
129     {
130         *obj = iface;
131     }
132     else
133     {
134         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
135         return E_NOINTERFACE;
136     }
137     ISWbemProperty_AddRef( iface );
138     return S_OK;
139 }
140 
141 static HRESULT WINAPI property_GetTypeInfoCount( ISWbemProperty *iface, UINT *count )
142 {
143     struct property *property = impl_from_ISWbemProperty( iface );
144     TRACE( "%p, %p\n", property, count );
145     *count = 1;
146     return S_OK;
147 }
148 
149 static HRESULT WINAPI property_GetTypeInfo( ISWbemProperty *iface, UINT index,
150                                             LCID lcid, ITypeInfo **info )
151 {
152     struct property *property = impl_from_ISWbemProperty( iface );
153     TRACE( "%p, %u, %u, %p\n", property, index, lcid, info );
154 
155     return get_typeinfo( ISWbemProperty_tid, info );
156 }
157 
158 static HRESULT WINAPI property_GetIDsOfNames( ISWbemProperty *iface, REFIID riid, LPOLESTR *names,
159                                               UINT count, LCID lcid, DISPID *dispid )
160 {
161     struct property *property = impl_from_ISWbemProperty( iface );
162     ITypeInfo *typeinfo;
163     HRESULT hr;
164 
165     TRACE( "%p, %s, %p, %u, %u, %p\n", property, debugstr_guid(riid), names, count, lcid, dispid );
166 
167     if (!names || !count || !dispid) return E_INVALIDARG;
168 
169     hr = get_typeinfo( ISWbemProperty_tid, &typeinfo );
170     if (SUCCEEDED(hr))
171     {
172         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
173         ITypeInfo_Release( typeinfo );
174     }
175     return hr;
176 }
177 
178 static HRESULT WINAPI property_Invoke( ISWbemProperty *iface, DISPID member, REFIID riid,
179                                        LCID lcid, WORD flags, DISPPARAMS *params,
180                                        VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
181 {
182     struct property *property = impl_from_ISWbemProperty( iface );
183     ITypeInfo *typeinfo;
184     HRESULT hr;
185 
186     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", property, member, debugstr_guid(riid),
187            lcid, flags, params, result, excep_info, arg_err );
188 
189     hr = get_typeinfo( ISWbemProperty_tid, &typeinfo );
190     if (SUCCEEDED(hr))
191     {
192         hr = ITypeInfo_Invoke( typeinfo, &property->ISWbemProperty_iface, member, flags,
193                                params, result, excep_info, arg_err );
194         ITypeInfo_Release( typeinfo );
195     }
196     return hr;
197 }
198 
199 static HRESULT WINAPI property_get_Value( ISWbemProperty *iface, VARIANT *value )
200 {
201     struct property *property = impl_from_ISWbemProperty( iface );
202 
203     TRACE( "%p %p\n", property, value );
204 
205     return IWbemClassObject_Get( property->object, property->name, 0, value, NULL, NULL );
206 }
207 
208 static HRESULT WINAPI property_put_Value( ISWbemProperty *iface, VARIANT *varValue )
209 {
210     FIXME( "\n" );
211     return E_NOTIMPL;
212 }
213 
214 static HRESULT WINAPI property_get_Name( ISWbemProperty *iface, BSTR *strName )
215 {
216     FIXME( "\n" );
217     return E_NOTIMPL;
218 }
219 
220 static HRESULT WINAPI property_get_IsLocal( ISWbemProperty *iface, VARIANT_BOOL *bIsLocal )
221 {
222     FIXME( "\n" );
223     return E_NOTIMPL;
224 }
225 
226 static HRESULT WINAPI property_get_Origin( ISWbemProperty *iface, BSTR *strOrigin )
227 {
228     FIXME( "\n" );
229     return E_NOTIMPL;
230 }
231 
232 static HRESULT WINAPI property_get_CIMType( ISWbemProperty *iface, WbemCimtypeEnum *iCimType )
233 {
234     FIXME( "\n" );
235     return E_NOTIMPL;
236 }
237 
238 static HRESULT WINAPI property_get_Qualifiers_( ISWbemProperty *iface, ISWbemQualifierSet **objWbemQualifierSet )
239 {
240     FIXME( "\n" );
241     return E_NOTIMPL;
242 }
243 
244 static HRESULT WINAPI property_get_IsArray( ISWbemProperty *iface, VARIANT_BOOL *bIsArray )
245 {
246     FIXME( "\n" );
247     return E_NOTIMPL;
248 }
249 
250 static const ISWbemPropertyVtbl property_vtbl =
251 {
252     property_QueryInterface,
253     property_AddRef,
254     property_Release,
255     property_GetTypeInfoCount,
256     property_GetTypeInfo,
257     property_GetIDsOfNames,
258     property_Invoke,
259     property_get_Value,
260     property_put_Value,
261     property_get_Name,
262     property_get_IsLocal,
263     property_get_Origin,
264     property_get_CIMType,
265     property_get_Qualifiers_,
266     property_get_IsArray
267 };
268 
269 static HRESULT SWbemProperty_create( IWbemClassObject *wbem_object, BSTR name, ISWbemProperty **obj )
270 {
271     struct property *property;
272 
273     TRACE( "%p, %p\n", obj, wbem_object );
274 
275     if (!(property = heap_alloc( sizeof(*property) ))) return E_OUTOFMEMORY;
276     property->ISWbemProperty_iface.lpVtbl = &property_vtbl;
277     property->refs = 1;
278     property->object = wbem_object;
279     IWbemClassObject_AddRef( property->object );
280     property->name = SysAllocStringLen( name, SysStringLen( name ) );
281     *obj = &property->ISWbemProperty_iface;
282     TRACE( "returning iface %p\n", *obj );
283     return S_OK;
284 }
285 
286 struct propertyset
287 {
288     ISWbemPropertySet ISWbemPropertySet_iface;
289     LONG refs;
290     IWbemClassObject *object;
291 };
292 
293 static inline struct propertyset *impl_from_ISWbemPropertySet(
294     ISWbemPropertySet *iface )
295 {
296     return CONTAINING_RECORD( iface, struct propertyset, ISWbemPropertySet_iface );
297 }
298 
299 static ULONG WINAPI propertyset_AddRef( ISWbemPropertySet *iface )
300 {
301     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
302     return InterlockedIncrement( &propertyset->refs );
303 }
304 
305 static ULONG WINAPI propertyset_Release( ISWbemPropertySet *iface )
306 {
307     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
308     LONG refs = InterlockedDecrement( &propertyset->refs );
309     if (!refs)
310     {
311         TRACE( "destroying %p\n", propertyset );
312         IWbemClassObject_Release( propertyset->object );
313         heap_free( propertyset );
314     }
315     return refs;
316 }
317 
318 static HRESULT WINAPI propertyset_QueryInterface( ISWbemPropertySet *iface,
319                                                   REFIID riid, void **obj )
320 {
321     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
322 
323     TRACE( "%p %s %p\n", propertyset, debugstr_guid(riid), obj );
324 
325     if (IsEqualGUID( riid, &IID_ISWbemPropertySet ) ||
326         IsEqualGUID( riid, &IID_IDispatch ) ||
327         IsEqualGUID( riid, &IID_IUnknown ))
328     {
329         *obj = iface;
330     }
331     else
332     {
333         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
334         return E_NOINTERFACE;
335     }
336     ISWbemPropertySet_AddRef( iface );
337     return S_OK;
338 }
339 
340 static HRESULT WINAPI propertyset_GetTypeInfoCount( ISWbemPropertySet *iface, UINT *count )
341 {
342     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
343     TRACE( "%p, %p\n", propertyset, count );
344     *count = 1;
345     return S_OK;
346 }
347 
348 static HRESULT WINAPI propertyset_GetTypeInfo( ISWbemPropertySet *iface,
349                                                UINT index, LCID lcid, ITypeInfo **info )
350 {
351     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
352     TRACE( "%p, %u, %u, %p\n", propertyset, index, lcid, info );
353 
354     return get_typeinfo( ISWbemPropertySet_tid, info );
355 }
356 
357 static HRESULT WINAPI propertyset_GetIDsOfNames( ISWbemPropertySet *iface, REFIID riid, LPOLESTR *names,
358                                                  UINT count, LCID lcid, DISPID *dispid )
359 {
360     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
361     ITypeInfo *typeinfo;
362     HRESULT hr;
363 
364     TRACE( "%p, %s, %p, %u, %u, %p\n", propertyset, debugstr_guid(riid), names, count, lcid, dispid );
365 
366     if (!names || !count || !dispid) return E_INVALIDARG;
367 
368     hr = get_typeinfo( ISWbemPropertySet_tid, &typeinfo );
369     if (SUCCEEDED(hr))
370     {
371         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
372         ITypeInfo_Release( typeinfo );
373     }
374     return hr;
375 }
376 
377 static HRESULT WINAPI propertyset_Invoke( ISWbemPropertySet *iface, DISPID member, REFIID riid,
378                                           LCID lcid, WORD flags, DISPPARAMS *params,
379                                           VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err )
380 {
381     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
382     ITypeInfo *typeinfo;
383     HRESULT hr;
384 
385     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", propertyset, member, debugstr_guid(riid),
386            lcid, flags, params, result, excep_info, arg_err );
387 
388     hr = get_typeinfo( ISWbemPropertySet_tid, &typeinfo );
389     if (SUCCEEDED(hr))
390     {
391         hr = ITypeInfo_Invoke( typeinfo, &propertyset->ISWbemPropertySet_iface, member, flags,
392                                params, result, excep_info, arg_err );
393         ITypeInfo_Release( typeinfo );
394     }
395     return hr;
396 }
397 
398 static HRESULT WINAPI propertyset_get__NewEnum( ISWbemPropertySet *iface, IUnknown **unk )
399 {
400     FIXME( "\n" );
401     return E_NOTIMPL;
402 }
403 
404 static HRESULT WINAPI propertyset_Item( ISWbemPropertySet *iface, BSTR name,
405                                         LONG flags, ISWbemProperty **prop )
406 {
407     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
408     HRESULT hr;
409     VARIANT var;
410 
411     TRACE( "%p, %s, %08x, %p\n", propertyset, debugstr_w(name), flags, prop );
412 
413     hr = IWbemClassObject_Get( propertyset->object, name, 0, &var, NULL, NULL );
414     if (SUCCEEDED(hr))
415     {
416         hr = SWbemProperty_create( propertyset->object, name, prop );
417         VariantClear( &var );
418     }
419     return hr;
420 }
421 
422 static HRESULT WINAPI propertyset_get_Count( ISWbemPropertySet *iface, LONG *count )
423 {
424     FIXME( "\n" );
425     return E_NOTIMPL;
426 }
427 
428 static HRESULT WINAPI propertyset_Add( ISWbemPropertySet *iface, BSTR name, WbemCimtypeEnum type,
429                                        VARIANT_BOOL is_array, LONG flags, ISWbemProperty **prop )
430 {
431     FIXME( "\n" );
432     return E_NOTIMPL;
433 }
434 
435 static HRESULT WINAPI propertyset_Remove( ISWbemPropertySet *iface, BSTR name, LONG flags )
436 {
437     FIXME( "\n" );
438     return E_NOTIMPL;
439 }
440 
441 static const ISWbemPropertySetVtbl propertyset_vtbl =
442 {
443     propertyset_QueryInterface,
444     propertyset_AddRef,
445     propertyset_Release,
446     propertyset_GetTypeInfoCount,
447     propertyset_GetTypeInfo,
448     propertyset_GetIDsOfNames,
449     propertyset_Invoke,
450     propertyset_get__NewEnum,
451     propertyset_Item,
452     propertyset_get_Count,
453     propertyset_Add,
454     propertyset_Remove
455 };
456 
457 static HRESULT SWbemPropertySet_create( IWbemClassObject *wbem_object, ISWbemPropertySet **obj )
458 {
459     struct propertyset *propertyset;
460 
461     TRACE( "%p, %p\n", obj, wbem_object );
462 
463     if (!(propertyset = heap_alloc( sizeof(*propertyset) ))) return E_OUTOFMEMORY;
464     propertyset->ISWbemPropertySet_iface.lpVtbl = &propertyset_vtbl;
465     propertyset->refs = 1;
466     propertyset->object = wbem_object;
467     IWbemClassObject_AddRef( propertyset->object );
468     *obj = &propertyset->ISWbemPropertySet_iface;
469 
470     TRACE( "returning iface %p\n", *obj );
471     return S_OK;
472 }
473 
474 #define DISPID_BASE 0x1800000
475 
476 struct member
477 {
478     BSTR name;
479     DISPID dispid;
480 };
481 
482 struct object
483 {
484     ISWbemObject ISWbemObject_iface;
485     LONG refs;
486     IWbemClassObject *object;
487     struct member *members;
488     UINT nb_members;
489     DISPID last_dispid;
490 };
491 
492 static inline struct object *impl_from_ISWbemObject(
493     ISWbemObject *iface )
494 {
495     return CONTAINING_RECORD( iface, struct object, ISWbemObject_iface );
496 }
497 
498 static ULONG WINAPI object_AddRef(
499     ISWbemObject *iface )
500 {
501     struct object *object = impl_from_ISWbemObject( iface );
502     return InterlockedIncrement( &object->refs );
503 }
504 
505 static ULONG WINAPI object_Release(
506     ISWbemObject *iface )
507 {
508     struct object *object = impl_from_ISWbemObject( iface );
509     LONG refs = InterlockedDecrement( &object->refs );
510     if (!refs)
511     {
512         UINT i;
513 
514         TRACE( "destroying %p\n", object );
515         IWbemClassObject_Release( object->object );
516         for (i = 0; i < object->nb_members; i++) SysFreeString( object->members[i].name );
517         heap_free( object->members );
518         heap_free( object );
519     }
520     return refs;
521 }
522 
523 static HRESULT WINAPI object_QueryInterface(
524     ISWbemObject *iface,
525     REFIID riid,
526     void **ppvObject )
527 {
528     struct object *object = impl_from_ISWbemObject( iface );
529 
530     TRACE( "%p %s %p\n", object, debugstr_guid(riid), ppvObject );
531 
532     if (IsEqualGUID( riid, &IID_ISWbemObject ) ||
533         IsEqualGUID( riid, &IID_IDispatch ) ||
534         IsEqualGUID( riid, &IID_IUnknown ))
535     {
536         *ppvObject = iface;
537     }
538     else
539     {
540         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
541         return E_NOINTERFACE;
542     }
543     ISWbemObject_AddRef( iface );
544     return S_OK;
545 }
546 
547 static HRESULT WINAPI object_GetTypeInfoCount(
548     ISWbemObject *iface,
549     UINT *count )
550 {
551     struct object *object = impl_from_ISWbemObject( iface );
552 
553     TRACE( "%p, %p\n", object, count );
554     *count = 1;
555     return S_OK;
556 }
557 
558 static HRESULT WINAPI object_GetTypeInfo(
559     ISWbemObject *iface,
560     UINT index,
561     LCID lcid,
562     ITypeInfo **info )
563 {
564     struct object *object = impl_from_ISWbemObject( iface );
565     FIXME( "%p, %u, %u, %p\n", object, index, lcid, info );
566     return E_NOTIMPL;
567 }
568 
569 static HRESULT init_members( struct object *object )
570 {
571     LONG bound, i;
572     SAFEARRAY *sa;
573     HRESULT hr;
574 
575     if (object->members) return S_OK;
576 
577     hr = IWbemClassObject_GetNames( object->object, NULL, 0, NULL, &sa );
578     if (FAILED( hr )) return hr;
579     hr = SafeArrayGetUBound( sa, 1, &bound );
580     if (FAILED( hr ))
581     {
582         SafeArrayDestroy( sa );
583         return hr;
584     }
585     if (!(object->members = heap_alloc( sizeof(struct member) * (bound + 1) )))
586     {
587         SafeArrayDestroy( sa );
588         return E_OUTOFMEMORY;
589     }
590     for (i = 0; i <= bound; i++)
591     {
592         hr = SafeArrayGetElement( sa, &i, &object->members[i].name );
593         if (FAILED( hr ))
594         {
595             for (i--; i >= 0; i--) SysFreeString( object->members[i].name );
596             SafeArrayDestroy( sa );
597             heap_free( object->members );
598             object->members = NULL;
599             return E_OUTOFMEMORY;
600         }
601         object->members[i].dispid = 0;
602     }
603     object->nb_members = bound + 1;
604     SafeArrayDestroy( sa );
605     return S_OK;
606 }
607 
608 static DISPID get_member_dispid( struct object *object, const WCHAR *name )
609 {
610     UINT i;
611     for (i = 0; i < object->nb_members; i++)
612     {
613         if (!strcmpiW( object->members[i].name, name ))
614         {
615             if (!object->members[i].dispid) object->members[i].dispid = ++object->last_dispid;
616             return object->members[i].dispid;
617         }
618     }
619     return DISPID_UNKNOWN;
620 }
621 
622 static HRESULT WINAPI object_GetIDsOfNames(
623     ISWbemObject *iface,
624     REFIID riid,
625     LPOLESTR *names,
626     UINT count,
627     LCID lcid,
628     DISPID *dispid )
629 {
630     struct object *object = impl_from_ISWbemObject( iface );
631     HRESULT hr;
632     UINT i;
633     ITypeInfo *typeinfo;
634 
635     TRACE( "%p, %s, %p, %u, %u, %p\n", object, debugstr_guid(riid), names, count, lcid, dispid );
636 
637     if (!names || !count || !dispid) return E_INVALIDARG;
638 
639     hr = init_members( object );
640     if (FAILED( hr )) return hr;
641 
642     hr = get_typeinfo( ISWbemObject_tid, &typeinfo );
643     if (SUCCEEDED(hr))
644     {
645         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
646         ITypeInfo_Release( typeinfo );
647     }
648     if (SUCCEEDED(hr)) return hr;
649 
650     for (i = 0; i < count; i++)
651     {
652         if ((dispid[i] = get_member_dispid( object, names[i] )) == DISPID_UNKNOWN) break;
653     }
654     if (i != count) return DISP_E_UNKNOWNNAME;
655     return S_OK;
656 }
657 
658 static BSTR get_member_name( struct object *object, DISPID dispid )
659 {
660     UINT i;
661     for (i = 0; i < object->nb_members; i++)
662     {
663         if (object->members[i].dispid == dispid) return object->members[i].name;
664     }
665     return NULL;
666 }
667 
668 static HRESULT WINAPI object_Invoke(
669     ISWbemObject *iface,
670     DISPID member,
671     REFIID riid,
672     LCID lcid,
673     WORD flags,
674     DISPPARAMS *params,
675     VARIANT *result,
676     EXCEPINFO *excep_info,
677     UINT *arg_err )
678 {
679     struct object *object = impl_from_ISWbemObject( iface );
680     BSTR name;
681     ITypeInfo *typeinfo;
682     HRESULT hr;
683 
684     TRACE( "%p, %x, %s, %u, %x, %p, %p, %p, %p\n", object, member, debugstr_guid(riid),
685            lcid, flags, params, result, excep_info, arg_err );
686 
687     if (member <= DISPID_BASE)
688     {
689         hr = get_typeinfo( ISWbemObject_tid, &typeinfo );
690         if (SUCCEEDED(hr))
691         {
692             hr = ITypeInfo_Invoke( typeinfo, &object->ISWbemObject_iface, member, flags,
693                                    params, result, excep_info, arg_err );
694             ITypeInfo_Release( typeinfo );
695         }
696         return hr;
697     }
698 
699     if (flags != (DISPATCH_METHOD|DISPATCH_PROPERTYGET))
700     {
701         FIXME( "flags %x not supported\n", flags );
702         return E_NOTIMPL;
703     }
704     if (!(name = get_member_name( object, member )))
705         return DISP_E_MEMBERNOTFOUND;
706 
707     memset( params, 0, sizeof(*params) );
708     return IWbemClassObject_Get( object->object, name, 0, result, NULL, NULL );
709 }
710 
711 static HRESULT WINAPI object_Put_(
712     ISWbemObject *iface,
713     LONG iFlags,
714     IDispatch *objWbemNamedValueSet,
715     ISWbemObjectPath **objWbemObjectPath )
716 {
717     FIXME( "\n" );
718     return E_NOTIMPL;
719 }
720 
721 static HRESULT WINAPI object_PutAsync_(
722     ISWbemObject *iface,
723     IDispatch *objWbemSink,
724     LONG iFlags,
725     IDispatch *objWbemNamedValueSet,
726     IDispatch *objWbemAsyncContext )
727 {
728     FIXME( "\n" );
729     return E_NOTIMPL;
730 }
731 
732 static HRESULT WINAPI object_Delete_(
733     ISWbemObject *iface,
734     LONG iFlags,
735     IDispatch *objWbemNamedValueSet )
736 {
737     FIXME( "\n" );
738     return E_NOTIMPL;
739 }
740 
741 static HRESULT WINAPI object_DeleteAsync_(
742     ISWbemObject *iface,
743     IDispatch *objWbemSink,
744     LONG iFlags,
745     IDispatch *objWbemNamedValueSet,
746     IDispatch *objWbemAsyncContext )
747 {
748     FIXME( "\n" );
749     return E_NOTIMPL;
750 }
751 
752 static HRESULT WINAPI object_Instances_(
753     ISWbemObject *iface,
754     LONG iFlags,
755     IDispatch *objWbemNamedValueSet,
756     ISWbemObjectSet **objWbemObjectSet )
757 {
758     FIXME( "\n" );
759     return E_NOTIMPL;
760 }
761 
762 static HRESULT WINAPI object_InstancesAsync_(
763     ISWbemObject *iface,
764     IDispatch *objWbemSink,
765     LONG iFlags,
766     IDispatch *objWbemNamedValueSet,
767     IDispatch *objWbemAsyncContext )
768 {
769     FIXME( "\n" );
770     return E_NOTIMPL;
771 }
772 
773 static HRESULT WINAPI object_Subclasses_(
774     ISWbemObject *iface,
775     LONG iFlags,
776     IDispatch *objWbemNamedValueSet,
777     ISWbemObjectSet **objWbemObjectSet )
778 {
779     FIXME( "\n" );
780     return E_NOTIMPL;
781 }
782 
783 static HRESULT WINAPI object_SubclassesAsync_(
784     ISWbemObject *iface,
785     IDispatch *objWbemSink,
786     LONG iFlags,
787     IDispatch *objWbemNamedValueSet,
788     IDispatch *objWbemAsyncContext )
789 {
790     FIXME( "\n" );
791     return E_NOTIMPL;
792 }
793 
794 static HRESULT WINAPI object_Associators_(
795     ISWbemObject *iface,
796     BSTR strAssocClass,
797     BSTR strResultClass,
798     BSTR strResultRole,
799     BSTR strRole,
800     VARIANT_BOOL bClassesOnly,
801     VARIANT_BOOL bSchemaOnly,
802     BSTR strRequiredAssocQualifier,
803     BSTR strRequiredQualifier,
804     LONG iFlags,
805     IDispatch *objWbemNamedValueSet,
806     ISWbemObjectSet **objWbemObjectSet )
807 {
808     FIXME( "\n" );
809     return E_NOTIMPL;
810 }
811 
812 static HRESULT WINAPI object_AssociatorsAsync_(
813     ISWbemObject *iface,
814     IDispatch *objWbemSink,
815     BSTR strAssocClass,
816     BSTR strResultClass,
817     BSTR strResultRole,
818     BSTR strRole,
819     VARIANT_BOOL bClassesOnly,
820     VARIANT_BOOL bSchemaOnly,
821     BSTR strRequiredAssocQualifier,
822     BSTR strRequiredQualifier,
823     LONG iFlags,
824     IDispatch *objWbemNamedValueSet,
825     IDispatch *objWbemAsyncContext )
826 {
827     FIXME( "\n" );
828     return E_NOTIMPL;
829 }
830 
831 static HRESULT WINAPI object_References_(
832     ISWbemObject *iface,
833     BSTR strResultClass,
834     BSTR strRole,
835     VARIANT_BOOL bClassesOnly,
836     VARIANT_BOOL bSchemaOnly,
837     BSTR strRequiredQualifier,
838     LONG iFlags,
839     IDispatch *objWbemNamedValueSet,
840     ISWbemObjectSet **objWbemObjectSet )
841 {
842     FIXME( "\n" );
843     return E_NOTIMPL;
844 }
845 
846 static HRESULT WINAPI object_ReferencesAsync_(
847     ISWbemObject *iface,
848     IDispatch *objWbemSink,
849     BSTR strResultClass,
850     BSTR strRole,
851     VARIANT_BOOL bClassesOnly,
852     VARIANT_BOOL bSchemaOnly,
853     BSTR strRequiredQualifier,
854     LONG iFlags,
855     IDispatch *objWbemNamedValueSet,
856     IDispatch *objWbemAsyncContext )
857 {
858     FIXME( "\n" );
859     return E_NOTIMPL;
860 }
861 
862 static HRESULT WINAPI object_ExecMethod_(
863     ISWbemObject *iface,
864     BSTR strMethodName,
865     IDispatch *objWbemInParameters,
866     LONG iFlags,
867     IDispatch *objWbemNamedValueSet,
868     ISWbemObject **objWbemOutParameters )
869 {
870     FIXME( "\n" );
871     return E_NOTIMPL;
872 }
873 
874 static HRESULT WINAPI object_ExecMethodAsync_(
875     ISWbemObject *iface,
876     IDispatch *objWbemSink,
877     BSTR strMethodName,
878     IDispatch *objWbemInParameters,
879     LONG iFlags,
880     IDispatch *objWbemNamedValueSet,
881     IDispatch *objWbemAsyncContext )
882 {
883     FIXME( "\n" );
884     return E_NOTIMPL;
885 }
886 
887 static HRESULT WINAPI object_Clone_(
888     ISWbemObject *iface,
889     ISWbemObject **objWbemObject )
890 {
891     FIXME( "\n" );
892     return E_NOTIMPL;
893 }
894 
895 static HRESULT WINAPI object_GetObjectText_(
896     ISWbemObject *iface,
897     LONG iFlags,
898     BSTR *strObjectText )
899 {
900     FIXME( "\n" );
901     return E_NOTIMPL;
902 }
903 
904 static HRESULT WINAPI object_SpawnDerivedClass_(
905     ISWbemObject *iface,
906     LONG iFlags,
907     ISWbemObject **objWbemObject )
908 {
909     FIXME( "\n" );
910     return E_NOTIMPL;
911 }
912 
913 static HRESULT WINAPI object_SpawnInstance_(
914     ISWbemObject *iface,
915     LONG iFlags,
916     ISWbemObject **objWbemObject )
917 {
918     FIXME( "\n" );
919     return E_NOTIMPL;
920 }
921 
922 static HRESULT WINAPI object_CompareTo_(
923     ISWbemObject *iface,
924     IDispatch *objWbemObject,
925     LONG iFlags,
926     VARIANT_BOOL *bResult )
927 {
928     FIXME( "\n" );
929     return E_NOTIMPL;
930 }
931 
932 static HRESULT WINAPI object_get_Qualifiers_(
933     ISWbemObject *iface,
934     ISWbemQualifierSet **objWbemQualifierSet )
935 {
936     FIXME( "\n" );
937     return E_NOTIMPL;
938 }
939 
940 static HRESULT WINAPI object_get_Properties_( ISWbemObject *iface, ISWbemPropertySet **prop_set )
941 {
942     struct object *object = impl_from_ISWbemObject( iface );
943 
944     TRACE( "%p, %p\n", object, prop_set );
945     return SWbemPropertySet_create( object->object, prop_set );
946 }
947 
948 static HRESULT WINAPI object_get_Methods_(
949     ISWbemObject *iface,
950     ISWbemMethodSet **objWbemMethodSet )
951 {
952     FIXME( "\n" );
953     return E_NOTIMPL;
954 }
955 
956 static HRESULT WINAPI object_get_Derivation_(
957     ISWbemObject *iface,
958     VARIANT *strClassNameArray )
959 {
960     FIXME( "\n" );
961     return E_NOTIMPL;
962 }
963 
964 static HRESULT WINAPI object_get_Path_(
965     ISWbemObject *iface,
966     ISWbemObjectPath **objWbemObjectPath )
967 {
968     FIXME( "\n" );
969     return E_NOTIMPL;
970 }
971 
972 static HRESULT WINAPI object_get_Security_(
973     ISWbemObject *iface,
974     ISWbemSecurity **objWbemSecurity )
975 {
976     FIXME( "\n" );
977     return E_NOTIMPL;
978 }
979 
980 static const ISWbemObjectVtbl object_vtbl =
981 {
982     object_QueryInterface,
983     object_AddRef,
984     object_Release,
985     object_GetTypeInfoCount,
986     object_GetTypeInfo,
987     object_GetIDsOfNames,
988     object_Invoke,
989     object_Put_,
990     object_PutAsync_,
991     object_Delete_,
992     object_DeleteAsync_,
993     object_Instances_,
994     object_InstancesAsync_,
995     object_Subclasses_,
996     object_SubclassesAsync_,
997     object_Associators_,
998     object_AssociatorsAsync_,
999     object_References_,
1000     object_ReferencesAsync_,
1001     object_ExecMethod_,
1002     object_ExecMethodAsync_,
1003     object_Clone_,
1004     object_GetObjectText_,
1005     object_SpawnDerivedClass_,
1006     object_SpawnInstance_,
1007     object_CompareTo_,
1008     object_get_Qualifiers_,
1009     object_get_Properties_,
1010     object_get_Methods_,
1011     object_get_Derivation_,
1012     object_get_Path_,
1013     object_get_Security_
1014 };
1015 
1016 static HRESULT SWbemObject_create( IWbemClassObject *wbem_object, ISWbemObject **obj )
1017 {
1018     struct object *object;
1019 
1020     TRACE( "%p, %p\n", obj, wbem_object );
1021 
1022     if (!(object = heap_alloc( sizeof(*object) ))) return E_OUTOFMEMORY;
1023     object->ISWbemObject_iface.lpVtbl = &object_vtbl;
1024     object->refs = 1;
1025     object->object = wbem_object;
1026     IWbemClassObject_AddRef( object->object );
1027     object->members = NULL;
1028     object->nb_members = 0;
1029     object->last_dispid = DISPID_BASE;
1030 
1031     *obj = &object->ISWbemObject_iface;
1032     TRACE( "returning iface %p\n", *obj );
1033     return S_OK;
1034 }
1035 
1036 struct objectset
1037 {
1038     ISWbemObjectSet ISWbemObjectSet_iface;
1039     LONG refs;
1040     IEnumWbemClassObject *objectenum;
1041     LONG count;
1042 };
1043 
1044 static inline struct objectset *impl_from_ISWbemObjectSet(
1045     ISWbemObjectSet *iface )
1046 {
1047     return CONTAINING_RECORD( iface, struct objectset, ISWbemObjectSet_iface );
1048 }
1049 
1050 static ULONG WINAPI objectset_AddRef(
1051     ISWbemObjectSet *iface )
1052 {
1053     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1054     return InterlockedIncrement( &objectset->refs );
1055 }
1056 
1057 static ULONG WINAPI objectset_Release(
1058     ISWbemObjectSet *iface )
1059 {
1060     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1061     LONG refs = InterlockedDecrement( &objectset->refs );
1062     if (!refs)
1063     {
1064         TRACE( "destroying %p\n", objectset );
1065         IEnumWbemClassObject_Release( objectset->objectenum );
1066         heap_free( objectset );
1067     }
1068     return refs;
1069 }
1070 
1071 static HRESULT WINAPI objectset_QueryInterface(
1072     ISWbemObjectSet *iface,
1073     REFIID riid,
1074     void **ppvObject )
1075 {
1076     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1077 
1078     TRACE( "%p %s %p\n", objectset, debugstr_guid(riid), ppvObject );
1079 
1080     if (IsEqualGUID( riid, &IID_ISWbemObjectSet ) ||
1081         IsEqualGUID( riid, &IID_IDispatch ) ||
1082         IsEqualGUID( riid, &IID_IUnknown ))
1083     {
1084         *ppvObject = iface;
1085     }
1086     else
1087     {
1088         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1089         return E_NOINTERFACE;
1090     }
1091     ISWbemObjectSet_AddRef( iface );
1092     return S_OK;
1093 }
1094 
1095 static HRESULT WINAPI objectset_GetTypeInfoCount(
1096     ISWbemObjectSet *iface,
1097     UINT *count )
1098 {
1099     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1100     TRACE( "%p, %p\n", objectset, count );
1101     *count = 1;
1102     return S_OK;
1103 }
1104 
1105 static HRESULT WINAPI objectset_GetTypeInfo(
1106     ISWbemObjectSet *iface,
1107     UINT index,
1108     LCID lcid,
1109     ITypeInfo **info )
1110 {
1111     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1112     TRACE( "%p, %u, %u, %p\n", objectset, index, lcid, info );
1113 
1114     return get_typeinfo( ISWbemObjectSet_tid, info );
1115 }
1116 
1117 static HRESULT WINAPI objectset_GetIDsOfNames(
1118     ISWbemObjectSet *iface,
1119     REFIID riid,
1120     LPOLESTR *names,
1121     UINT count,
1122     LCID lcid,
1123     DISPID *dispid )
1124 {
1125     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1126     ITypeInfo *typeinfo;
1127     HRESULT hr;
1128 
1129     TRACE( "%p, %s, %p, %u, %u, %p\n", objectset, debugstr_guid(riid), names, count, lcid, dispid );
1130 
1131     if (!names || !count || !dispid) return E_INVALIDARG;
1132 
1133     hr = get_typeinfo( ISWbemObjectSet_tid, &typeinfo );
1134     if (SUCCEEDED(hr))
1135     {
1136         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
1137         ITypeInfo_Release( typeinfo );
1138     }
1139     return hr;
1140 }
1141 
1142 static HRESULT WINAPI objectset_Invoke(
1143     ISWbemObjectSet *iface,
1144     DISPID member,
1145     REFIID riid,
1146     LCID lcid,
1147     WORD flags,
1148     DISPPARAMS *params,
1149     VARIANT *result,
1150     EXCEPINFO *excep_info,
1151     UINT *arg_err )
1152 {
1153     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1154     ITypeInfo *typeinfo;
1155     HRESULT hr;
1156 
1157     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", objectset, member, debugstr_guid(riid),
1158            lcid, flags, params, result, excep_info, arg_err );
1159 
1160     hr = get_typeinfo( ISWbemObjectSet_tid, &typeinfo );
1161     if (SUCCEEDED(hr))
1162     {
1163         hr = ITypeInfo_Invoke( typeinfo, &objectset->ISWbemObjectSet_iface, member, flags,
1164                                params, result, excep_info, arg_err );
1165         ITypeInfo_Release( typeinfo );
1166     }
1167     return hr;
1168 }
1169 
1170 static HRESULT WINAPI objectset_get__NewEnum(
1171     ISWbemObjectSet *iface,
1172     IUnknown **pUnk )
1173 {
1174     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1175     IEnumWbemClassObject *objectenum;
1176     HRESULT hr;
1177 
1178     TRACE( "%p, %p\n", objectset, pUnk );
1179 
1180     hr = IEnumWbemClassObject_Clone( objectset->objectenum, &objectenum );
1181     if (FAILED( hr )) return hr;
1182 
1183     hr = EnumVARIANT_create( objectenum, (IEnumVARIANT **)pUnk );
1184     IEnumWbemClassObject_Release( objectenum );
1185     return hr;
1186 }
1187 
1188 static HRESULT WINAPI objectset_Item(
1189     ISWbemObjectSet *iface,
1190     BSTR strObjectPath,
1191     LONG iFlags,
1192     ISWbemObject **objWbemObject )
1193 {
1194     FIXME( "\n" );
1195     return E_NOTIMPL;
1196 }
1197 
1198 static HRESULT WINAPI objectset_get_Count(
1199     ISWbemObjectSet *iface,
1200     LONG *iCount )
1201 {
1202     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1203 
1204     TRACE( "%p, %p\n", objectset, iCount );
1205 
1206     *iCount = objectset->count;
1207     return S_OK;
1208 }
1209 
1210 static HRESULT WINAPI objectset_get_Security_(
1211     ISWbemObjectSet *iface,
1212     ISWbemSecurity **objWbemSecurity )
1213 {
1214     FIXME( "\n" );
1215     return E_NOTIMPL;
1216 }
1217 
1218 static HRESULT WINAPI objectset_ItemIndex(
1219     ISWbemObjectSet *iface,
1220     LONG lIndex,
1221     ISWbemObject **objWbemObject )
1222 {
1223     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1224     LONG count;
1225     HRESULT hr;
1226     IEnumVARIANT *enum_var;
1227     VARIANT var;
1228 
1229     TRACE( "%p, %d, %p\n", objectset, lIndex, objWbemObject );
1230 
1231     *objWbemObject = NULL;
1232     hr = ISWbemObjectSet_get_Count( iface, &count );
1233     if (FAILED(hr)) return hr;
1234 
1235     if (lIndex >= count) return WBEM_E_NOT_FOUND;
1236 
1237     hr = ISWbemObjectSet_get__NewEnum( iface, (IUnknown **)&enum_var );
1238     if (FAILED(hr)) return hr;
1239 
1240     IEnumVARIANT_Reset( enum_var );
1241     hr = IEnumVARIANT_Skip( enum_var, lIndex );
1242     if (SUCCEEDED(hr))
1243         hr = IEnumVARIANT_Next( enum_var, 1, &var, NULL );
1244     IEnumVARIANT_Release( enum_var );
1245 
1246     if (SUCCEEDED(hr))
1247     {
1248         if (V_VT( &var ) == VT_DISPATCH)
1249             hr = IDispatch_QueryInterface( V_DISPATCH( &var ), &IID_ISWbemObject, (void **)objWbemObject );
1250         else
1251             hr = WBEM_E_NOT_FOUND;
1252         VariantClear( &var );
1253     }
1254 
1255     return hr;
1256 }
1257 
1258 static const ISWbemObjectSetVtbl objectset_vtbl =
1259 {
1260     objectset_QueryInterface,
1261     objectset_AddRef,
1262     objectset_Release,
1263     objectset_GetTypeInfoCount,
1264     objectset_GetTypeInfo,
1265     objectset_GetIDsOfNames,
1266     objectset_Invoke,
1267     objectset_get__NewEnum,
1268     objectset_Item,
1269     objectset_get_Count,
1270     objectset_get_Security_,
1271     objectset_ItemIndex
1272 };
1273 
1274 static LONG get_object_count( IEnumWbemClassObject *iter )
1275 {
1276     LONG count = 0;
1277     while (IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 ) == S_OK) count++;
1278     IEnumWbemClassObject_Reset( iter );
1279     return count;
1280 }
1281 
1282 static HRESULT SWbemObjectSet_create( IEnumWbemClassObject *wbem_objectenum, ISWbemObjectSet **obj )
1283 {
1284     struct objectset *objectset;
1285 
1286     TRACE( "%p, %p\n", obj, wbem_objectenum );
1287 
1288     if (!(objectset = heap_alloc( sizeof(*objectset) ))) return E_OUTOFMEMORY;
1289     objectset->ISWbemObjectSet_iface.lpVtbl = &objectset_vtbl;
1290     objectset->refs = 1;
1291     objectset->objectenum = wbem_objectenum;
1292     IEnumWbemClassObject_AddRef( objectset->objectenum );
1293     objectset->count = get_object_count( objectset->objectenum );
1294 
1295     *obj = &objectset->ISWbemObjectSet_iface;
1296     TRACE( "returning iface %p\n", *obj );
1297     return S_OK;
1298 }
1299 
1300 struct enumvar
1301 {
1302     IEnumVARIANT IEnumVARIANT_iface;
1303     LONG refs;
1304     IEnumWbemClassObject *objectenum;
1305 };
1306 
1307 static inline struct enumvar *impl_from_IEnumVARIANT(
1308     IEnumVARIANT *iface )
1309 {
1310     return CONTAINING_RECORD( iface, struct enumvar, IEnumVARIANT_iface );
1311 }
1312 
1313 static ULONG WINAPI enumvar_AddRef(
1314     IEnumVARIANT *iface )
1315 {
1316     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1317     return InterlockedIncrement( &enumvar->refs );
1318 }
1319 
1320 static ULONG WINAPI enumvar_Release(
1321     IEnumVARIANT *iface )
1322 {
1323     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1324     LONG refs = InterlockedDecrement( &enumvar->refs );
1325     if (!refs)
1326     {
1327         TRACE( "destroying %p\n", enumvar );
1328         IEnumWbemClassObject_Release( enumvar->objectenum );
1329         heap_free( enumvar );
1330     }
1331     return refs;
1332 }
1333 
1334 static HRESULT WINAPI enumvar_QueryInterface(
1335     IEnumVARIANT *iface,
1336     REFIID riid,
1337     void **ppvObject )
1338 {
1339     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1340 
1341     TRACE( "%p %s %p\n", enumvar, debugstr_guid(riid), ppvObject );
1342 
1343     if (IsEqualGUID( riid, &IID_IEnumVARIANT ) ||
1344         IsEqualGUID( riid, &IID_IUnknown ))
1345     {
1346         *ppvObject = iface;
1347     }
1348     else
1349     {
1350         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1351         return E_NOINTERFACE;
1352     }
1353     IEnumVARIANT_AddRef( iface );
1354     return S_OK;
1355 }
1356 
1357 static HRESULT WINAPI enumvar_Next( IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched )
1358 {
1359     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1360     IWbemClassObject *obj;
1361     ULONG count = 0;
1362 
1363     TRACE( "%p, %u, %p, %p\n", iface, celt, var, fetched );
1364 
1365     if (celt) IEnumWbemClassObject_Next( enumvar->objectenum, WBEM_INFINITE, 1, &obj, &count );
1366     if (count)
1367     {
1368         ISWbemObject *sobj;
1369         HRESULT hr;
1370 
1371         hr = SWbemObject_create( obj, &sobj );
1372         IWbemClassObject_Release( obj );
1373         if (FAILED( hr )) return hr;
1374 
1375         V_VT( var ) = VT_DISPATCH;
1376         V_DISPATCH( var ) = (IDispatch *)sobj;
1377     }
1378     if (fetched) *fetched = count;
1379     return (count < celt) ? S_FALSE : S_OK;
1380 }
1381 
1382 static HRESULT WINAPI enumvar_Skip( IEnumVARIANT *iface, ULONG celt )
1383 {
1384     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1385 
1386     TRACE( "%p, %u\n", iface, celt );
1387 
1388     return IEnumWbemClassObject_Skip( enumvar->objectenum, WBEM_INFINITE, celt );
1389 }
1390 
1391 static HRESULT WINAPI enumvar_Reset( IEnumVARIANT *iface )
1392 {
1393     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1394 
1395     TRACE( "%p\n", iface );
1396 
1397     return IEnumWbemClassObject_Reset( enumvar->objectenum );
1398 }
1399 
1400 static HRESULT WINAPI enumvar_Clone( IEnumVARIANT *iface, IEnumVARIANT **penum )
1401 {
1402     FIXME( "%p, %p\n", iface, penum );
1403     return E_NOTIMPL;
1404 }
1405 
1406 static const struct IEnumVARIANTVtbl enumvar_vtbl =
1407 {
1408     enumvar_QueryInterface,
1409     enumvar_AddRef,
1410     enumvar_Release,
1411     enumvar_Next,
1412     enumvar_Skip,
1413     enumvar_Reset,
1414     enumvar_Clone
1415 };
1416 
1417 static HRESULT EnumVARIANT_create( IEnumWbemClassObject *objectenum, IEnumVARIANT **obj )
1418 {
1419     struct enumvar *enumvar;
1420 
1421     if (!(enumvar = heap_alloc( sizeof(*enumvar) ))) return E_OUTOFMEMORY;
1422     enumvar->IEnumVARIANT_iface.lpVtbl = &enumvar_vtbl;
1423     enumvar->refs = 1;
1424     enumvar->objectenum = objectenum;
1425     IEnumWbemClassObject_AddRef( enumvar->objectenum );
1426 
1427     *obj = &enumvar->IEnumVARIANT_iface;
1428     TRACE( "returning iface %p\n", *obj );
1429     return S_OK;
1430 }
1431 
1432 struct services
1433 {
1434     ISWbemServices ISWbemServices_iface;
1435     LONG refs;
1436     IWbemServices *services;
1437 };
1438 
1439 static inline struct services *impl_from_ISWbemServices(
1440     ISWbemServices *iface )
1441 {
1442     return CONTAINING_RECORD( iface, struct services, ISWbemServices_iface );
1443 }
1444 
1445 static ULONG WINAPI services_AddRef(
1446     ISWbemServices *iface )
1447 {
1448     struct services *services = impl_from_ISWbemServices( iface );
1449     return InterlockedIncrement( &services->refs );
1450 }
1451 
1452 static ULONG WINAPI services_Release(
1453     ISWbemServices *iface )
1454 {
1455     struct services *services = impl_from_ISWbemServices( iface );
1456     LONG refs = InterlockedDecrement( &services->refs );
1457     if (!refs)
1458     {
1459         TRACE( "destroying %p\n", services );
1460         IWbemServices_Release( services->services );
1461         heap_free( services );
1462     }
1463     return refs;
1464 }
1465 
1466 static HRESULT WINAPI services_QueryInterface(
1467     ISWbemServices *iface,
1468     REFIID riid,
1469     void **ppvObject )
1470 {
1471     struct services *services = impl_from_ISWbemServices( iface );
1472 
1473     TRACE( "%p %s %p\n", services, debugstr_guid(riid), ppvObject );
1474 
1475     if (IsEqualGUID( riid, &IID_ISWbemServices ) ||
1476         IsEqualGUID( riid, &IID_IDispatch ) ||
1477         IsEqualGUID( riid, &IID_IUnknown ))
1478     {
1479         *ppvObject = iface;
1480     }
1481     else
1482     {
1483         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1484         return E_NOINTERFACE;
1485     }
1486     ISWbemServices_AddRef( iface );
1487     return S_OK;
1488 }
1489 
1490 static HRESULT WINAPI services_GetTypeInfoCount(
1491     ISWbemServices *iface,
1492     UINT *count )
1493 {
1494     struct services *services = impl_from_ISWbemServices( iface );
1495     TRACE( "%p, %p\n", services, count );
1496 
1497     *count = 1;
1498     return S_OK;
1499 }
1500 
1501 static HRESULT WINAPI services_GetTypeInfo(
1502     ISWbemServices *iface,
1503     UINT index,
1504     LCID lcid,
1505     ITypeInfo **info )
1506 {
1507     struct services *services = impl_from_ISWbemServices( iface );
1508     TRACE( "%p, %u, %u, %p\n", services, index, lcid, info );
1509 
1510     return get_typeinfo( ISWbemServices_tid, info );
1511 }
1512 
1513 static HRESULT WINAPI services_GetIDsOfNames(
1514     ISWbemServices *iface,
1515     REFIID riid,
1516     LPOLESTR *names,
1517     UINT count,
1518     LCID lcid,
1519     DISPID *dispid )
1520 {
1521     struct services *services = impl_from_ISWbemServices( iface );
1522     ITypeInfo *typeinfo;
1523     HRESULT hr;
1524 
1525     TRACE( "%p, %s, %p, %u, %u, %p\n", services, debugstr_guid(riid), names, count, lcid, dispid );
1526 
1527     if (!names || !count || !dispid) return E_INVALIDARG;
1528 
1529     hr = get_typeinfo( ISWbemServices_tid, &typeinfo );
1530     if (SUCCEEDED(hr))
1531     {
1532         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
1533         ITypeInfo_Release( typeinfo );
1534     }
1535     return hr;
1536 }
1537 
1538 static HRESULT WINAPI services_Invoke(
1539     ISWbemServices *iface,
1540     DISPID member,
1541     REFIID riid,
1542     LCID lcid,
1543     WORD flags,
1544     DISPPARAMS *params,
1545     VARIANT *result,
1546     EXCEPINFO *excep_info,
1547     UINT *arg_err )
1548 {
1549     struct services *services = impl_from_ISWbemServices( iface );
1550     ITypeInfo *typeinfo;
1551     HRESULT hr;
1552 
1553     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", services, member, debugstr_guid(riid),
1554            lcid, flags, params, result, excep_info, arg_err );
1555 
1556     hr = get_typeinfo( ISWbemServices_tid, &typeinfo );
1557     if (SUCCEEDED(hr))
1558     {
1559         hr = ITypeInfo_Invoke( typeinfo, &services->ISWbemServices_iface, member, flags,
1560                                params, result, excep_info, arg_err );
1561         ITypeInfo_Release( typeinfo );
1562     }
1563     return hr;
1564 }
1565 
1566 static HRESULT WINAPI services_Get(
1567     ISWbemServices *iface,
1568     BSTR strObjectPath,
1569     LONG iFlags,
1570     IDispatch *objWbemNamedValueSet,
1571     ISWbemObject **objWbemObject )
1572 {
1573     struct services *services = impl_from_ISWbemServices( iface );
1574     IWbemClassObject *obj;
1575     HRESULT hr;
1576 
1577     TRACE( "%p, %s, %d, %p, %p\n", iface, debugstr_w(strObjectPath), iFlags, objWbemNamedValueSet,
1578            objWbemObject );
1579 
1580     if (objWbemNamedValueSet) FIXME( "ignoring context\n" );
1581 
1582     hr = IWbemServices_GetObject( services->services, strObjectPath, iFlags, NULL, &obj, NULL );
1583     if (hr != S_OK) return hr;
1584 
1585     hr = SWbemObject_create( obj, objWbemObject );
1586     IWbemClassObject_Release( obj );
1587     return hr;
1588 }
1589 
1590 static HRESULT WINAPI services_GetAsync(
1591     ISWbemServices *iface,
1592     IDispatch *objWbemSink,
1593     BSTR strObjectPath,
1594     LONG iFlags,
1595     IDispatch *objWbemNamedValueSet,
1596     IDispatch *objWbemAsyncContext )
1597 {
1598     FIXME( "\n" );
1599     return E_NOTIMPL;
1600 }
1601 
1602 static HRESULT WINAPI services_Delete(
1603     ISWbemServices *iface,
1604     BSTR strObjectPath,
1605     LONG iFlags,
1606     IDispatch *objWbemNamedValueSet )
1607 {
1608     FIXME( "\n" );
1609     return E_NOTIMPL;
1610 }
1611 
1612 static HRESULT WINAPI services_DeleteAsync(
1613     ISWbemServices* This,
1614     IDispatch *objWbemSink,
1615     BSTR strObjectPath,
1616     LONG iFlags,
1617     IDispatch *objWbemNamedValueSet,
1618     IDispatch *objWbemAsyncContext )
1619 {
1620     FIXME( "\n" );
1621     return E_NOTIMPL;
1622 }
1623 
1624 static BSTR build_query_string( const WCHAR *class )
1625 {
1626     static const WCHAR selectW[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
1627     UINT len = strlenW(class) + sizeof(selectW) / sizeof(selectW[0]);
1628     BSTR ret;
1629 
1630     if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
1631     strcpyW( ret, selectW );
1632     strcatW( ret, class );
1633     return ret;
1634 }
1635 
1636 static HRESULT WINAPI services_InstancesOf(
1637     ISWbemServices *iface,
1638     BSTR strClass,
1639     LONG iFlags,
1640     IDispatch *objWbemNamedValueSet,
1641     ISWbemObjectSet **objWbemObjectSet )
1642 {
1643     static const WCHAR wqlW[] = {'W','Q','L',0};
1644     BSTR query, wql = SysAllocString( wqlW );
1645     HRESULT hr;
1646 
1647     TRACE( "%p, %s, %x, %p, %p\n", iface, debugstr_w(strClass), iFlags, objWbemNamedValueSet,
1648            objWbemObjectSet );
1649 
1650     if (!(query = build_query_string( strClass )))
1651     {
1652         SysFreeString( wql );
1653         return E_OUTOFMEMORY;
1654     }
1655     hr = ISWbemServices_ExecQuery( iface, query, wql, iFlags, objWbemNamedValueSet, objWbemObjectSet );
1656     SysFreeString( wql );
1657     SysFreeString( query );
1658     return hr;
1659 }
1660 
1661 static HRESULT WINAPI services_InstancesOfAsync(
1662     ISWbemServices *iface,
1663     IDispatch *objWbemSink,
1664     BSTR strClass,
1665     LONG iFlags,
1666     IDispatch *objWbemNamedValueSet,
1667     IDispatch *objWbemAsyncContext )
1668 {
1669     FIXME( "\n" );
1670     return E_NOTIMPL;
1671 }
1672 
1673 static HRESULT WINAPI services_SubclassesOf(
1674     ISWbemServices *iface,
1675     BSTR strSuperclass,
1676     LONG iFlags,
1677     IDispatch *objWbemNamedValueSet,
1678     ISWbemObjectSet **objWbemObjectSet )
1679 {
1680     FIXME( "\n" );
1681     return E_NOTIMPL;
1682 }
1683 
1684 static HRESULT WINAPI services_SubclassesOfAsync(
1685     ISWbemServices *iface,
1686     IDispatch *objWbemSink,
1687     BSTR strSuperclass,
1688     LONG iFlags,
1689     IDispatch *objWbemNamedValueSet,
1690     IDispatch *objWbemAsyncContext )
1691 {
1692     FIXME( "\n" );
1693     return E_NOTIMPL;
1694 }
1695 
1696 static HRESULT WINAPI services_ExecQuery(
1697     ISWbemServices *iface,
1698     BSTR strQuery,
1699     BSTR strQueryLanguage,
1700     LONG iFlags,
1701     IDispatch *objWbemNamedValueSet,
1702     ISWbemObjectSet **objWbemObjectSet )
1703 {
1704     struct services *services = impl_from_ISWbemServices( iface );
1705     IEnumWbemClassObject *iter;
1706     HRESULT hr;
1707 
1708     TRACE( "%p, %s, %s, %x, %p, %p\n", iface, debugstr_w(strQuery), debugstr_w(strQueryLanguage),
1709            iFlags, objWbemNamedValueSet, objWbemObjectSet );
1710 
1711     if (objWbemNamedValueSet) FIXME( "ignoring context\n" );
1712 
1713     hr = IWbemServices_ExecQuery( services->services, strQueryLanguage, strQuery, iFlags, NULL, &iter );
1714     if (hr != S_OK) return hr;
1715 
1716     hr = SWbemObjectSet_create( iter, objWbemObjectSet );
1717     IEnumWbemClassObject_Release( iter );
1718     return hr;
1719 }
1720 
1721 static HRESULT WINAPI services_ExecQueryAsync(
1722     ISWbemServices *iface,
1723     IDispatch *objWbemSink,
1724     BSTR strQuery,
1725     BSTR strQueryLanguage,
1726     LONG lFlags,
1727     IDispatch *objWbemNamedValueSet,
1728     IDispatch *objWbemAsyncContext )
1729 {
1730     FIXME( "\n" );
1731     return E_NOTIMPL;
1732 }
1733 
1734 static HRESULT WINAPI services_AssociatorsOf(
1735     ISWbemServices *iface,
1736     BSTR strObjectPath,
1737     BSTR strAssocClass,
1738     BSTR strResultClass,
1739     BSTR strResultRole,
1740     BSTR strRole,
1741     VARIANT_BOOL bClassesOnly,
1742     VARIANT_BOOL bSchemaOnly,
1743     BSTR strRequiredAssocQualifier,
1744     BSTR strRequiredQualifier,
1745     LONG iFlags,
1746     IDispatch *objWbemNamedValueSet,
1747     ISWbemObjectSet **objWbemObjectSet )
1748 {
1749     FIXME( "\n" );
1750     return E_NOTIMPL;
1751 }
1752 
1753 static HRESULT WINAPI services_AssociatorsOfAsync(
1754     ISWbemServices *iface,
1755     IDispatch *objWbemSink,
1756     BSTR strObjectPath,
1757     BSTR strAssocClass,
1758     BSTR strResultClass,
1759     BSTR strResultRole,
1760     BSTR strRole,
1761     VARIANT_BOOL bClassesOnly,
1762     VARIANT_BOOL bSchemaOnly,
1763     BSTR strRequiredAssocQualifier,
1764     BSTR strRequiredQualifier,
1765     LONG iFlags,
1766     IDispatch *objWbemNamedValueSet,
1767     IDispatch *objWbemAsyncContext )
1768 {
1769     FIXME( "\n" );
1770     return E_NOTIMPL;
1771 }
1772 
1773 static HRESULT WINAPI services_ReferencesTo(
1774     ISWbemServices *iface,
1775     BSTR strObjectPath,
1776     BSTR strResultClass,
1777     BSTR strRole,
1778     VARIANT_BOOL bClassesOnly,
1779     VARIANT_BOOL bSchemaOnly,
1780     BSTR strRequiredQualifier,
1781     LONG iFlags,
1782     IDispatch *objWbemNamedValueSet,
1783     ISWbemObjectSet **objWbemObjectSet )
1784 {
1785     FIXME( "\n" );
1786     return E_NOTIMPL;
1787 }
1788 
1789 static HRESULT WINAPI services_ReferencesToAsync(
1790     ISWbemServices *iface,
1791     IDispatch *objWbemSink,
1792     BSTR strObjectPath,
1793     BSTR strResultClass,
1794     BSTR strRole,
1795     VARIANT_BOOL bClassesOnly,
1796     VARIANT_BOOL bSchemaOnly,
1797     BSTR strRequiredQualifier,
1798     LONG iFlags,
1799     IDispatch *objWbemNamedValueSet,
1800     IDispatch *objWbemAsyncContext )
1801 {
1802     FIXME( "\n" );
1803     return E_NOTIMPL;
1804 }
1805 
1806 static HRESULT WINAPI services_ExecNotificationQuery(
1807     ISWbemServices *iface,
1808     BSTR strQuery,
1809     BSTR strQueryLanguage,
1810     LONG iFlags,
1811     IDispatch *objWbemNamedValueSet,
1812     ISWbemEventSource **objWbemEventSource )
1813 {
1814     FIXME( "\n" );
1815     return E_NOTIMPL;
1816 }
1817 
1818 static HRESULT WINAPI services_ExecNotificationQueryAsync(
1819     ISWbemServices *iface,
1820     IDispatch *objWbemSink,
1821     BSTR strQuery,
1822     BSTR strQueryLanguage,
1823     LONG iFlags,
1824     IDispatch *objWbemNamedValueSet,
1825     IDispatch *objWbemAsyncContext )
1826 {
1827     FIXME( "\n" );
1828     return E_NOTIMPL;
1829 }
1830 
1831 static HRESULT WINAPI services_ExecMethod(
1832     ISWbemServices *iface,
1833     BSTR strObjectPath,
1834     BSTR strMethodName,
1835     IDispatch *objWbemInParameters,
1836     LONG iFlags,
1837     IDispatch *objWbemNamedValueSet,
1838     ISWbemObject **objWbemOutParameters )
1839 {
1840     FIXME( "\n" );
1841     return E_NOTIMPL;
1842 }
1843 
1844 static HRESULT WINAPI services_ExecMethodAsync(
1845     ISWbemServices *iface,
1846     IDispatch *objWbemSink,
1847     BSTR strObjectPath,
1848     BSTR strMethodName,
1849     IDispatch *objWbemInParameters,
1850     LONG iFlags,
1851     IDispatch *objWbemNamedValueSet,
1852     IDispatch *objWbemAsyncContext )
1853 {
1854     FIXME( "\n" );
1855     return E_NOTIMPL;
1856 }
1857 
1858 static HRESULT WINAPI services_get_Security_(
1859         ISWbemServices *iface,
1860         ISWbemSecurity **objWbemSecurity )
1861 {
1862     TRACE( "%p, %p\n", iface, objWbemSecurity );
1863 
1864     if (!objWbemSecurity)
1865         return E_INVALIDARG;
1866 
1867     return ISWbemSecurity_create( objWbemSecurity );
1868 }
1869 
1870 static const ISWbemServicesVtbl services_vtbl =
1871 {
1872     services_QueryInterface,
1873     services_AddRef,
1874     services_Release,
1875     services_GetTypeInfoCount,
1876     services_GetTypeInfo,
1877     services_GetIDsOfNames,
1878     services_Invoke,
1879     services_Get,
1880     services_GetAsync,
1881     services_Delete,
1882     services_DeleteAsync,
1883     services_InstancesOf,
1884     services_InstancesOfAsync,
1885     services_SubclassesOf,
1886     services_SubclassesOfAsync,
1887     services_ExecQuery,
1888     services_ExecQueryAsync,
1889     services_AssociatorsOf,
1890     services_AssociatorsOfAsync,
1891     services_ReferencesTo,
1892     services_ReferencesToAsync,
1893     services_ExecNotificationQuery,
1894     services_ExecNotificationQueryAsync,
1895     services_ExecMethod,
1896     services_ExecMethodAsync,
1897     services_get_Security_
1898 };
1899 
1900 static HRESULT SWbemServices_create( IWbemServices *wbem_services, ISWbemServices **obj )
1901 {
1902     struct services *services;
1903 
1904     TRACE( "%p, %p\n", obj, wbem_services );
1905 
1906     if (!(services = heap_alloc( sizeof(*services) ))) return E_OUTOFMEMORY;
1907     services->ISWbemServices_iface.lpVtbl = &services_vtbl;
1908     services->refs = 1;
1909     services->services = wbem_services;
1910     IWbemServices_AddRef( services->services );
1911 
1912     *obj = &services->ISWbemServices_iface;
1913     TRACE( "returning iface %p\n", *obj );
1914     return S_OK;
1915 }
1916 
1917 struct locator
1918 {
1919     ISWbemLocator ISWbemLocator_iface;
1920     LONG refs;
1921     IWbemLocator *locator;
1922 };
1923 
1924 static inline struct locator *impl_from_ISWbemLocator( ISWbemLocator *iface )
1925 {
1926     return CONTAINING_RECORD( iface, struct locator, ISWbemLocator_iface );
1927 }
1928 
1929 static ULONG WINAPI locator_AddRef(
1930     ISWbemLocator *iface )
1931 {
1932     struct locator *locator = impl_from_ISWbemLocator( iface );
1933     return InterlockedIncrement( &locator->refs );
1934 }
1935 
1936 static ULONG WINAPI locator_Release(
1937     ISWbemLocator *iface )
1938 {
1939     struct locator *locator = impl_from_ISWbemLocator( iface );
1940     LONG refs = InterlockedDecrement( &locator->refs );
1941     if (!refs)
1942     {
1943         TRACE( "destroying %p\n", locator );
1944         if (locator->locator)
1945             IWbemLocator_Release( locator->locator );
1946         heap_free( locator );
1947     }
1948     return refs;
1949 }
1950 
1951 static HRESULT WINAPI locator_QueryInterface(
1952     ISWbemLocator *iface,
1953     REFIID riid,
1954     void **ppvObject )
1955 {
1956     struct locator *locator = impl_from_ISWbemLocator( iface );
1957 
1958     TRACE( "%p, %s, %p\n", locator, debugstr_guid( riid ), ppvObject );
1959 
1960     if (IsEqualGUID( riid, &IID_ISWbemLocator ) ||
1961         IsEqualGUID( riid, &IID_IDispatch ) ||
1962         IsEqualGUID( riid, &IID_IUnknown ))
1963     {
1964         *ppvObject = iface;
1965     }
1966     else
1967     {
1968         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1969         return E_NOINTERFACE;
1970     }
1971     ISWbemLocator_AddRef( iface );
1972     return S_OK;
1973 }
1974 
1975 static HRESULT WINAPI locator_GetTypeInfoCount(
1976     ISWbemLocator *iface,
1977     UINT *count )
1978 {
1979     struct locator *locator = impl_from_ISWbemLocator( iface );
1980 
1981     TRACE( "%p, %p\n", locator, count );
1982     *count = 1;
1983     return S_OK;
1984 }
1985 
1986 static HRESULT WINAPI locator_GetTypeInfo(
1987     ISWbemLocator *iface,
1988     UINT index,
1989     LCID lcid,
1990     ITypeInfo **info )
1991 {
1992     struct locator *locator = impl_from_ISWbemLocator( iface );
1993     TRACE( "%p, %u, %u, %p\n", locator, index, lcid, info );
1994 
1995     return get_typeinfo( ISWbemLocator_tid, info );
1996 }
1997 
1998 static HRESULT WINAPI locator_GetIDsOfNames(
1999     ISWbemLocator *iface,
2000     REFIID riid,
2001     LPOLESTR *names,
2002     UINT count,
2003     LCID lcid,
2004     DISPID *dispid )
2005 {
2006     struct locator *locator = impl_from_ISWbemLocator( iface );
2007     ITypeInfo *typeinfo;
2008     HRESULT hr;
2009 
2010     TRACE( "%p, %s, %p, %u, %u, %p\n", locator, debugstr_guid(riid), names, count, lcid, dispid );
2011 
2012     if (!names || !count || !dispid) return E_INVALIDARG;
2013 
2014     hr = get_typeinfo( ISWbemLocator_tid, &typeinfo );
2015     if (SUCCEEDED(hr))
2016     {
2017         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
2018         ITypeInfo_Release( typeinfo );
2019     }
2020     return hr;
2021 }
2022 
2023 static HRESULT WINAPI locator_Invoke(
2024     ISWbemLocator *iface,
2025     DISPID member,
2026     REFIID riid,
2027     LCID lcid,
2028     WORD flags,
2029     DISPPARAMS *params,
2030     VARIANT *result,
2031     EXCEPINFO *excep_info,
2032     UINT *arg_err )
2033 {
2034     struct locator *locator = impl_from_ISWbemLocator( iface );
2035     ITypeInfo *typeinfo;
2036     HRESULT hr;
2037 
2038     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", locator, member, debugstr_guid(riid),
2039            lcid, flags, params, result, excep_info, arg_err );
2040 
2041     hr = get_typeinfo( ISWbemLocator_tid, &typeinfo );
2042     if (SUCCEEDED(hr))
2043     {
2044         hr = ITypeInfo_Invoke( typeinfo, &locator->ISWbemLocator_iface, member, flags,
2045                                params, result, excep_info, arg_err );
2046         ITypeInfo_Release( typeinfo );
2047     }
2048     return hr;
2049 }
2050 
2051 static BSTR build_resource_string( BSTR server, BSTR namespace )
2052 {
2053     static const WCHAR defaultW[] = {'r','o','o','t','\\','d','e','f','a','u','l','t',0};
2054     ULONG len, len_server = 0, len_namespace = 0;
2055     BSTR ret;
2056 
2057     if (server && *server) len_server = strlenW( server );
2058     else len_server = 1;
2059     if (namespace && *namespace) len_namespace = strlenW( namespace );
2060     else len_namespace = sizeof(defaultW) / sizeof(defaultW[0]) - 1;
2061 
2062     if (!(ret = SysAllocStringLen( NULL, 2 + len_server + 1 + len_namespace ))) return NULL;
2063 
2064     ret[0] = ret[1] = '\\';
2065     if (server && *server) strcpyW( ret + 2, server );
2066     else ret[2] = '.';
2067 
2068     len = len_server + 2;
2069     ret[len++] = '\\';
2070 
2071     if (namespace && *namespace) strcpyW( ret + len, namespace );
2072     else strcpyW( ret + len, defaultW );
2073     return ret;
2074 }
2075 
2076 static HRESULT WINAPI locator_ConnectServer(
2077     ISWbemLocator *iface,
2078     BSTR strServer,
2079     BSTR strNamespace,
2080     BSTR strUser,
2081     BSTR strPassword,
2082     BSTR strLocale,
2083     BSTR strAuthority,
2084     LONG iSecurityFlags,
2085     IDispatch *objWbemNamedValueSet,
2086     ISWbemServices **objWbemServices )
2087 {
2088     struct locator *locator = impl_from_ISWbemLocator( iface );
2089     IWbemServices *services;
2090     BSTR resource;
2091     HRESULT hr;
2092 
2093     TRACE( "%p, %s, %s, %s, %p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strServer),
2094            debugstr_w(strNamespace), debugstr_w(strUser), strPassword, debugstr_w(strLocale),
2095            debugstr_w(strAuthority), iSecurityFlags, objWbemNamedValueSet, objWbemServices );
2096 
2097     if (objWbemNamedValueSet) FIXME( "context not supported\n" );
2098 
2099     if (!locator->locator)
2100     {
2101         hr = CoCreateInstance( &CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemLocator,
2102                                (void **)&locator->locator );
2103         if (hr != S_OK) return hr;
2104     }
2105 
2106     if (!(resource = build_resource_string( strServer, strNamespace ))) return E_OUTOFMEMORY;
2107     hr = IWbemLocator_ConnectServer( locator->locator, resource, strUser, strPassword, strLocale,
2108                                      iSecurityFlags, strAuthority, NULL, &services );
2109     SysFreeString( resource );
2110     if (hr != S_OK) return hr;
2111 
2112     hr = SWbemServices_create( services, objWbemServices );
2113     IWbemServices_Release( services );
2114     return hr;
2115 }
2116 
2117 static HRESULT WINAPI locator_get_Security_(
2118     ISWbemLocator *iface,
2119     ISWbemSecurity **objWbemSecurity )
2120 {
2121     TRACE( "%p, %p\n", iface, objWbemSecurity );
2122 
2123     if (!objWbemSecurity)
2124         return E_INVALIDARG;
2125 
2126     return ISWbemSecurity_create( objWbemSecurity );
2127 }
2128 
2129 static const ISWbemLocatorVtbl locator_vtbl =
2130 {
2131     locator_QueryInterface,
2132     locator_AddRef,
2133     locator_Release,
2134     locator_GetTypeInfoCount,
2135     locator_GetTypeInfo,
2136     locator_GetIDsOfNames,
2137     locator_Invoke,
2138     locator_ConnectServer,
2139     locator_get_Security_
2140 };
2141 
2142 HRESULT SWbemLocator_create( void **obj )
2143 {
2144     struct locator *locator;
2145 
2146     TRACE( "%p\n", obj );
2147 
2148     if (!(locator = heap_alloc( sizeof(*locator) ))) return E_OUTOFMEMORY;
2149     locator->ISWbemLocator_iface.lpVtbl = &locator_vtbl;
2150     locator->refs = 1;
2151     locator->locator = NULL;
2152 
2153     *obj = &locator->ISWbemLocator_iface;
2154     TRACE( "returning iface %p\n", *obj );
2155     return S_OK;
2156 }
2157 
2158 struct security
2159 {
2160     ISWbemSecurity ISWbemSecurity_iface;
2161     LONG refs;
2162     WbemImpersonationLevelEnum  implevel;
2163     WbemAuthenticationLevelEnum authlevel;
2164 };
2165 
2166 static inline struct security *impl_from_ISWbemSecurity( ISWbemSecurity *iface )
2167 {
2168     return CONTAINING_RECORD( iface, struct security, ISWbemSecurity_iface );
2169 }
2170 
2171 static ULONG WINAPI security_AddRef(
2172     ISWbemSecurity *iface )
2173 {
2174     struct security *security = impl_from_ISWbemSecurity( iface );
2175     return InterlockedIncrement( &security->refs );
2176 }
2177 
2178 static ULONG WINAPI security_Release(
2179     ISWbemSecurity *iface )
2180 {
2181     struct security *security = impl_from_ISWbemSecurity( iface );
2182     LONG refs = InterlockedDecrement( &security->refs );
2183     if (!refs)
2184     {
2185         TRACE( "destroying %p\n", security );
2186         heap_free( security );
2187     }
2188     return refs;
2189 }
2190 
2191 static HRESULT WINAPI security_QueryInterface(
2192     ISWbemSecurity *iface,
2193     REFIID riid,
2194     void **ppvObject )
2195 {
2196     struct security *security = impl_from_ISWbemSecurity( iface );
2197     TRACE( "%p, %s, %p\n", security, debugstr_guid( riid ), ppvObject );
2198 
2199     if (IsEqualGUID( riid, &IID_ISWbemSecurity ) ||
2200         IsEqualGUID( riid, &IID_IDispatch ) ||
2201         IsEqualGUID( riid, &IID_IUnknown ))
2202     {
2203         *ppvObject = iface;
2204     }
2205     else
2206     {
2207         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
2208         return E_NOINTERFACE;
2209     }
2210     ISWbemSecurity_AddRef( iface );
2211     return S_OK;
2212 }
2213 
2214 static HRESULT WINAPI security_GetTypeInfoCount(
2215     ISWbemSecurity *iface,
2216     UINT *count )
2217 {
2218     struct security *security = impl_from_ISWbemSecurity( iface );
2219     TRACE( "%p, %p\n", security, count );
2220 
2221     *count = 1;
2222     return S_OK;
2223 }
2224 
2225 static HRESULT WINAPI security_GetTypeInfo(
2226     ISWbemSecurity *iface,
2227     UINT index,
2228     LCID lcid,
2229     ITypeInfo **info )
2230 {
2231     struct security *security = impl_from_ISWbemSecurity( iface );
2232     TRACE( "%p, %u, %u, %p\n", security, index, lcid, info );
2233 
2234     return get_typeinfo( ISWbemSecurity_tid, info );
2235 }
2236 
2237 static HRESULT WINAPI security_GetIDsOfNames(
2238     ISWbemSecurity *iface,
2239     REFIID riid,
2240     LPOLESTR *names,
2241     UINT count,
2242     LCID lcid,
2243     DISPID *dispid )
2244 {
2245     struct security *security = impl_from_ISWbemSecurity( iface );
2246     ITypeInfo *typeinfo;
2247     HRESULT hr;
2248 
2249     TRACE( "%p, %s, %p, %u, %u, %p\n", security, debugstr_guid(riid), names, count, lcid, dispid );
2250 
2251     if (!names || !count || !dispid) return E_INVALIDARG;
2252 
2253     hr = get_typeinfo( ISWbemSecurity_tid, &typeinfo );
2254     if (SUCCEEDED(hr))
2255     {
2256         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
2257         ITypeInfo_Release( typeinfo );
2258     }
2259     return hr;
2260 }
2261 
2262 static HRESULT WINAPI security_Invoke(
2263     ISWbemSecurity *iface,
2264     DISPID member,
2265     REFIID riid,
2266     LCID lcid,
2267     WORD flags,
2268     DISPPARAMS *params,
2269     VARIANT *result,
2270     EXCEPINFO *excep_info,
2271     UINT *arg_err )
2272 {
2273     struct security *security = impl_from_ISWbemSecurity( iface );
2274     ITypeInfo *typeinfo;
2275     HRESULT hr;
2276 
2277     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", security, member, debugstr_guid(riid),
2278            lcid, flags, params, result, excep_info, arg_err );
2279 
2280     hr = get_typeinfo( ISWbemSecurity_tid, &typeinfo );
2281     if (SUCCEEDED(hr))
2282     {
2283         hr = ITypeInfo_Invoke( typeinfo, &security->ISWbemSecurity_iface, member, flags,
2284                                params, result, excep_info, arg_err );
2285         ITypeInfo_Release( typeinfo );
2286     }
2287     return hr;
2288 }
2289 
2290 static HRESULT WINAPI security_get_ImpersonationLevel_(
2291     ISWbemSecurity *iface,
2292     WbemImpersonationLevelEnum *impersonation_level )
2293 {
2294     struct security *security = impl_from_ISWbemSecurity( iface );
2295     FIXME( "%p, %p: stub\n", security, impersonation_level );
2296 
2297     if (!impersonation_level)
2298         return E_INVALIDARG;
2299 
2300     *impersonation_level = security->implevel;
2301     return S_OK;
2302 }
2303 
2304 static HRESULT WINAPI security_put_ImpersonationLevel_(
2305     ISWbemSecurity *iface,
2306     WbemImpersonationLevelEnum impersonation_level )
2307 {
2308     struct security *security = impl_from_ISWbemSecurity( iface );
2309     FIXME( "%p, %d: stub\n", security, impersonation_level );
2310 
2311     security->implevel = impersonation_level;
2312     return S_OK;
2313 }
2314 
2315 static HRESULT WINAPI security_get_AuthenticationLevel_(
2316     ISWbemSecurity *iface,
2317     WbemAuthenticationLevelEnum *authentication_level )
2318 {
2319     struct security *security = impl_from_ISWbemSecurity( iface );
2320     FIXME( "%p, %p: stub\n", security, authentication_level );
2321 
2322     if (!authentication_level)
2323         return E_INVALIDARG;
2324 
2325     *authentication_level = security->authlevel;
2326     return S_OK;
2327 }
2328 
2329 static HRESULT WINAPI security_put_AuthenticationLevel_(
2330     ISWbemSecurity *iface,
2331     WbemAuthenticationLevelEnum authentication_level )
2332 {
2333     struct security *security = impl_from_ISWbemSecurity( iface );
2334     FIXME( "%p, %d: stub\n", security, authentication_level );
2335 
2336     security->authlevel = authentication_level;
2337     return S_OK;
2338 }
2339 
2340 static HRESULT WINAPI security_get_Privileges_(
2341     ISWbemSecurity *iface,
2342     ISWbemPrivilegeSet **privilege_set )
2343 {
2344     struct security *security = impl_from_ISWbemSecurity( iface );
2345     FIXME( "%p, %p: stub\n", security, privilege_set );
2346 
2347     if (!privilege_set)
2348         return E_INVALIDARG;
2349 
2350     return E_NOTIMPL;
2351 }
2352 
2353 static const ISWbemSecurityVtbl security_vtbl =
2354 {
2355     security_QueryInterface,
2356     security_AddRef,
2357     security_Release,
2358     security_GetTypeInfoCount,
2359     security_GetTypeInfo,
2360     security_GetIDsOfNames,
2361     security_Invoke,
2362     security_get_ImpersonationLevel_,
2363     security_put_ImpersonationLevel_,
2364     security_get_AuthenticationLevel_,
2365     security_put_AuthenticationLevel_,
2366     security_get_Privileges_
2367 };
2368 
2369 static HRESULT ISWbemSecurity_create( ISWbemSecurity **obj )
2370 {
2371     struct security *security;
2372 
2373     TRACE( "%p\n", obj );
2374 
2375     if (!(security = heap_alloc( sizeof(*security) ))) return E_OUTOFMEMORY;
2376     security->ISWbemSecurity_iface.lpVtbl = &security_vtbl;
2377     security->refs = 1;
2378     security->implevel = wbemImpersonationLevelAnonymous;
2379     security->authlevel = wbemAuthenticationLevelDefault;
2380 
2381     *obj = &security->ISWbemSecurity_iface;
2382     TRACE( "returning iface %p\n", *obj );
2383     return S_OK;
2384 }
2385