wbemprox: Make some signature table functions static.
[wine] / dlls / wbemprox / class.c
1 /*
2  * Copyright 2012 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 "objbase.h"
27 #include "wbemcli.h"
28
29 #include "wine/debug.h"
30 #include "wbemprox_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
33
34 struct enum_class_object
35 {
36     IEnumWbemClassObject IEnumWbemClassObject_iface;
37     LONG refs;
38     struct query *query;
39     UINT index;
40 };
41
42 static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
43     IEnumWbemClassObject *iface )
44 {
45     return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface);
46 }
47
48 static ULONG WINAPI enum_class_object_AddRef(
49     IEnumWbemClassObject *iface )
50 {
51     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
52     return InterlockedIncrement( &ec->refs );
53 }
54
55 static ULONG WINAPI enum_class_object_Release(
56     IEnumWbemClassObject *iface )
57 {
58     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
59     LONG refs = InterlockedDecrement( &ec->refs );
60     if (!refs)
61     {
62         TRACE("destroying %p\n", ec);
63         release_query( ec->query );
64         heap_free( ec );
65     }
66     return refs;
67 }
68
69 static HRESULT WINAPI enum_class_object_QueryInterface(
70     IEnumWbemClassObject *iface,
71     REFIID riid,
72     void **ppvObject )
73 {
74     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
75
76     TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject );
77
78     if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) ||
79          IsEqualGUID( riid, &IID_IUnknown ) )
80     {
81         *ppvObject = ec;
82     }
83     else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
84     {
85         *ppvObject = &client_security;
86         return S_OK;
87     }
88     else
89     {
90         FIXME("interface %s not implemented\n", debugstr_guid(riid));
91         return E_NOINTERFACE;
92     }
93     IEnumWbemClassObject_AddRef( iface );
94     return S_OK;
95 }
96
97 static HRESULT WINAPI enum_class_object_Reset(
98     IEnumWbemClassObject *iface )
99 {
100     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
101
102     TRACE("%p\n", iface);
103
104     ec->index = 0;
105     return WBEM_S_NO_ERROR;
106 }
107
108 static HRESULT WINAPI enum_class_object_Next(
109     IEnumWbemClassObject *iface,
110     LONG lTimeout,
111     ULONG uCount,
112     IWbemClassObject **apObjects,
113     ULONG *puReturned )
114 {
115     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
116     struct view *view = ec->query->view;
117     HRESULT hr;
118
119     TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
120
121     if (!uCount) return WBEM_S_FALSE;
122     if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
123     if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
124
125     *puReturned = 0;
126     if (ec->index + uCount > view->count) return WBEM_S_FALSE;
127
128     hr = WbemClassObject_create( NULL, iface, ec->index, (void **)apObjects );
129     if (hr != S_OK) return hr;
130
131     ec->index++;
132     *puReturned = 1;
133     if (ec->index == view->count) return WBEM_S_FALSE;
134     if (uCount > 1) return WBEM_S_TIMEDOUT;
135     return WBEM_S_NO_ERROR;
136 }
137
138 static HRESULT WINAPI enum_class_object_NextAsync(
139     IEnumWbemClassObject *iface,
140     ULONG uCount,
141     IWbemObjectSink *pSink )
142 {
143     FIXME("%p, %u, %p\n", iface, uCount, pSink);
144     return E_NOTIMPL;
145 }
146
147 static HRESULT WINAPI enum_class_object_Clone(
148     IEnumWbemClassObject *iface,
149     IEnumWbemClassObject **ppEnum )
150 {
151     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
152
153     TRACE("%p, %p\n", iface, ppEnum);
154
155     return EnumWbemClassObject_create( NULL, ec->query, (void **)ppEnum );
156 }
157
158 static HRESULT WINAPI enum_class_object_Skip(
159     IEnumWbemClassObject *iface,
160     LONG lTimeout,
161     ULONG nCount )
162 {
163     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
164     struct view *view = ec->query->view;
165
166     TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
167
168     if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
169
170     if (!view->count) return WBEM_S_FALSE;
171
172     if (nCount > view->count - ec->index)
173     {
174         ec->index = view->count - 1;
175         return WBEM_S_FALSE;
176     }
177     ec->index += nCount;
178     return WBEM_S_NO_ERROR;
179 }
180
181 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
182 {
183     enum_class_object_QueryInterface,
184     enum_class_object_AddRef,
185     enum_class_object_Release,
186     enum_class_object_Reset,
187     enum_class_object_Next,
188     enum_class_object_NextAsync,
189     enum_class_object_Clone,
190     enum_class_object_Skip
191 };
192
193 HRESULT EnumWbemClassObject_create(
194     IUnknown *pUnkOuter, struct query *query, LPVOID *ppObj )
195 {
196     struct enum_class_object *ec;
197
198     TRACE("%p, %p\n", pUnkOuter, ppObj);
199
200     ec = heap_alloc( sizeof(*ec) );
201     if (!ec) return E_OUTOFMEMORY;
202
203     ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
204     ec->refs  = 1;
205     ec->query = query;
206     addref_query( query );
207     ec->index = 0;
208
209     *ppObj = &ec->IEnumWbemClassObject_iface;
210
211     TRACE("returning iface %p\n", *ppObj);
212     return S_OK;
213 }
214
215 struct class_object
216 {
217     IWbemClassObject IWbemClassObject_iface;
218     LONG refs;
219     IEnumWbemClassObject *iter;
220     UINT index;
221 };
222
223 static inline struct class_object *impl_from_IWbemClassObject(
224     IWbemClassObject *iface )
225 {
226     return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
227 }
228
229 static ULONG WINAPI class_object_AddRef(
230     IWbemClassObject *iface )
231 {
232     struct class_object *co = impl_from_IWbemClassObject( iface );
233     return InterlockedIncrement( &co->refs );
234 }
235
236 static ULONG WINAPI class_object_Release(
237     IWbemClassObject *iface )
238 {
239     struct class_object *co = impl_from_IWbemClassObject( iface );
240     LONG refs = InterlockedDecrement( &co->refs );
241     if (!refs)
242     {
243         TRACE("destroying %p\n", co);
244         if (co->iter) IEnumWbemClassObject_Release( co->iter );
245         heap_free( co );
246     }
247     return refs;
248 }
249
250 static HRESULT WINAPI class_object_QueryInterface(
251     IWbemClassObject *iface,
252     REFIID riid,
253     void **ppvObject )
254 {
255     struct class_object *co = impl_from_IWbemClassObject( iface );
256
257     TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
258
259     if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
260          IsEqualGUID( riid, &IID_IUnknown ) )
261     {
262         *ppvObject = co;
263     }
264     else
265     {
266         FIXME("interface %s not implemented\n", debugstr_guid(riid));
267         return E_NOINTERFACE;
268     }
269     IWbemClassObject_AddRef( iface );
270     return S_OK;
271 }
272
273 static HRESULT WINAPI class_object_GetQualifierSet(
274     IWbemClassObject *iface,
275     IWbemQualifierSet **ppQualSet )
276 {
277     FIXME("%p, %p\n", iface, ppQualSet);
278     return E_NOTIMPL;
279 }
280
281 static HRESULT WINAPI class_object_Get(
282     IWbemClassObject *iface,
283     LPCWSTR wszName,
284     LONG lFlags,
285     VARIANT *pVal,
286     CIMTYPE *pType,
287     LONG *plFlavor )
288 {
289     struct class_object *co = impl_from_IWbemClassObject( iface );
290     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
291     struct view *view = ec->query->view;
292
293     TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
294
295     return get_propval( view, co->index, wszName, pVal, pType, plFlavor );
296 }
297
298 static HRESULT WINAPI class_object_Put(
299     IWbemClassObject *iface,
300     LPCWSTR wszName,
301     LONG lFlags,
302     VARIANT *pVal,
303     CIMTYPE Type )
304 {
305     struct class_object *co = impl_from_IWbemClassObject( iface );
306     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
307     struct view *view = ec->query->view;
308
309     TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
310
311     return put_propval( view, co->index, wszName, pVal, Type );
312 }
313
314 static HRESULT WINAPI class_object_Delete(
315     IWbemClassObject *iface,
316     LPCWSTR wszName )
317 {
318     FIXME("%p, %s\n", iface, debugstr_w(wszName));
319     return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI class_object_GetNames(
323     IWbemClassObject *iface,
324     LPCWSTR wszQualifierName,
325     LONG lFlags,
326     VARIANT *pQualifierVal,
327     SAFEARRAY **pNames )
328 {
329     struct class_object *co = impl_from_IWbemClassObject( iface );
330     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
331
332     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszQualifierName), lFlags, pQualifierVal, pNames);
333
334     if (wszQualifierName || pQualifierVal)
335     {
336         FIXME("qualifier not supported\n");
337         return E_NOTIMPL;
338     }
339     if (lFlags != WBEM_FLAG_ALWAYS)
340     {
341         FIXME("flags %08x not supported\n", lFlags);
342         return E_NOTIMPL;
343     }
344     return get_properties( ec->query->view, pNames );
345 }
346
347 static HRESULT WINAPI class_object_BeginEnumeration(
348     IWbemClassObject *iface,
349     LONG lEnumFlags )
350 {
351     FIXME("%p, %08x\n", iface, lEnumFlags);
352     return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI class_object_Next(
356     IWbemClassObject *iface,
357     LONG lFlags,
358     BSTR *strName,
359     VARIANT *pVal,
360     CIMTYPE *pType,
361     LONG *plFlavor )
362 {
363     FIXME("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
364     return E_NOTIMPL;
365 }
366
367 static HRESULT WINAPI class_object_EndEnumeration(
368     IWbemClassObject *iface )
369 {
370     FIXME("%p\n", iface);
371     return E_NOTIMPL;
372 }
373
374 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
375     IWbemClassObject *iface,
376     LPCWSTR wszProperty,
377     IWbemQualifierSet **ppQualSet )
378 {
379     FIXME("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
380     return E_NOTIMPL;
381 }
382
383 static HRESULT WINAPI class_object_Clone(
384     IWbemClassObject *iface,
385     IWbemClassObject **ppCopy )
386 {
387     FIXME("%p, %p\n", iface, ppCopy);
388     return E_NOTIMPL;
389 }
390
391 static HRESULT WINAPI class_object_GetObjectText(
392     IWbemClassObject *iface,
393     LONG lFlags,
394     BSTR *pstrObjectText )
395 {
396     FIXME("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
397     return E_NOTIMPL;
398 }
399
400 static HRESULT WINAPI class_object_SpawnDerivedClass(
401     IWbemClassObject *iface,
402     LONG lFlags,
403     IWbemClassObject **ppNewClass )
404 {
405     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
406     return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI class_object_SpawnInstance(
410     IWbemClassObject *iface,
411     LONG lFlags,
412     IWbemClassObject **ppNewInstance )
413 {
414     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
415     return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI class_object_CompareTo(
419     IWbemClassObject *iface,
420     LONG lFlags,
421     IWbemClassObject *pCompareTo )
422 {
423     FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
424     return E_NOTIMPL;
425 }
426
427 static HRESULT WINAPI class_object_GetPropertyOrigin(
428     IWbemClassObject *iface,
429     LPCWSTR wszName,
430     BSTR *pstrClassName )
431 {
432     FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
433     return E_NOTIMPL;
434 }
435
436 static HRESULT WINAPI class_object_InheritsFrom(
437     IWbemClassObject *iface,
438     LPCWSTR strAncestor )
439 {
440     FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
441     return E_NOTIMPL;
442 }
443
444 static UINT count_instances( IEnumWbemClassObject *iter )
445 {
446     UINT count = 0;
447     while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
448     IEnumWbemClassObject_Reset( iter );
449     return count;
450 }
451
452 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
453 {
454     switch (type)
455     {
456     case CIM_SINT16:
457         *(INT16 *)ptr = val;
458         break;
459     case CIM_UINT16:
460         *(UINT16 *)ptr = val;
461         break;
462     case CIM_SINT32:
463         *(INT32 *)ptr = val;
464         break;
465     case CIM_UINT32:
466         *(UINT32 *)ptr = val;
467         break;
468     default:
469         FIXME("unhandled type %u\n", type);
470         break;
471     }
472 }
473
474 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
475                                            struct column **cols, BYTE **data )
476 {
477     static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
478     static const WCHAR typeW[] = {'T','y','p','e',0};
479     static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0};
480     struct column *columns;
481     BYTE *row;
482     IWbemClassObject *param;
483     VARIANT val;
484     HRESULT hr = E_OUTOFMEMORY;
485     UINT offset = 0;
486     ULONG count;
487     int i = 0;
488
489     count = count_instances( iter );
490     if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
491     if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
492
493     for (;;)
494     {
495         IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
496         if (!count) break;
497
498         hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL );
499         if (hr != S_OK) goto error;
500         columns[i].name = heap_strdupW( V_BSTR( &val ) );
501         VariantClear( &val );
502
503         hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL );
504         if (hr != S_OK) goto error;
505         columns[i].type    = V_UI4( &val );
506         columns[i].vartype = 0;
507
508         hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
509         if (hr != S_OK) goto error;
510         if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
511         offset += get_type_size( columns[i].type );
512
513         IWbemClassObject_Release( param );
514         i++;
515     }
516     *num_cols = i;
517     *cols = columns;
518     *data = row;
519     return S_OK;
520
521 error:
522     for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
523     heap_free( columns );
524     heap_free( row );
525     return hr;
526 }
527
528 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
529 {
530     HRESULT hr;
531     struct table *table;
532     struct column *columns;
533     UINT num_cols;
534     BYTE *row;
535
536     hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
537     if (hr != S_OK) return hr;
538
539     if (!(table = create_table( name, num_cols, columns, 1, row, NULL )))
540     {
541         free_columns( columns, num_cols );
542         heap_free( row );
543         return E_OUTOFMEMORY;
544     }
545     if (!add_table( table )) free_table( table ); /* already exists */
546     return S_OK;
547 }
548
549 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
550 {
551     static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
552     static const WCHAR outW[] = {'O','U','T',0};
553     static const WCHAR inW[] = {'I','N',0};
554     UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method );
555     WCHAR *ret;
556
557     if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
558     sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW );
559     return struprW( ret );
560 }
561
562 static HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
563                                  IWbemClassObject **sig )
564 {
565     static const WCHAR selectW[] =
566         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
567          '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
568          'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
569          'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
570          'D','i','r','e','c','t','i','o','n','%','s',0};
571     static const WCHAR geW[] = {'>','=','0',0};
572     static const WCHAR leW[] = {'<','=','0',0};
573     UINT len = SIZEOF(selectW) + SIZEOF(geW);
574     IEnumWbemClassObject *iter;
575     WCHAR *query, *name;
576     HRESULT hr;
577
578     len += strlenW( class ) + strlenW( method );
579     if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
580     sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW );
581
582     hr = exec_query( query, &iter );
583     heap_free( query );
584     if (hr != S_OK) return hr;
585
586     if (!(name = build_signature_table_name( class, method, dir )))
587     {
588         IEnumWbemClassObject_Release( iter );
589         return E_OUTOFMEMORY;
590     }
591     hr = create_signature_table( iter, name );
592     IEnumWbemClassObject_Release( iter );
593     if (hr != S_OK)
594     {
595         heap_free( name );
596         return hr;
597     }
598     return get_object( name, sig );
599 }
600
601 static HRESULT WINAPI class_object_GetMethod(
602     IWbemClassObject *iface,
603     LPCWSTR wszName,
604     LONG lFlags,
605     IWbemClassObject **ppInSignature,
606     IWbemClassObject **ppOutSignature )
607 {
608     struct class_object *co = impl_from_IWbemClassObject( iface );
609     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
610     struct view *view = ec->query->view;
611     HRESULT hr;
612
613     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
614
615     hr = create_signature( view->table->name, wszName, PARAM_IN, ppInSignature );
616     if (hr != S_OK) return hr;
617
618     hr = create_signature( view->table->name, wszName, PARAM_OUT, ppOutSignature );
619     if (hr != S_OK) IWbemClassObject_Release( *ppInSignature );
620     return hr;
621 }
622
623 static HRESULT WINAPI class_object_PutMethod(
624     IWbemClassObject *iface,
625     LPCWSTR wszName,
626     LONG lFlags,
627     IWbemClassObject *pInSignature,
628     IWbemClassObject *pOutSignature )
629 {
630     FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
631     return E_NOTIMPL;
632 }
633
634 static HRESULT WINAPI class_object_DeleteMethod(
635     IWbemClassObject *iface,
636     LPCWSTR wszName )
637 {
638     FIXME("%p, %s\n", iface, debugstr_w(wszName));
639     return E_NOTIMPL;
640 }
641
642 static HRESULT WINAPI class_object_BeginMethodEnumeration(
643     IWbemClassObject *iface,
644     LONG lEnumFlags)
645 {
646     FIXME("%p, %08x\n", iface, lEnumFlags);
647     return E_NOTIMPL;
648 }
649
650 static HRESULT WINAPI class_object_NextMethod(
651     IWbemClassObject *iface,
652     LONG lFlags,
653     BSTR *pstrName,
654     IWbemClassObject **ppInSignature,
655     IWbemClassObject **ppOutSignature)
656 {
657     FIXME("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
658     return E_NOTIMPL;
659 }
660
661 static HRESULT WINAPI class_object_EndMethodEnumeration(
662     IWbemClassObject *iface )
663 {
664     FIXME("%p\n", iface);
665     return E_NOTIMPL;
666 }
667
668 static HRESULT WINAPI class_object_GetMethodQualifierSet(
669     IWbemClassObject *iface,
670     LPCWSTR wszMethod,
671     IWbemQualifierSet **ppQualSet)
672 {
673     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
674     return E_NOTIMPL;
675 }
676
677 static HRESULT WINAPI class_object_GetMethodOrigin(
678     IWbemClassObject *iface,
679     LPCWSTR wszMethodName,
680     BSTR *pstrClassName)
681 {
682     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
683     return E_NOTIMPL;
684 }
685
686 static const IWbemClassObjectVtbl class_object_vtbl =
687 {
688     class_object_QueryInterface,
689     class_object_AddRef,
690     class_object_Release,
691     class_object_GetQualifierSet,
692     class_object_Get,
693     class_object_Put,
694     class_object_Delete,
695     class_object_GetNames,
696     class_object_BeginEnumeration,
697     class_object_Next,
698     class_object_EndEnumeration,
699     class_object_GetPropertyQualifierSet,
700     class_object_Clone,
701     class_object_GetObjectText,
702     class_object_SpawnDerivedClass,
703     class_object_SpawnInstance,
704     class_object_CompareTo,
705     class_object_GetPropertyOrigin,
706     class_object_InheritsFrom,
707     class_object_GetMethod,
708     class_object_PutMethod,
709     class_object_DeleteMethod,
710     class_object_BeginMethodEnumeration,
711     class_object_NextMethod,
712     class_object_EndMethodEnumeration,
713     class_object_GetMethodQualifierSet,
714     class_object_GetMethodOrigin
715 };
716
717 HRESULT WbemClassObject_create(
718     IUnknown *pUnkOuter, IEnumWbemClassObject *iter, UINT index, LPVOID *ppObj )
719 {
720     struct class_object *co;
721
722     TRACE("%p, %p\n", pUnkOuter, ppObj);
723
724     co = heap_alloc( sizeof(*co) );
725     if (!co) return E_OUTOFMEMORY;
726
727     co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
728     co->refs  = 1;
729     co->iter  = iter;
730     co->index = index;
731     if (iter) IEnumWbemClassObject_AddRef( iter );
732
733     *ppObj = &co->IWbemClassObject_iface;
734
735     TRACE("returning iface %p\n", *ppObj);
736     return S_OK;
737 }