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