wbemprox: Store the class name in the class object.
[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 = create_class_object( view->table->name, iface, ec->index, 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     WCHAR *name;
220     IEnumWbemClassObject *iter;
221     UINT index;
222 };
223
224 static inline struct class_object *impl_from_IWbemClassObject(
225     IWbemClassObject *iface )
226 {
227     return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
228 }
229
230 static ULONG WINAPI class_object_AddRef(
231     IWbemClassObject *iface )
232 {
233     struct class_object *co = impl_from_IWbemClassObject( iface );
234     return InterlockedIncrement( &co->refs );
235 }
236
237 static ULONG WINAPI class_object_Release(
238     IWbemClassObject *iface )
239 {
240     struct class_object *co = impl_from_IWbemClassObject( iface );
241     LONG refs = InterlockedDecrement( &co->refs );
242     if (!refs)
243     {
244         TRACE("destroying %p\n", co);
245         if (co->iter) IEnumWbemClassObject_Release( co->iter );
246         heap_free( co->name );
247         heap_free( co );
248     }
249     return refs;
250 }
251
252 static HRESULT WINAPI class_object_QueryInterface(
253     IWbemClassObject *iface,
254     REFIID riid,
255     void **ppvObject )
256 {
257     struct class_object *co = impl_from_IWbemClassObject( iface );
258
259     TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
260
261     if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
262          IsEqualGUID( riid, &IID_IUnknown ) )
263     {
264         *ppvObject = co;
265     }
266     else
267     {
268         FIXME("interface %s not implemented\n", debugstr_guid(riid));
269         return E_NOINTERFACE;
270     }
271     IWbemClassObject_AddRef( iface );
272     return S_OK;
273 }
274
275 static HRESULT WINAPI class_object_GetQualifierSet(
276     IWbemClassObject *iface,
277     IWbemQualifierSet **ppQualSet )
278 {
279     FIXME("%p, %p\n", iface, ppQualSet);
280     return E_NOTIMPL;
281 }
282
283 static HRESULT WINAPI class_object_Get(
284     IWbemClassObject *iface,
285     LPCWSTR wszName,
286     LONG lFlags,
287     VARIANT *pVal,
288     CIMTYPE *pType,
289     LONG *plFlavor )
290 {
291     struct class_object *co = impl_from_IWbemClassObject( iface );
292     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
293     struct view *view = ec->query->view;
294
295     TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
296
297     return get_propval( view, co->index, wszName, pVal, pType, plFlavor );
298 }
299
300 static HRESULT WINAPI class_object_Put(
301     IWbemClassObject *iface,
302     LPCWSTR wszName,
303     LONG lFlags,
304     VARIANT *pVal,
305     CIMTYPE Type )
306 {
307     struct class_object *co = impl_from_IWbemClassObject( iface );
308     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
309     struct view *view = ec->query->view;
310
311     TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
312
313     return put_propval( view, co->index, wszName, pVal, Type );
314 }
315
316 static HRESULT WINAPI class_object_Delete(
317     IWbemClassObject *iface,
318     LPCWSTR wszName )
319 {
320     FIXME("%p, %s\n", iface, debugstr_w(wszName));
321     return E_NOTIMPL;
322 }
323
324 static HRESULT WINAPI class_object_GetNames(
325     IWbemClassObject *iface,
326     LPCWSTR wszQualifierName,
327     LONG lFlags,
328     VARIANT *pQualifierVal,
329     SAFEARRAY **pNames )
330 {
331     struct class_object *co = impl_from_IWbemClassObject( iface );
332     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
333
334     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszQualifierName), lFlags, pQualifierVal, pNames);
335
336     if (wszQualifierName || pQualifierVal)
337     {
338         FIXME("qualifier not supported\n");
339         return E_NOTIMPL;
340     }
341     if (lFlags != WBEM_FLAG_ALWAYS)
342     {
343         FIXME("flags %08x not supported\n", lFlags);
344         return E_NOTIMPL;
345     }
346     return get_properties( ec->query->view, pNames );
347 }
348
349 static HRESULT WINAPI class_object_BeginEnumeration(
350     IWbemClassObject *iface,
351     LONG lEnumFlags )
352 {
353     FIXME("%p, %08x\n", iface, lEnumFlags);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI class_object_Next(
358     IWbemClassObject *iface,
359     LONG lFlags,
360     BSTR *strName,
361     VARIANT *pVal,
362     CIMTYPE *pType,
363     LONG *plFlavor )
364 {
365     FIXME("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
366     return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI class_object_EndEnumeration(
370     IWbemClassObject *iface )
371 {
372     FIXME("%p\n", iface);
373     return E_NOTIMPL;
374 }
375
376 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
377     IWbemClassObject *iface,
378     LPCWSTR wszProperty,
379     IWbemQualifierSet **ppQualSet )
380 {
381     FIXME("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
382     return E_NOTIMPL;
383 }
384
385 static HRESULT WINAPI class_object_Clone(
386     IWbemClassObject *iface,
387     IWbemClassObject **ppCopy )
388 {
389     FIXME("%p, %p\n", iface, ppCopy);
390     return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI class_object_GetObjectText(
394     IWbemClassObject *iface,
395     LONG lFlags,
396     BSTR *pstrObjectText )
397 {
398     FIXME("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
399     return E_NOTIMPL;
400 }
401
402 static HRESULT WINAPI class_object_SpawnDerivedClass(
403     IWbemClassObject *iface,
404     LONG lFlags,
405     IWbemClassObject **ppNewClass )
406 {
407     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
408     return E_NOTIMPL;
409 }
410
411 static HRESULT WINAPI class_object_SpawnInstance(
412     IWbemClassObject *iface,
413     LONG lFlags,
414     IWbemClassObject **ppNewInstance )
415 {
416     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
417     return E_NOTIMPL;
418 }
419
420 static HRESULT WINAPI class_object_CompareTo(
421     IWbemClassObject *iface,
422     LONG lFlags,
423     IWbemClassObject *pCompareTo )
424 {
425     FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
426     return E_NOTIMPL;
427 }
428
429 static HRESULT WINAPI class_object_GetPropertyOrigin(
430     IWbemClassObject *iface,
431     LPCWSTR wszName,
432     BSTR *pstrClassName )
433 {
434     FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
435     return E_NOTIMPL;
436 }
437
438 static HRESULT WINAPI class_object_InheritsFrom(
439     IWbemClassObject *iface,
440     LPCWSTR strAncestor )
441 {
442     FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
443     return E_NOTIMPL;
444 }
445
446 static UINT count_instances( IEnumWbemClassObject *iter )
447 {
448     UINT count = 0;
449     while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
450     IEnumWbemClassObject_Reset( iter );
451     return count;
452 }
453
454 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
455 {
456     switch (type)
457     {
458     case CIM_SINT16:
459         *(INT16 *)ptr = val;
460         break;
461     case CIM_UINT16:
462         *(UINT16 *)ptr = val;
463         break;
464     case CIM_SINT32:
465         *(INT32 *)ptr = val;
466         break;
467     case CIM_UINT32:
468         *(UINT32 *)ptr = val;
469         break;
470     default:
471         FIXME("unhandled type %u\n", type);
472         break;
473     }
474 }
475
476 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
477                                            struct column **cols, BYTE **data )
478 {
479     static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
480     static const WCHAR typeW[] = {'T','y','p','e',0};
481     static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0};
482     struct column *columns;
483     BYTE *row;
484     IWbemClassObject *param;
485     VARIANT val;
486     HRESULT hr = E_OUTOFMEMORY;
487     UINT offset = 0;
488     ULONG count;
489     int i = 0;
490
491     count = count_instances( iter );
492     if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
493     if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
494
495     for (;;)
496     {
497         IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
498         if (!count) break;
499
500         hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL );
501         if (hr != S_OK) goto error;
502         columns[i].name = heap_strdupW( V_BSTR( &val ) );
503         VariantClear( &val );
504
505         hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL );
506         if (hr != S_OK) goto error;
507         columns[i].type    = V_UI4( &val );
508         columns[i].vartype = 0;
509
510         hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
511         if (hr != S_OK) goto error;
512         if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
513         offset += get_type_size( columns[i].type );
514
515         IWbemClassObject_Release( param );
516         i++;
517     }
518     *num_cols = i;
519     *cols = columns;
520     *data = row;
521     return S_OK;
522
523 error:
524     for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
525     heap_free( columns );
526     heap_free( row );
527     return hr;
528 }
529
530 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
531 {
532     HRESULT hr;
533     struct table *table;
534     struct column *columns;
535     UINT num_cols;
536     BYTE *row;
537
538     hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
539     if (hr != S_OK) return hr;
540
541     if (!(table = create_table( name, num_cols, columns, 1, row, NULL )))
542     {
543         free_columns( columns, num_cols );
544         heap_free( row );
545         return E_OUTOFMEMORY;
546     }
547     if (!add_table( table )) free_table( table ); /* already exists */
548     return S_OK;
549 }
550
551 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
552 {
553     static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
554     static const WCHAR outW[] = {'O','U','T',0};
555     static const WCHAR inW[] = {'I','N',0};
556     UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method );
557     WCHAR *ret;
558
559     if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
560     sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW );
561     return struprW( ret );
562 }
563
564 static HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
565                                  IWbemClassObject **sig )
566 {
567     static const WCHAR selectW[] =
568         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
569          '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
570          'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
571          'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
572          'D','i','r','e','c','t','i','o','n','%','s',0};
573     static const WCHAR geW[] = {'>','=','0',0};
574     static const WCHAR leW[] = {'<','=','0',0};
575     UINT len = SIZEOF(selectW) + SIZEOF(geW);
576     IEnumWbemClassObject *iter;
577     WCHAR *query, *name;
578     HRESULT hr;
579
580     len += strlenW( class ) + strlenW( method );
581     if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
582     sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW );
583
584     hr = exec_query( query, &iter );
585     heap_free( query );
586     if (hr != S_OK) return hr;
587
588     if (!(name = build_signature_table_name( class, method, dir )))
589     {
590         IEnumWbemClassObject_Release( iter );
591         return E_OUTOFMEMORY;
592     }
593     hr = create_signature_table( iter, name );
594     IEnumWbemClassObject_Release( iter );
595     if (hr != S_OK)
596     {
597         heap_free( name );
598         return hr;
599     }
600     return get_object( name, sig );
601 }
602
603 static HRESULT WINAPI class_object_GetMethod(
604     IWbemClassObject *iface,
605     LPCWSTR wszName,
606     LONG lFlags,
607     IWbemClassObject **ppInSignature,
608     IWbemClassObject **ppOutSignature )
609 {
610     struct class_object *co = impl_from_IWbemClassObject( iface );
611     HRESULT hr;
612
613     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
614
615     hr = create_signature( co->name, wszName, PARAM_IN, ppInSignature );
616     if (hr != S_OK) return hr;
617
618     hr = create_signature( co->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 create_class_object(
718     const WCHAR *name, IEnumWbemClassObject *iter, UINT index, IWbemClassObject **obj )
719 {
720     struct class_object *co;
721
722     TRACE("%s, %p\n", debugstr_w(name), obj);
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->name  = heap_strdupW( name );
730     if (!co->name)
731     {
732         heap_free( co );
733         return E_OUTOFMEMORY;
734     }
735     co->iter  = iter;
736     co->index = index;
737     if (iter) IEnumWbemClassObject_AddRef( iter );
738
739     *obj = &co->IWbemClassObject_iface;
740
741     TRACE("returning iface %p\n", *obj);
742     return S_OK;
743 }