xref: /reactos/dll/win32/wbemdisp/locator.c (revision 8786e12d)
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     static const WCHAR propcountW[] = {'_','_','P','R','O','P','E','R','T','Y','_','C','O','U','N','T',0};
442     struct propertyset *propertyset = impl_from_ISWbemPropertySet( iface );
443     HRESULT hr;
444     VARIANT val;
445 
446     TRACE( "%p, %p\n", propertyset, count );
447 
448     hr = IWbemClassObject_Get( propertyset->object, propcountW, 0, &val, NULL, NULL );
449     if (SUCCEEDED(hr))
450     {
451         *count = V_I4( &val );
452     }
453     return hr;
454 }
455 
456 static HRESULT WINAPI propertyset_Add( ISWbemPropertySet *iface, BSTR name, WbemCimtypeEnum type,
457                                        VARIANT_BOOL is_array, LONG flags, ISWbemProperty **prop )
458 {
459     FIXME( "\n" );
460     return E_NOTIMPL;
461 }
462 
463 static HRESULT WINAPI propertyset_Remove( ISWbemPropertySet *iface, BSTR name, LONG flags )
464 {
465     FIXME( "\n" );
466     return E_NOTIMPL;
467 }
468 
469 static const ISWbemPropertySetVtbl propertyset_vtbl =
470 {
471     propertyset_QueryInterface,
472     propertyset_AddRef,
473     propertyset_Release,
474     propertyset_GetTypeInfoCount,
475     propertyset_GetTypeInfo,
476     propertyset_GetIDsOfNames,
477     propertyset_Invoke,
478     propertyset_get__NewEnum,
479     propertyset_Item,
480     propertyset_get_Count,
481     propertyset_Add,
482     propertyset_Remove
483 };
484 
485 static HRESULT SWbemPropertySet_create( IWbemClassObject *wbem_object, ISWbemPropertySet **obj )
486 {
487     struct propertyset *propertyset;
488 
489     TRACE( "%p, %p\n", obj, wbem_object );
490 
491     if (!(propertyset = heap_alloc( sizeof(*propertyset) ))) return E_OUTOFMEMORY;
492     propertyset->ISWbemPropertySet_iface.lpVtbl = &propertyset_vtbl;
493     propertyset->refs = 1;
494     propertyset->object = wbem_object;
495     IWbemClassObject_AddRef( propertyset->object );
496     *obj = &propertyset->ISWbemPropertySet_iface;
497 
498     TRACE( "returning iface %p\n", *obj );
499     return S_OK;
500 }
501 
502 #define DISPID_BASE         0x1800000
503 #define DISPID_BASE_METHOD  0x1000000
504 
505 struct member
506 {
507     BSTR name;
508     BOOL is_method;
509     DISPID dispid;
510 };
511 
512 struct object
513 {
514     ISWbemObject ISWbemObject_iface;
515     LONG refs;
516     IWbemClassObject *object;
517     struct member *members;
518     UINT nb_members;
519     DISPID last_dispid;
520     DISPID last_dispid_method;
521 };
522 
523 static inline struct object *impl_from_ISWbemObject(
524     ISWbemObject *iface )
525 {
526     return CONTAINING_RECORD( iface, struct object, ISWbemObject_iface );
527 }
528 
529 static ULONG WINAPI object_AddRef(
530     ISWbemObject *iface )
531 {
532     struct object *object = impl_from_ISWbemObject( iface );
533     return InterlockedIncrement( &object->refs );
534 }
535 
536 static ULONG WINAPI object_Release(
537     ISWbemObject *iface )
538 {
539     struct object *object = impl_from_ISWbemObject( iface );
540     LONG refs = InterlockedDecrement( &object->refs );
541     if (!refs)
542     {
543         UINT i;
544 
545         TRACE( "destroying %p\n", object );
546         IWbemClassObject_Release( object->object );
547         for (i = 0; i < object->nb_members; i++) SysFreeString( object->members[i].name );
548         heap_free( object->members );
549         heap_free( object );
550     }
551     return refs;
552 }
553 
554 static HRESULT WINAPI object_QueryInterface(
555     ISWbemObject *iface,
556     REFIID riid,
557     void **ppvObject )
558 {
559     struct object *object = impl_from_ISWbemObject( iface );
560 
561     TRACE( "%p %s %p\n", object, debugstr_guid(riid), ppvObject );
562 
563     if (IsEqualGUID( riid, &IID_ISWbemObject ) ||
564         IsEqualGUID( riid, &IID_IDispatch ) ||
565         IsEqualGUID( riid, &IID_IUnknown ))
566     {
567         *ppvObject = iface;
568     }
569     else
570     {
571         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
572         return E_NOINTERFACE;
573     }
574     ISWbemObject_AddRef( iface );
575     return S_OK;
576 }
577 
578 static HRESULT WINAPI object_GetTypeInfoCount(
579     ISWbemObject *iface,
580     UINT *count )
581 {
582     struct object *object = impl_from_ISWbemObject( iface );
583 
584     TRACE( "%p, %p\n", object, count );
585     *count = 1;
586     return S_OK;
587 }
588 
589 static HRESULT WINAPI object_GetTypeInfo(
590     ISWbemObject *iface,
591     UINT index,
592     LCID lcid,
593     ITypeInfo **info )
594 {
595     struct object *object = impl_from_ISWbemObject( iface );
596     FIXME( "%p, %u, %u, %p\n", object, index, lcid, info );
597     return E_NOTIMPL;
598 }
599 
600 static HRESULT init_members( struct object *object )
601 {
602     IWbemClassObject *sig_in, *sig_out;
603     LONG i = 0, count = 0;
604     BSTR name;
605     HRESULT hr;
606 
607     if (object->members) return S_OK;
608 
609     hr = IWbemClassObject_BeginEnumeration( object->object, 0 );
610     if (SUCCEEDED( hr ))
611     {
612         while (IWbemClassObject_Next( object->object, 0, NULL, NULL, NULL, NULL ) == S_OK) count++;
613         IWbemClassObject_EndEnumeration( object->object );
614     }
615 
616     hr = IWbemClassObject_BeginMethodEnumeration( object->object, 0 );
617     if (SUCCEEDED( hr ))
618     {
619         while (IWbemClassObject_NextMethod( object->object, 0, &name, &sig_in, &sig_out ) == S_OK)
620         {
621             count++;
622             SysFreeString( name );
623             IWbemClassObject_Release( sig_in );
624             IWbemClassObject_Release( sig_out );
625         }
626         IWbemClassObject_EndMethodEnumeration( object->object );
627     }
628 
629     if (!(object->members = heap_alloc( sizeof(struct member) * count ))) return E_OUTOFMEMORY;
630 
631     hr = IWbemClassObject_BeginEnumeration( object->object, 0 );
632     if (SUCCEEDED( hr ))
633     {
634         while (IWbemClassObject_Next( object->object, 0, &name, NULL, NULL, NULL ) == S_OK)
635         {
636             object->members[i].name      = name;
637             object->members[i].is_method = FALSE;
638             object->members[i].dispid    = 0;
639             if (++i > count)
640             {
641                 IWbemClassObject_EndEnumeration( object->object );
642                 goto error;
643             }
644             TRACE( "added property %s\n", debugstr_w(name) );
645         }
646         IWbemClassObject_EndEnumeration( object->object );
647     }
648 
649     hr = IWbemClassObject_BeginMethodEnumeration( object->object, 0 );
650     if (SUCCEEDED( hr ))
651     {
652         while (IWbemClassObject_NextMethod( object->object, 0, &name, &sig_in, &sig_out ) == S_OK)
653         {
654             object->members[i].name      = name;
655             object->members[i].is_method = TRUE;
656             object->members[i].dispid    = 0;
657             if (++i > count)
658             {
659                 IWbemClassObject_EndMethodEnumeration( object->object );
660                 goto error;
661             }
662             IWbemClassObject_Release( sig_in );
663             IWbemClassObject_Release( sig_out );
664             TRACE( "added method %s\n", debugstr_w(name) );
665         }
666         IWbemClassObject_EndMethodEnumeration( object->object );
667     }
668 
669     object->nb_members = count;
670     TRACE( "added %u members\n", object->nb_members );
671     return S_OK;
672 
673 error:
674     for (--i; i >= 0; i--) SysFreeString( object->members[i].name );
675     heap_free( object->members );
676     object->members = NULL;
677     object->nb_members = 0;
678     return E_FAIL;
679 }
680 
681 static DISPID get_member_dispid( struct object *object, const WCHAR *name )
682 {
683     UINT i;
684     for (i = 0; i < object->nb_members; i++)
685     {
686         if (!strcmpiW( object->members[i].name, name ))
687         {
688             if (!object->members[i].dispid)
689             {
690                 if (object->members[i].is_method)
691                     object->members[i].dispid = ++object->last_dispid_method;
692                 else
693                     object->members[i].dispid = ++object->last_dispid;
694             }
695             return object->members[i].dispid;
696         }
697     }
698     return DISPID_UNKNOWN;
699 }
700 
701 static HRESULT WINAPI object_GetIDsOfNames(
702     ISWbemObject *iface,
703     REFIID riid,
704     LPOLESTR *names,
705     UINT count,
706     LCID lcid,
707     DISPID *dispid )
708 {
709     struct object *object = impl_from_ISWbemObject( iface );
710     HRESULT hr;
711     UINT i;
712     ITypeInfo *typeinfo;
713 
714     TRACE( "%p, %s, %p, %u, %u, %p\n", object, debugstr_guid(riid), names, count, lcid, dispid );
715 
716     if (!names || !count || !dispid) return E_INVALIDARG;
717 
718     hr = init_members( object );
719     if (FAILED( hr )) return hr;
720 
721     hr = get_typeinfo( ISWbemObject_tid, &typeinfo );
722     if (SUCCEEDED(hr))
723     {
724         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
725         ITypeInfo_Release( typeinfo );
726     }
727     if (SUCCEEDED(hr)) return hr;
728 
729     for (i = 0; i < count; i++)
730     {
731         if ((dispid[i] = get_member_dispid( object, names[i] )) == DISPID_UNKNOWN) break;
732     }
733     if (i != count) return DISP_E_UNKNOWNNAME;
734     return S_OK;
735 }
736 
737 static BSTR get_member_name( struct object *object, DISPID dispid )
738 {
739     UINT i;
740     for (i = 0; i < object->nb_members; i++)
741     {
742         if (object->members[i].dispid == dispid) return object->members[i].name;
743     }
744     return NULL;
745 }
746 
747 static HRESULT WINAPI object_Invoke(
748     ISWbemObject *iface,
749     DISPID member,
750     REFIID riid,
751     LCID lcid,
752     WORD flags,
753     DISPPARAMS *params,
754     VARIANT *result,
755     EXCEPINFO *excep_info,
756     UINT *arg_err )
757 {
758     struct object *object = impl_from_ISWbemObject( iface );
759     BSTR name;
760     ITypeInfo *typeinfo;
761     HRESULT hr;
762 
763     TRACE( "%p, %x, %s, %u, %x, %p, %p, %p, %p\n", object, member, debugstr_guid(riid),
764            lcid, flags, params, result, excep_info, arg_err );
765 
766     if (member <= DISPID_BASE_METHOD)
767     {
768         hr = get_typeinfo( ISWbemObject_tid, &typeinfo );
769         if (SUCCEEDED(hr))
770         {
771             hr = ITypeInfo_Invoke( typeinfo, &object->ISWbemObject_iface, member, flags,
772                                    params, result, excep_info, arg_err );
773             ITypeInfo_Release( typeinfo );
774         }
775         return hr;
776     }
777 
778     if (flags != (DISPATCH_METHOD|DISPATCH_PROPERTYGET))
779     {
780         FIXME( "flags %x not supported\n", flags );
781         return E_NOTIMPL;
782     }
783     if (!(name = get_member_name( object, member )))
784         return DISP_E_MEMBERNOTFOUND;
785 
786     memset( params, 0, sizeof(*params) );
787     return IWbemClassObject_Get( object->object, name, 0, result, NULL, NULL );
788 }
789 
790 static HRESULT WINAPI object_Put_(
791     ISWbemObject *iface,
792     LONG iFlags,
793     IDispatch *objWbemNamedValueSet,
794     ISWbemObjectPath **objWbemObjectPath )
795 {
796     FIXME( "\n" );
797     return E_NOTIMPL;
798 }
799 
800 static HRESULT WINAPI object_PutAsync_(
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_Delete_(
812     ISWbemObject *iface,
813     LONG iFlags,
814     IDispatch *objWbemNamedValueSet )
815 {
816     FIXME( "\n" );
817     return E_NOTIMPL;
818 }
819 
820 static HRESULT WINAPI object_DeleteAsync_(
821     ISWbemObject *iface,
822     IDispatch *objWbemSink,
823     LONG iFlags,
824     IDispatch *objWbemNamedValueSet,
825     IDispatch *objWbemAsyncContext )
826 {
827     FIXME( "\n" );
828     return E_NOTIMPL;
829 }
830 
831 static HRESULT WINAPI object_Instances_(
832     ISWbemObject *iface,
833     LONG iFlags,
834     IDispatch *objWbemNamedValueSet,
835     ISWbemObjectSet **objWbemObjectSet )
836 {
837     FIXME( "\n" );
838     return E_NOTIMPL;
839 }
840 
841 static HRESULT WINAPI object_InstancesAsync_(
842     ISWbemObject *iface,
843     IDispatch *objWbemSink,
844     LONG iFlags,
845     IDispatch *objWbemNamedValueSet,
846     IDispatch *objWbemAsyncContext )
847 {
848     FIXME( "\n" );
849     return E_NOTIMPL;
850 }
851 
852 static HRESULT WINAPI object_Subclasses_(
853     ISWbemObject *iface,
854     LONG iFlags,
855     IDispatch *objWbemNamedValueSet,
856     ISWbemObjectSet **objWbemObjectSet )
857 {
858     FIXME( "\n" );
859     return E_NOTIMPL;
860 }
861 
862 static HRESULT WINAPI object_SubclassesAsync_(
863     ISWbemObject *iface,
864     IDispatch *objWbemSink,
865     LONG iFlags,
866     IDispatch *objWbemNamedValueSet,
867     IDispatch *objWbemAsyncContext )
868 {
869     FIXME( "\n" );
870     return E_NOTIMPL;
871 }
872 
873 static HRESULT WINAPI object_Associators_(
874     ISWbemObject *iface,
875     BSTR strAssocClass,
876     BSTR strResultClass,
877     BSTR strResultRole,
878     BSTR strRole,
879     VARIANT_BOOL bClassesOnly,
880     VARIANT_BOOL bSchemaOnly,
881     BSTR strRequiredAssocQualifier,
882     BSTR strRequiredQualifier,
883     LONG iFlags,
884     IDispatch *objWbemNamedValueSet,
885     ISWbemObjectSet **objWbemObjectSet )
886 {
887     FIXME( "\n" );
888     return E_NOTIMPL;
889 }
890 
891 static HRESULT WINAPI object_AssociatorsAsync_(
892     ISWbemObject *iface,
893     IDispatch *objWbemSink,
894     BSTR strAssocClass,
895     BSTR strResultClass,
896     BSTR strResultRole,
897     BSTR strRole,
898     VARIANT_BOOL bClassesOnly,
899     VARIANT_BOOL bSchemaOnly,
900     BSTR strRequiredAssocQualifier,
901     BSTR strRequiredQualifier,
902     LONG iFlags,
903     IDispatch *objWbemNamedValueSet,
904     IDispatch *objWbemAsyncContext )
905 {
906     FIXME( "\n" );
907     return E_NOTIMPL;
908 }
909 
910 static HRESULT WINAPI object_References_(
911     ISWbemObject *iface,
912     BSTR strResultClass,
913     BSTR strRole,
914     VARIANT_BOOL bClassesOnly,
915     VARIANT_BOOL bSchemaOnly,
916     BSTR strRequiredQualifier,
917     LONG iFlags,
918     IDispatch *objWbemNamedValueSet,
919     ISWbemObjectSet **objWbemObjectSet )
920 {
921     FIXME( "\n" );
922     return E_NOTIMPL;
923 }
924 
925 static HRESULT WINAPI object_ReferencesAsync_(
926     ISWbemObject *iface,
927     IDispatch *objWbemSink,
928     BSTR strResultClass,
929     BSTR strRole,
930     VARIANT_BOOL bClassesOnly,
931     VARIANT_BOOL bSchemaOnly,
932     BSTR strRequiredQualifier,
933     LONG iFlags,
934     IDispatch *objWbemNamedValueSet,
935     IDispatch *objWbemAsyncContext )
936 {
937     FIXME( "\n" );
938     return E_NOTIMPL;
939 }
940 
941 static HRESULT WINAPI object_ExecMethod_(
942     ISWbemObject *iface,
943     BSTR strMethodName,
944     IDispatch *objWbemInParameters,
945     LONG iFlags,
946     IDispatch *objWbemNamedValueSet,
947     ISWbemObject **objWbemOutParameters )
948 {
949     FIXME( "\n" );
950     return E_NOTIMPL;
951 }
952 
953 static HRESULT WINAPI object_ExecMethodAsync_(
954     ISWbemObject *iface,
955     IDispatch *objWbemSink,
956     BSTR strMethodName,
957     IDispatch *objWbemInParameters,
958     LONG iFlags,
959     IDispatch *objWbemNamedValueSet,
960     IDispatch *objWbemAsyncContext )
961 {
962     FIXME( "\n" );
963     return E_NOTIMPL;
964 }
965 
966 static HRESULT WINAPI object_Clone_(
967     ISWbemObject *iface,
968     ISWbemObject **objWbemObject )
969 {
970     FIXME( "\n" );
971     return E_NOTIMPL;
972 }
973 
974 static HRESULT WINAPI object_GetObjectText_(
975     ISWbemObject *iface,
976     LONG iFlags,
977     BSTR *strObjectText )
978 {
979     FIXME( "\n" );
980     return E_NOTIMPL;
981 }
982 
983 static HRESULT WINAPI object_SpawnDerivedClass_(
984     ISWbemObject *iface,
985     LONG iFlags,
986     ISWbemObject **objWbemObject )
987 {
988     FIXME( "\n" );
989     return E_NOTIMPL;
990 }
991 
992 static HRESULT WINAPI object_SpawnInstance_(
993     ISWbemObject *iface,
994     LONG iFlags,
995     ISWbemObject **objWbemObject )
996 {
997     FIXME( "\n" );
998     return E_NOTIMPL;
999 }
1000 
1001 static HRESULT WINAPI object_CompareTo_(
1002     ISWbemObject *iface,
1003     IDispatch *objWbemObject,
1004     LONG iFlags,
1005     VARIANT_BOOL *bResult )
1006 {
1007     FIXME( "\n" );
1008     return E_NOTIMPL;
1009 }
1010 
1011 static HRESULT WINAPI object_get_Qualifiers_(
1012     ISWbemObject *iface,
1013     ISWbemQualifierSet **objWbemQualifierSet )
1014 {
1015     FIXME( "\n" );
1016     return E_NOTIMPL;
1017 }
1018 
1019 static HRESULT WINAPI object_get_Properties_( ISWbemObject *iface, ISWbemPropertySet **prop_set )
1020 {
1021     struct object *object = impl_from_ISWbemObject( iface );
1022 
1023     TRACE( "%p, %p\n", object, prop_set );
1024     return SWbemPropertySet_create( object->object, prop_set );
1025 }
1026 
1027 static HRESULT WINAPI object_get_Methods_(
1028     ISWbemObject *iface,
1029     ISWbemMethodSet **objWbemMethodSet )
1030 {
1031     FIXME( "\n" );
1032     return E_NOTIMPL;
1033 }
1034 
1035 static HRESULT WINAPI object_get_Derivation_(
1036     ISWbemObject *iface,
1037     VARIANT *strClassNameArray )
1038 {
1039     FIXME( "\n" );
1040     return E_NOTIMPL;
1041 }
1042 
1043 static HRESULT WINAPI object_get_Path_(
1044     ISWbemObject *iface,
1045     ISWbemObjectPath **objWbemObjectPath )
1046 {
1047     FIXME( "\n" );
1048     return E_NOTIMPL;
1049 }
1050 
1051 static HRESULT WINAPI object_get_Security_(
1052     ISWbemObject *iface,
1053     ISWbemSecurity **objWbemSecurity )
1054 {
1055     FIXME( "\n" );
1056     return E_NOTIMPL;
1057 }
1058 
1059 static const ISWbemObjectVtbl object_vtbl =
1060 {
1061     object_QueryInterface,
1062     object_AddRef,
1063     object_Release,
1064     object_GetTypeInfoCount,
1065     object_GetTypeInfo,
1066     object_GetIDsOfNames,
1067     object_Invoke,
1068     object_Put_,
1069     object_PutAsync_,
1070     object_Delete_,
1071     object_DeleteAsync_,
1072     object_Instances_,
1073     object_InstancesAsync_,
1074     object_Subclasses_,
1075     object_SubclassesAsync_,
1076     object_Associators_,
1077     object_AssociatorsAsync_,
1078     object_References_,
1079     object_ReferencesAsync_,
1080     object_ExecMethod_,
1081     object_ExecMethodAsync_,
1082     object_Clone_,
1083     object_GetObjectText_,
1084     object_SpawnDerivedClass_,
1085     object_SpawnInstance_,
1086     object_CompareTo_,
1087     object_get_Qualifiers_,
1088     object_get_Properties_,
1089     object_get_Methods_,
1090     object_get_Derivation_,
1091     object_get_Path_,
1092     object_get_Security_
1093 };
1094 
1095 static HRESULT SWbemObject_create( IWbemClassObject *wbem_object, ISWbemObject **obj )
1096 {
1097     struct object *object;
1098 
1099     TRACE( "%p, %p\n", obj, wbem_object );
1100 
1101     if (!(object = heap_alloc( sizeof(*object) ))) return E_OUTOFMEMORY;
1102     object->ISWbemObject_iface.lpVtbl = &object_vtbl;
1103     object->refs = 1;
1104     object->object = wbem_object;
1105     IWbemClassObject_AddRef( object->object );
1106     object->members = NULL;
1107     object->nb_members = 0;
1108     object->last_dispid = DISPID_BASE;
1109     object->last_dispid_method = DISPID_BASE_METHOD;
1110 
1111     *obj = &object->ISWbemObject_iface;
1112     TRACE( "returning iface %p\n", *obj );
1113     return S_OK;
1114 }
1115 
1116 struct objectset
1117 {
1118     ISWbemObjectSet ISWbemObjectSet_iface;
1119     LONG refs;
1120     IEnumWbemClassObject *objectenum;
1121     LONG count;
1122 };
1123 
1124 static inline struct objectset *impl_from_ISWbemObjectSet(
1125     ISWbemObjectSet *iface )
1126 {
1127     return CONTAINING_RECORD( iface, struct objectset, ISWbemObjectSet_iface );
1128 }
1129 
1130 static ULONG WINAPI objectset_AddRef(
1131     ISWbemObjectSet *iface )
1132 {
1133     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1134     return InterlockedIncrement( &objectset->refs );
1135 }
1136 
1137 static ULONG WINAPI objectset_Release(
1138     ISWbemObjectSet *iface )
1139 {
1140     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1141     LONG refs = InterlockedDecrement( &objectset->refs );
1142     if (!refs)
1143     {
1144         TRACE( "destroying %p\n", objectset );
1145         IEnumWbemClassObject_Release( objectset->objectenum );
1146         heap_free( objectset );
1147     }
1148     return refs;
1149 }
1150 
1151 static HRESULT WINAPI objectset_QueryInterface(
1152     ISWbemObjectSet *iface,
1153     REFIID riid,
1154     void **ppvObject )
1155 {
1156     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1157 
1158     TRACE( "%p %s %p\n", objectset, debugstr_guid(riid), ppvObject );
1159 
1160     if (IsEqualGUID( riid, &IID_ISWbemObjectSet ) ||
1161         IsEqualGUID( riid, &IID_IDispatch ) ||
1162         IsEqualGUID( riid, &IID_IUnknown ))
1163     {
1164         *ppvObject = iface;
1165     }
1166     else
1167     {
1168         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1169         return E_NOINTERFACE;
1170     }
1171     ISWbemObjectSet_AddRef( iface );
1172     return S_OK;
1173 }
1174 
1175 static HRESULT WINAPI objectset_GetTypeInfoCount(
1176     ISWbemObjectSet *iface,
1177     UINT *count )
1178 {
1179     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1180     TRACE( "%p, %p\n", objectset, count );
1181     *count = 1;
1182     return S_OK;
1183 }
1184 
1185 static HRESULT WINAPI objectset_GetTypeInfo(
1186     ISWbemObjectSet *iface,
1187     UINT index,
1188     LCID lcid,
1189     ITypeInfo **info )
1190 {
1191     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1192     TRACE( "%p, %u, %u, %p\n", objectset, index, lcid, info );
1193 
1194     return get_typeinfo( ISWbemObjectSet_tid, info );
1195 }
1196 
1197 static HRESULT WINAPI objectset_GetIDsOfNames(
1198     ISWbemObjectSet *iface,
1199     REFIID riid,
1200     LPOLESTR *names,
1201     UINT count,
1202     LCID lcid,
1203     DISPID *dispid )
1204 {
1205     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1206     ITypeInfo *typeinfo;
1207     HRESULT hr;
1208 
1209     TRACE( "%p, %s, %p, %u, %u, %p\n", objectset, debugstr_guid(riid), names, count, lcid, dispid );
1210 
1211     if (!names || !count || !dispid) return E_INVALIDARG;
1212 
1213     hr = get_typeinfo( ISWbemObjectSet_tid, &typeinfo );
1214     if (SUCCEEDED(hr))
1215     {
1216         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
1217         ITypeInfo_Release( typeinfo );
1218     }
1219     return hr;
1220 }
1221 
1222 static HRESULT WINAPI objectset_Invoke(
1223     ISWbemObjectSet *iface,
1224     DISPID member,
1225     REFIID riid,
1226     LCID lcid,
1227     WORD flags,
1228     DISPPARAMS *params,
1229     VARIANT *result,
1230     EXCEPINFO *excep_info,
1231     UINT *arg_err )
1232 {
1233     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1234     ITypeInfo *typeinfo;
1235     HRESULT hr;
1236 
1237     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", objectset, member, debugstr_guid(riid),
1238            lcid, flags, params, result, excep_info, arg_err );
1239 
1240     hr = get_typeinfo( ISWbemObjectSet_tid, &typeinfo );
1241     if (SUCCEEDED(hr))
1242     {
1243         hr = ITypeInfo_Invoke( typeinfo, &objectset->ISWbemObjectSet_iface, member, flags,
1244                                params, result, excep_info, arg_err );
1245         ITypeInfo_Release( typeinfo );
1246     }
1247     return hr;
1248 }
1249 
1250 static HRESULT WINAPI objectset_get__NewEnum(
1251     ISWbemObjectSet *iface,
1252     IUnknown **pUnk )
1253 {
1254     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1255     IEnumWbemClassObject *objectenum;
1256     HRESULT hr;
1257 
1258     TRACE( "%p, %p\n", objectset, pUnk );
1259 
1260     hr = IEnumWbemClassObject_Clone( objectset->objectenum, &objectenum );
1261     if (FAILED( hr )) return hr;
1262 
1263     hr = EnumVARIANT_create( objectenum, (IEnumVARIANT **)pUnk );
1264     IEnumWbemClassObject_Release( objectenum );
1265     return hr;
1266 }
1267 
1268 static HRESULT WINAPI objectset_Item(
1269     ISWbemObjectSet *iface,
1270     BSTR strObjectPath,
1271     LONG iFlags,
1272     ISWbemObject **objWbemObject )
1273 {
1274     FIXME( "\n" );
1275     return E_NOTIMPL;
1276 }
1277 
1278 static HRESULT WINAPI objectset_get_Count(
1279     ISWbemObjectSet *iface,
1280     LONG *iCount )
1281 {
1282     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1283 
1284     TRACE( "%p, %p\n", objectset, iCount );
1285 
1286     *iCount = objectset->count;
1287     return S_OK;
1288 }
1289 
1290 static HRESULT WINAPI objectset_get_Security_(
1291     ISWbemObjectSet *iface,
1292     ISWbemSecurity **objWbemSecurity )
1293 {
1294     FIXME( "\n" );
1295     return E_NOTIMPL;
1296 }
1297 
1298 static HRESULT WINAPI objectset_ItemIndex(
1299     ISWbemObjectSet *iface,
1300     LONG lIndex,
1301     ISWbemObject **objWbemObject )
1302 {
1303     struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
1304     LONG count;
1305     HRESULT hr;
1306     IEnumVARIANT *enum_var;
1307     VARIANT var;
1308 
1309     TRACE( "%p, %d, %p\n", objectset, lIndex, objWbemObject );
1310 
1311     *objWbemObject = NULL;
1312     hr = ISWbemObjectSet_get_Count( iface, &count );
1313     if (FAILED(hr)) return hr;
1314 
1315     if (lIndex >= count) return WBEM_E_NOT_FOUND;
1316 
1317     hr = ISWbemObjectSet_get__NewEnum( iface, (IUnknown **)&enum_var );
1318     if (FAILED(hr)) return hr;
1319 
1320     IEnumVARIANT_Reset( enum_var );
1321     hr = IEnumVARIANT_Skip( enum_var, lIndex );
1322     if (SUCCEEDED(hr))
1323         hr = IEnumVARIANT_Next( enum_var, 1, &var, NULL );
1324     IEnumVARIANT_Release( enum_var );
1325 
1326     if (SUCCEEDED(hr))
1327     {
1328         if (V_VT( &var ) == VT_DISPATCH)
1329             hr = IDispatch_QueryInterface( V_DISPATCH( &var ), &IID_ISWbemObject, (void **)objWbemObject );
1330         else
1331             hr = WBEM_E_NOT_FOUND;
1332         VariantClear( &var );
1333     }
1334 
1335     return hr;
1336 }
1337 
1338 static const ISWbemObjectSetVtbl objectset_vtbl =
1339 {
1340     objectset_QueryInterface,
1341     objectset_AddRef,
1342     objectset_Release,
1343     objectset_GetTypeInfoCount,
1344     objectset_GetTypeInfo,
1345     objectset_GetIDsOfNames,
1346     objectset_Invoke,
1347     objectset_get__NewEnum,
1348     objectset_Item,
1349     objectset_get_Count,
1350     objectset_get_Security_,
1351     objectset_ItemIndex
1352 };
1353 
1354 static LONG get_object_count( IEnumWbemClassObject *iter )
1355 {
1356     LONG count = 0;
1357     while (IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 ) == S_OK) count++;
1358     IEnumWbemClassObject_Reset( iter );
1359     return count;
1360 }
1361 
1362 static HRESULT SWbemObjectSet_create( IEnumWbemClassObject *wbem_objectenum, ISWbemObjectSet **obj )
1363 {
1364     struct objectset *objectset;
1365 
1366     TRACE( "%p, %p\n", obj, wbem_objectenum );
1367 
1368     if (!(objectset = heap_alloc( sizeof(*objectset) ))) return E_OUTOFMEMORY;
1369     objectset->ISWbemObjectSet_iface.lpVtbl = &objectset_vtbl;
1370     objectset->refs = 1;
1371     objectset->objectenum = wbem_objectenum;
1372     IEnumWbemClassObject_AddRef( objectset->objectenum );
1373     objectset->count = get_object_count( objectset->objectenum );
1374 
1375     *obj = &objectset->ISWbemObjectSet_iface;
1376     TRACE( "returning iface %p\n", *obj );
1377     return S_OK;
1378 }
1379 
1380 struct enumvar
1381 {
1382     IEnumVARIANT IEnumVARIANT_iface;
1383     LONG refs;
1384     IEnumWbemClassObject *objectenum;
1385 };
1386 
1387 static inline struct enumvar *impl_from_IEnumVARIANT(
1388     IEnumVARIANT *iface )
1389 {
1390     return CONTAINING_RECORD( iface, struct enumvar, IEnumVARIANT_iface );
1391 }
1392 
1393 static ULONG WINAPI enumvar_AddRef(
1394     IEnumVARIANT *iface )
1395 {
1396     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1397     return InterlockedIncrement( &enumvar->refs );
1398 }
1399 
1400 static ULONG WINAPI enumvar_Release(
1401     IEnumVARIANT *iface )
1402 {
1403     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1404     LONG refs = InterlockedDecrement( &enumvar->refs );
1405     if (!refs)
1406     {
1407         TRACE( "destroying %p\n", enumvar );
1408         IEnumWbemClassObject_Release( enumvar->objectenum );
1409         heap_free( enumvar );
1410     }
1411     return refs;
1412 }
1413 
1414 static HRESULT WINAPI enumvar_QueryInterface(
1415     IEnumVARIANT *iface,
1416     REFIID riid,
1417     void **ppvObject )
1418 {
1419     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1420 
1421     TRACE( "%p %s %p\n", enumvar, debugstr_guid(riid), ppvObject );
1422 
1423     if (IsEqualGUID( riid, &IID_IEnumVARIANT ) ||
1424         IsEqualGUID( riid, &IID_IUnknown ))
1425     {
1426         *ppvObject = iface;
1427     }
1428     else
1429     {
1430         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1431         return E_NOINTERFACE;
1432     }
1433     IEnumVARIANT_AddRef( iface );
1434     return S_OK;
1435 }
1436 
1437 static HRESULT WINAPI enumvar_Next( IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched )
1438 {
1439     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1440     IWbemClassObject *obj;
1441     ULONG count = 0;
1442 
1443     TRACE( "%p, %u, %p, %p\n", iface, celt, var, fetched );
1444 
1445     if (celt) IEnumWbemClassObject_Next( enumvar->objectenum, WBEM_INFINITE, 1, &obj, &count );
1446     if (count)
1447     {
1448         ISWbemObject *sobj;
1449         HRESULT hr;
1450 
1451         hr = SWbemObject_create( obj, &sobj );
1452         IWbemClassObject_Release( obj );
1453         if (FAILED( hr )) return hr;
1454 
1455         V_VT( var ) = VT_DISPATCH;
1456         V_DISPATCH( var ) = (IDispatch *)sobj;
1457     }
1458     if (fetched) *fetched = count;
1459     return (count < celt) ? S_FALSE : S_OK;
1460 }
1461 
1462 static HRESULT WINAPI enumvar_Skip( IEnumVARIANT *iface, ULONG celt )
1463 {
1464     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1465 
1466     TRACE( "%p, %u\n", iface, celt );
1467 
1468     return IEnumWbemClassObject_Skip( enumvar->objectenum, WBEM_INFINITE, celt );
1469 }
1470 
1471 static HRESULT WINAPI enumvar_Reset( IEnumVARIANT *iface )
1472 {
1473     struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
1474 
1475     TRACE( "%p\n", iface );
1476 
1477     return IEnumWbemClassObject_Reset( enumvar->objectenum );
1478 }
1479 
1480 static HRESULT WINAPI enumvar_Clone( IEnumVARIANT *iface, IEnumVARIANT **penum )
1481 {
1482     FIXME( "%p, %p\n", iface, penum );
1483     return E_NOTIMPL;
1484 }
1485 
1486 static const struct IEnumVARIANTVtbl enumvar_vtbl =
1487 {
1488     enumvar_QueryInterface,
1489     enumvar_AddRef,
1490     enumvar_Release,
1491     enumvar_Next,
1492     enumvar_Skip,
1493     enumvar_Reset,
1494     enumvar_Clone
1495 };
1496 
1497 static HRESULT EnumVARIANT_create( IEnumWbemClassObject *objectenum, IEnumVARIANT **obj )
1498 {
1499     struct enumvar *enumvar;
1500 
1501     if (!(enumvar = heap_alloc( sizeof(*enumvar) ))) return E_OUTOFMEMORY;
1502     enumvar->IEnumVARIANT_iface.lpVtbl = &enumvar_vtbl;
1503     enumvar->refs = 1;
1504     enumvar->objectenum = objectenum;
1505     IEnumWbemClassObject_AddRef( enumvar->objectenum );
1506 
1507     *obj = &enumvar->IEnumVARIANT_iface;
1508     TRACE( "returning iface %p\n", *obj );
1509     return S_OK;
1510 }
1511 
1512 struct services
1513 {
1514     ISWbemServices ISWbemServices_iface;
1515     LONG refs;
1516     IWbemServices *services;
1517 };
1518 
1519 static inline struct services *impl_from_ISWbemServices(
1520     ISWbemServices *iface )
1521 {
1522     return CONTAINING_RECORD( iface, struct services, ISWbemServices_iface );
1523 }
1524 
1525 static ULONG WINAPI services_AddRef(
1526     ISWbemServices *iface )
1527 {
1528     struct services *services = impl_from_ISWbemServices( iface );
1529     return InterlockedIncrement( &services->refs );
1530 }
1531 
1532 static ULONG WINAPI services_Release(
1533     ISWbemServices *iface )
1534 {
1535     struct services *services = impl_from_ISWbemServices( iface );
1536     LONG refs = InterlockedDecrement( &services->refs );
1537     if (!refs)
1538     {
1539         TRACE( "destroying %p\n", services );
1540         IWbemServices_Release( services->services );
1541         heap_free( services );
1542     }
1543     return refs;
1544 }
1545 
1546 static HRESULT WINAPI services_QueryInterface(
1547     ISWbemServices *iface,
1548     REFIID riid,
1549     void **ppvObject )
1550 {
1551     struct services *services = impl_from_ISWbemServices( iface );
1552 
1553     TRACE( "%p %s %p\n", services, debugstr_guid(riid), ppvObject );
1554 
1555     if (IsEqualGUID( riid, &IID_ISWbemServices ) ||
1556         IsEqualGUID( riid, &IID_IDispatch ) ||
1557         IsEqualGUID( riid, &IID_IUnknown ))
1558     {
1559         *ppvObject = iface;
1560     }
1561     else
1562     {
1563         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1564         return E_NOINTERFACE;
1565     }
1566     ISWbemServices_AddRef( iface );
1567     return S_OK;
1568 }
1569 
1570 static HRESULT WINAPI services_GetTypeInfoCount(
1571     ISWbemServices *iface,
1572     UINT *count )
1573 {
1574     struct services *services = impl_from_ISWbemServices( iface );
1575     TRACE( "%p, %p\n", services, count );
1576 
1577     *count = 1;
1578     return S_OK;
1579 }
1580 
1581 static HRESULT WINAPI services_GetTypeInfo(
1582     ISWbemServices *iface,
1583     UINT index,
1584     LCID lcid,
1585     ITypeInfo **info )
1586 {
1587     struct services *services = impl_from_ISWbemServices( iface );
1588     TRACE( "%p, %u, %u, %p\n", services, index, lcid, info );
1589 
1590     return get_typeinfo( ISWbemServices_tid, info );
1591 }
1592 
1593 static HRESULT WINAPI services_GetIDsOfNames(
1594     ISWbemServices *iface,
1595     REFIID riid,
1596     LPOLESTR *names,
1597     UINT count,
1598     LCID lcid,
1599     DISPID *dispid )
1600 {
1601     struct services *services = impl_from_ISWbemServices( iface );
1602     ITypeInfo *typeinfo;
1603     HRESULT hr;
1604 
1605     TRACE( "%p, %s, %p, %u, %u, %p\n", services, debugstr_guid(riid), names, count, lcid, dispid );
1606 
1607     if (!names || !count || !dispid) return E_INVALIDARG;
1608 
1609     hr = get_typeinfo( ISWbemServices_tid, &typeinfo );
1610     if (SUCCEEDED(hr))
1611     {
1612         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
1613         ITypeInfo_Release( typeinfo );
1614     }
1615     return hr;
1616 }
1617 
1618 static HRESULT WINAPI services_Invoke(
1619     ISWbemServices *iface,
1620     DISPID member,
1621     REFIID riid,
1622     LCID lcid,
1623     WORD flags,
1624     DISPPARAMS *params,
1625     VARIANT *result,
1626     EXCEPINFO *excep_info,
1627     UINT *arg_err )
1628 {
1629     struct services *services = impl_from_ISWbemServices( iface );
1630     ITypeInfo *typeinfo;
1631     HRESULT hr;
1632 
1633     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", services, member, debugstr_guid(riid),
1634            lcid, flags, params, result, excep_info, arg_err );
1635 
1636     hr = get_typeinfo( ISWbemServices_tid, &typeinfo );
1637     if (SUCCEEDED(hr))
1638     {
1639         hr = ITypeInfo_Invoke( typeinfo, &services->ISWbemServices_iface, member, flags,
1640                                params, result, excep_info, arg_err );
1641         ITypeInfo_Release( typeinfo );
1642     }
1643     return hr;
1644 }
1645 
1646 static HRESULT WINAPI services_Get(
1647     ISWbemServices *iface,
1648     BSTR strObjectPath,
1649     LONG iFlags,
1650     IDispatch *objWbemNamedValueSet,
1651     ISWbemObject **objWbemObject )
1652 {
1653     struct services *services = impl_from_ISWbemServices( iface );
1654     IWbemClassObject *obj;
1655     HRESULT hr;
1656 
1657     TRACE( "%p, %s, %d, %p, %p\n", iface, debugstr_w(strObjectPath), iFlags, objWbemNamedValueSet,
1658            objWbemObject );
1659 
1660     if (objWbemNamedValueSet) FIXME( "ignoring context\n" );
1661 
1662     hr = IWbemServices_GetObject( services->services, strObjectPath, iFlags, NULL, &obj, NULL );
1663     if (hr != S_OK) return hr;
1664 
1665     hr = SWbemObject_create( obj, objWbemObject );
1666     IWbemClassObject_Release( obj );
1667     return hr;
1668 }
1669 
1670 static HRESULT WINAPI services_GetAsync(
1671     ISWbemServices *iface,
1672     IDispatch *objWbemSink,
1673     BSTR strObjectPath,
1674     LONG iFlags,
1675     IDispatch *objWbemNamedValueSet,
1676     IDispatch *objWbemAsyncContext )
1677 {
1678     FIXME( "\n" );
1679     return E_NOTIMPL;
1680 }
1681 
1682 static HRESULT WINAPI services_Delete(
1683     ISWbemServices *iface,
1684     BSTR strObjectPath,
1685     LONG iFlags,
1686     IDispatch *objWbemNamedValueSet )
1687 {
1688     FIXME( "\n" );
1689     return E_NOTIMPL;
1690 }
1691 
1692 static HRESULT WINAPI services_DeleteAsync(
1693     ISWbemServices* This,
1694     IDispatch *objWbemSink,
1695     BSTR strObjectPath,
1696     LONG iFlags,
1697     IDispatch *objWbemNamedValueSet,
1698     IDispatch *objWbemAsyncContext )
1699 {
1700     FIXME( "\n" );
1701     return E_NOTIMPL;
1702 }
1703 
1704 static BSTR build_query_string( const WCHAR *class )
1705 {
1706     static const WCHAR selectW[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
1707     UINT len = strlenW(class) + ARRAY_SIZE(selectW);
1708     BSTR ret;
1709 
1710     if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
1711     strcpyW( ret, selectW );
1712     strcatW( ret, class );
1713     return ret;
1714 }
1715 
1716 static HRESULT WINAPI services_InstancesOf(
1717     ISWbemServices *iface,
1718     BSTR strClass,
1719     LONG iFlags,
1720     IDispatch *objWbemNamedValueSet,
1721     ISWbemObjectSet **objWbemObjectSet )
1722 {
1723     static const WCHAR wqlW[] = {'W','Q','L',0};
1724     BSTR query, wql = SysAllocString( wqlW );
1725     HRESULT hr;
1726 
1727     TRACE( "%p, %s, %x, %p, %p\n", iface, debugstr_w(strClass), iFlags, objWbemNamedValueSet,
1728            objWbemObjectSet );
1729 
1730     if (!(query = build_query_string( strClass )))
1731     {
1732         SysFreeString( wql );
1733         return E_OUTOFMEMORY;
1734     }
1735     hr = ISWbemServices_ExecQuery( iface, query, wql, iFlags, objWbemNamedValueSet, objWbemObjectSet );
1736     SysFreeString( wql );
1737     SysFreeString( query );
1738     return hr;
1739 }
1740 
1741 static HRESULT WINAPI services_InstancesOfAsync(
1742     ISWbemServices *iface,
1743     IDispatch *objWbemSink,
1744     BSTR strClass,
1745     LONG iFlags,
1746     IDispatch *objWbemNamedValueSet,
1747     IDispatch *objWbemAsyncContext )
1748 {
1749     FIXME( "\n" );
1750     return E_NOTIMPL;
1751 }
1752 
1753 static HRESULT WINAPI services_SubclassesOf(
1754     ISWbemServices *iface,
1755     BSTR strSuperclass,
1756     LONG iFlags,
1757     IDispatch *objWbemNamedValueSet,
1758     ISWbemObjectSet **objWbemObjectSet )
1759 {
1760     FIXME( "\n" );
1761     return E_NOTIMPL;
1762 }
1763 
1764 static HRESULT WINAPI services_SubclassesOfAsync(
1765     ISWbemServices *iface,
1766     IDispatch *objWbemSink,
1767     BSTR strSuperclass,
1768     LONG iFlags,
1769     IDispatch *objWbemNamedValueSet,
1770     IDispatch *objWbemAsyncContext )
1771 {
1772     FIXME( "\n" );
1773     return E_NOTIMPL;
1774 }
1775 
1776 static HRESULT WINAPI services_ExecQuery(
1777     ISWbemServices *iface,
1778     BSTR strQuery,
1779     BSTR strQueryLanguage,
1780     LONG iFlags,
1781     IDispatch *objWbemNamedValueSet,
1782     ISWbemObjectSet **objWbemObjectSet )
1783 {
1784     struct services *services = impl_from_ISWbemServices( iface );
1785     IEnumWbemClassObject *iter;
1786     HRESULT hr;
1787 
1788     TRACE( "%p, %s, %s, %x, %p, %p\n", iface, debugstr_w(strQuery), debugstr_w(strQueryLanguage),
1789            iFlags, objWbemNamedValueSet, objWbemObjectSet );
1790 
1791     if (objWbemNamedValueSet) FIXME( "ignoring context\n" );
1792 
1793     hr = IWbemServices_ExecQuery( services->services, strQueryLanguage, strQuery, iFlags, NULL, &iter );
1794     if (hr != S_OK) return hr;
1795 
1796     hr = SWbemObjectSet_create( iter, objWbemObjectSet );
1797     IEnumWbemClassObject_Release( iter );
1798     return hr;
1799 }
1800 
1801 static HRESULT WINAPI services_ExecQueryAsync(
1802     ISWbemServices *iface,
1803     IDispatch *objWbemSink,
1804     BSTR strQuery,
1805     BSTR strQueryLanguage,
1806     LONG lFlags,
1807     IDispatch *objWbemNamedValueSet,
1808     IDispatch *objWbemAsyncContext )
1809 {
1810     FIXME( "\n" );
1811     return E_NOTIMPL;
1812 }
1813 
1814 static HRESULT WINAPI services_AssociatorsOf(
1815     ISWbemServices *iface,
1816     BSTR strObjectPath,
1817     BSTR strAssocClass,
1818     BSTR strResultClass,
1819     BSTR strResultRole,
1820     BSTR strRole,
1821     VARIANT_BOOL bClassesOnly,
1822     VARIANT_BOOL bSchemaOnly,
1823     BSTR strRequiredAssocQualifier,
1824     BSTR strRequiredQualifier,
1825     LONG iFlags,
1826     IDispatch *objWbemNamedValueSet,
1827     ISWbemObjectSet **objWbemObjectSet )
1828 {
1829     FIXME( "\n" );
1830     return E_NOTIMPL;
1831 }
1832 
1833 static HRESULT WINAPI services_AssociatorsOfAsync(
1834     ISWbemServices *iface,
1835     IDispatch *objWbemSink,
1836     BSTR strObjectPath,
1837     BSTR strAssocClass,
1838     BSTR strResultClass,
1839     BSTR strResultRole,
1840     BSTR strRole,
1841     VARIANT_BOOL bClassesOnly,
1842     VARIANT_BOOL bSchemaOnly,
1843     BSTR strRequiredAssocQualifier,
1844     BSTR strRequiredQualifier,
1845     LONG iFlags,
1846     IDispatch *objWbemNamedValueSet,
1847     IDispatch *objWbemAsyncContext )
1848 {
1849     FIXME( "\n" );
1850     return E_NOTIMPL;
1851 }
1852 
1853 static HRESULT WINAPI services_ReferencesTo(
1854     ISWbemServices *iface,
1855     BSTR strObjectPath,
1856     BSTR strResultClass,
1857     BSTR strRole,
1858     VARIANT_BOOL bClassesOnly,
1859     VARIANT_BOOL bSchemaOnly,
1860     BSTR strRequiredQualifier,
1861     LONG iFlags,
1862     IDispatch *objWbemNamedValueSet,
1863     ISWbemObjectSet **objWbemObjectSet )
1864 {
1865     FIXME( "\n" );
1866     return E_NOTIMPL;
1867 }
1868 
1869 static HRESULT WINAPI services_ReferencesToAsync(
1870     ISWbemServices *iface,
1871     IDispatch *objWbemSink,
1872     BSTR strObjectPath,
1873     BSTR strResultClass,
1874     BSTR strRole,
1875     VARIANT_BOOL bClassesOnly,
1876     VARIANT_BOOL bSchemaOnly,
1877     BSTR strRequiredQualifier,
1878     LONG iFlags,
1879     IDispatch *objWbemNamedValueSet,
1880     IDispatch *objWbemAsyncContext )
1881 {
1882     FIXME( "\n" );
1883     return E_NOTIMPL;
1884 }
1885 
1886 static HRESULT WINAPI services_ExecNotificationQuery(
1887     ISWbemServices *iface,
1888     BSTR strQuery,
1889     BSTR strQueryLanguage,
1890     LONG iFlags,
1891     IDispatch *objWbemNamedValueSet,
1892     ISWbemEventSource **objWbemEventSource )
1893 {
1894     FIXME( "\n" );
1895     return E_NOTIMPL;
1896 }
1897 
1898 static HRESULT WINAPI services_ExecNotificationQueryAsync(
1899     ISWbemServices *iface,
1900     IDispatch *objWbemSink,
1901     BSTR strQuery,
1902     BSTR strQueryLanguage,
1903     LONG iFlags,
1904     IDispatch *objWbemNamedValueSet,
1905     IDispatch *objWbemAsyncContext )
1906 {
1907     FIXME( "\n" );
1908     return E_NOTIMPL;
1909 }
1910 
1911 static HRESULT WINAPI services_ExecMethod(
1912     ISWbemServices *iface,
1913     BSTR strObjectPath,
1914     BSTR strMethodName,
1915     IDispatch *objWbemInParameters,
1916     LONG iFlags,
1917     IDispatch *objWbemNamedValueSet,
1918     ISWbemObject **objWbemOutParameters )
1919 {
1920     FIXME( "\n" );
1921     return E_NOTIMPL;
1922 }
1923 
1924 static HRESULT WINAPI services_ExecMethodAsync(
1925     ISWbemServices *iface,
1926     IDispatch *objWbemSink,
1927     BSTR strObjectPath,
1928     BSTR strMethodName,
1929     IDispatch *objWbemInParameters,
1930     LONG iFlags,
1931     IDispatch *objWbemNamedValueSet,
1932     IDispatch *objWbemAsyncContext )
1933 {
1934     FIXME( "\n" );
1935     return E_NOTIMPL;
1936 }
1937 
1938 static HRESULT WINAPI services_get_Security_(
1939         ISWbemServices *iface,
1940         ISWbemSecurity **objWbemSecurity )
1941 {
1942     TRACE( "%p, %p\n", iface, objWbemSecurity );
1943 
1944     if (!objWbemSecurity)
1945         return E_INVALIDARG;
1946 
1947     return ISWbemSecurity_create( objWbemSecurity );
1948 }
1949 
1950 static const ISWbemServicesVtbl services_vtbl =
1951 {
1952     services_QueryInterface,
1953     services_AddRef,
1954     services_Release,
1955     services_GetTypeInfoCount,
1956     services_GetTypeInfo,
1957     services_GetIDsOfNames,
1958     services_Invoke,
1959     services_Get,
1960     services_GetAsync,
1961     services_Delete,
1962     services_DeleteAsync,
1963     services_InstancesOf,
1964     services_InstancesOfAsync,
1965     services_SubclassesOf,
1966     services_SubclassesOfAsync,
1967     services_ExecQuery,
1968     services_ExecQueryAsync,
1969     services_AssociatorsOf,
1970     services_AssociatorsOfAsync,
1971     services_ReferencesTo,
1972     services_ReferencesToAsync,
1973     services_ExecNotificationQuery,
1974     services_ExecNotificationQueryAsync,
1975     services_ExecMethod,
1976     services_ExecMethodAsync,
1977     services_get_Security_
1978 };
1979 
1980 static HRESULT SWbemServices_create( IWbemServices *wbem_services, ISWbemServices **obj )
1981 {
1982     struct services *services;
1983 
1984     TRACE( "%p, %p\n", obj, wbem_services );
1985 
1986     if (!(services = heap_alloc( sizeof(*services) ))) return E_OUTOFMEMORY;
1987     services->ISWbemServices_iface.lpVtbl = &services_vtbl;
1988     services->refs = 1;
1989     services->services = wbem_services;
1990     IWbemServices_AddRef( services->services );
1991 
1992     *obj = &services->ISWbemServices_iface;
1993     TRACE( "returning iface %p\n", *obj );
1994     return S_OK;
1995 }
1996 
1997 struct locator
1998 {
1999     ISWbemLocator ISWbemLocator_iface;
2000     LONG refs;
2001     IWbemLocator *locator;
2002 };
2003 
2004 static inline struct locator *impl_from_ISWbemLocator( ISWbemLocator *iface )
2005 {
2006     return CONTAINING_RECORD( iface, struct locator, ISWbemLocator_iface );
2007 }
2008 
2009 static ULONG WINAPI locator_AddRef(
2010     ISWbemLocator *iface )
2011 {
2012     struct locator *locator = impl_from_ISWbemLocator( iface );
2013     return InterlockedIncrement( &locator->refs );
2014 }
2015 
2016 static ULONG WINAPI locator_Release(
2017     ISWbemLocator *iface )
2018 {
2019     struct locator *locator = impl_from_ISWbemLocator( iface );
2020     LONG refs = InterlockedDecrement( &locator->refs );
2021     if (!refs)
2022     {
2023         TRACE( "destroying %p\n", locator );
2024         if (locator->locator)
2025             IWbemLocator_Release( locator->locator );
2026         heap_free( locator );
2027     }
2028     return refs;
2029 }
2030 
2031 static HRESULT WINAPI locator_QueryInterface(
2032     ISWbemLocator *iface,
2033     REFIID riid,
2034     void **ppvObject )
2035 {
2036     struct locator *locator = impl_from_ISWbemLocator( iface );
2037 
2038     TRACE( "%p, %s, %p\n", locator, debugstr_guid( riid ), ppvObject );
2039 
2040     if (IsEqualGUID( riid, &IID_ISWbemLocator ) ||
2041         IsEqualGUID( riid, &IID_IDispatch ) ||
2042         IsEqualGUID( riid, &IID_IUnknown ))
2043     {
2044         *ppvObject = iface;
2045     }
2046     else
2047     {
2048         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
2049         return E_NOINTERFACE;
2050     }
2051     ISWbemLocator_AddRef( iface );
2052     return S_OK;
2053 }
2054 
2055 static HRESULT WINAPI locator_GetTypeInfoCount(
2056     ISWbemLocator *iface,
2057     UINT *count )
2058 {
2059     struct locator *locator = impl_from_ISWbemLocator( iface );
2060 
2061     TRACE( "%p, %p\n", locator, count );
2062     *count = 1;
2063     return S_OK;
2064 }
2065 
2066 static HRESULT WINAPI locator_GetTypeInfo(
2067     ISWbemLocator *iface,
2068     UINT index,
2069     LCID lcid,
2070     ITypeInfo **info )
2071 {
2072     struct locator *locator = impl_from_ISWbemLocator( iface );
2073     TRACE( "%p, %u, %u, %p\n", locator, index, lcid, info );
2074 
2075     return get_typeinfo( ISWbemLocator_tid, info );
2076 }
2077 
2078 static HRESULT WINAPI locator_GetIDsOfNames(
2079     ISWbemLocator *iface,
2080     REFIID riid,
2081     LPOLESTR *names,
2082     UINT count,
2083     LCID lcid,
2084     DISPID *dispid )
2085 {
2086     struct locator *locator = impl_from_ISWbemLocator( iface );
2087     ITypeInfo *typeinfo;
2088     HRESULT hr;
2089 
2090     TRACE( "%p, %s, %p, %u, %u, %p\n", locator, debugstr_guid(riid), names, count, lcid, dispid );
2091 
2092     if (!names || !count || !dispid) return E_INVALIDARG;
2093 
2094     hr = get_typeinfo( ISWbemLocator_tid, &typeinfo );
2095     if (SUCCEEDED(hr))
2096     {
2097         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
2098         ITypeInfo_Release( typeinfo );
2099     }
2100     return hr;
2101 }
2102 
2103 static HRESULT WINAPI locator_Invoke(
2104     ISWbemLocator *iface,
2105     DISPID member,
2106     REFIID riid,
2107     LCID lcid,
2108     WORD flags,
2109     DISPPARAMS *params,
2110     VARIANT *result,
2111     EXCEPINFO *excep_info,
2112     UINT *arg_err )
2113 {
2114     struct locator *locator = impl_from_ISWbemLocator( iface );
2115     ITypeInfo *typeinfo;
2116     HRESULT hr;
2117 
2118     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", locator, member, debugstr_guid(riid),
2119            lcid, flags, params, result, excep_info, arg_err );
2120 
2121     hr = get_typeinfo( ISWbemLocator_tid, &typeinfo );
2122     if (SUCCEEDED(hr))
2123     {
2124         hr = ITypeInfo_Invoke( typeinfo, &locator->ISWbemLocator_iface, member, flags,
2125                                params, result, excep_info, arg_err );
2126         ITypeInfo_Release( typeinfo );
2127     }
2128     return hr;
2129 }
2130 
2131 static BSTR build_resource_string( BSTR server, BSTR namespace )
2132 {
2133     static const WCHAR defaultW[] = {'r','o','o','t','\\','d','e','f','a','u','l','t',0};
2134     ULONG len, len_server = 0, len_namespace = 0;
2135     BSTR ret;
2136 
2137     if (server && *server) len_server = strlenW( server );
2138     else len_server = 1;
2139     if (namespace && *namespace) len_namespace = strlenW( namespace );
2140     else len_namespace = ARRAY_SIZE(defaultW) - 1;
2141 
2142     if (!(ret = SysAllocStringLen( NULL, 2 + len_server + 1 + len_namespace ))) return NULL;
2143 
2144     ret[0] = ret[1] = '\\';
2145     if (server && *server) strcpyW( ret + 2, server );
2146     else ret[2] = '.';
2147 
2148     len = len_server + 2;
2149     ret[len++] = '\\';
2150 
2151     if (namespace && *namespace) strcpyW( ret + len, namespace );
2152     else strcpyW( ret + len, defaultW );
2153     return ret;
2154 }
2155 
2156 static HRESULT WINAPI locator_ConnectServer(
2157     ISWbemLocator *iface,
2158     BSTR strServer,
2159     BSTR strNamespace,
2160     BSTR strUser,
2161     BSTR strPassword,
2162     BSTR strLocale,
2163     BSTR strAuthority,
2164     LONG iSecurityFlags,
2165     IDispatch *objWbemNamedValueSet,
2166     ISWbemServices **objWbemServices )
2167 {
2168     struct locator *locator = impl_from_ISWbemLocator( iface );
2169     IWbemServices *services;
2170     BSTR resource;
2171     HRESULT hr;
2172 
2173     TRACE( "%p, %s, %s, %s, %p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strServer),
2174            debugstr_w(strNamespace), debugstr_w(strUser), strPassword, debugstr_w(strLocale),
2175            debugstr_w(strAuthority), iSecurityFlags, objWbemNamedValueSet, objWbemServices );
2176 
2177     if (objWbemNamedValueSet) FIXME( "context not supported\n" );
2178 
2179     if (!locator->locator)
2180     {
2181         hr = CoCreateInstance( &CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemLocator,
2182                                (void **)&locator->locator );
2183         if (hr != S_OK) return hr;
2184     }
2185 
2186     if (!(resource = build_resource_string( strServer, strNamespace ))) return E_OUTOFMEMORY;
2187     hr = IWbemLocator_ConnectServer( locator->locator, resource, strUser, strPassword, strLocale,
2188                                      iSecurityFlags, strAuthority, NULL, &services );
2189     SysFreeString( resource );
2190     if (hr != S_OK) return hr;
2191 
2192     hr = SWbemServices_create( services, objWbemServices );
2193     IWbemServices_Release( services );
2194     return hr;
2195 }
2196 
2197 static HRESULT WINAPI locator_get_Security_(
2198     ISWbemLocator *iface,
2199     ISWbemSecurity **objWbemSecurity )
2200 {
2201     TRACE( "%p, %p\n", iface, objWbemSecurity );
2202 
2203     if (!objWbemSecurity)
2204         return E_INVALIDARG;
2205 
2206     return ISWbemSecurity_create( objWbemSecurity );
2207 }
2208 
2209 static const ISWbemLocatorVtbl locator_vtbl =
2210 {
2211     locator_QueryInterface,
2212     locator_AddRef,
2213     locator_Release,
2214     locator_GetTypeInfoCount,
2215     locator_GetTypeInfo,
2216     locator_GetIDsOfNames,
2217     locator_Invoke,
2218     locator_ConnectServer,
2219     locator_get_Security_
2220 };
2221 
2222 HRESULT SWbemLocator_create( void **obj )
2223 {
2224     struct locator *locator;
2225 
2226     TRACE( "%p\n", obj );
2227 
2228     if (!(locator = heap_alloc( sizeof(*locator) ))) return E_OUTOFMEMORY;
2229     locator->ISWbemLocator_iface.lpVtbl = &locator_vtbl;
2230     locator->refs = 1;
2231     locator->locator = NULL;
2232 
2233     *obj = &locator->ISWbemLocator_iface;
2234     TRACE( "returning iface %p\n", *obj );
2235     return S_OK;
2236 }
2237 
2238 struct security
2239 {
2240     ISWbemSecurity ISWbemSecurity_iface;
2241     LONG refs;
2242     WbemImpersonationLevelEnum  implevel;
2243     WbemAuthenticationLevelEnum authlevel;
2244 };
2245 
2246 static inline struct security *impl_from_ISWbemSecurity( ISWbemSecurity *iface )
2247 {
2248     return CONTAINING_RECORD( iface, struct security, ISWbemSecurity_iface );
2249 }
2250 
2251 static ULONG WINAPI security_AddRef(
2252     ISWbemSecurity *iface )
2253 {
2254     struct security *security = impl_from_ISWbemSecurity( iface );
2255     return InterlockedIncrement( &security->refs );
2256 }
2257 
2258 static ULONG WINAPI security_Release(
2259     ISWbemSecurity *iface )
2260 {
2261     struct security *security = impl_from_ISWbemSecurity( iface );
2262     LONG refs = InterlockedDecrement( &security->refs );
2263     if (!refs)
2264     {
2265         TRACE( "destroying %p\n", security );
2266         heap_free( security );
2267     }
2268     return refs;
2269 }
2270 
2271 static HRESULT WINAPI security_QueryInterface(
2272     ISWbemSecurity *iface,
2273     REFIID riid,
2274     void **ppvObject )
2275 {
2276     struct security *security = impl_from_ISWbemSecurity( iface );
2277     TRACE( "%p, %s, %p\n", security, debugstr_guid( riid ), ppvObject );
2278 
2279     if (IsEqualGUID( riid, &IID_ISWbemSecurity ) ||
2280         IsEqualGUID( riid, &IID_IDispatch ) ||
2281         IsEqualGUID( riid, &IID_IUnknown ))
2282     {
2283         *ppvObject = iface;
2284     }
2285     else
2286     {
2287         FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
2288         return E_NOINTERFACE;
2289     }
2290     ISWbemSecurity_AddRef( iface );
2291     return S_OK;
2292 }
2293 
2294 static HRESULT WINAPI security_GetTypeInfoCount(
2295     ISWbemSecurity *iface,
2296     UINT *count )
2297 {
2298     struct security *security = impl_from_ISWbemSecurity( iface );
2299     TRACE( "%p, %p\n", security, count );
2300 
2301     *count = 1;
2302     return S_OK;
2303 }
2304 
2305 static HRESULT WINAPI security_GetTypeInfo(
2306     ISWbemSecurity *iface,
2307     UINT index,
2308     LCID lcid,
2309     ITypeInfo **info )
2310 {
2311     struct security *security = impl_from_ISWbemSecurity( iface );
2312     TRACE( "%p, %u, %u, %p\n", security, index, lcid, info );
2313 
2314     return get_typeinfo( ISWbemSecurity_tid, info );
2315 }
2316 
2317 static HRESULT WINAPI security_GetIDsOfNames(
2318     ISWbemSecurity *iface,
2319     REFIID riid,
2320     LPOLESTR *names,
2321     UINT count,
2322     LCID lcid,
2323     DISPID *dispid )
2324 {
2325     struct security *security = impl_from_ISWbemSecurity( iface );
2326     ITypeInfo *typeinfo;
2327     HRESULT hr;
2328 
2329     TRACE( "%p, %s, %p, %u, %u, %p\n", security, debugstr_guid(riid), names, count, lcid, dispid );
2330 
2331     if (!names || !count || !dispid) return E_INVALIDARG;
2332 
2333     hr = get_typeinfo( ISWbemSecurity_tid, &typeinfo );
2334     if (SUCCEEDED(hr))
2335     {
2336         hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
2337         ITypeInfo_Release( typeinfo );
2338     }
2339     return hr;
2340 }
2341 
2342 static HRESULT WINAPI security_Invoke(
2343     ISWbemSecurity *iface,
2344     DISPID member,
2345     REFIID riid,
2346     LCID lcid,
2347     WORD flags,
2348     DISPPARAMS *params,
2349     VARIANT *result,
2350     EXCEPINFO *excep_info,
2351     UINT *arg_err )
2352 {
2353     struct security *security = impl_from_ISWbemSecurity( iface );
2354     ITypeInfo *typeinfo;
2355     HRESULT hr;
2356 
2357     TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", security, member, debugstr_guid(riid),
2358            lcid, flags, params, result, excep_info, arg_err );
2359 
2360     hr = get_typeinfo( ISWbemSecurity_tid, &typeinfo );
2361     if (SUCCEEDED(hr))
2362     {
2363         hr = ITypeInfo_Invoke( typeinfo, &security->ISWbemSecurity_iface, member, flags,
2364                                params, result, excep_info, arg_err );
2365         ITypeInfo_Release( typeinfo );
2366     }
2367     return hr;
2368 }
2369 
2370 static HRESULT WINAPI security_get_ImpersonationLevel(
2371     ISWbemSecurity *iface,
2372     WbemImpersonationLevelEnum *impersonation_level )
2373 {
2374     struct security *security = impl_from_ISWbemSecurity( iface );
2375     FIXME( "%p, %p: stub\n", security, impersonation_level );
2376 
2377     if (!impersonation_level)
2378         return E_INVALIDARG;
2379 
2380     *impersonation_level = security->implevel;
2381     return S_OK;
2382 }
2383 
2384 static HRESULT WINAPI security_put_ImpersonationLevel(
2385     ISWbemSecurity *iface,
2386     WbemImpersonationLevelEnum impersonation_level )
2387 {
2388     struct security *security = impl_from_ISWbemSecurity( iface );
2389     FIXME( "%p, %d: stub\n", security, impersonation_level );
2390 
2391     security->implevel = impersonation_level;
2392     return S_OK;
2393 }
2394 
2395 static HRESULT WINAPI security_get_AuthenticationLevel(
2396     ISWbemSecurity *iface,
2397     WbemAuthenticationLevelEnum *authentication_level )
2398 {
2399     struct security *security = impl_from_ISWbemSecurity( iface );
2400     FIXME( "%p, %p: stub\n", security, authentication_level );
2401 
2402     if (!authentication_level)
2403         return E_INVALIDARG;
2404 
2405     *authentication_level = security->authlevel;
2406     return S_OK;
2407 }
2408 
2409 static HRESULT WINAPI security_put_AuthenticationLevel(
2410     ISWbemSecurity *iface,
2411     WbemAuthenticationLevelEnum authentication_level )
2412 {
2413     struct security *security = impl_from_ISWbemSecurity( iface );
2414     FIXME( "%p, %d: stub\n", security, authentication_level );
2415 
2416     security->authlevel = authentication_level;
2417     return S_OK;
2418 }
2419 
2420 static HRESULT WINAPI security_get_Privileges(
2421     ISWbemSecurity *iface,
2422     ISWbemPrivilegeSet **privilege_set )
2423 {
2424     struct security *security = impl_from_ISWbemSecurity( iface );
2425     FIXME( "%p, %p: stub\n", security, privilege_set );
2426 
2427     if (!privilege_set)
2428         return E_INVALIDARG;
2429 
2430     return E_NOTIMPL;
2431 }
2432 
2433 static const ISWbemSecurityVtbl security_vtbl =
2434 {
2435     security_QueryInterface,
2436     security_AddRef,
2437     security_Release,
2438     security_GetTypeInfoCount,
2439     security_GetTypeInfo,
2440     security_GetIDsOfNames,
2441     security_Invoke,
2442     security_get_ImpersonationLevel,
2443     security_put_ImpersonationLevel,
2444     security_get_AuthenticationLevel,
2445     security_put_AuthenticationLevel,
2446     security_get_Privileges
2447 };
2448 
2449 static HRESULT ISWbemSecurity_create( ISWbemSecurity **obj )
2450 {
2451     struct security *security;
2452 
2453     TRACE( "%p\n", obj );
2454 
2455     if (!(security = heap_alloc( sizeof(*security) ))) return E_OUTOFMEMORY;
2456     security->ISWbemSecurity_iface.lpVtbl = &security_vtbl;
2457     security->refs = 1;
2458     security->implevel = wbemImpersonationLevelImpersonate;
2459     security->authlevel = wbemAuthenticationLevelPktPrivacy;
2460 
2461     *obj = &security->ISWbemSecurity_iface;
2462     TRACE( "returning iface %p\n", *obj );
2463     return S_OK;
2464 }
2465