msvcrt: Support 64-bit RTTI in __RTtypeid function.
[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     UINT index_method;
223     UINT index_property;
224 };
225
226 static inline struct class_object *impl_from_IWbemClassObject(
227     IWbemClassObject *iface )
228 {
229     return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
230 }
231
232 static ULONG WINAPI class_object_AddRef(
233     IWbemClassObject *iface )
234 {
235     struct class_object *co = impl_from_IWbemClassObject( iface );
236     return InterlockedIncrement( &co->refs );
237 }
238
239 static ULONG WINAPI class_object_Release(
240     IWbemClassObject *iface )
241 {
242     struct class_object *co = impl_from_IWbemClassObject( iface );
243     LONG refs = InterlockedDecrement( &co->refs );
244     if (!refs)
245     {
246         TRACE("destroying %p\n", co);
247         if (co->iter) IEnumWbemClassObject_Release( co->iter );
248         heap_free( co->name );
249         heap_free( co );
250     }
251     return refs;
252 }
253
254 static HRESULT WINAPI class_object_QueryInterface(
255     IWbemClassObject *iface,
256     REFIID riid,
257     void **ppvObject )
258 {
259     struct class_object *co = impl_from_IWbemClassObject( iface );
260
261     TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
262
263     if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
264          IsEqualGUID( riid, &IID_IUnknown ) )
265     {
266         *ppvObject = co;
267     }
268     else
269     {
270         FIXME("interface %s not implemented\n", debugstr_guid(riid));
271         return E_NOINTERFACE;
272     }
273     IWbemClassObject_AddRef( iface );
274     return S_OK;
275 }
276
277 static HRESULT WINAPI class_object_GetQualifierSet(
278     IWbemClassObject *iface,
279     IWbemQualifierSet **ppQualSet )
280 {
281     FIXME("%p, %p\n", iface, ppQualSet);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI class_object_Get(
286     IWbemClassObject *iface,
287     LPCWSTR wszName,
288     LONG lFlags,
289     VARIANT *pVal,
290     CIMTYPE *pType,
291     LONG *plFlavor )
292 {
293     struct class_object *co = impl_from_IWbemClassObject( iface );
294     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
295     struct view *view = ec->query->view;
296
297     TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
298
299     return get_propval( view, co->index, wszName, pVal, pType, plFlavor );
300 }
301
302 static HRESULT WINAPI class_object_Put(
303     IWbemClassObject *iface,
304     LPCWSTR wszName,
305     LONG lFlags,
306     VARIANT *pVal,
307     CIMTYPE Type )
308 {
309     struct class_object *co = impl_from_IWbemClassObject( iface );
310     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
311     struct view *view = ec->query->view;
312
313     TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
314
315     return put_propval( view, co->index, wszName, pVal, Type );
316 }
317
318 static HRESULT WINAPI class_object_Delete(
319     IWbemClassObject *iface,
320     LPCWSTR wszName )
321 {
322     FIXME("%p, %s\n", iface, debugstr_w(wszName));
323     return E_NOTIMPL;
324 }
325
326 static HRESULT WINAPI class_object_GetNames(
327     IWbemClassObject *iface,
328     LPCWSTR wszQualifierName,
329     LONG lFlags,
330     VARIANT *pQualifierVal,
331     SAFEARRAY **pNames )
332 {
333     struct class_object *co = impl_from_IWbemClassObject( iface );
334     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
335
336     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszQualifierName), lFlags, pQualifierVal, pNames);
337
338     if (wszQualifierName || pQualifierVal)
339     {
340         FIXME("qualifier not supported\n");
341         return E_NOTIMPL;
342     }
343     if (lFlags != WBEM_FLAG_ALWAYS)
344     {
345         FIXME("flags %08x not supported\n", lFlags);
346         return E_NOTIMPL;
347     }
348     return get_properties( ec->query->view, pNames );
349 }
350
351 static HRESULT WINAPI class_object_BeginEnumeration(
352     IWbemClassObject *iface,
353     LONG lEnumFlags )
354 {
355     struct class_object *co = impl_from_IWbemClassObject( iface );
356
357     TRACE("%p, %08x\n", iface, lEnumFlags);
358
359     if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
360
361     co->index_property = 0;
362     return S_OK;
363 }
364
365 static HRESULT WINAPI class_object_Next(
366     IWbemClassObject *iface,
367     LONG lFlags,
368     BSTR *strName,
369     VARIANT *pVal,
370     CIMTYPE *pType,
371     LONG *plFlavor )
372 {
373     struct class_object *co = impl_from_IWbemClassObject( iface );
374     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
375     struct view *view = ec->query->view;
376     const WCHAR *property;
377     HRESULT hr;
378
379     TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
380
381     if (!(property = get_property_name( co->name, co->index_property ))) return WBEM_S_NO_MORE_DATA;
382     if (!(*strName = SysAllocString( property ))) return E_OUTOFMEMORY;
383     if ((hr = get_propval( view, co->index, property, pVal, pType, plFlavor ) != S_OK))
384     {
385         SysFreeString( *strName );
386         return hr;
387     }
388     co->index_property++;
389     return S_OK;
390 }
391
392 static HRESULT WINAPI class_object_EndEnumeration(
393     IWbemClassObject *iface )
394 {
395     struct class_object *co = impl_from_IWbemClassObject( iface );
396
397     TRACE("%p\n", iface);
398
399     co->index_property = 0;
400     return S_OK;
401 }
402
403 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
404     IWbemClassObject *iface,
405     LPCWSTR wszProperty,
406     IWbemQualifierSet **ppQualSet )
407 {
408     FIXME("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
409     return E_NOTIMPL;
410 }
411
412 static HRESULT WINAPI class_object_Clone(
413     IWbemClassObject *iface,
414     IWbemClassObject **ppCopy )
415 {
416     FIXME("%p, %p\n", iface, ppCopy);
417     return E_NOTIMPL;
418 }
419
420 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
421 {
422     static const WCHAR fmtW[] = {'\n','\t','%','s',' ','=',' ','%','s',';',0};
423     BSTR value, ret;
424     WCHAR *p;
425     UINT i;
426
427     *len = 0;
428     for (i = 0; i < table->num_cols; i++)
429     {
430         *len += sizeof(fmtW) / sizeof(fmtW[0]);
431         *len += strlenW( table->columns[i].name );
432         value = get_value_bstr( table, row, i );
433         *len += SysStringLen( value );
434         SysFreeString( value );
435     }
436     if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
437     p = ret;
438     for (i = 0; i < table->num_cols; i++)
439     {
440         value = get_value_bstr( table, row, i );
441         p += sprintfW( p, fmtW, table->columns[i].name, value );
442         SysFreeString( value );
443     }
444     return ret;
445 }
446
447 static BSTR get_object_text( const struct view *view, UINT index )
448 {
449     static const WCHAR fmtW[] =
450         {'\n','i','n','s','t','a','n','c','e',' ','o','f',' ','%','s','\n','{','%','s','\n','}',';',0};
451     UINT len, len_body, row = view->result[index];
452     BSTR ret, body;
453
454     len = sizeof(fmtW) / sizeof(fmtW[0]);
455     len += strlenW( view->table->name );
456     if (!(body = get_body_text( view->table, row, &len_body ))) return NULL;
457     len += len_body;
458
459     if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
460     sprintfW( ret, fmtW, view->table->name, body );
461     SysFreeString( body );
462     return ret;
463 }
464
465 static HRESULT WINAPI class_object_GetObjectText(
466     IWbemClassObject *iface,
467     LONG lFlags,
468     BSTR *pstrObjectText )
469 {
470     struct class_object *co = impl_from_IWbemClassObject( iface );
471     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
472     struct view *view = ec->query->view;
473     BSTR text;
474
475     TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
476
477     if (lFlags) FIXME("flags %08x not implemented\n", lFlags);
478
479     if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
480     *pstrObjectText = text;
481     return S_OK;
482 }
483
484 static HRESULT WINAPI class_object_SpawnDerivedClass(
485     IWbemClassObject *iface,
486     LONG lFlags,
487     IWbemClassObject **ppNewClass )
488 {
489     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
490     return E_NOTIMPL;
491 }
492
493 static HRESULT WINAPI class_object_SpawnInstance(
494     IWbemClassObject *iface,
495     LONG lFlags,
496     IWbemClassObject **ppNewInstance )
497 {
498     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
499     return E_NOTIMPL;
500 }
501
502 static HRESULT WINAPI class_object_CompareTo(
503     IWbemClassObject *iface,
504     LONG lFlags,
505     IWbemClassObject *pCompareTo )
506 {
507     FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
508     return E_NOTIMPL;
509 }
510
511 static HRESULT WINAPI class_object_GetPropertyOrigin(
512     IWbemClassObject *iface,
513     LPCWSTR wszName,
514     BSTR *pstrClassName )
515 {
516     FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
517     return E_NOTIMPL;
518 }
519
520 static HRESULT WINAPI class_object_InheritsFrom(
521     IWbemClassObject *iface,
522     LPCWSTR strAncestor )
523 {
524     FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
525     return E_NOTIMPL;
526 }
527
528 static UINT count_instances( IEnumWbemClassObject *iter )
529 {
530     UINT count = 0;
531     while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
532     IEnumWbemClassObject_Reset( iter );
533     return count;
534 }
535
536 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
537 {
538     switch (type)
539     {
540     case CIM_SINT16:
541         *(INT16 *)ptr = val;
542         break;
543     case CIM_UINT16:
544         *(UINT16 *)ptr = val;
545         break;
546     case CIM_SINT32:
547         *(INT32 *)ptr = val;
548         break;
549     case CIM_UINT32:
550         *(UINT32 *)ptr = val;
551         break;
552     default:
553         FIXME("unhandled type %u\n", type);
554         break;
555     }
556 }
557
558 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
559                                            struct column **cols, BYTE **data )
560 {
561     static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
562     static const WCHAR typeW[] = {'T','y','p','e',0};
563     static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0};
564     struct column *columns;
565     BYTE *row;
566     IWbemClassObject *param;
567     VARIANT val;
568     HRESULT hr = E_OUTOFMEMORY;
569     UINT offset = 0;
570     ULONG count;
571     int i = 0;
572
573     count = count_instances( iter );
574     if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
575     if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
576
577     for (;;)
578     {
579         IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
580         if (!count) break;
581
582         hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL );
583         if (hr != S_OK) goto error;
584         columns[i].name = heap_strdupW( V_BSTR( &val ) );
585         VariantClear( &val );
586
587         hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL );
588         if (hr != S_OK) goto error;
589         columns[i].type    = V_UI4( &val );
590         columns[i].vartype = 0;
591
592         hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
593         if (hr != S_OK) goto error;
594         if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
595         offset += get_type_size( columns[i].type );
596
597         IWbemClassObject_Release( param );
598         i++;
599     }
600     *num_cols = i;
601     *cols = columns;
602     *data = row;
603     return S_OK;
604
605 error:
606     for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
607     heap_free( columns );
608     heap_free( row );
609     return hr;
610 }
611
612 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
613 {
614     HRESULT hr;
615     struct table *table;
616     struct column *columns;
617     UINT num_cols;
618     BYTE *row;
619
620     hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
621     if (hr != S_OK) return hr;
622
623     if (!(table = create_table( name, num_cols, columns, 1, row, NULL )))
624     {
625         free_columns( columns, num_cols );
626         heap_free( row );
627         return E_OUTOFMEMORY;
628     }
629     if (!add_table( table )) free_table( table ); /* already exists */
630     return S_OK;
631 }
632
633 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
634 {
635     static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
636     static const WCHAR outW[] = {'O','U','T',0};
637     static const WCHAR inW[] = {'I','N',0};
638     UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method );
639     WCHAR *ret;
640
641     if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
642     sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW );
643     return struprW( ret );
644 }
645
646 static HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
647                                  IWbemClassObject **sig )
648 {
649     static const WCHAR selectW[] =
650         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
651          '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
652          'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
653          'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
654          'D','i','r','e','c','t','i','o','n','%','s',0};
655     static const WCHAR geW[] = {'>','=','0',0};
656     static const WCHAR leW[] = {'<','=','0',0};
657     UINT len = SIZEOF(selectW) + SIZEOF(geW);
658     IEnumWbemClassObject *iter;
659     WCHAR *query, *name;
660     HRESULT hr;
661
662     len += strlenW( class ) + strlenW( method );
663     if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
664     sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW );
665
666     hr = exec_query( query, &iter );
667     heap_free( query );
668     if (hr != S_OK) return hr;
669
670     if (!(name = build_signature_table_name( class, method, dir )))
671     {
672         IEnumWbemClassObject_Release( iter );
673         return E_OUTOFMEMORY;
674     }
675     hr = create_signature_table( iter, name );
676     IEnumWbemClassObject_Release( iter );
677     if (hr != S_OK)
678     {
679         heap_free( name );
680         return hr;
681     }
682     return get_object( name, sig );
683 }
684
685 static HRESULT WINAPI class_object_GetMethod(
686     IWbemClassObject *iface,
687     LPCWSTR wszName,
688     LONG lFlags,
689     IWbemClassObject **ppInSignature,
690     IWbemClassObject **ppOutSignature )
691 {
692     struct class_object *co = impl_from_IWbemClassObject( iface );
693     HRESULT hr;
694
695     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
696
697     hr = create_signature( co->name, wszName, PARAM_IN, ppInSignature );
698     if (hr != S_OK) return hr;
699
700     hr = create_signature( co->name, wszName, PARAM_OUT, ppOutSignature );
701     if (hr != S_OK) IWbemClassObject_Release( *ppInSignature );
702     return hr;
703 }
704
705 static HRESULT WINAPI class_object_PutMethod(
706     IWbemClassObject *iface,
707     LPCWSTR wszName,
708     LONG lFlags,
709     IWbemClassObject *pInSignature,
710     IWbemClassObject *pOutSignature )
711 {
712     FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
713     return E_NOTIMPL;
714 }
715
716 static HRESULT WINAPI class_object_DeleteMethod(
717     IWbemClassObject *iface,
718     LPCWSTR wszName )
719 {
720     FIXME("%p, %s\n", iface, debugstr_w(wszName));
721     return E_NOTIMPL;
722 }
723
724 static HRESULT WINAPI class_object_BeginMethodEnumeration(
725     IWbemClassObject *iface,
726     LONG lEnumFlags)
727 {
728     struct class_object *co = impl_from_IWbemClassObject( iface );
729
730     TRACE("%p, %08x\n", iface, lEnumFlags);
731
732     if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
733
734     if (co->iter)
735     {
736         WARN("not allowed on instance\n");
737         return WBEM_E_ILLEGAL_OPERATION;
738     }
739     co->index_method = 0;
740     return S_OK;
741 }
742
743 static HRESULT WINAPI class_object_NextMethod(
744     IWbemClassObject *iface,
745     LONG lFlags,
746     BSTR *pstrName,
747     IWbemClassObject **ppInSignature,
748     IWbemClassObject **ppOutSignature)
749 {
750     struct class_object *co = impl_from_IWbemClassObject( iface );
751     const WCHAR *method;
752     HRESULT hr;
753
754     TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
755
756     if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
757
758     hr = create_signature( co->name, method, PARAM_IN, ppInSignature );
759     if (hr != S_OK) return hr;
760
761     hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature );
762     if (hr != S_OK) IWbemClassObject_Release( *ppInSignature );
763     else
764     {
765         if (!(*pstrName = SysAllocString( method )))
766         {
767             IWbemClassObject_Release( *ppInSignature );
768             IWbemClassObject_Release( *ppOutSignature );
769             return E_OUTOFMEMORY;
770         }
771         co->index_method++;
772     }
773     return hr;
774 }
775
776 static HRESULT WINAPI class_object_EndMethodEnumeration(
777     IWbemClassObject *iface )
778 {
779     struct class_object *co = impl_from_IWbemClassObject( iface );
780
781     TRACE("%p\n", iface);
782
783     co->index_method = 0;
784     return S_OK;
785 }
786
787 static HRESULT WINAPI class_object_GetMethodQualifierSet(
788     IWbemClassObject *iface,
789     LPCWSTR wszMethod,
790     IWbemQualifierSet **ppQualSet)
791 {
792     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
793     return E_NOTIMPL;
794 }
795
796 static HRESULT WINAPI class_object_GetMethodOrigin(
797     IWbemClassObject *iface,
798     LPCWSTR wszMethodName,
799     BSTR *pstrClassName)
800 {
801     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
802     return E_NOTIMPL;
803 }
804
805 static const IWbemClassObjectVtbl class_object_vtbl =
806 {
807     class_object_QueryInterface,
808     class_object_AddRef,
809     class_object_Release,
810     class_object_GetQualifierSet,
811     class_object_Get,
812     class_object_Put,
813     class_object_Delete,
814     class_object_GetNames,
815     class_object_BeginEnumeration,
816     class_object_Next,
817     class_object_EndEnumeration,
818     class_object_GetPropertyQualifierSet,
819     class_object_Clone,
820     class_object_GetObjectText,
821     class_object_SpawnDerivedClass,
822     class_object_SpawnInstance,
823     class_object_CompareTo,
824     class_object_GetPropertyOrigin,
825     class_object_InheritsFrom,
826     class_object_GetMethod,
827     class_object_PutMethod,
828     class_object_DeleteMethod,
829     class_object_BeginMethodEnumeration,
830     class_object_NextMethod,
831     class_object_EndMethodEnumeration,
832     class_object_GetMethodQualifierSet,
833     class_object_GetMethodOrigin
834 };
835
836 HRESULT create_class_object(
837     const WCHAR *name, IEnumWbemClassObject *iter, UINT index, IWbemClassObject **obj )
838 {
839     struct class_object *co;
840
841     TRACE("%s, %p\n", debugstr_w(name), obj);
842
843     co = heap_alloc( sizeof(*co) );
844     if (!co) return E_OUTOFMEMORY;
845
846     co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
847     co->refs  = 1;
848     co->name  = heap_strdupW( name );
849     if (!co->name)
850     {
851         heap_free( co );
852         return E_OUTOFMEMORY;
853     }
854     co->iter           = iter;
855     co->index          = index;
856     co->index_method   = 0;
857     co->index_property = 0;
858     if (iter) IEnumWbemClassObject_AddRef( iter );
859
860     *obj = &co->IWbemClassObject_iface;
861
862     TRACE("returning iface %p\n", *obj);
863     return S_OK;
864 }