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