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