[WBEMDISP] Sync with Wine Staging 1.7.37. CORE-9246
[reactos.git] / reactos / dll / win32 / wbemdisp / locator.c
1 /*
2 * Copyright 2013 Hans Leidekker for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include "wbemdisp_private.h"
20
21 #include <wbemcli.h>
22
23 static HRESULT EnumVARIANT_create( IEnumWbemClassObject *, IEnumVARIANT ** );
24
25 enum type_id
26 {
27 ISWbemLocator_tid,
28 ISWbemObject_tid,
29 ISWbemObjectSet_tid,
30 ISWbemServices_tid,
31 last_tid
32 };
33
34 static ITypeLib *wbemdisp_typelib;
35 static ITypeInfo *wbemdisp_typeinfo[last_tid];
36
37 static REFIID wbemdisp_tid_id[] =
38 {
39 &IID_ISWbemLocator,
40 &IID_ISWbemObject,
41 &IID_ISWbemObjectSet,
42 &IID_ISWbemServices
43 };
44
45 static HRESULT get_typeinfo( enum type_id tid, ITypeInfo **ret )
46 {
47 HRESULT hr;
48
49 if (!wbemdisp_typelib)
50 {
51 ITypeLib *typelib;
52
53 hr = LoadRegTypeLib( &LIBID_WbemScripting, 1, 2, LOCALE_SYSTEM_DEFAULT, &typelib );
54 if (FAILED( hr ))
55 {
56 ERR( "LoadRegTypeLib failed: %08x\n", hr );
57 return hr;
58 }
59 if (InterlockedCompareExchangePointer( (void **)&wbemdisp_typelib, typelib, NULL ))
60 ITypeLib_Release( typelib );
61 }
62 if (!wbemdisp_typeinfo[tid])
63 {
64 ITypeInfo *typeinfo;
65
66 hr = ITypeLib_GetTypeInfoOfGuid( wbemdisp_typelib, wbemdisp_tid_id[tid], &typeinfo );
67 if (FAILED( hr ))
68 {
69 ERR( "GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(wbemdisp_tid_id[tid]), hr );
70 return hr;
71 }
72 if (InterlockedCompareExchangePointer( (void **)(wbemdisp_typeinfo + tid), typeinfo, NULL ))
73 ITypeInfo_Release( typeinfo );
74 }
75 *ret = wbemdisp_typeinfo[tid];
76 ITypeInfo_AddRef( *ret );
77 return S_OK;
78 }
79
80 #define DISPID_BASE 0x1800000
81
82 struct member
83 {
84 BSTR name;
85 DISPID dispid;
86 };
87
88 struct object
89 {
90 ISWbemObject ISWbemObject_iface;
91 LONG refs;
92 IWbemClassObject *object;
93 struct member *members;
94 UINT nb_members;
95 DISPID last_dispid;
96 };
97
98 static inline struct object *impl_from_ISWbemObject(
99 ISWbemObject *iface )
100 {
101 return CONTAINING_RECORD( iface, struct object, ISWbemObject_iface );
102 }
103
104 static ULONG WINAPI object_AddRef(
105 ISWbemObject *iface )
106 {
107 struct object *object = impl_from_ISWbemObject( iface );
108 return InterlockedIncrement( &object->refs );
109 }
110
111 static ULONG WINAPI object_Release(
112 ISWbemObject *iface )
113 {
114 struct object *object = impl_from_ISWbemObject( iface );
115 LONG refs = InterlockedDecrement( &object->refs );
116 if (!refs)
117 {
118 UINT i;
119
120 TRACE( "destroying %p\n", object );
121 IWbemClassObject_Release( object->object );
122 for (i = 0; i < object->nb_members; i++) SysFreeString( object->members[i].name );
123 heap_free( object->members );
124 heap_free( object );
125 }
126 return refs;
127 }
128
129 static HRESULT WINAPI object_QueryInterface(
130 ISWbemObject *iface,
131 REFIID riid,
132 void **ppvObject )
133 {
134 struct object *object = impl_from_ISWbemObject( iface );
135
136 TRACE( "%p %s %p\n", object, debugstr_guid(riid), ppvObject );
137
138 if (IsEqualGUID( riid, &IID_ISWbemObject ) ||
139 IsEqualGUID( riid, &IID_IDispatch ) ||
140 IsEqualGUID( riid, &IID_IUnknown ))
141 {
142 *ppvObject = object;
143 }
144 else
145 {
146 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
147 return E_NOINTERFACE;
148 }
149 ISWbemObject_AddRef( iface );
150 return S_OK;
151 }
152
153 static HRESULT WINAPI object_GetTypeInfoCount(
154 ISWbemObject *iface,
155 UINT *count )
156 {
157 struct object *object = impl_from_ISWbemObject( iface );
158
159 TRACE( "%p, %p\n", object, count );
160 *count = 1;
161 return S_OK;
162 }
163
164 static HRESULT WINAPI object_GetTypeInfo(
165 ISWbemObject *iface,
166 UINT index,
167 LCID lcid,
168 ITypeInfo **info )
169 {
170 struct object *object = impl_from_ISWbemObject( iface );
171 FIXME( "%p, %u, %u, %p\n", object, index, lcid, info );
172 return E_NOTIMPL;
173 }
174
175 #define DISPID_BASE 0x1800000
176
177 static HRESULT init_members( struct object *object )
178 {
179 LONG bound, i;
180 SAFEARRAY *sa;
181 HRESULT hr;
182
183 if (object->members) return S_OK;
184
185 hr = IWbemClassObject_GetNames( object->object, NULL, 0, NULL, &sa );
186 if (FAILED( hr )) return hr;
187 hr = SafeArrayGetUBound( sa, 1, &bound );
188 if (FAILED( hr ))
189 {
190 SafeArrayDestroy( sa );
191 return hr;
192 }
193 if (!(object->members = heap_alloc( sizeof(struct member) * (bound + 1) )))
194 {
195 SafeArrayDestroy( sa );
196 return E_OUTOFMEMORY;
197 }
198 for (i = 0; i <= bound; i++)
199 {
200 hr = SafeArrayGetElement( sa, &i, &object->members[i].name );
201 if (FAILED( hr ))
202 {
203 for (i--; i >= 0; i--) SysFreeString( object->members[i].name );
204 SafeArrayDestroy( sa );
205 heap_free( object->members );
206 object->members = NULL;
207 return E_OUTOFMEMORY;
208 }
209 object->members[i].dispid = 0;
210 }
211 object->nb_members = bound + 1;
212 SafeArrayDestroy( sa );
213 return S_OK;
214 }
215
216 static DISPID get_member_dispid( struct object *object, const WCHAR *name )
217 {
218 UINT i;
219 for (i = 0; i < object->nb_members; i++)
220 {
221 if (!strcmpiW( object->members[i].name, name ))
222 {
223 if (!object->members[i].dispid) object->members[i].dispid = ++object->last_dispid;
224 return object->members[i].dispid;
225 }
226 }
227 return DISPID_UNKNOWN;
228 }
229
230 static HRESULT WINAPI object_GetIDsOfNames(
231 ISWbemObject *iface,
232 REFIID riid,
233 LPOLESTR *names,
234 UINT count,
235 LCID lcid,
236 DISPID *dispid )
237 {
238 struct object *object = impl_from_ISWbemObject( iface );
239 HRESULT hr;
240 UINT i;
241
242 TRACE( "%p, %s, %p, %u, %u, %p\n", object, debugstr_guid(riid), names, count, lcid, dispid );
243
244 if (!names || !count || !dispid) return E_INVALIDARG;
245
246 hr = init_members( object );
247 if (FAILED( hr )) return hr;
248
249 for (i = 0; i < count; i++)
250 {
251 if ((dispid[i] = get_member_dispid( object, names[i] )) == DISPID_UNKNOWN) break;
252 }
253 if (i != count) return DISP_E_UNKNOWNNAME;
254 return S_OK;
255 }
256
257 static BSTR get_member_name( struct object *object, DISPID dispid )
258 {
259 UINT i;
260 for (i = 0; i < object->nb_members; i++)
261 {
262 if (object->members[i].dispid == dispid) return object->members[i].name;
263 }
264 return NULL;
265 }
266
267 static HRESULT WINAPI object_Invoke(
268 ISWbemObject *iface,
269 DISPID member,
270 REFIID riid,
271 LCID lcid,
272 WORD flags,
273 DISPPARAMS *params,
274 VARIANT *result,
275 EXCEPINFO *excep_info,
276 UINT *arg_err )
277 {
278 struct object *object = impl_from_ISWbemObject( iface );
279 BSTR name;
280
281 TRACE( "%p, %x, %s, %u, %x, %p, %p, %p, %p\n", object, member, debugstr_guid(riid),
282 lcid, flags, params, result, excep_info, arg_err );
283
284 if (flags != (DISPATCH_METHOD|DISPATCH_PROPERTYGET))
285 {
286 FIXME( "flags %x not supported\n", flags );
287 return E_NOTIMPL;
288 }
289 if (!(name = get_member_name( object, member )))
290 return DISP_E_MEMBERNOTFOUND;
291
292 memset( params, 0, sizeof(*params) );
293 return IWbemClassObject_Get( object->object, name, 0, result, NULL, NULL );
294 }
295
296 static HRESULT WINAPI object_Put_(
297 ISWbemObject *iface,
298 LONG iFlags,
299 IDispatch *objWbemNamedValueSet,
300 ISWbemObjectPath **objWbemObjectPath )
301 {
302 FIXME( "\n" );
303 return E_NOTIMPL;
304 }
305
306 static const ISWbemObjectVtbl object_vtbl =
307 {
308 object_QueryInterface,
309 object_AddRef,
310 object_Release,
311 object_GetTypeInfoCount,
312 object_GetTypeInfo,
313 object_GetIDsOfNames,
314 object_Invoke,
315 object_Put_
316 };
317
318 static HRESULT SWbemObject_create( IWbemClassObject *wbem_object, ISWbemObject **obj )
319 {
320 struct object *object;
321
322 TRACE( "%p, %p\n", obj, wbem_object );
323
324 if (!(object = heap_alloc( sizeof(*object) ))) return E_OUTOFMEMORY;
325 object->ISWbemObject_iface.lpVtbl = &object_vtbl;
326 object->refs = 1;
327 object->object = wbem_object;
328 IWbemClassObject_AddRef( object->object );
329 object->members = NULL;
330 object->nb_members = 0;
331 object->last_dispid = DISPID_BASE;
332
333 *obj = &object->ISWbemObject_iface;
334 TRACE( "returning iface %p\n", *obj );
335 return S_OK;
336 }
337
338 struct objectset
339 {
340 ISWbemObjectSet ISWbemObjectSet_iface;
341 LONG refs;
342 IEnumWbemClassObject *objectenum;
343 };
344
345 static inline struct objectset *impl_from_ISWbemObjectSet(
346 ISWbemObjectSet *iface )
347 {
348 return CONTAINING_RECORD( iface, struct objectset, ISWbemObjectSet_iface );
349 }
350
351 static ULONG WINAPI objectset_AddRef(
352 ISWbemObjectSet *iface )
353 {
354 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
355 return InterlockedIncrement( &objectset->refs );
356 }
357
358 static ULONG WINAPI objectset_Release(
359 ISWbemObjectSet *iface )
360 {
361 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
362 LONG refs = InterlockedDecrement( &objectset->refs );
363 if (!refs)
364 {
365 TRACE( "destroying %p\n", objectset );
366 IEnumWbemClassObject_Release( objectset->objectenum );
367 heap_free( objectset );
368 }
369 return refs;
370 }
371
372 static HRESULT WINAPI objectset_QueryInterface(
373 ISWbemObjectSet *iface,
374 REFIID riid,
375 void **ppvObject )
376 {
377 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
378
379 TRACE( "%p %s %p\n", objectset, debugstr_guid(riid), ppvObject );
380
381 if (IsEqualGUID( riid, &IID_ISWbemObjectSet ) ||
382 IsEqualGUID( riid, &IID_IDispatch ) ||
383 IsEqualGUID( riid, &IID_IUnknown ))
384 {
385 *ppvObject = objectset;
386 }
387 else
388 {
389 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
390 return E_NOINTERFACE;
391 }
392 ISWbemObjectSet_AddRef( iface );
393 return S_OK;
394 }
395
396 static HRESULT WINAPI objectset_GetTypeInfoCount(
397 ISWbemObjectSet *iface,
398 UINT *count )
399 {
400 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
401 TRACE( "%p, %p\n", objectset, count );
402 *count = 1;
403 return S_OK;
404 }
405
406 static HRESULT WINAPI objectset_GetTypeInfo(
407 ISWbemObjectSet *iface,
408 UINT index,
409 LCID lcid,
410 ITypeInfo **info )
411 {
412 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
413 TRACE( "%p, %u, %u, %p\n", objectset, index, lcid, info );
414
415 return get_typeinfo( ISWbemObjectSet_tid, info );
416 }
417
418 static HRESULT WINAPI objectset_GetIDsOfNames(
419 ISWbemObjectSet *iface,
420 REFIID riid,
421 LPOLESTR *names,
422 UINT count,
423 LCID lcid,
424 DISPID *dispid )
425 {
426 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
427 ITypeInfo *typeinfo;
428 HRESULT hr;
429
430 TRACE( "%p, %s, %p, %u, %u, %p\n", objectset, debugstr_guid(riid), names, count, lcid, dispid );
431
432 if (!names || !count || !dispid) return E_INVALIDARG;
433
434 hr = get_typeinfo( ISWbemObjectSet_tid, &typeinfo );
435 if (SUCCEEDED(hr))
436 {
437 hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
438 ITypeInfo_Release( typeinfo );
439 }
440 return hr;
441 }
442
443 static HRESULT WINAPI objectset_Invoke(
444 ISWbemObjectSet *iface,
445 DISPID member,
446 REFIID riid,
447 LCID lcid,
448 WORD flags,
449 DISPPARAMS *params,
450 VARIANT *result,
451 EXCEPINFO *excep_info,
452 UINT *arg_err )
453 {
454 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
455 ITypeInfo *typeinfo;
456 HRESULT hr;
457
458 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", objectset, member, debugstr_guid(riid),
459 lcid, flags, params, result, excep_info, arg_err );
460
461 hr = get_typeinfo( ISWbemObjectSet_tid, &typeinfo );
462 if (SUCCEEDED(hr))
463 {
464 hr = ITypeInfo_Invoke( typeinfo, &objectset->ISWbemObjectSet_iface, member, flags,
465 params, result, excep_info, arg_err );
466 ITypeInfo_Release( typeinfo );
467 }
468 return hr;
469 }
470
471 static HRESULT WINAPI objectset_get__NewEnum(
472 ISWbemObjectSet *iface,
473 IUnknown **pUnk )
474 {
475 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
476 IEnumWbemClassObject *objectenum;
477 HRESULT hr;
478
479 TRACE( "%p, %p\n", objectset, pUnk );
480
481 hr = IEnumWbemClassObject_Clone( objectset->objectenum, &objectenum );
482 if (FAILED( hr )) return hr;
483
484 hr = EnumVARIANT_create( objectenum, (IEnumVARIANT **)pUnk );
485 IEnumWbemClassObject_Release( objectenum );
486 return hr;
487 }
488
489 static HRESULT WINAPI objectset_Item(
490 ISWbemObjectSet *iface,
491 BSTR strObjectPath,
492 LONG iFlags,
493 ISWbemObject **objWbemObject )
494 {
495 FIXME( "\n" );
496 return E_NOTIMPL;
497 }
498
499 static HRESULT WINAPI objectset_get_Count(
500 ISWbemObjectSet *iface,
501 LONG *iCount )
502 {
503 struct objectset *objectset = impl_from_ISWbemObjectSet( iface );
504 LONG count = 0, total = 0;
505
506 TRACE( "%p, %p\n", objectset, iCount );
507
508 while (IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, 1 ) == S_OK) count++;
509
510 IEnumWbemClassObject_Reset( objectset->objectenum );
511 while (IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, 1 ) == S_OK) total++;
512
513 count = total - count;
514 IEnumWbemClassObject_Reset( objectset->objectenum );
515 while (count--) IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, 1 );
516
517 *iCount = total;
518 return S_OK;
519 }
520
521 static HRESULT WINAPI objectset_get_Security_(
522 ISWbemObjectSet *iface,
523 ISWbemSecurity **objWbemSecurity )
524 {
525 FIXME( "\n" );
526 return E_NOTIMPL;
527 }
528
529 static HRESULT WINAPI objectset_ItemIndex(
530 ISWbemObjectSet *iface,
531 LONG lIndex,
532 ISWbemObject **objWbemObject )
533 {
534 FIXME( "\n" );
535 return E_NOTIMPL;
536 }
537
538 static const ISWbemObjectSetVtbl objectset_vtbl =
539 {
540 objectset_QueryInterface,
541 objectset_AddRef,
542 objectset_Release,
543 objectset_GetTypeInfoCount,
544 objectset_GetTypeInfo,
545 objectset_GetIDsOfNames,
546 objectset_Invoke,
547 objectset_get__NewEnum,
548 objectset_Item,
549 objectset_get_Count,
550 objectset_get_Security_,
551 objectset_ItemIndex
552 };
553
554 static HRESULT SWbemObjectSet_create( IEnumWbemClassObject *wbem_objectenum, ISWbemObjectSet **obj )
555 {
556 struct objectset *objectset;
557
558 TRACE( "%p, %p\n", obj, wbem_objectenum );
559
560 if (!(objectset = heap_alloc( sizeof(*objectset) ))) return E_OUTOFMEMORY;
561 objectset->ISWbemObjectSet_iface.lpVtbl = &objectset_vtbl;
562 objectset->refs = 1;
563 objectset->objectenum = wbem_objectenum;
564 IEnumWbemClassObject_AddRef( objectset->objectenum );
565
566 *obj = &objectset->ISWbemObjectSet_iface;
567 TRACE( "returning iface %p\n", *obj );
568 return S_OK;
569 }
570
571 struct enumvar
572 {
573 IEnumVARIANT IEnumVARIANT_iface;
574 LONG refs;
575 IEnumWbemClassObject *objectenum;
576 };
577
578 static inline struct enumvar *impl_from_IEnumVARIANT(
579 IEnumVARIANT *iface )
580 {
581 return CONTAINING_RECORD( iface, struct enumvar, IEnumVARIANT_iface );
582 }
583
584 static ULONG WINAPI enumvar_AddRef(
585 IEnumVARIANT *iface )
586 {
587 struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
588 return InterlockedIncrement( &enumvar->refs );
589 }
590
591 static ULONG WINAPI enumvar_Release(
592 IEnumVARIANT *iface )
593 {
594 struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
595 LONG refs = InterlockedDecrement( &enumvar->refs );
596 if (!refs)
597 {
598 TRACE( "destroying %p\n", enumvar );
599 IEnumWbemClassObject_Release( enumvar->objectenum );
600 heap_free( enumvar );
601 }
602 return refs;
603 }
604
605 static HRESULT WINAPI enumvar_QueryInterface(
606 IEnumVARIANT *iface,
607 REFIID riid,
608 void **ppvObject )
609 {
610 struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
611
612 TRACE( "%p %s %p\n", enumvar, debugstr_guid(riid), ppvObject );
613
614 if (IsEqualGUID( riid, &IID_IEnumVARIANT ) ||
615 IsEqualGUID( riid, &IID_IUnknown ))
616 {
617 *ppvObject = enumvar;
618 }
619 else
620 {
621 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
622 return E_NOINTERFACE;
623 }
624 IEnumVARIANT_AddRef( iface );
625 return S_OK;
626 }
627
628 static HRESULT WINAPI enumvar_Next( IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched )
629 {
630 struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
631 IWbemClassObject *obj;
632 ULONG count = 0;
633
634 TRACE( "%p, %u, %p, %p\n", iface, celt, var, fetched );
635
636 if (celt) IEnumWbemClassObject_Next( enumvar->objectenum, WBEM_INFINITE, 1, &obj, &count );
637 if (count)
638 {
639 ISWbemObject *sobj;
640 HRESULT hr;
641
642 hr = SWbemObject_create( obj, &sobj );
643 IWbemClassObject_Release( obj );
644 if (FAILED( hr )) return hr;
645
646 V_VT( var ) = VT_DISPATCH;
647 V_DISPATCH( var ) = (IDispatch *)sobj;
648 }
649 if (fetched) *fetched = count;
650 return (count < celt) ? S_FALSE : S_OK;
651 }
652
653 static HRESULT WINAPI enumvar_Skip( IEnumVARIANT *iface, ULONG celt )
654 {
655 struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
656
657 TRACE( "%p, %u\n", iface, celt );
658
659 return IEnumWbemClassObject_Skip( enumvar->objectenum, WBEM_INFINITE, celt );
660 }
661
662 static HRESULT WINAPI enumvar_Reset( IEnumVARIANT *iface )
663 {
664 struct enumvar *enumvar = impl_from_IEnumVARIANT( iface );
665
666 TRACE( "%p\n", iface );
667
668 return IEnumWbemClassObject_Reset( enumvar->objectenum );
669 }
670
671 static HRESULT WINAPI enumvar_Clone( IEnumVARIANT *iface, IEnumVARIANT **penum )
672 {
673 FIXME( "%p, %p\n", iface, penum );
674 return E_NOTIMPL;
675 }
676
677 static const struct IEnumVARIANTVtbl enumvar_vtbl =
678 {
679 enumvar_QueryInterface,
680 enumvar_AddRef,
681 enumvar_Release,
682 enumvar_Next,
683 enumvar_Skip,
684 enumvar_Reset,
685 enumvar_Clone
686 };
687
688 static HRESULT EnumVARIANT_create( IEnumWbemClassObject *objectenum, IEnumVARIANT **obj )
689 {
690 struct enumvar *enumvar;
691
692 if (!(enumvar = heap_alloc( sizeof(*enumvar) ))) return E_OUTOFMEMORY;
693 enumvar->IEnumVARIANT_iface.lpVtbl = &enumvar_vtbl;
694 enumvar->refs = 1;
695 enumvar->objectenum = objectenum;
696 IEnumWbemClassObject_AddRef( enumvar->objectenum );
697
698 *obj = &enumvar->IEnumVARIANT_iface;
699 TRACE( "returning iface %p\n", *obj );
700 return S_OK;
701 }
702
703 struct services
704 {
705 ISWbemServices ISWbemServices_iface;
706 LONG refs;
707 IWbemServices *services;
708 };
709
710 static inline struct services *impl_from_ISWbemServices(
711 ISWbemServices *iface )
712 {
713 return CONTAINING_RECORD( iface, struct services, ISWbemServices_iface );
714 }
715
716 static ULONG WINAPI services_AddRef(
717 ISWbemServices *iface )
718 {
719 struct services *services = impl_from_ISWbemServices( iface );
720 return InterlockedIncrement( &services->refs );
721 }
722
723 static ULONG WINAPI services_Release(
724 ISWbemServices *iface )
725 {
726 struct services *services = impl_from_ISWbemServices( iface );
727 LONG refs = InterlockedDecrement( &services->refs );
728 if (!refs)
729 {
730 TRACE( "destroying %p\n", services );
731 IWbemServices_Release( services->services );
732 heap_free( services );
733 }
734 return refs;
735 }
736
737 static HRESULT WINAPI services_QueryInterface(
738 ISWbemServices *iface,
739 REFIID riid,
740 void **ppvObject )
741 {
742 struct services *services = impl_from_ISWbemServices( iface );
743
744 TRACE( "%p %s %p\n", services, debugstr_guid(riid), ppvObject );
745
746 if (IsEqualGUID( riid, &IID_ISWbemServices ) ||
747 IsEqualGUID( riid, &IID_IDispatch ) ||
748 IsEqualGUID( riid, &IID_IUnknown ))
749 {
750 *ppvObject = services;
751 }
752 else
753 {
754 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
755 return E_NOINTERFACE;
756 }
757 ISWbemServices_AddRef( iface );
758 return S_OK;
759 }
760
761 static HRESULT WINAPI services_GetTypeInfoCount(
762 ISWbemServices *iface,
763 UINT *count )
764 {
765 struct services *services = impl_from_ISWbemServices( iface );
766 TRACE( "%p, %p\n", services, count );
767
768 *count = 1;
769 return S_OK;
770 }
771
772 static HRESULT WINAPI services_GetTypeInfo(
773 ISWbemServices *iface,
774 UINT index,
775 LCID lcid,
776 ITypeInfo **info )
777 {
778 struct services *services = impl_from_ISWbemServices( iface );
779 TRACE( "%p, %u, %u, %p\n", services, index, lcid, info );
780
781 return get_typeinfo( ISWbemServices_tid, info );
782 }
783
784 static HRESULT WINAPI services_GetIDsOfNames(
785 ISWbemServices *iface,
786 REFIID riid,
787 LPOLESTR *names,
788 UINT count,
789 LCID lcid,
790 DISPID *dispid )
791 {
792 struct services *services = impl_from_ISWbemServices( iface );
793 ITypeInfo *typeinfo;
794 HRESULT hr;
795
796 TRACE( "%p, %s, %p, %u, %u, %p\n", services, debugstr_guid(riid), names, count, lcid, dispid );
797
798 if (!names || !count || !dispid) return E_INVALIDARG;
799
800 hr = get_typeinfo( ISWbemServices_tid, &typeinfo );
801 if (SUCCEEDED(hr))
802 {
803 hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
804 ITypeInfo_Release( typeinfo );
805 }
806 return hr;
807 }
808
809 static HRESULT WINAPI services_Invoke(
810 ISWbemServices *iface,
811 DISPID member,
812 REFIID riid,
813 LCID lcid,
814 WORD flags,
815 DISPPARAMS *params,
816 VARIANT *result,
817 EXCEPINFO *excep_info,
818 UINT *arg_err )
819 {
820 struct services *services = impl_from_ISWbemServices( iface );
821 ITypeInfo *typeinfo;
822 HRESULT hr;
823
824 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", services, member, debugstr_guid(riid),
825 lcid, flags, params, result, excep_info, arg_err );
826
827 hr = get_typeinfo( ISWbemServices_tid, &typeinfo );
828 if (SUCCEEDED(hr))
829 {
830 hr = ITypeInfo_Invoke( typeinfo, &services->ISWbemServices_iface, member, flags,
831 params, result, excep_info, arg_err );
832 ITypeInfo_Release( typeinfo );
833 }
834 return hr;
835 }
836
837 static HRESULT WINAPI services_Get(
838 ISWbemServices *iface,
839 BSTR strObjectPath,
840 LONG iFlags,
841 IDispatch *objWbemNamedValueSet,
842 ISWbemObject **objWbemObject )
843 {
844 struct services *services = impl_from_ISWbemServices( iface );
845 IWbemClassObject *obj;
846 HRESULT hr;
847
848 TRACE( "%p, %s, %d, %p, %p\n", iface, debugstr_w(strObjectPath), iFlags, objWbemNamedValueSet,
849 objWbemObject );
850
851 if (objWbemNamedValueSet) FIXME( "ignoring context\n" );
852
853 hr = IWbemServices_GetObject( services->services, strObjectPath, iFlags, NULL, &obj, NULL );
854 if (hr != S_OK) return hr;
855
856 hr = SWbemObject_create( obj, objWbemObject );
857 IWbemClassObject_Release( obj );
858 return hr;
859 }
860
861 static HRESULT WINAPI services_GetAsync(
862 ISWbemServices *iface,
863 IDispatch *objWbemSink,
864 BSTR strObjectPath,
865 LONG iFlags,
866 IDispatch *objWbemNamedValueSet,
867 IDispatch *objWbemAsyncContext )
868 {
869 FIXME( "\n" );
870 return E_NOTIMPL;
871 }
872
873 static HRESULT WINAPI services_Delete(
874 ISWbemServices *iface,
875 BSTR strObjectPath,
876 LONG iFlags,
877 IDispatch *objWbemNamedValueSet )
878 {
879 FIXME( "\n" );
880 return E_NOTIMPL;
881 }
882
883 static HRESULT WINAPI services_DeleteAsync(
884 ISWbemServices* This,
885 IDispatch *objWbemSink,
886 BSTR strObjectPath,
887 LONG iFlags,
888 IDispatch *objWbemNamedValueSet,
889 IDispatch *objWbemAsyncContext )
890 {
891 FIXME( "\n" );
892 return E_NOTIMPL;
893 }
894
895 static BSTR build_query_string( const WCHAR *class )
896 {
897 static const WCHAR selectW[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
898 UINT len = strlenW(class) + sizeof(selectW) / sizeof(selectW[0]);
899 BSTR ret;
900
901 if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
902 strcpyW( ret, selectW );
903 strcatW( ret, class );
904 return ret;
905 }
906
907 static HRESULT WINAPI services_InstancesOf(
908 ISWbemServices *iface,
909 BSTR strClass,
910 LONG iFlags,
911 IDispatch *objWbemNamedValueSet,
912 ISWbemObjectSet **objWbemObjectSet )
913 {
914 static const WCHAR wqlW[] = {'W','Q','L',0};
915 BSTR query, wql = SysAllocString( wqlW );
916 HRESULT hr;
917
918 TRACE( "%p, %s, %x, %p, %p\n", iface, debugstr_w(strClass), iFlags, objWbemNamedValueSet,
919 objWbemObjectSet );
920
921 if (!(query = build_query_string( strClass )))
922 {
923 SysFreeString( wql );
924 return E_OUTOFMEMORY;
925 }
926 hr = ISWbemServices_ExecQuery( iface, query, wql, iFlags, objWbemNamedValueSet, objWbemObjectSet );
927 SysFreeString( wql );
928 SysFreeString( query );
929 return hr;
930 }
931
932 static HRESULT WINAPI services_InstancesOfAsync(
933 ISWbemServices *iface,
934 IDispatch *objWbemSink,
935 BSTR strClass,
936 LONG iFlags,
937 IDispatch *objWbemNamedValueSet,
938 IDispatch *objWbemAsyncContext )
939 {
940 FIXME( "\n" );
941 return E_NOTIMPL;
942 }
943
944 static HRESULT WINAPI services_SubclassesOf(
945 ISWbemServices *iface,
946 BSTR strSuperclass,
947 LONG iFlags,
948 IDispatch *objWbemNamedValueSet,
949 ISWbemObjectSet **objWbemObjectSet )
950 {
951 FIXME( "\n" );
952 return E_NOTIMPL;
953 }
954
955 static HRESULT WINAPI services_SubclassesOfAsync(
956 ISWbemServices *iface,
957 IDispatch *objWbemSink,
958 BSTR strSuperclass,
959 LONG iFlags,
960 IDispatch *objWbemNamedValueSet,
961 IDispatch *objWbemAsyncContext )
962 {
963 FIXME( "\n" );
964 return E_NOTIMPL;
965 }
966
967 static HRESULT WINAPI services_ExecQuery(
968 ISWbemServices *iface,
969 BSTR strQuery,
970 BSTR strQueryLanguage,
971 LONG iFlags,
972 IDispatch *objWbemNamedValueSet,
973 ISWbemObjectSet **objWbemObjectSet )
974 {
975 struct services *services = impl_from_ISWbemServices( iface );
976 IEnumWbemClassObject *iter;
977 HRESULT hr;
978
979 TRACE( "%p, %s, %s, %x, %p, %p\n", iface, debugstr_w(strQuery), debugstr_w(strQueryLanguage),
980 iFlags, objWbemNamedValueSet, objWbemObjectSet );
981
982 if (objWbemNamedValueSet) FIXME( "ignoring context\n" );
983
984 hr = IWbemServices_ExecQuery( services->services, strQueryLanguage, strQuery, iFlags, NULL, &iter );
985 if (hr != S_OK) return hr;
986
987 hr = SWbemObjectSet_create( iter, objWbemObjectSet );
988 IEnumWbemClassObject_Release( iter );
989 return hr;
990 }
991
992 static HRESULT WINAPI services_ExecQueryAsync(
993 ISWbemServices *iface,
994 IDispatch *objWbemSink,
995 BSTR strQuery,
996 BSTR strQueryLanguage,
997 LONG lFlags,
998 IDispatch *objWbemNamedValueSet,
999 IDispatch *objWbemAsyncContext )
1000 {
1001 FIXME( "\n" );
1002 return E_NOTIMPL;
1003 }
1004
1005 static HRESULT WINAPI services_AssociatorsOf(
1006 ISWbemServices *iface,
1007 BSTR strObjectPath,
1008 BSTR strAssocClass,
1009 BSTR strResultClass,
1010 BSTR strResultRole,
1011 BSTR strRole,
1012 VARIANT_BOOL bClassesOnly,
1013 VARIANT_BOOL bSchemaOnly,
1014 BSTR strRequiredAssocQualifier,
1015 BSTR strRequiredQualifier,
1016 LONG iFlags,
1017 IDispatch *objWbemNamedValueSet,
1018 ISWbemObjectSet **objWbemObjectSet )
1019 {
1020 FIXME( "\n" );
1021 return E_NOTIMPL;
1022 }
1023
1024 static HRESULT WINAPI services_AssociatorsOfAsync(
1025 ISWbemServices *iface,
1026 IDispatch *objWbemSink,
1027 BSTR strObjectPath,
1028 BSTR strAssocClass,
1029 BSTR strResultClass,
1030 BSTR strResultRole,
1031 BSTR strRole,
1032 VARIANT_BOOL bClassesOnly,
1033 VARIANT_BOOL bSchemaOnly,
1034 BSTR strRequiredAssocQualifier,
1035 BSTR strRequiredQualifier,
1036 LONG iFlags,
1037 IDispatch *objWbemNamedValueSet,
1038 IDispatch *objWbemAsyncContext )
1039 {
1040 FIXME( "\n" );
1041 return E_NOTIMPL;
1042 }
1043
1044 static HRESULT WINAPI services_ReferencesTo(
1045 ISWbemServices *iface,
1046 BSTR strObjectPath,
1047 BSTR strResultClass,
1048 BSTR strRole,
1049 VARIANT_BOOL bClassesOnly,
1050 VARIANT_BOOL bSchemaOnly,
1051 BSTR strRequiredQualifier,
1052 LONG iFlags,
1053 IDispatch *objWbemNamedValueSet,
1054 ISWbemObjectSet **objWbemObjectSet )
1055 {
1056 FIXME( "\n" );
1057 return E_NOTIMPL;
1058 }
1059
1060 static HRESULT WINAPI services_ReferencesToAsync(
1061 ISWbemServices *iface,
1062 IDispatch *objWbemSink,
1063 BSTR strObjectPath,
1064 BSTR strResultClass,
1065 BSTR strRole,
1066 VARIANT_BOOL bClassesOnly,
1067 VARIANT_BOOL bSchemaOnly,
1068 BSTR strRequiredQualifier,
1069 LONG iFlags,
1070 IDispatch *objWbemNamedValueSet,
1071 IDispatch *objWbemAsyncContext )
1072 {
1073 FIXME( "\n" );
1074 return E_NOTIMPL;
1075 }
1076
1077 static HRESULT WINAPI services_ExecNotificationQuery(
1078 ISWbemServices *iface,
1079 BSTR strQuery,
1080 BSTR strQueryLanguage,
1081 LONG iFlags,
1082 IDispatch *objWbemNamedValueSet,
1083 ISWbemEventSource **objWbemEventSource )
1084 {
1085 FIXME( "\n" );
1086 return E_NOTIMPL;
1087 }
1088
1089 static HRESULT WINAPI services_ExecNotificationQueryAsync(
1090 ISWbemServices *iface,
1091 IDispatch *objWbemSink,
1092 BSTR strQuery,
1093 BSTR strQueryLanguage,
1094 LONG iFlags,
1095 IDispatch *objWbemNamedValueSet,
1096 IDispatch *objWbemAsyncContext )
1097 {
1098 FIXME( "\n" );
1099 return E_NOTIMPL;
1100 }
1101
1102 static HRESULT WINAPI services_ExecMethod(
1103 ISWbemServices *iface,
1104 BSTR strObjectPath,
1105 BSTR strMethodName,
1106 IDispatch *objWbemInParameters,
1107 LONG iFlags,
1108 IDispatch *objWbemNamedValueSet,
1109 ISWbemObject **objWbemOutParameters )
1110 {
1111 FIXME( "\n" );
1112 return E_NOTIMPL;
1113 }
1114
1115 static HRESULT WINAPI services_ExecMethodAsync(
1116 ISWbemServices *iface,
1117 IDispatch *objWbemSink,
1118 BSTR strObjectPath,
1119 BSTR strMethodName,
1120 IDispatch *objWbemInParameters,
1121 LONG iFlags,
1122 IDispatch *objWbemNamedValueSet,
1123 IDispatch *objWbemAsyncContext )
1124 {
1125 FIXME( "\n" );
1126 return E_NOTIMPL;
1127 }
1128
1129 static HRESULT WINAPI services_get_Security_(
1130 ISWbemServices *iface,
1131 ISWbemSecurity **objWbemSecurity )
1132 {
1133 FIXME( "\n" );
1134 return E_NOTIMPL;
1135 }
1136
1137 static const ISWbemServicesVtbl services_vtbl =
1138 {
1139 services_QueryInterface,
1140 services_AddRef,
1141 services_Release,
1142 services_GetTypeInfoCount,
1143 services_GetTypeInfo,
1144 services_GetIDsOfNames,
1145 services_Invoke,
1146 services_Get,
1147 services_GetAsync,
1148 services_Delete,
1149 services_DeleteAsync,
1150 services_InstancesOf,
1151 services_InstancesOfAsync,
1152 services_SubclassesOf,
1153 services_SubclassesOfAsync,
1154 services_ExecQuery,
1155 services_ExecQueryAsync,
1156 services_AssociatorsOf,
1157 services_AssociatorsOfAsync,
1158 services_ReferencesTo,
1159 services_ReferencesToAsync,
1160 services_ExecNotificationQuery,
1161 services_ExecNotificationQueryAsync,
1162 services_ExecMethod,
1163 services_ExecMethodAsync,
1164 services_get_Security_
1165 };
1166
1167 static HRESULT SWbemServices_create( IWbemServices *wbem_services, ISWbemServices **obj )
1168 {
1169 struct services *services;
1170
1171 TRACE( "%p, %p\n", obj, wbem_services );
1172
1173 if (!(services = heap_alloc( sizeof(*services) ))) return E_OUTOFMEMORY;
1174 services->ISWbemServices_iface.lpVtbl = &services_vtbl;
1175 services->refs = 1;
1176 services->services = wbem_services;
1177 IWbemServices_AddRef( services->services );
1178
1179 *obj = &services->ISWbemServices_iface;
1180 TRACE( "returning iface %p\n", *obj );
1181 return S_OK;
1182 }
1183
1184 struct locator
1185 {
1186 ISWbemLocator ISWbemLocator_iface;
1187 LONG refs;
1188 IWbemLocator *locator;
1189 };
1190
1191 static inline struct locator *impl_from_ISWbemLocator( ISWbemLocator *iface )
1192 {
1193 return CONTAINING_RECORD( iface, struct locator, ISWbemLocator_iface );
1194 }
1195
1196 static ULONG WINAPI locator_AddRef(
1197 ISWbemLocator *iface )
1198 {
1199 struct locator *locator = impl_from_ISWbemLocator( iface );
1200 return InterlockedIncrement( &locator->refs );
1201 }
1202
1203 static ULONG WINAPI locator_Release(
1204 ISWbemLocator *iface )
1205 {
1206 struct locator *locator = impl_from_ISWbemLocator( iface );
1207 LONG refs = InterlockedDecrement( &locator->refs );
1208 if (!refs)
1209 {
1210 TRACE( "destroying %p\n", locator );
1211 IWbemLocator_Release( locator->locator );
1212 heap_free( locator );
1213 }
1214 return refs;
1215 }
1216
1217 static HRESULT WINAPI locator_QueryInterface(
1218 ISWbemLocator *iface,
1219 REFIID riid,
1220 void **ppvObject )
1221 {
1222 struct locator *locator = impl_from_ISWbemLocator( iface );
1223
1224 TRACE( "%p, %s, %p\n", locator, debugstr_guid( riid ), ppvObject );
1225
1226 if (IsEqualGUID( riid, &IID_ISWbemLocator ) ||
1227 IsEqualGUID( riid, &IID_IDispatch ) ||
1228 IsEqualGUID( riid, &IID_IUnknown ))
1229 {
1230 *ppvObject = iface;
1231 }
1232 else
1233 {
1234 FIXME( "interface %s not implemented\n", debugstr_guid(riid) );
1235 return E_NOINTERFACE;
1236 }
1237 ISWbemLocator_AddRef( iface );
1238 return S_OK;
1239 }
1240
1241 static HRESULT WINAPI locator_GetTypeInfoCount(
1242 ISWbemLocator *iface,
1243 UINT *count )
1244 {
1245 struct locator *locator = impl_from_ISWbemLocator( iface );
1246
1247 TRACE( "%p, %p\n", locator, count );
1248 *count = 1;
1249 return S_OK;
1250 }
1251
1252 static HRESULT WINAPI locator_GetTypeInfo(
1253 ISWbemLocator *iface,
1254 UINT index,
1255 LCID lcid,
1256 ITypeInfo **info )
1257 {
1258 struct locator *locator = impl_from_ISWbemLocator( iface );
1259 TRACE( "%p, %u, %u, %p\n", locator, index, lcid, info );
1260
1261 return get_typeinfo( ISWbemLocator_tid, info );
1262 }
1263
1264 static HRESULT WINAPI locator_GetIDsOfNames(
1265 ISWbemLocator *iface,
1266 REFIID riid,
1267 LPOLESTR *names,
1268 UINT count,
1269 LCID lcid,
1270 DISPID *dispid )
1271 {
1272 struct locator *locator = impl_from_ISWbemLocator( iface );
1273 ITypeInfo *typeinfo;
1274 HRESULT hr;
1275
1276 TRACE( "%p, %s, %p, %u, %u, %p\n", locator, debugstr_guid(riid), names, count, lcid, dispid );
1277
1278 if (!names || !count || !dispid) return E_INVALIDARG;
1279
1280 hr = get_typeinfo( ISWbemLocator_tid, &typeinfo );
1281 if (SUCCEEDED(hr))
1282 {
1283 hr = ITypeInfo_GetIDsOfNames( typeinfo, names, count, dispid );
1284 ITypeInfo_Release( typeinfo );
1285 }
1286 return hr;
1287 }
1288
1289 static HRESULT WINAPI locator_Invoke(
1290 ISWbemLocator *iface,
1291 DISPID member,
1292 REFIID riid,
1293 LCID lcid,
1294 WORD flags,
1295 DISPPARAMS *params,
1296 VARIANT *result,
1297 EXCEPINFO *excep_info,
1298 UINT *arg_err )
1299 {
1300 struct locator *locator = impl_from_ISWbemLocator( iface );
1301 ITypeInfo *typeinfo;
1302 HRESULT hr;
1303
1304 TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", locator, member, debugstr_guid(riid),
1305 lcid, flags, params, result, excep_info, arg_err );
1306
1307 hr = get_typeinfo( ISWbemLocator_tid, &typeinfo );
1308 if (SUCCEEDED(hr))
1309 {
1310 hr = ITypeInfo_Invoke( typeinfo, &locator->ISWbemLocator_iface, member, flags,
1311 params, result, excep_info, arg_err );
1312 ITypeInfo_Release( typeinfo );
1313 }
1314 return hr;
1315 }
1316
1317 static BSTR build_resource_string( BSTR server, BSTR namespace )
1318 {
1319 static const WCHAR defaultW[] = {'r','o','o','t','\\','d','e','f','a','u','l','t',0};
1320 ULONG len, len_server = 0, len_namespace = 0;
1321 BSTR ret;
1322
1323 if (server && *server) len_server = strlenW( server );
1324 else len_server = 1;
1325 if (namespace && *namespace) len_namespace = strlenW( namespace );
1326 else len_namespace = sizeof(defaultW) / sizeof(defaultW[0]) - 1;
1327
1328 if (!(ret = SysAllocStringLen( NULL, 2 + len_server + 1 + len_namespace ))) return NULL;
1329
1330 ret[0] = ret[1] = '\\';
1331 if (server && *server) strcpyW( ret + 2, server );
1332 else ret[2] = '.';
1333
1334 len = len_server + 2;
1335 ret[len++] = '\\';
1336
1337 if (namespace && *namespace) strcpyW( ret + len, namespace );
1338 else strcpyW( ret + len, defaultW );
1339 return ret;
1340 }
1341
1342 static HRESULT WINAPI locator_ConnectServer(
1343 ISWbemLocator *iface,
1344 BSTR strServer,
1345 BSTR strNamespace,
1346 BSTR strUser,
1347 BSTR strPassword,
1348 BSTR strLocale,
1349 BSTR strAuthority,
1350 LONG iSecurityFlags,
1351 IDispatch *objWbemNamedValueSet,
1352 ISWbemServices **objWbemServices )
1353 {
1354 struct locator *locator = impl_from_ISWbemLocator( iface );
1355 IWbemServices *services;
1356 BSTR resource;
1357 HRESULT hr;
1358
1359 TRACE( "%p, %s, %s, %s, %p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strServer),
1360 debugstr_w(strNamespace), debugstr_w(strUser), strPassword, debugstr_w(strLocale),
1361 debugstr_w(strAuthority), iSecurityFlags, objWbemNamedValueSet, objWbemServices );
1362
1363 if (objWbemNamedValueSet) FIXME( "context not supported\n" );
1364
1365 if (!locator->locator)
1366 {
1367 hr = CoCreateInstance( &CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemLocator,
1368 (void **)&locator->locator );
1369 if (hr != S_OK) return hr;
1370 }
1371
1372 if (!(resource = build_resource_string( strServer, strNamespace ))) return E_OUTOFMEMORY;
1373 hr = IWbemLocator_ConnectServer( locator->locator, resource, strUser, strPassword, strLocale,
1374 iSecurityFlags, strAuthority, NULL, &services );
1375 SysFreeString( resource );
1376 if (hr != S_OK) return hr;
1377
1378 hr = SWbemServices_create( services, objWbemServices );
1379 IWbemServices_Release( services );
1380 return hr;
1381 }
1382
1383 static HRESULT WINAPI locator_get_Security_(
1384 ISWbemLocator *iface,
1385 ISWbemSecurity **objWbemSecurity )
1386 {
1387 FIXME( "%p, %p\n", iface, objWbemSecurity );
1388 return E_NOTIMPL;
1389 }
1390
1391 static const ISWbemLocatorVtbl locator_vtbl =
1392 {
1393 locator_QueryInterface,
1394 locator_AddRef,
1395 locator_Release,
1396 locator_GetTypeInfoCount,
1397 locator_GetTypeInfo,
1398 locator_GetIDsOfNames,
1399 locator_Invoke,
1400 locator_ConnectServer,
1401 locator_get_Security_
1402 };
1403
1404 HRESULT SWbemLocator_create( void **obj )
1405 {
1406 struct locator *locator;
1407
1408 TRACE( "%p\n", obj );
1409
1410 if (!(locator = heap_alloc( sizeof(*locator) ))) return E_OUTOFMEMORY;
1411 locator->ISWbemLocator_iface.lpVtbl = &locator_vtbl;
1412 locator->refs = 1;
1413 locator->locator = NULL;
1414
1415 *obj = &locator->ISWbemLocator_iface;
1416 TRACE( "returning iface %p\n", *obj );
1417 return S_OK;
1418 }