xref: /reactos/dll/win32/wbemprox/class.c (revision 628f4c99)
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 <stdarg.h>
22 #ifdef __REACTOS__
23 #include <wchar.h>
24 #endif
25 
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 #include "wbemcli.h"
30 
31 #include "wine/debug.h"
32 #include "wbemprox_private.h"
33 
34 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
35 
36 struct enum_class_object
37 {
38     IEnumWbemClassObject IEnumWbemClassObject_iface;
39     LONG refs;
40     struct query *query;
41     UINT index;
42 };
43 
impl_from_IEnumWbemClassObject(IEnumWbemClassObject * iface)44 static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
45     IEnumWbemClassObject *iface )
46 {
47     return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface);
48 }
49 
enum_class_object_AddRef(IEnumWbemClassObject * iface)50 static ULONG WINAPI enum_class_object_AddRef(
51     IEnumWbemClassObject *iface )
52 {
53     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
54     return InterlockedIncrement( &ec->refs );
55 }
56 
enum_class_object_Release(IEnumWbemClassObject * iface)57 static ULONG WINAPI enum_class_object_Release(
58     IEnumWbemClassObject *iface )
59 {
60     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
61     LONG refs = InterlockedDecrement( &ec->refs );
62     if (!refs)
63     {
64         TRACE("destroying %p\n", ec);
65         release_query( ec->query );
66         heap_free( ec );
67     }
68     return refs;
69 }
70 
enum_class_object_QueryInterface(IEnumWbemClassObject * iface,REFIID riid,void ** ppvObject)71 static HRESULT WINAPI enum_class_object_QueryInterface(
72     IEnumWbemClassObject *iface,
73     REFIID riid,
74     void **ppvObject )
75 {
76     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
77 
78     TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject );
79 
80     if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) ||
81          IsEqualGUID( riid, &IID_IUnknown ) )
82     {
83         *ppvObject = ec;
84     }
85     else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
86     {
87         *ppvObject = &client_security;
88         return S_OK;
89     }
90     else
91     {
92         FIXME("interface %s not implemented\n", debugstr_guid(riid));
93         return E_NOINTERFACE;
94     }
95     IEnumWbemClassObject_AddRef( iface );
96     return S_OK;
97 }
98 
enum_class_object_Reset(IEnumWbemClassObject * iface)99 static HRESULT WINAPI enum_class_object_Reset(
100     IEnumWbemClassObject *iface )
101 {
102     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
103 
104     TRACE("%p\n", iface);
105 
106     ec->index = 0;
107     return WBEM_S_NO_ERROR;
108 }
109 
enum_class_object_Next(IEnumWbemClassObject * iface,LONG lTimeout,ULONG uCount,IWbemClassObject ** apObjects,ULONG * puReturned)110 static HRESULT WINAPI enum_class_object_Next(
111     IEnumWbemClassObject *iface,
112     LONG lTimeout,
113     ULONG uCount,
114     IWbemClassObject **apObjects,
115     ULONG *puReturned )
116 {
117     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
118     struct view *view = ec->query->view;
119     struct table *table;
120     static int once = 0;
121     HRESULT hr;
122 
123     TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
124 
125     if (!uCount) return WBEM_S_FALSE;
126     if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
127     if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
128 
129     *puReturned = 0;
130     if (ec->index >= view->result_count) return WBEM_S_FALSE;
131 
132     table = get_view_table( view, ec->index );
133     hr = create_class_object( table->name, iface, ec->index, NULL, apObjects );
134     if (hr != S_OK) return hr;
135 
136     ec->index++;
137     *puReturned = 1;
138     if (ec->index == view->result_count && uCount > 1) return WBEM_S_FALSE;
139     if (uCount > 1) return WBEM_S_TIMEDOUT;
140     return WBEM_S_NO_ERROR;
141 }
142 
enum_class_object_NextAsync(IEnumWbemClassObject * iface,ULONG uCount,IWbemObjectSink * pSink)143 static HRESULT WINAPI enum_class_object_NextAsync(
144     IEnumWbemClassObject *iface,
145     ULONG uCount,
146     IWbemObjectSink *pSink )
147 {
148     FIXME("%p, %u, %p\n", iface, uCount, pSink);
149     return E_NOTIMPL;
150 }
151 
enum_class_object_Clone(IEnumWbemClassObject * iface,IEnumWbemClassObject ** ppEnum)152 static HRESULT WINAPI enum_class_object_Clone(
153     IEnumWbemClassObject *iface,
154     IEnumWbemClassObject **ppEnum )
155 {
156     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
157 
158     TRACE("%p, %p\n", iface, ppEnum);
159 
160     return EnumWbemClassObject_create( ec->query, (void **)ppEnum );
161 }
162 
enum_class_object_Skip(IEnumWbemClassObject * iface,LONG lTimeout,ULONG nCount)163 static HRESULT WINAPI enum_class_object_Skip(
164     IEnumWbemClassObject *iface,
165     LONG lTimeout,
166     ULONG nCount )
167 {
168     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
169     struct view *view = ec->query->view;
170     static int once = 0;
171 
172     TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
173 
174     if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
175 
176     if (!view->result_count) return WBEM_S_FALSE;
177 
178     if (nCount > view->result_count - ec->index)
179     {
180         ec->index = view->result_count - 1;
181         return WBEM_S_FALSE;
182     }
183     ec->index += nCount;
184     return WBEM_S_NO_ERROR;
185 }
186 
187 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
188 {
189     enum_class_object_QueryInterface,
190     enum_class_object_AddRef,
191     enum_class_object_Release,
192     enum_class_object_Reset,
193     enum_class_object_Next,
194     enum_class_object_NextAsync,
195     enum_class_object_Clone,
196     enum_class_object_Skip
197 };
198 
EnumWbemClassObject_create(struct query * query,LPVOID * ppObj)199 HRESULT EnumWbemClassObject_create( struct query *query, LPVOID *ppObj )
200 {
201     struct enum_class_object *ec;
202 
203     TRACE("%p\n", ppObj);
204 
205     ec = heap_alloc( sizeof(*ec) );
206     if (!ec) return E_OUTOFMEMORY;
207 
208     ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
209     ec->refs  = 1;
210     ec->query = addref_query( query );
211     ec->index = 0;
212 
213     *ppObj = &ec->IEnumWbemClassObject_iface;
214 
215     TRACE("returning iface %p\n", *ppObj);
216     return S_OK;
217 }
218 
create_record(struct table * table)219 static struct record *create_record( struct table *table )
220 {
221     UINT i;
222     struct record *record;
223 
224     if (!(record = heap_alloc( sizeof(struct record) ))) return NULL;
225     if (!(record->fields = heap_alloc( table->num_cols * sizeof(struct field) )))
226     {
227         heap_free( record );
228         return NULL;
229     }
230     for (i = 0; i < table->num_cols; i++)
231     {
232         record->fields[i].type    = table->columns[i].type;
233         record->fields[i].u.ival  = 0;
234     }
235     record->count = table->num_cols;
236     record->table = addref_table( table );
237     return record;
238 }
239 
destroy_array(struct array * array,CIMTYPE type)240 void destroy_array( struct array *array, CIMTYPE type )
241 {
242     UINT i;
243     if (!array) return;
244     if (type == CIM_STRING || type == CIM_DATETIME || type == CIM_REFERENCE)
245     {
246         for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * array->elem_size) );
247     }
248     heap_free( array->ptr );
249     heap_free( array );
250 }
251 
destroy_record(struct record * record)252 static void destroy_record( struct record *record )
253 {
254     UINT i;
255 
256     if (!record) return;
257     release_table( record->table );
258     for (i = 0; i < record->count; i++)
259     {
260         if (record->fields[i].type == CIM_STRING ||
261             record->fields[i].type == CIM_DATETIME ||
262             record->fields[i].type == CIM_REFERENCE) heap_free( record->fields[i].u.sval );
263         else if (record->fields[i].type & CIM_FLAG_ARRAY)
264             destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK );
265     }
266     heap_free( record->fields );
267     heap_free( record );
268 }
269 
270 struct class_object
271 {
272     IWbemClassObject IWbemClassObject_iface;
273     LONG refs;
274     WCHAR *name;
275     IEnumWbemClassObject *iter;
276     UINT index;
277     UINT index_method;
278     UINT index_property;
279     struct record *record; /* uncommitted instance */
280 };
281 
impl_from_IWbemClassObject(IWbemClassObject * iface)282 static inline struct class_object *impl_from_IWbemClassObject(
283     IWbemClassObject *iface )
284 {
285     return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
286 }
287 
class_object_AddRef(IWbemClassObject * iface)288 static ULONG WINAPI class_object_AddRef(
289     IWbemClassObject *iface )
290 {
291     struct class_object *co = impl_from_IWbemClassObject( iface );
292     return InterlockedIncrement( &co->refs );
293 }
294 
class_object_Release(IWbemClassObject * iface)295 static ULONG WINAPI class_object_Release(
296     IWbemClassObject *iface )
297 {
298     struct class_object *co = impl_from_IWbemClassObject( iface );
299     LONG refs = InterlockedDecrement( &co->refs );
300     if (!refs)
301     {
302         TRACE("destroying %p\n", co);
303         if (co->iter) IEnumWbemClassObject_Release( co->iter );
304         destroy_record( co->record );
305         heap_free( co->name );
306         heap_free( co );
307     }
308     return refs;
309 }
310 
class_object_QueryInterface(IWbemClassObject * iface,REFIID riid,void ** ppvObject)311 static HRESULT WINAPI class_object_QueryInterface(
312     IWbemClassObject *iface,
313     REFIID riid,
314     void **ppvObject )
315 {
316     struct class_object *co = impl_from_IWbemClassObject( iface );
317 
318     TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
319 
320     if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
321          IsEqualGUID( riid, &IID_IUnknown ) )
322     {
323         *ppvObject = co;
324     }
325     else if (IsEqualGUID( riid, &IID_IClientSecurity ))
326     {
327         *ppvObject = &client_security;
328         return S_OK;
329     }
330     else
331     {
332         FIXME("interface %s not implemented\n", debugstr_guid(riid));
333         return E_NOINTERFACE;
334     }
335     IWbemClassObject_AddRef( iface );
336     return S_OK;
337 }
338 
class_object_GetQualifierSet(IWbemClassObject * iface,IWbemQualifierSet ** ppQualSet)339 static HRESULT WINAPI class_object_GetQualifierSet(
340     IWbemClassObject *iface,
341     IWbemQualifierSet **ppQualSet )
342 {
343     struct class_object *co = impl_from_IWbemClassObject( iface );
344 
345     TRACE("%p, %p\n", iface, ppQualSet);
346 
347     return WbemQualifierSet_create( co->name, NULL, (void **)ppQualSet );
348 }
349 
record_get_value(const struct record * record,UINT index,VARIANT * var,CIMTYPE * type)350 static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type )
351 {
352     VARTYPE vartype = to_vartype( record->fields[index].type & CIM_TYPE_MASK );
353 
354     if (type) *type = record->fields[index].type;
355 
356     if (record->fields[index].type & CIM_FLAG_ARRAY)
357     {
358         V_VT( var ) = vartype | VT_ARRAY;
359         V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & CIM_TYPE_MASK );
360         return S_OK;
361     }
362     switch (record->fields[index].type)
363     {
364     case CIM_STRING:
365     case CIM_DATETIME:
366     case CIM_REFERENCE:
367         V_BSTR( var ) = SysAllocString( record->fields[index].u.sval );
368         break;
369     case CIM_SINT32:
370         V_I4( var ) = record->fields[index].u.ival;
371         break;
372     case CIM_UINT32:
373         V_UI4( var ) = record->fields[index].u.ival;
374         break;
375     default:
376         FIXME("unhandled type %u\n", record->fields[index].type);
377         return WBEM_E_INVALID_PARAMETER;
378     }
379     V_VT( var ) = vartype;
380     return S_OK;
381 }
382 
class_object_Get(IWbemClassObject * iface,LPCWSTR wszName,LONG lFlags,VARIANT * pVal,CIMTYPE * pType,LONG * plFlavor)383 static HRESULT WINAPI class_object_Get(
384     IWbemClassObject *iface,
385     LPCWSTR wszName,
386     LONG lFlags,
387     VARIANT *pVal,
388     CIMTYPE *pType,
389     LONG *plFlavor )
390 {
391     struct class_object *co = impl_from_IWbemClassObject( iface );
392     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
393 
394     TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
395 
396     if (co->record)
397     {
398         UINT index;
399         HRESULT hr;
400 
401         if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
402         return record_get_value( co->record, index, pVal, pType );
403     }
404     return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor );
405 }
406 
record_set_value(struct record * record,UINT index,VARIANT * var)407 static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var )
408 {
409     LONGLONG val;
410     CIMTYPE type;
411     HRESULT hr;
412 
413     if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr;
414     if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH;
415 
416     if (type & CIM_FLAG_ARRAY)
417     {
418         record->fields[index].u.aval = (struct array *)(INT_PTR)val;
419         return S_OK;
420     }
421     switch (type)
422     {
423     case CIM_STRING:
424     case CIM_DATETIME:
425     case CIM_REFERENCE:
426         record->fields[index].u.sval = (WCHAR *)(INT_PTR)val;
427         return S_OK;
428     case CIM_SINT16:
429     case CIM_UINT16:
430     case CIM_SINT32:
431     case CIM_UINT32:
432         record->fields[index].u.ival = val;
433         return S_OK;
434     default:
435         FIXME("unhandled type %u\n", type);
436         break;
437     }
438     return WBEM_E_INVALID_PARAMETER;
439 }
440 
class_object_Put(IWbemClassObject * iface,LPCWSTR wszName,LONG lFlags,VARIANT * pVal,CIMTYPE Type)441 static HRESULT WINAPI class_object_Put(
442     IWbemClassObject *iface,
443     LPCWSTR wszName,
444     LONG lFlags,
445     VARIANT *pVal,
446     CIMTYPE Type )
447 {
448     struct class_object *co = impl_from_IWbemClassObject( iface );
449     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
450 
451     TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
452 
453     if (co->record)
454     {
455         UINT index;
456         HRESULT hr;
457 
458         if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
459         return record_set_value( co->record, index, pVal );
460     }
461     return put_propval( ec->query->view, co->index, wszName, pVal, Type );
462 }
463 
class_object_Delete(IWbemClassObject * iface,LPCWSTR wszName)464 static HRESULT WINAPI class_object_Delete(
465     IWbemClassObject *iface,
466     LPCWSTR wszName )
467 {
468     FIXME("%p, %s\n", iface, debugstr_w(wszName));
469     return E_NOTIMPL;
470 }
471 
class_object_GetNames(IWbemClassObject * iface,LPCWSTR wszQualifierName,LONG lFlags,VARIANT * pQualifierVal,SAFEARRAY ** pNames)472 static HRESULT WINAPI class_object_GetNames(
473     IWbemClassObject *iface,
474     LPCWSTR wszQualifierName,
475     LONG lFlags,
476     VARIANT *pQualifierVal,
477     SAFEARRAY **pNames )
478 {
479     struct class_object *co = impl_from_IWbemClassObject( iface );
480     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
481 
482     TRACE("%p, %s, %08x, %s, %p\n", iface, debugstr_w(wszQualifierName), lFlags,
483           debugstr_variant(pQualifierVal), pNames);
484 
485     if (lFlags != WBEM_FLAG_ALWAYS &&
486         lFlags != WBEM_FLAG_NONSYSTEM_ONLY &&
487         lFlags != WBEM_FLAG_SYSTEM_ONLY)
488     {
489         FIXME("flags %08x not supported\n", lFlags);
490         return E_NOTIMPL;
491     }
492     if (wszQualifierName || pQualifierVal)
493         FIXME("qualifier not supported\n");
494 
495     return get_properties( ec->query->view, co->index, lFlags, pNames );
496 }
497 
class_object_BeginEnumeration(IWbemClassObject * iface,LONG lEnumFlags)498 static HRESULT WINAPI class_object_BeginEnumeration(
499     IWbemClassObject *iface,
500     LONG lEnumFlags )
501 {
502     struct class_object *co = impl_from_IWbemClassObject( iface );
503 
504     TRACE("%p, %08x\n", iface, lEnumFlags);
505 
506     if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
507 
508     co->index_property = 0;
509     return S_OK;
510 }
511 
class_object_Next(IWbemClassObject * iface,LONG lFlags,BSTR * strName,VARIANT * pVal,CIMTYPE * pType,LONG * plFlavor)512 static HRESULT WINAPI class_object_Next(
513     IWbemClassObject *iface,
514     LONG lFlags,
515     BSTR *strName,
516     VARIANT *pVal,
517     CIMTYPE *pType,
518     LONG *plFlavor )
519 {
520     struct class_object *obj = impl_from_IWbemClassObject( iface );
521     struct enum_class_object *iter = impl_from_IEnumWbemClassObject( obj->iter );
522     struct view *view = iter->query->view;
523     struct table *table = get_view_table( view, obj->index );
524     BSTR prop;
525     HRESULT hr;
526     UINT i;
527 
528     TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
529 
530     for (i = obj->index_property; i < table->num_cols; i++)
531     {
532         if (is_method( table, i )) continue;
533         if (!is_result_prop( view, table->columns[i].name )) continue;
534         if (!(prop = SysAllocString( table->columns[i].name ))) return E_OUTOFMEMORY;
535         if ((hr = get_propval( view, obj->index, prop, pVal, pType, plFlavor )) != S_OK)
536         {
537             SysFreeString( prop );
538             return hr;
539         }
540 
541         obj->index_property = i + 1;
542         if (strName) *strName = prop;
543         else SysFreeString( prop );
544 
545         return S_OK;
546     }
547     return WBEM_S_NO_MORE_DATA;
548 }
549 
class_object_EndEnumeration(IWbemClassObject * iface)550 static HRESULT WINAPI class_object_EndEnumeration(
551     IWbemClassObject *iface )
552 {
553     struct class_object *co = impl_from_IWbemClassObject( iface );
554 
555     TRACE("%p\n", iface);
556 
557     co->index_property = 0;
558     return S_OK;
559 }
560 
class_object_GetPropertyQualifierSet(IWbemClassObject * iface,LPCWSTR wszProperty,IWbemQualifierSet ** ppQualSet)561 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
562     IWbemClassObject *iface,
563     LPCWSTR wszProperty,
564     IWbemQualifierSet **ppQualSet )
565 {
566     struct class_object *co = impl_from_IWbemClassObject( iface );
567 
568     TRACE("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
569 
570     return WbemQualifierSet_create( co->name, wszProperty, (void **)ppQualSet );
571 }
572 
class_object_Clone(IWbemClassObject * iface,IWbemClassObject ** ppCopy)573 static HRESULT WINAPI class_object_Clone(
574     IWbemClassObject *iface,
575     IWbemClassObject **ppCopy )
576 {
577     FIXME("%p, %p\n", iface, ppCopy);
578     return E_NOTIMPL;
579 }
580 
get_body_text(const struct table * table,UINT row,UINT * len)581 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
582 {
583     static const WCHAR fmtW[] = {'\n','\t','%','s',' ','=',' ','%','s',';',0};
584     BSTR value, ret;
585     WCHAR *p;
586     UINT i;
587 
588     *len = 0;
589     for (i = 0; i < table->num_cols; i++)
590     {
591         if ((value = get_value_bstr( table, row, i )))
592         {
593             *len += ARRAY_SIZE( fmtW );
594             *len += lstrlenW( table->columns[i].name );
595             *len += SysStringLen( value );
596             SysFreeString( value );
597         }
598     }
599     if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
600     p = ret;
601     for (i = 0; i < table->num_cols; i++)
602     {
603         if ((value = get_value_bstr( table, row, i )))
604         {
605             p += swprintf( p, fmtW, table->columns[i].name, value );
606             SysFreeString( value );
607         }
608     }
609     return ret;
610 }
611 
get_object_text(const struct view * view,UINT index)612 static BSTR get_object_text( const struct view *view, UINT index )
613 {
614     static const WCHAR fmtW[] =
615         {'\n','i','n','s','t','a','n','c','e',' ','o','f',' ','%','s','\n','{','%','s','\n','}',';',0};
616     UINT len, len_body, row = view->result[index];
617     struct table *table = get_view_table( view, index );
618     BSTR ret, body;
619 
620     len = ARRAY_SIZE( fmtW );
621     len += lstrlenW( table->name );
622     if (!(body = get_body_text( table, row, &len_body ))) return NULL;
623     len += len_body;
624 
625     if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
626     swprintf( ret, fmtW, table->name, body );
627     SysFreeString( body );
628     return ret;
629 }
630 
class_object_GetObjectText(IWbemClassObject * iface,LONG lFlags,BSTR * pstrObjectText)631 static HRESULT WINAPI class_object_GetObjectText(
632     IWbemClassObject *iface,
633     LONG lFlags,
634     BSTR *pstrObjectText )
635 {
636     struct class_object *co = impl_from_IWbemClassObject( iface );
637     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
638     struct view *view = ec->query->view;
639     BSTR text;
640 
641     TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
642 
643     if (lFlags) FIXME("flags %08x not implemented\n", lFlags);
644 
645     if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
646     *pstrObjectText = text;
647     return S_OK;
648 }
649 
class_object_SpawnDerivedClass(IWbemClassObject * iface,LONG lFlags,IWbemClassObject ** ppNewClass)650 static HRESULT WINAPI class_object_SpawnDerivedClass(
651     IWbemClassObject *iface,
652     LONG lFlags,
653     IWbemClassObject **ppNewClass )
654 {
655     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
656     return E_NOTIMPL;
657 }
658 
class_object_SpawnInstance(IWbemClassObject * iface,LONG lFlags,IWbemClassObject ** ppNewInstance)659 static HRESULT WINAPI class_object_SpawnInstance(
660     IWbemClassObject *iface,
661     LONG lFlags,
662     IWbemClassObject **ppNewInstance )
663 {
664     struct class_object *co = impl_from_IWbemClassObject( iface );
665     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
666     struct table *table = get_view_table( ec->query->view, co->index );
667     struct record *record;
668 
669     TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
670 
671     if (!(record = create_record( table ))) return E_OUTOFMEMORY;
672 
673     return create_class_object( co->name, NULL, 0, record, ppNewInstance );
674 }
675 
class_object_CompareTo(IWbemClassObject * iface,LONG lFlags,IWbemClassObject * pCompareTo)676 static HRESULT WINAPI class_object_CompareTo(
677     IWbemClassObject *iface,
678     LONG lFlags,
679     IWbemClassObject *pCompareTo )
680 {
681     FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
682     return E_NOTIMPL;
683 }
684 
class_object_GetPropertyOrigin(IWbemClassObject * iface,LPCWSTR wszName,BSTR * pstrClassName)685 static HRESULT WINAPI class_object_GetPropertyOrigin(
686     IWbemClassObject *iface,
687     LPCWSTR wszName,
688     BSTR *pstrClassName )
689 {
690     FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
691     return E_NOTIMPL;
692 }
693 
class_object_InheritsFrom(IWbemClassObject * iface,LPCWSTR strAncestor)694 static HRESULT WINAPI class_object_InheritsFrom(
695     IWbemClassObject *iface,
696     LPCWSTR strAncestor )
697 {
698     FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
699     return E_NOTIMPL;
700 }
701 
count_instances(IEnumWbemClassObject * iter)702 static UINT count_instances( IEnumWbemClassObject *iter )
703 {
704     UINT count = 0;
705     while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
706     IEnumWbemClassObject_Reset( iter );
707     return count;
708 }
709 
set_default_value(CIMTYPE type,UINT val,BYTE * ptr)710 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
711 {
712     switch (type)
713     {
714     case CIM_SINT16:
715         *(INT16 *)ptr = val;
716         break;
717     case CIM_UINT16:
718         *(UINT16 *)ptr = val;
719         break;
720     case CIM_SINT32:
721         *(INT32 *)ptr = val;
722         break;
723     case CIM_UINT32:
724         *(UINT32 *)ptr = val;
725         break;
726     default:
727         FIXME("unhandled type %u\n", type);
728         break;
729     }
730 }
731 
create_signature_columns_and_data(IEnumWbemClassObject * iter,UINT * num_cols,struct column ** cols,BYTE ** data)732 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
733                                            struct column **cols, BYTE **data )
734 {
735     static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
736     static const WCHAR typeW[] = {'T','y','p','e',0};
737     static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0};
738     struct column *columns;
739     BYTE *row;
740     IWbemClassObject *param;
741     VARIANT val;
742     HRESULT hr = E_OUTOFMEMORY;
743     UINT offset = 0;
744     ULONG count;
745     int i = 0;
746 
747     count = count_instances( iter );
748     if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
749     if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
750 
751     for (;;)
752     {
753         IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
754         if (!count) break;
755 
756         hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL );
757         if (hr != S_OK) goto error;
758         columns[i].name = heap_strdupW( V_BSTR( &val ) );
759         VariantClear( &val );
760 
761         hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL );
762         if (hr != S_OK) goto error;
763         columns[i].type = V_UI4( &val );
764 
765         hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
766         if (hr != S_OK) goto error;
767         if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
768         offset += get_type_size( columns[i].type );
769 
770         IWbemClassObject_Release( param );
771         i++;
772     }
773     *num_cols = i;
774     *cols = columns;
775     *data = row;
776     return S_OK;
777 
778 error:
779     for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
780     heap_free( columns );
781     heap_free( row );
782     return hr;
783 }
784 
create_signature_table(IEnumWbemClassObject * iter,WCHAR * name)785 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
786 {
787     HRESULT hr;
788     struct table *table;
789     struct column *columns;
790     UINT num_cols;
791     BYTE *row;
792 
793     hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
794     if (hr != S_OK) return hr;
795 
796     if (!(table = create_table( name, num_cols, columns, 1, 1, row, NULL )))
797     {
798         free_columns( columns, num_cols );
799         heap_free( row );
800         return E_OUTOFMEMORY;
801     }
802     if (!add_table( table )) free_table( table ); /* already exists */
803     return S_OK;
804 }
805 
build_signature_table_name(const WCHAR * class,const WCHAR * method,enum param_direction dir)806 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
807 {
808     static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
809     static const WCHAR outW[] = {'O','U','T',0};
810     static const WCHAR inW[] = {'I','N',0};
811     UINT len = ARRAY_SIZE(fmtW) + ARRAY_SIZE(outW) + lstrlenW( class ) + lstrlenW( method );
812     WCHAR *ret;
813 
814     if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
815     swprintf( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW );
816     return _wcsupr( ret );
817 }
818 
create_signature(const WCHAR * class,const WCHAR * method,enum param_direction dir,IWbemClassObject ** sig)819 HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
820                           IWbemClassObject **sig )
821 {
822     static const WCHAR selectW[] =
823         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
824          '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
825          'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
826          'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
827          'D','i','r','e','c','t','i','o','n','%','s',0};
828     static const WCHAR geW[] = {'>','=','0',0};
829     static const WCHAR leW[] = {'<','=','0',0};
830     UINT len = ARRAY_SIZE(selectW) + ARRAY_SIZE(geW);
831     IEnumWbemClassObject *iter;
832     WCHAR *query, *name;
833     HRESULT hr;
834 
835     len += lstrlenW( class ) + lstrlenW( method );
836     if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
837     swprintf( query, selectW, class, method, dir >= 0 ? geW : leW );
838 
839     hr = exec_query( query, &iter );
840     heap_free( query );
841     if (hr != S_OK) return hr;
842 
843     if (!count_instances( iter ))
844     {
845         *sig = NULL;
846         IEnumWbemClassObject_Release( iter );
847         return S_OK;
848     }
849 
850     if (!(name = build_signature_table_name( class, method, dir )))
851     {
852         IEnumWbemClassObject_Release( iter );
853         return E_OUTOFMEMORY;
854     }
855     hr = create_signature_table( iter, name );
856     IEnumWbemClassObject_Release( iter );
857     if (hr == S_OK)
858         hr = get_object( name, sig );
859 
860     heap_free( name );
861     return hr;
862 }
863 
class_object_GetMethod(IWbemClassObject * iface,LPCWSTR wszName,LONG lFlags,IWbemClassObject ** ppInSignature,IWbemClassObject ** ppOutSignature)864 static HRESULT WINAPI class_object_GetMethod(
865     IWbemClassObject *iface,
866     LPCWSTR wszName,
867     LONG lFlags,
868     IWbemClassObject **ppInSignature,
869     IWbemClassObject **ppOutSignature )
870 {
871     struct class_object *co = impl_from_IWbemClassObject( iface );
872     IWbemClassObject *in, *out;
873     HRESULT hr;
874 
875     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
876 
877     hr = create_signature( co->name, wszName, PARAM_IN, &in );
878     if (hr != S_OK) return hr;
879 
880     hr = create_signature( co->name, wszName, PARAM_OUT, &out );
881     if (hr == S_OK)
882     {
883         if (ppInSignature) *ppInSignature = in;
884         else if (in) IWbemClassObject_Release( in );
885         if (ppOutSignature) *ppOutSignature = out;
886         else if (out) IWbemClassObject_Release( out );
887     }
888     else IWbemClassObject_Release( in );
889     return hr;
890 }
891 
class_object_PutMethod(IWbemClassObject * iface,LPCWSTR wszName,LONG lFlags,IWbemClassObject * pInSignature,IWbemClassObject * pOutSignature)892 static HRESULT WINAPI class_object_PutMethod(
893     IWbemClassObject *iface,
894     LPCWSTR wszName,
895     LONG lFlags,
896     IWbemClassObject *pInSignature,
897     IWbemClassObject *pOutSignature )
898 {
899     FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
900     return E_NOTIMPL;
901 }
902 
class_object_DeleteMethod(IWbemClassObject * iface,LPCWSTR wszName)903 static HRESULT WINAPI class_object_DeleteMethod(
904     IWbemClassObject *iface,
905     LPCWSTR wszName )
906 {
907     FIXME("%p, %s\n", iface, debugstr_w(wszName));
908     return E_NOTIMPL;
909 }
910 
class_object_BeginMethodEnumeration(IWbemClassObject * iface,LONG lEnumFlags)911 static HRESULT WINAPI class_object_BeginMethodEnumeration(
912     IWbemClassObject *iface,
913     LONG lEnumFlags)
914 {
915     struct class_object *co = impl_from_IWbemClassObject( iface );
916 
917     TRACE("%p, %08x\n", iface, lEnumFlags);
918 
919     if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
920 
921     co->index_method = 0;
922     return S_OK;
923 }
924 
class_object_NextMethod(IWbemClassObject * iface,LONG lFlags,BSTR * pstrName,IWbemClassObject ** ppInSignature,IWbemClassObject ** ppOutSignature)925 static HRESULT WINAPI class_object_NextMethod(
926     IWbemClassObject *iface,
927     LONG lFlags,
928     BSTR *pstrName,
929     IWbemClassObject **ppInSignature,
930     IWbemClassObject **ppOutSignature)
931 {
932     struct class_object *co = impl_from_IWbemClassObject( iface );
933     BSTR method;
934     HRESULT hr;
935 
936     TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
937 
938     if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
939 
940     hr = create_signature( co->name, method, PARAM_IN, ppInSignature );
941     if (hr != S_OK)
942     {
943         SysFreeString( method );
944         return hr;
945     }
946     hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature );
947     if (hr != S_OK)
948     {
949         SysFreeString( method );
950         if (*ppInSignature)
951             IWbemClassObject_Release( *ppInSignature );
952     }
953     else
954     {
955         *pstrName = method;
956         co->index_method++;
957     }
958     return hr;
959 }
960 
class_object_EndMethodEnumeration(IWbemClassObject * iface)961 static HRESULT WINAPI class_object_EndMethodEnumeration(
962     IWbemClassObject *iface )
963 {
964     struct class_object *co = impl_from_IWbemClassObject( iface );
965 
966     TRACE("%p\n", iface);
967 
968     co->index_method = 0;
969     return S_OK;
970 }
971 
class_object_GetMethodQualifierSet(IWbemClassObject * iface,LPCWSTR wszMethod,IWbemQualifierSet ** ppQualSet)972 static HRESULT WINAPI class_object_GetMethodQualifierSet(
973     IWbemClassObject *iface,
974     LPCWSTR wszMethod,
975     IWbemQualifierSet **ppQualSet)
976 {
977     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
978     return E_NOTIMPL;
979 }
980 
class_object_GetMethodOrigin(IWbemClassObject * iface,LPCWSTR wszMethodName,BSTR * pstrClassName)981 static HRESULT WINAPI class_object_GetMethodOrigin(
982     IWbemClassObject *iface,
983     LPCWSTR wszMethodName,
984     BSTR *pstrClassName)
985 {
986     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
987     return E_NOTIMPL;
988 }
989 
990 static const IWbemClassObjectVtbl class_object_vtbl =
991 {
992     class_object_QueryInterface,
993     class_object_AddRef,
994     class_object_Release,
995     class_object_GetQualifierSet,
996     class_object_Get,
997     class_object_Put,
998     class_object_Delete,
999     class_object_GetNames,
1000     class_object_BeginEnumeration,
1001     class_object_Next,
1002     class_object_EndEnumeration,
1003     class_object_GetPropertyQualifierSet,
1004     class_object_Clone,
1005     class_object_GetObjectText,
1006     class_object_SpawnDerivedClass,
1007     class_object_SpawnInstance,
1008     class_object_CompareTo,
1009     class_object_GetPropertyOrigin,
1010     class_object_InheritsFrom,
1011     class_object_GetMethod,
1012     class_object_PutMethod,
1013     class_object_DeleteMethod,
1014     class_object_BeginMethodEnumeration,
1015     class_object_NextMethod,
1016     class_object_EndMethodEnumeration,
1017     class_object_GetMethodQualifierSet,
1018     class_object_GetMethodOrigin
1019 };
1020 
create_class_object(const WCHAR * name,IEnumWbemClassObject * iter,UINT index,struct record * record,IWbemClassObject ** obj)1021 HRESULT create_class_object( const WCHAR *name, IEnumWbemClassObject *iter, UINT index,
1022                              struct record *record, IWbemClassObject **obj )
1023 {
1024     struct class_object *co;
1025 
1026     TRACE("%s, %p\n", debugstr_w(name), obj);
1027 
1028     co = heap_alloc( sizeof(*co) );
1029     if (!co) return E_OUTOFMEMORY;
1030 
1031     co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
1032     co->refs  = 1;
1033     if (!name) co->name = NULL;
1034     else if (!(co->name = heap_strdupW( name )))
1035     {
1036         heap_free( co );
1037         return E_OUTOFMEMORY;
1038     }
1039     co->iter           = iter;
1040     co->index          = index;
1041     co->index_method   = 0;
1042     co->index_property = 0;
1043     co->record         = record;
1044     if (iter) IEnumWbemClassObject_AddRef( iter );
1045 
1046     *obj = &co->IWbemClassObject_iface;
1047 
1048     TRACE("returning iface %p\n", *obj);
1049     return S_OK;
1050 }
1051