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, ¶m, &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