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