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