psapi/tests: Adjust margin for win10.
[wine/multimedia.git] / dlls / wbemprox / class.c
blobafb9f8c1debfab6c66b7d7373fef4a62234e8d06
1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
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.
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.
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
19 #define COBJMACROS
21 #include "config.h"
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
27 #include "wbemcli.h"
29 #include "wine/debug.h"
30 #include "wbemprox_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
34 struct enum_class_object
36 IEnumWbemClassObject IEnumWbemClassObject_iface;
37 LONG refs;
38 struct query *query;
39 UINT index;
42 static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
43 IEnumWbemClassObject *iface )
45 return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface);
48 static ULONG WINAPI enum_class_object_AddRef(
49 IEnumWbemClassObject *iface )
51 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
52 return InterlockedIncrement( &ec->refs );
55 static ULONG WINAPI enum_class_object_Release(
56 IEnumWbemClassObject *iface )
58 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
59 LONG refs = InterlockedDecrement( &ec->refs );
60 if (!refs)
62 TRACE("destroying %p\n", ec);
63 release_query( ec->query );
64 heap_free( ec );
66 return refs;
69 static HRESULT WINAPI enum_class_object_QueryInterface(
70 IEnumWbemClassObject *iface,
71 REFIID riid,
72 void **ppvObject )
74 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
76 TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject );
78 if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) ||
79 IsEqualGUID( riid, &IID_IUnknown ) )
81 *ppvObject = ec;
83 else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
85 *ppvObject = &client_security;
86 return S_OK;
88 else
90 FIXME("interface %s not implemented\n", debugstr_guid(riid));
91 return E_NOINTERFACE;
93 IEnumWbemClassObject_AddRef( iface );
94 return S_OK;
97 static HRESULT WINAPI enum_class_object_Reset(
98 IEnumWbemClassObject *iface )
100 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
102 TRACE("%p\n", iface);
104 ec->index = 0;
105 return WBEM_S_NO_ERROR;
108 static HRESULT WINAPI enum_class_object_Next(
109 IEnumWbemClassObject *iface,
110 LONG lTimeout,
111 ULONG uCount,
112 IWbemClassObject **apObjects,
113 ULONG *puReturned )
115 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
116 struct view *view = ec->query->view;
117 HRESULT hr;
119 TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
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");
125 *puReturned = 0;
126 if (ec->index >= view->count) return WBEM_S_FALSE;
128 hr = create_class_object( view->table->name, iface, ec->index, NULL, apObjects );
129 if (hr != S_OK) return hr;
131 ec->index++;
132 *puReturned = 1;
133 if (ec->index == view->count && uCount > 1) return WBEM_S_FALSE;
134 if (uCount > 1) return WBEM_S_TIMEDOUT;
135 return WBEM_S_NO_ERROR;
138 static HRESULT WINAPI enum_class_object_NextAsync(
139 IEnumWbemClassObject *iface,
140 ULONG uCount,
141 IWbemObjectSink *pSink )
143 FIXME("%p, %u, %p\n", iface, uCount, pSink);
144 return E_NOTIMPL;
147 static HRESULT WINAPI enum_class_object_Clone(
148 IEnumWbemClassObject *iface,
149 IEnumWbemClassObject **ppEnum )
151 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
153 TRACE("%p, %p\n", iface, ppEnum);
155 return EnumWbemClassObject_create( ec->query, (void **)ppEnum );
158 static HRESULT WINAPI enum_class_object_Skip(
159 IEnumWbemClassObject *iface,
160 LONG lTimeout,
161 ULONG nCount )
163 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
164 struct view *view = ec->query->view;
166 TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
168 if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
170 if (!view->count) return WBEM_S_FALSE;
172 if (nCount > view->count - ec->index)
174 ec->index = view->count - 1;
175 return WBEM_S_FALSE;
177 ec->index += nCount;
178 return WBEM_S_NO_ERROR;
181 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
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
193 HRESULT EnumWbemClassObject_create( struct query *query, LPVOID *ppObj )
195 struct enum_class_object *ec;
197 TRACE("%p\n", ppObj);
199 ec = heap_alloc( sizeof(*ec) );
200 if (!ec) return E_OUTOFMEMORY;
202 ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
203 ec->refs = 1;
204 ec->query = addref_query( query );
205 ec->index = 0;
207 *ppObj = &ec->IEnumWbemClassObject_iface;
209 TRACE("returning iface %p\n", *ppObj);
210 return S_OK;
213 static struct record *create_record( struct table *table )
215 UINT i;
216 struct record *record;
218 if (!(record = heap_alloc( sizeof(struct record) ))) return NULL;
219 if (!(record->fields = heap_alloc( table->num_cols * sizeof(struct field) )))
221 heap_free( record );
222 return NULL;
224 for (i = 0; i < table->num_cols; i++)
226 record->fields[i].type = table->columns[i].type;
227 record->fields[i].vartype = table->columns[i].vartype;
228 record->fields[i].u.ival = 0;
230 record->count = table->num_cols;
231 record->table = addref_table( table );
232 return record;
235 void destroy_array( struct array *array, CIMTYPE type )
237 UINT i, size;
239 if (!array) return;
240 if (type == CIM_STRING || type == CIM_DATETIME)
242 size = get_type_size( type );
243 for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * size) );
245 heap_free( array->ptr );
246 heap_free( array );
249 static void destroy_record( struct record *record )
251 UINT i;
253 if (!record) return;
254 release_table( record->table );
255 for (i = 0; i < record->count; i++)
257 if (record->fields[i].type == CIM_STRING || record->fields[i].type == CIM_DATETIME)
258 heap_free( record->fields[i].u.sval );
259 else if (record->fields[i].type & CIM_FLAG_ARRAY)
260 destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK );
262 heap_free( record->fields );
263 heap_free( record );
266 struct class_object
268 IWbemClassObject IWbemClassObject_iface;
269 LONG refs;
270 WCHAR *name;
271 IEnumWbemClassObject *iter;
272 UINT index;
273 UINT index_method;
274 UINT index_property;
275 struct record *record; /* uncommitted instance */
278 static inline struct class_object *impl_from_IWbemClassObject(
279 IWbemClassObject *iface )
281 return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
284 static ULONG WINAPI class_object_AddRef(
285 IWbemClassObject *iface )
287 struct class_object *co = impl_from_IWbemClassObject( iface );
288 return InterlockedIncrement( &co->refs );
291 static ULONG WINAPI class_object_Release(
292 IWbemClassObject *iface )
294 struct class_object *co = impl_from_IWbemClassObject( iface );
295 LONG refs = InterlockedDecrement( &co->refs );
296 if (!refs)
298 TRACE("destroying %p\n", co);
299 if (co->iter) IEnumWbemClassObject_Release( co->iter );
300 destroy_record( co->record );
301 heap_free( co->name );
302 heap_free( co );
304 return refs;
307 static HRESULT WINAPI class_object_QueryInterface(
308 IWbemClassObject *iface,
309 REFIID riid,
310 void **ppvObject )
312 struct class_object *co = impl_from_IWbemClassObject( iface );
314 TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
316 if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
317 IsEqualGUID( riid, &IID_IUnknown ) )
319 *ppvObject = co;
321 else if (IsEqualGUID( riid, &IID_IClientSecurity ))
323 *ppvObject = &client_security;
324 return S_OK;
326 else
328 FIXME("interface %s not implemented\n", debugstr_guid(riid));
329 return E_NOINTERFACE;
331 IWbemClassObject_AddRef( iface );
332 return S_OK;
335 static HRESULT WINAPI class_object_GetQualifierSet(
336 IWbemClassObject *iface,
337 IWbemQualifierSet **ppQualSet )
339 FIXME("%p, %p\n", iface, ppQualSet);
340 return E_NOTIMPL;
343 static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type )
345 VARTYPE vartype = record->fields[index].vartype;
347 if (type) *type = record->fields[index].type;
349 if (record->fields[index].type & CIM_FLAG_ARRAY)
351 V_VT( var ) = vartype ? vartype : to_vartype( record->fields[index].type & CIM_TYPE_MASK ) | VT_ARRAY;
352 V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & CIM_TYPE_MASK );
353 return S_OK;
355 switch (record->fields[index].type)
357 case CIM_STRING:
358 case CIM_DATETIME:
359 if (!vartype) vartype = VT_BSTR;
360 V_BSTR( var ) = SysAllocString( record->fields[index].u.sval );
361 break;
362 case CIM_SINT32:
363 if (!vartype) vartype = VT_I4;
364 V_I4( var ) = record->fields[index].u.ival;
365 break;
366 case CIM_UINT32:
367 if (!vartype) vartype = VT_UI4;
368 V_UI4( var ) = record->fields[index].u.ival;
369 break;
370 default:
371 FIXME("unhandled type %u\n", record->fields[index].type);
372 return WBEM_E_INVALID_PARAMETER;
374 V_VT( var ) = vartype;
375 return S_OK;
378 static HRESULT WINAPI class_object_Get(
379 IWbemClassObject *iface,
380 LPCWSTR wszName,
381 LONG lFlags,
382 VARIANT *pVal,
383 CIMTYPE *pType,
384 LONG *plFlavor )
386 struct class_object *co = impl_from_IWbemClassObject( iface );
387 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
389 TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
391 if (co->record)
393 UINT index;
394 HRESULT hr;
396 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
397 return record_get_value( co->record, index, pVal, pType );
399 return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor );
402 static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var )
404 LONGLONG val;
405 CIMTYPE type;
406 HRESULT hr;
408 if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr;
409 if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH;
411 if (type & CIM_FLAG_ARRAY)
413 record->fields[index].u.aval = (struct array *)(INT_PTR)val;
414 return S_OK;
416 switch (type)
418 case CIM_STRING:
419 case CIM_DATETIME:
420 record->fields[index].u.sval = (WCHAR *)(INT_PTR)val;
421 return S_OK;
422 case CIM_SINT16:
423 case CIM_UINT16:
424 case CIM_SINT32:
425 case CIM_UINT32:
426 record->fields[index].u.ival = val;
427 return S_OK;
428 default:
429 FIXME("unhandled type %u\n", type);
430 break;
432 return WBEM_E_INVALID_PARAMETER;
435 static HRESULT WINAPI class_object_Put(
436 IWbemClassObject *iface,
437 LPCWSTR wszName,
438 LONG lFlags,
439 VARIANT *pVal,
440 CIMTYPE Type )
442 struct class_object *co = impl_from_IWbemClassObject( iface );
443 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
445 TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
447 if (co->record)
449 UINT index;
450 HRESULT hr;
452 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
453 return record_set_value( co->record, index, pVal );
455 return put_propval( ec->query->view, co->index, wszName, pVal, Type );
458 static HRESULT WINAPI class_object_Delete(
459 IWbemClassObject *iface,
460 LPCWSTR wszName )
462 FIXME("%p, %s\n", iface, debugstr_w(wszName));
463 return E_NOTIMPL;
466 static HRESULT WINAPI class_object_GetNames(
467 IWbemClassObject *iface,
468 LPCWSTR wszQualifierName,
469 LONG lFlags,
470 VARIANT *pQualifierVal,
471 SAFEARRAY **pNames )
473 struct class_object *co = impl_from_IWbemClassObject( iface );
474 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
476 TRACE("%p, %s, %08x, %s, %p\n", iface, debugstr_w(wszQualifierName), lFlags,
477 debugstr_variant(pQualifierVal), pNames);
479 if (lFlags != WBEM_FLAG_ALWAYS &&
480 lFlags != WBEM_FLAG_NONSYSTEM_ONLY &&
481 lFlags != WBEM_FLAG_SYSTEM_ONLY)
483 FIXME("flags %08x not supported\n", lFlags);
484 return E_NOTIMPL;
486 if (wszQualifierName || pQualifierVal)
487 FIXME("qualifier not supported\n");
489 return get_properties( ec->query->view, lFlags, pNames );
492 static HRESULT WINAPI class_object_BeginEnumeration(
493 IWbemClassObject *iface,
494 LONG lEnumFlags )
496 struct class_object *co = impl_from_IWbemClassObject( iface );
498 TRACE("%p, %08x\n", iface, lEnumFlags);
500 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
502 co->index_property = 0;
503 return S_OK;
506 static HRESULT WINAPI class_object_Next(
507 IWbemClassObject *iface,
508 LONG lFlags,
509 BSTR *strName,
510 VARIANT *pVal,
511 CIMTYPE *pType,
512 LONG *plFlavor )
514 struct class_object *obj = impl_from_IWbemClassObject( iface );
515 struct enum_class_object *iter = impl_from_IEnumWbemClassObject( obj->iter );
516 struct view *view = iter->query->view;
517 BSTR prop;
518 HRESULT hr;
519 UINT i;
521 TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
523 for (i = obj->index_property; i < view->table->num_cols; i++)
525 if (is_method( view->table, i )) continue;
526 if (!is_selected_prop( view, view->table->columns[i].name )) continue;
527 if (!(prop = SysAllocString( view->table->columns[i].name ))) return E_OUTOFMEMORY;
528 if ((hr = get_propval( view, obj->index, prop, pVal, pType, plFlavor )) != S_OK)
530 SysFreeString( prop );
531 return hr;
533 obj->index_property = i + 1;
534 *strName = prop;
535 return S_OK;
537 return WBEM_S_NO_MORE_DATA;
540 static HRESULT WINAPI class_object_EndEnumeration(
541 IWbemClassObject *iface )
543 struct class_object *co = impl_from_IWbemClassObject( iface );
545 TRACE("%p\n", iface);
547 co->index_property = 0;
548 return S_OK;
551 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
552 IWbemClassObject *iface,
553 LPCWSTR wszProperty,
554 IWbemQualifierSet **ppQualSet )
556 struct class_object *co = impl_from_IWbemClassObject( iface );
558 TRACE("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
560 return WbemQualifierSet_create( co->name, wszProperty, (void **)ppQualSet );
563 static HRESULT WINAPI class_object_Clone(
564 IWbemClassObject *iface,
565 IWbemClassObject **ppCopy )
567 FIXME("%p, %p\n", iface, ppCopy);
568 return E_NOTIMPL;
571 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
573 static const WCHAR fmtW[] = {'\n','\t','%','s',' ','=',' ','%','s',';',0};
574 BSTR value, ret;
575 WCHAR *p;
576 UINT i;
578 *len = 0;
579 for (i = 0; i < table->num_cols; i++)
581 if ((value = get_value_bstr( table, row, i )))
583 *len += sizeof(fmtW) / sizeof(fmtW[0]);
584 *len += strlenW( table->columns[i].name );
585 *len += SysStringLen( value );
586 SysFreeString( value );
589 if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
590 p = ret;
591 for (i = 0; i < table->num_cols; i++)
593 if ((value = get_value_bstr( table, row, i )))
595 p += sprintfW( p, fmtW, table->columns[i].name, value );
596 SysFreeString( value );
599 return ret;
602 static BSTR get_object_text( const struct view *view, UINT index )
604 static const WCHAR fmtW[] =
605 {'\n','i','n','s','t','a','n','c','e',' ','o','f',' ','%','s','\n','{','%','s','\n','}',';',0};
606 UINT len, len_body, row = view->result[index];
607 BSTR ret, body;
609 len = sizeof(fmtW) / sizeof(fmtW[0]);
610 len += strlenW( view->table->name );
611 if (!(body = get_body_text( view->table, row, &len_body ))) return NULL;
612 len += len_body;
614 if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
615 sprintfW( ret, fmtW, view->table->name, body );
616 SysFreeString( body );
617 return ret;
620 static HRESULT WINAPI class_object_GetObjectText(
621 IWbemClassObject *iface,
622 LONG lFlags,
623 BSTR *pstrObjectText )
625 struct class_object *co = impl_from_IWbemClassObject( iface );
626 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
627 struct view *view = ec->query->view;
628 BSTR text;
630 TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
632 if (lFlags) FIXME("flags %08x not implemented\n", lFlags);
634 if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
635 *pstrObjectText = text;
636 return S_OK;
639 static HRESULT WINAPI class_object_SpawnDerivedClass(
640 IWbemClassObject *iface,
641 LONG lFlags,
642 IWbemClassObject **ppNewClass )
644 FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
645 return E_NOTIMPL;
648 static HRESULT WINAPI class_object_SpawnInstance(
649 IWbemClassObject *iface,
650 LONG lFlags,
651 IWbemClassObject **ppNewInstance )
653 struct class_object *co = impl_from_IWbemClassObject( iface );
654 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
655 struct view *view = ec->query->view;
656 struct record *record;
658 TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
660 if (!(record = create_record( view->table ))) return E_OUTOFMEMORY;
662 return create_class_object( co->name, NULL, 0, record, ppNewInstance );
665 static HRESULT WINAPI class_object_CompareTo(
666 IWbemClassObject *iface,
667 LONG lFlags,
668 IWbemClassObject *pCompareTo )
670 FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
671 return E_NOTIMPL;
674 static HRESULT WINAPI class_object_GetPropertyOrigin(
675 IWbemClassObject *iface,
676 LPCWSTR wszName,
677 BSTR *pstrClassName )
679 FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
680 return E_NOTIMPL;
683 static HRESULT WINAPI class_object_InheritsFrom(
684 IWbemClassObject *iface,
685 LPCWSTR strAncestor )
687 FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
688 return E_NOTIMPL;
691 static UINT count_instances( IEnumWbemClassObject *iter )
693 UINT count = 0;
694 while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
695 IEnumWbemClassObject_Reset( iter );
696 return count;
699 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
701 switch (type)
703 case CIM_SINT16:
704 *(INT16 *)ptr = val;
705 break;
706 case CIM_UINT16:
707 *(UINT16 *)ptr = val;
708 break;
709 case CIM_SINT32:
710 *(INT32 *)ptr = val;
711 break;
712 case CIM_UINT32:
713 *(UINT32 *)ptr = val;
714 break;
715 default:
716 FIXME("unhandled type %u\n", type);
717 break;
721 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
722 struct column **cols, BYTE **data )
724 static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
725 static const WCHAR typeW[] = {'T','y','p','e',0};
726 static const WCHAR varianttypeW[] = {'V','a','r','i','a','n','t','T','y','p','e',0};
727 static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0};
728 struct column *columns;
729 BYTE *row;
730 IWbemClassObject *param;
731 VARIANT val;
732 HRESULT hr = E_OUTOFMEMORY;
733 UINT offset = 0;
734 ULONG count;
735 int i = 0;
737 count = count_instances( iter );
738 if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
739 if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
741 for (;;)
743 IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
744 if (!count) break;
746 hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL );
747 if (hr != S_OK) goto error;
748 columns[i].name = heap_strdupW( V_BSTR( &val ) );
749 VariantClear( &val );
751 hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL );
752 if (hr != S_OK) goto error;
753 columns[i].type = V_UI4( &val );
755 hr = IWbemClassObject_Get( param, varianttypeW, 0, &val, NULL, NULL );
756 if (hr != S_OK) goto error;
757 columns[i].vartype = V_UI4( &val );
759 hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
760 if (hr != S_OK) goto error;
761 if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
762 offset += get_type_size( columns[i].type );
764 IWbemClassObject_Release( param );
765 i++;
767 *num_cols = i;
768 *cols = columns;
769 *data = row;
770 return S_OK;
772 error:
773 for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
774 heap_free( columns );
775 heap_free( row );
776 return hr;
779 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
781 HRESULT hr;
782 struct table *table;
783 struct column *columns;
784 UINT num_cols;
785 BYTE *row;
787 hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
788 if (hr != S_OK) return hr;
790 if (!(table = create_table( name, num_cols, columns, 1, 1, row, NULL )))
792 free_columns( columns, num_cols );
793 heap_free( row );
794 return E_OUTOFMEMORY;
796 if (!add_table( table )) free_table( table ); /* already exists */
797 return S_OK;
800 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
802 static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
803 static const WCHAR outW[] = {'O','U','T',0};
804 static const WCHAR inW[] = {'I','N',0};
805 UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method );
806 WCHAR *ret;
808 if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
809 sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW );
810 return struprW( ret );
813 HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
814 IWbemClassObject **sig )
816 static const WCHAR selectW[] =
817 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
818 '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
819 'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
820 'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
821 'D','i','r','e','c','t','i','o','n','%','s',0};
822 static const WCHAR geW[] = {'>','=','0',0};
823 static const WCHAR leW[] = {'<','=','0',0};
824 UINT len = SIZEOF(selectW) + SIZEOF(geW);
825 IEnumWbemClassObject *iter;
826 WCHAR *query, *name;
827 HRESULT hr;
829 len += strlenW( class ) + strlenW( method );
830 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
831 sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW );
833 hr = exec_query( query, &iter );
834 heap_free( query );
835 if (hr != S_OK) return hr;
837 if (!(name = build_signature_table_name( class, method, dir )))
839 IEnumWbemClassObject_Release( iter );
840 return E_OUTOFMEMORY;
842 hr = create_signature_table( iter, name );
843 IEnumWbemClassObject_Release( iter );
844 if (hr == S_OK)
845 hr = get_object( name, sig );
847 heap_free( name );
848 return hr;
851 static HRESULT WINAPI class_object_GetMethod(
852 IWbemClassObject *iface,
853 LPCWSTR wszName,
854 LONG lFlags,
855 IWbemClassObject **ppInSignature,
856 IWbemClassObject **ppOutSignature )
858 struct class_object *co = impl_from_IWbemClassObject( iface );
859 IWbemClassObject *in, *out;
860 HRESULT hr;
862 TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
864 hr = create_signature( co->name, wszName, PARAM_IN, &in );
865 if (hr != S_OK) return hr;
867 hr = create_signature( co->name, wszName, PARAM_OUT, &out );
868 if (hr == S_OK)
870 if (ppInSignature) *ppInSignature = in;
871 else IWbemClassObject_Release( in );
872 if (ppOutSignature) *ppOutSignature = out;
873 else IWbemClassObject_Release( out );
875 else IWbemClassObject_Release( in );
876 return hr;
879 static HRESULT WINAPI class_object_PutMethod(
880 IWbemClassObject *iface,
881 LPCWSTR wszName,
882 LONG lFlags,
883 IWbemClassObject *pInSignature,
884 IWbemClassObject *pOutSignature )
886 FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
887 return E_NOTIMPL;
890 static HRESULT WINAPI class_object_DeleteMethod(
891 IWbemClassObject *iface,
892 LPCWSTR wszName )
894 FIXME("%p, %s\n", iface, debugstr_w(wszName));
895 return E_NOTIMPL;
898 static HRESULT WINAPI class_object_BeginMethodEnumeration(
899 IWbemClassObject *iface,
900 LONG lEnumFlags)
902 struct class_object *co = impl_from_IWbemClassObject( iface );
904 TRACE("%p, %08x\n", iface, lEnumFlags);
906 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
908 if (co->iter)
910 WARN("not allowed on instance\n");
911 return WBEM_E_ILLEGAL_OPERATION;
913 co->index_method = 0;
914 return S_OK;
917 static HRESULT WINAPI class_object_NextMethod(
918 IWbemClassObject *iface,
919 LONG lFlags,
920 BSTR *pstrName,
921 IWbemClassObject **ppInSignature,
922 IWbemClassObject **ppOutSignature)
924 struct class_object *co = impl_from_IWbemClassObject( iface );
925 BSTR method;
926 HRESULT hr;
928 TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
930 if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
932 hr = create_signature( co->name, method, PARAM_IN, ppInSignature );
933 if (hr != S_OK)
935 SysFreeString( method );
936 return hr;
938 hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature );
939 if (hr != S_OK)
941 SysFreeString( method );
942 IWbemClassObject_Release( *ppInSignature );
944 else
946 *pstrName = method;
947 co->index_method++;
949 return hr;
952 static HRESULT WINAPI class_object_EndMethodEnumeration(
953 IWbemClassObject *iface )
955 struct class_object *co = impl_from_IWbemClassObject( iface );
957 TRACE("%p\n", iface);
959 co->index_method = 0;
960 return S_OK;
963 static HRESULT WINAPI class_object_GetMethodQualifierSet(
964 IWbemClassObject *iface,
965 LPCWSTR wszMethod,
966 IWbemQualifierSet **ppQualSet)
968 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
969 return E_NOTIMPL;
972 static HRESULT WINAPI class_object_GetMethodOrigin(
973 IWbemClassObject *iface,
974 LPCWSTR wszMethodName,
975 BSTR *pstrClassName)
977 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
978 return E_NOTIMPL;
981 static const IWbemClassObjectVtbl class_object_vtbl =
983 class_object_QueryInterface,
984 class_object_AddRef,
985 class_object_Release,
986 class_object_GetQualifierSet,
987 class_object_Get,
988 class_object_Put,
989 class_object_Delete,
990 class_object_GetNames,
991 class_object_BeginEnumeration,
992 class_object_Next,
993 class_object_EndEnumeration,
994 class_object_GetPropertyQualifierSet,
995 class_object_Clone,
996 class_object_GetObjectText,
997 class_object_SpawnDerivedClass,
998 class_object_SpawnInstance,
999 class_object_CompareTo,
1000 class_object_GetPropertyOrigin,
1001 class_object_InheritsFrom,
1002 class_object_GetMethod,
1003 class_object_PutMethod,
1004 class_object_DeleteMethod,
1005 class_object_BeginMethodEnumeration,
1006 class_object_NextMethod,
1007 class_object_EndMethodEnumeration,
1008 class_object_GetMethodQualifierSet,
1009 class_object_GetMethodOrigin
1012 HRESULT create_class_object( const WCHAR *name, IEnumWbemClassObject *iter, UINT index,
1013 struct record *record, IWbemClassObject **obj )
1015 struct class_object *co;
1017 TRACE("%s, %p\n", debugstr_w(name), obj);
1019 co = heap_alloc( sizeof(*co) );
1020 if (!co) return E_OUTOFMEMORY;
1022 co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
1023 co->refs = 1;
1024 if (!name) co->name = NULL;
1025 else if (!(co->name = heap_strdupW( name )))
1027 heap_free( co );
1028 return E_OUTOFMEMORY;
1030 co->iter = iter;
1031 co->index = index;
1032 co->index_method = 0;
1033 co->index_property = 0;
1034 co->record = record;
1035 if (iter) IEnumWbemClassObject_AddRef( iter );
1037 *obj = &co->IWbemClassObject_iface;
1039 TRACE("returning iface %p\n", *obj);
1040 return S_OK;