xinput1_3/tests: Add some HID report tests.
[wine.git] / dlls / wbemprox / class.c
blob3b7bc066aea91fabf89c2cef7b088e01b0f84518
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 <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26 #include "wbemcli.h"
28 #include "wine/debug.h"
29 #include "wbemprox_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
33 struct enum_class_object
35 IEnumWbemClassObject IEnumWbemClassObject_iface;
36 LONG refs;
37 struct query *query;
38 UINT index;
41 static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
42 IEnumWbemClassObject *iface )
44 return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface);
47 static ULONG WINAPI enum_class_object_AddRef(
48 IEnumWbemClassObject *iface )
50 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
51 return InterlockedIncrement( &ec->refs );
54 static ULONG WINAPI enum_class_object_Release(
55 IEnumWbemClassObject *iface )
57 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
58 LONG refs = InterlockedDecrement( &ec->refs );
59 if (!refs)
61 TRACE("destroying %p\n", ec);
62 release_query( ec->query );
63 heap_free( ec );
65 return refs;
68 static HRESULT WINAPI enum_class_object_QueryInterface(
69 IEnumWbemClassObject *iface,
70 REFIID riid,
71 void **ppvObject )
73 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
75 TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject );
77 if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) ||
78 IsEqualGUID( riid, &IID_IUnknown ) )
80 *ppvObject = ec;
82 else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
84 *ppvObject = &client_security;
85 return S_OK;
87 else
89 FIXME("interface %s not implemented\n", debugstr_guid(riid));
90 return E_NOINTERFACE;
92 IEnumWbemClassObject_AddRef( iface );
93 return S_OK;
96 static HRESULT WINAPI enum_class_object_Reset(
97 IEnumWbemClassObject *iface )
99 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
101 TRACE("%p\n", iface);
103 ec->index = 0;
104 return WBEM_S_NO_ERROR;
107 static HRESULT WINAPI enum_class_object_Next(
108 IEnumWbemClassObject *iface,
109 LONG lTimeout,
110 ULONG uCount,
111 IWbemClassObject **apObjects,
112 ULONG *puReturned )
114 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
115 struct view *view = ec->query->view;
116 struct table *table;
117 static int once = 0;
118 HRESULT hr;
119 ULONG i, j;
121 TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
123 if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
124 if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
126 *puReturned = 0;
128 for (i = 0; i < uCount; i++)
130 if (ec->index >= view->result_count) return WBEM_S_FALSE;
131 table = get_view_table( view, ec->index );
132 hr = create_class_object( table->name, iface, ec->index, NULL, &apObjects[i] );
133 if (hr != S_OK)
135 for (j = 0; j < i; j++) IWbemClassObject_Release( apObjects[j] );
136 return hr;
138 ec->index++;
139 (*puReturned)++;
142 return WBEM_S_NO_ERROR;
145 static HRESULT WINAPI enum_class_object_NextAsync(
146 IEnumWbemClassObject *iface,
147 ULONG uCount,
148 IWbemObjectSink *pSink )
150 FIXME("%p, %u, %p\n", iface, uCount, pSink);
151 return E_NOTIMPL;
154 static HRESULT WINAPI enum_class_object_Clone(
155 IEnumWbemClassObject *iface,
156 IEnumWbemClassObject **ppEnum )
158 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
160 TRACE("%p, %p\n", iface, ppEnum);
162 return EnumWbemClassObject_create( ec->query, (void **)ppEnum );
165 static HRESULT WINAPI enum_class_object_Skip(
166 IEnumWbemClassObject *iface,
167 LONG lTimeout,
168 ULONG nCount )
170 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
171 struct view *view = ec->query->view;
172 static int once = 0;
174 TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
176 if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
178 if (!view->result_count) return WBEM_S_FALSE;
180 if (nCount > view->result_count - ec->index)
182 ec->index = view->result_count - 1;
183 return WBEM_S_FALSE;
185 ec->index += nCount;
186 return WBEM_S_NO_ERROR;
189 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
191 enum_class_object_QueryInterface,
192 enum_class_object_AddRef,
193 enum_class_object_Release,
194 enum_class_object_Reset,
195 enum_class_object_Next,
196 enum_class_object_NextAsync,
197 enum_class_object_Clone,
198 enum_class_object_Skip
201 HRESULT EnumWbemClassObject_create( struct query *query, LPVOID *ppObj )
203 struct enum_class_object *ec;
205 TRACE("%p\n", ppObj);
207 ec = heap_alloc( sizeof(*ec) );
208 if (!ec) return E_OUTOFMEMORY;
210 ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
211 ec->refs = 1;
212 ec->query = addref_query( query );
213 ec->index = 0;
215 *ppObj = &ec->IEnumWbemClassObject_iface;
217 TRACE("returning iface %p\n", *ppObj);
218 return S_OK;
221 static struct record *create_record( struct table *table )
223 UINT i;
224 struct record *record;
226 if (!(record = heap_alloc( sizeof(struct record) ))) return NULL;
227 if (!(record->fields = heap_alloc( table->num_cols * sizeof(struct field) )))
229 heap_free( record );
230 return NULL;
232 for (i = 0; i < table->num_cols; i++)
234 record->fields[i].type = table->columns[i].type;
235 record->fields[i].u.ival = 0;
237 record->count = table->num_cols;
238 record->table = addref_table( table );
239 return record;
242 void destroy_array( struct array *array, CIMTYPE type )
244 UINT i;
245 if (!array) return;
246 if (type == CIM_STRING || type == CIM_DATETIME || type == CIM_REFERENCE)
248 for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * array->elem_size) );
250 heap_free( array->ptr );
251 heap_free( array );
254 static void destroy_record( struct record *record )
256 UINT i;
258 if (!record) return;
259 release_table( record->table );
260 for (i = 0; i < record->count; i++)
262 if (record->fields[i].type == CIM_STRING ||
263 record->fields[i].type == CIM_DATETIME ||
264 record->fields[i].type == CIM_REFERENCE) heap_free( record->fields[i].u.sval );
265 else if (record->fields[i].type & CIM_FLAG_ARRAY)
266 destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK );
268 heap_free( record->fields );
269 heap_free( record );
272 struct class_object
274 IWbemClassObject IWbemClassObject_iface;
275 LONG refs;
276 WCHAR *name;
277 IEnumWbemClassObject *iter;
278 UINT index;
279 UINT index_method;
280 UINT index_property;
281 struct record *record; /* uncommitted instance */
284 static inline struct class_object *impl_from_IWbemClassObject(
285 IWbemClassObject *iface )
287 return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
290 static ULONG WINAPI class_object_AddRef(
291 IWbemClassObject *iface )
293 struct class_object *co = impl_from_IWbemClassObject( iface );
294 return InterlockedIncrement( &co->refs );
297 static ULONG WINAPI class_object_Release(
298 IWbemClassObject *iface )
300 struct class_object *co = impl_from_IWbemClassObject( iface );
301 LONG refs = InterlockedDecrement( &co->refs );
302 if (!refs)
304 TRACE("destroying %p\n", co);
305 if (co->iter) IEnumWbemClassObject_Release( co->iter );
306 destroy_record( co->record );
307 heap_free( co->name );
308 heap_free( co );
310 return refs;
313 static HRESULT WINAPI class_object_QueryInterface(
314 IWbemClassObject *iface,
315 REFIID riid,
316 void **ppvObject )
318 struct class_object *co = impl_from_IWbemClassObject( iface );
320 TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
322 if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
323 IsEqualGUID( riid, &IID_IUnknown ) )
325 *ppvObject = co;
327 else if (IsEqualGUID( riid, &IID_IClientSecurity ))
329 *ppvObject = &client_security;
330 return S_OK;
332 else
334 FIXME("interface %s not implemented\n", debugstr_guid(riid));
335 return E_NOINTERFACE;
337 IWbemClassObject_AddRef( iface );
338 return S_OK;
341 static HRESULT WINAPI class_object_GetQualifierSet(
342 IWbemClassObject *iface,
343 IWbemQualifierSet **ppQualSet )
345 struct class_object *co = impl_from_IWbemClassObject( iface );
347 TRACE("%p, %p\n", iface, ppQualSet);
349 return WbemQualifierSet_create( co->name, NULL, (void **)ppQualSet );
352 static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type )
354 VARTYPE vartype = to_vartype( record->fields[index].type & CIM_TYPE_MASK );
356 if (type) *type = record->fields[index].type;
357 if (!var) return S_OK;
359 if (record->fields[index].type & CIM_FLAG_ARRAY)
361 V_VT( var ) = vartype | VT_ARRAY;
362 V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & CIM_TYPE_MASK );
363 return S_OK;
365 switch (record->fields[index].type)
367 case CIM_STRING:
368 case CIM_DATETIME:
369 case CIM_REFERENCE:
370 V_BSTR( var ) = SysAllocString( record->fields[index].u.sval );
371 break;
372 case CIM_SINT32:
373 V_I4( var ) = record->fields[index].u.ival;
374 break;
375 case CIM_UINT32:
376 V_UI4( var ) = record->fields[index].u.ival;
377 break;
378 default:
379 FIXME("unhandled type %u\n", record->fields[index].type);
380 return WBEM_E_INVALID_PARAMETER;
382 V_VT( var ) = vartype;
383 return S_OK;
386 static HRESULT WINAPI class_object_Get(
387 IWbemClassObject *iface,
388 LPCWSTR wszName,
389 LONG lFlags,
390 VARIANT *pVal,
391 CIMTYPE *pType,
392 LONG *plFlavor )
394 struct class_object *co = impl_from_IWbemClassObject( iface );
395 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
397 TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
399 if (co->record)
401 UINT index;
402 HRESULT hr;
404 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
405 return record_get_value( co->record, index, pVal, pType );
407 return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor );
410 static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var )
412 LONGLONG val;
413 CIMTYPE type;
414 HRESULT hr;
416 if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr;
417 if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH;
419 if (type & CIM_FLAG_ARRAY)
421 record->fields[index].u.aval = (struct array *)(INT_PTR)val;
422 return S_OK;
424 switch (type)
426 case CIM_STRING:
427 case CIM_DATETIME:
428 case CIM_REFERENCE:
429 record->fields[index].u.sval = (WCHAR *)(INT_PTR)val;
430 return S_OK;
431 case CIM_SINT16:
432 case CIM_UINT16:
433 case CIM_SINT32:
434 case CIM_UINT32:
435 record->fields[index].u.ival = val;
436 return S_OK;
437 default:
438 FIXME("unhandled type %u\n", type);
439 break;
441 return WBEM_E_INVALID_PARAMETER;
444 static HRESULT WINAPI class_object_Put(
445 IWbemClassObject *iface,
446 LPCWSTR wszName,
447 LONG lFlags,
448 VARIANT *pVal,
449 CIMTYPE Type )
451 struct class_object *co = impl_from_IWbemClassObject( iface );
452 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
454 TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
456 if (co->record)
458 UINT index;
459 HRESULT hr;
461 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
462 return record_set_value( co->record, index, pVal );
465 if (!ec) return S_OK;
467 return put_propval( ec->query->view, co->index, wszName, pVal, Type );
470 static HRESULT WINAPI class_object_Delete(
471 IWbemClassObject *iface,
472 LPCWSTR wszName )
474 FIXME("%p, %s\n", iface, debugstr_w(wszName));
475 return E_NOTIMPL;
478 static HRESULT WINAPI class_object_GetNames(
479 IWbemClassObject *iface,
480 LPCWSTR wszQualifierName,
481 LONG lFlags,
482 VARIANT *pQualifierVal,
483 SAFEARRAY **pNames )
485 struct class_object *co = impl_from_IWbemClassObject( iface );
486 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
488 TRACE("%p, %s, %08x, %s, %p\n", iface, debugstr_w(wszQualifierName), lFlags,
489 debugstr_variant(pQualifierVal), pNames);
491 if (!pNames)
492 return WBEM_E_INVALID_PARAMETER;
494 /* Combination used in a handful of broken apps */
495 if (lFlags == (WBEM_FLAG_ALWAYS | WBEM_MASK_CONDITION_ORIGIN))
496 lFlags = WBEM_FLAG_ALWAYS;
498 if (lFlags && (lFlags != WBEM_FLAG_ALWAYS &&
499 lFlags != WBEM_FLAG_NONSYSTEM_ONLY &&
500 lFlags != WBEM_FLAG_SYSTEM_ONLY))
502 FIXME("flags %08x not supported\n", lFlags);
503 return E_NOTIMPL;
506 if (wszQualifierName || pQualifierVal)
507 FIXME("qualifier not supported\n");
509 return get_properties( ec->query->view, co->index, lFlags, pNames );
512 static HRESULT WINAPI class_object_BeginEnumeration(
513 IWbemClassObject *iface,
514 LONG lEnumFlags )
516 struct class_object *co = impl_from_IWbemClassObject( iface );
518 TRACE("%p, %08x\n", iface, lEnumFlags);
520 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
522 co->index_property = 0;
523 return S_OK;
526 static HRESULT WINAPI class_object_Next(
527 IWbemClassObject *iface,
528 LONG lFlags,
529 BSTR *strName,
530 VARIANT *pVal,
531 CIMTYPE *pType,
532 LONG *plFlavor )
534 struct class_object *obj = impl_from_IWbemClassObject( iface );
535 struct enum_class_object *iter = impl_from_IEnumWbemClassObject( obj->iter );
536 struct view *view = iter->query->view;
537 struct table *table = get_view_table( view, obj->index );
538 BSTR prop;
539 HRESULT hr;
540 UINT i;
542 TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
544 for (i = obj->index_property; i < table->num_cols; i++)
546 if (is_method( table, i )) continue;
547 if (!is_result_prop( view, table->columns[i].name )) continue;
548 if (!(prop = SysAllocString( table->columns[i].name ))) return E_OUTOFMEMORY;
549 if (obj->record)
551 UINT index;
553 if ((hr = get_column_index( table, table->columns[i].name, &index )) == S_OK)
554 hr = record_get_value( obj->record, index, pVal, pType );
556 else
557 hr = get_propval( view, obj->index, prop, pVal, pType, plFlavor );
559 if (FAILED(hr))
561 SysFreeString( prop );
562 return hr;
565 obj->index_property = i + 1;
566 if (strName) *strName = prop;
567 else SysFreeString( prop );
569 return S_OK;
571 return WBEM_S_NO_MORE_DATA;
574 static HRESULT WINAPI class_object_EndEnumeration(
575 IWbemClassObject *iface )
577 struct class_object *co = impl_from_IWbemClassObject( iface );
579 TRACE("%p\n", iface);
581 co->index_property = 0;
582 return S_OK;
585 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
586 IWbemClassObject *iface,
587 LPCWSTR wszProperty,
588 IWbemQualifierSet **ppQualSet )
590 struct class_object *co = impl_from_IWbemClassObject( iface );
592 TRACE("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
594 return WbemQualifierSet_create( co->name, wszProperty, (void **)ppQualSet );
597 static HRESULT WINAPI class_object_Clone(
598 IWbemClassObject *iface,
599 IWbemClassObject **ppCopy )
601 FIXME("%p, %p\n", iface, ppCopy);
602 return E_NOTIMPL;
605 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
607 BSTR value, ret;
608 WCHAR *p;
609 UINT i;
611 *len = 0;
612 for (i = 0; i < table->num_cols; i++)
614 if ((value = get_value_bstr( table, row, i )))
616 *len += ARRAY_SIZE( L"\n\t%s = %s;" );
617 *len += lstrlenW( table->columns[i].name );
618 *len += SysStringLen( value );
619 SysFreeString( value );
622 if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
623 p = ret;
624 for (i = 0; i < table->num_cols; i++)
626 if ((value = get_value_bstr( table, row, i )))
628 p += swprintf( p, *len - (p - ret), L"\n\t%s = %s;", table->columns[i].name, value );
629 SysFreeString( value );
632 return ret;
635 static BSTR get_object_text( const struct view *view, UINT index )
637 UINT len, len_body, row = view->result[index];
638 struct table *table = get_view_table( view, index );
639 BSTR ret, body;
641 len = ARRAY_SIZE( L"\ninstance of %s\n{%s\n};" );
642 len += lstrlenW( table->name );
643 if (!(body = get_body_text( table, row, &len_body ))) return NULL;
644 len += len_body;
646 if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
647 swprintf( ret, len, L"\ninstance of %s\n{%s\n};", table->name, body );
648 SysFreeString( body );
649 return ret;
652 static HRESULT WINAPI class_object_GetObjectText(
653 IWbemClassObject *iface,
654 LONG lFlags,
655 BSTR *pstrObjectText )
657 struct class_object *co = impl_from_IWbemClassObject( iface );
658 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
659 struct view *view = ec->query->view;
660 BSTR text;
662 TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
664 if (lFlags) FIXME("flags %08x not implemented\n", lFlags);
666 if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
667 *pstrObjectText = text;
668 return S_OK;
671 static HRESULT WINAPI class_object_SpawnDerivedClass(
672 IWbemClassObject *iface,
673 LONG lFlags,
674 IWbemClassObject **ppNewClass )
676 FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
677 return E_NOTIMPL;
680 static HRESULT WINAPI class_object_SpawnInstance(
681 IWbemClassObject *iface,
682 LONG lFlags,
683 IWbemClassObject **ppNewInstance )
685 struct class_object *co = impl_from_IWbemClassObject( iface );
686 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
687 struct table *table = get_view_table( ec->query->view, co->index );
688 IEnumWbemClassObject *iter;
689 struct record *record;
690 HRESULT hr;
692 TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
694 if (!(record = create_record( table ))) return E_OUTOFMEMORY;
695 if (FAILED(hr = IEnumWbemClassObject_Clone( co->iter, &iter )))
697 destroy_record( record );
698 return hr;
700 hr = create_class_object( co->name, iter, 0, record, ppNewInstance );
701 IEnumWbemClassObject_Release( iter );
702 return hr;
705 static HRESULT WINAPI class_object_CompareTo(
706 IWbemClassObject *iface,
707 LONG lFlags,
708 IWbemClassObject *pCompareTo )
710 FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
711 return E_NOTIMPL;
714 static HRESULT WINAPI class_object_GetPropertyOrigin(
715 IWbemClassObject *iface,
716 LPCWSTR wszName,
717 BSTR *pstrClassName )
719 FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
720 return E_NOTIMPL;
723 static HRESULT WINAPI class_object_InheritsFrom(
724 IWbemClassObject *iface,
725 LPCWSTR strAncestor )
727 FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
728 return E_NOTIMPL;
731 static UINT count_instances( IEnumWbemClassObject *iter )
733 UINT count = 0;
734 while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
735 IEnumWbemClassObject_Reset( iter );
736 return count;
739 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
741 switch (type)
743 case CIM_SINT16:
744 *(INT16 *)ptr = val;
745 break;
746 case CIM_UINT16:
747 *(UINT16 *)ptr = val;
748 break;
749 case CIM_SINT32:
750 *(INT32 *)ptr = val;
751 break;
752 case CIM_UINT32:
753 *(UINT32 *)ptr = val;
754 break;
755 default:
756 FIXME("unhandled type %u\n", type);
757 break;
761 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
762 struct column **cols, BYTE **data )
764 struct column *columns;
765 BYTE *row;
766 IWbemClassObject *param;
767 VARIANT val;
768 HRESULT hr = E_OUTOFMEMORY;
769 UINT offset = 0;
770 ULONG count;
771 int i = 0;
773 count = count_instances( iter );
774 if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
775 if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
777 for (;;)
779 IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
780 if (!count) break;
782 hr = IWbemClassObject_Get( param, L"Parameter", 0, &val, NULL, NULL );
783 if (hr != S_OK) goto error;
784 columns[i].name = heap_strdupW( V_BSTR( &val ) );
785 VariantClear( &val );
787 hr = IWbemClassObject_Get( param, L"Type", 0, &val, NULL, NULL );
788 if (hr != S_OK) goto error;
789 columns[i].type = V_UI4( &val );
791 hr = IWbemClassObject_Get( param, L"DefaultValue", 0, &val, NULL, NULL );
792 if (hr != S_OK) goto error;
793 if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
794 offset += get_type_size( columns[i].type );
796 IWbemClassObject_Release( param );
797 i++;
799 *num_cols = i;
800 *cols = columns;
801 *data = row;
802 return S_OK;
804 error:
805 for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
806 heap_free( columns );
807 heap_free( row );
808 return hr;
811 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
813 HRESULT hr;
814 struct table *table;
815 struct column *columns;
816 UINT num_cols;
817 BYTE *row;
819 hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
820 if (hr != S_OK) return hr;
822 if (!(table = create_table( name, num_cols, columns, 1, 1, row, NULL )))
824 free_columns( columns, num_cols );
825 heap_free( row );
826 return E_OUTOFMEMORY;
828 if (!add_table( table )) free_table( table ); /* already exists */
829 return S_OK;
832 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
834 UINT len = ARRAY_SIZE(L"__%s_%s_%s") + ARRAY_SIZE(L"OUT") + lstrlenW( class ) + lstrlenW( method );
835 WCHAR *ret;
837 if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
838 swprintf( ret, len, L"__%s_%s_%s", class, method, dir == PARAM_IN ? L"IN" : L"OUT" );
839 return wcsupr( ret );
842 HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
843 IWbemClassObject **sig )
845 static const WCHAR selectW[] = L"SELECT * FROM __PARAMETERS WHERE Class='%s' AND Method='%s' AND Direction%s";
846 UINT len = ARRAY_SIZE(selectW) + ARRAY_SIZE(L">=0");
847 IEnumWbemClassObject *iter;
848 WCHAR *query, *name;
849 HRESULT hr;
851 len += lstrlenW( class ) + lstrlenW( method );
852 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
853 swprintf( query, len, selectW, class, method, dir >= 0 ? L">=0" : L"<=0" );
855 hr = exec_query( query, &iter );
856 heap_free( query );
857 if (hr != S_OK) return hr;
859 if (!count_instances( iter ))
861 *sig = NULL;
862 IEnumWbemClassObject_Release( iter );
863 return S_OK;
866 if (!(name = build_signature_table_name( class, method, dir )))
868 IEnumWbemClassObject_Release( iter );
869 return E_OUTOFMEMORY;
871 hr = create_signature_table( iter, name );
872 IEnumWbemClassObject_Release( iter );
873 if (hr == S_OK)
874 hr = get_object( name, sig );
876 heap_free( name );
877 return hr;
880 static HRESULT WINAPI class_object_GetMethod(
881 IWbemClassObject *iface,
882 LPCWSTR wszName,
883 LONG lFlags,
884 IWbemClassObject **ppInSignature,
885 IWbemClassObject **ppOutSignature )
887 struct class_object *co = impl_from_IWbemClassObject( iface );
888 IWbemClassObject *in, *out;
889 struct table *table;
890 unsigned int i;
891 HRESULT hr;
893 TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
895 if (ppInSignature) *ppInSignature = NULL;
896 if (ppOutSignature) *ppOutSignature = NULL;
898 table = get_view_table( impl_from_IEnumWbemClassObject( co->iter )->query->view, co->index );
900 for (i = 0; i < table->num_cols; ++i)
902 if (is_method( table, i ) && !lstrcmpiW( table->columns[i].name, wszName )) break;
904 if (i == table->num_cols)
906 FIXME("Method %s not found in class %s.\n", debugstr_w(wszName), debugstr_w(co->name));
907 return WBEM_E_NOT_FOUND;
910 hr = create_signature( co->name, wszName, PARAM_IN, &in );
911 if (hr != S_OK) return hr;
913 hr = create_signature( co->name, wszName, PARAM_OUT, &out );
914 if (hr == S_OK)
916 if (ppInSignature) *ppInSignature = in;
917 else if (in) IWbemClassObject_Release( in );
918 if (ppOutSignature) *ppOutSignature = out;
919 else if (out) IWbemClassObject_Release( out );
921 else IWbemClassObject_Release( in );
922 return hr;
925 static HRESULT WINAPI class_object_PutMethod(
926 IWbemClassObject *iface,
927 LPCWSTR wszName,
928 LONG lFlags,
929 IWbemClassObject *pInSignature,
930 IWbemClassObject *pOutSignature )
932 FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
933 return E_NOTIMPL;
936 static HRESULT WINAPI class_object_DeleteMethod(
937 IWbemClassObject *iface,
938 LPCWSTR wszName )
940 FIXME("%p, %s\n", iface, debugstr_w(wszName));
941 return E_NOTIMPL;
944 static HRESULT WINAPI class_object_BeginMethodEnumeration(
945 IWbemClassObject *iface,
946 LONG lEnumFlags)
948 struct class_object *co = impl_from_IWbemClassObject( iface );
950 TRACE("%p, %08x\n", iface, lEnumFlags);
952 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
954 co->index_method = 0;
955 return S_OK;
958 static HRESULT WINAPI class_object_NextMethod(
959 IWbemClassObject *iface,
960 LONG lFlags,
961 BSTR *pstrName,
962 IWbemClassObject **ppInSignature,
963 IWbemClassObject **ppOutSignature)
965 struct class_object *co = impl_from_IWbemClassObject( iface );
966 BSTR method;
967 HRESULT hr;
969 TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
971 if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
973 hr = create_signature( co->name, method, PARAM_IN, ppInSignature );
974 if (hr != S_OK)
976 SysFreeString( method );
977 return hr;
979 hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature );
980 if (hr != S_OK)
982 SysFreeString( method );
983 if (*ppInSignature)
984 IWbemClassObject_Release( *ppInSignature );
986 else
988 *pstrName = method;
989 co->index_method++;
991 return hr;
994 static HRESULT WINAPI class_object_EndMethodEnumeration(
995 IWbemClassObject *iface )
997 struct class_object *co = impl_from_IWbemClassObject( iface );
999 TRACE("%p\n", iface);
1001 co->index_method = 0;
1002 return S_OK;
1005 static HRESULT WINAPI class_object_GetMethodQualifierSet(
1006 IWbemClassObject *iface,
1007 LPCWSTR wszMethod,
1008 IWbemQualifierSet **ppQualSet)
1010 struct class_object *co = impl_from_IWbemClassObject( iface );
1012 TRACE("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
1014 return WbemQualifierSet_create( co->name, wszMethod, (void **)ppQualSet );
1017 static HRESULT WINAPI class_object_GetMethodOrigin(
1018 IWbemClassObject *iface,
1019 LPCWSTR wszMethodName,
1020 BSTR *pstrClassName)
1022 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
1023 return E_NOTIMPL;
1026 static const IWbemClassObjectVtbl class_object_vtbl =
1028 class_object_QueryInterface,
1029 class_object_AddRef,
1030 class_object_Release,
1031 class_object_GetQualifierSet,
1032 class_object_Get,
1033 class_object_Put,
1034 class_object_Delete,
1035 class_object_GetNames,
1036 class_object_BeginEnumeration,
1037 class_object_Next,
1038 class_object_EndEnumeration,
1039 class_object_GetPropertyQualifierSet,
1040 class_object_Clone,
1041 class_object_GetObjectText,
1042 class_object_SpawnDerivedClass,
1043 class_object_SpawnInstance,
1044 class_object_CompareTo,
1045 class_object_GetPropertyOrigin,
1046 class_object_InheritsFrom,
1047 class_object_GetMethod,
1048 class_object_PutMethod,
1049 class_object_DeleteMethod,
1050 class_object_BeginMethodEnumeration,
1051 class_object_NextMethod,
1052 class_object_EndMethodEnumeration,
1053 class_object_GetMethodQualifierSet,
1054 class_object_GetMethodOrigin
1057 HRESULT create_class_object( const WCHAR *name, IEnumWbemClassObject *iter, UINT index,
1058 struct record *record, IWbemClassObject **obj )
1060 struct class_object *co;
1062 TRACE("%s, %p\n", debugstr_w(name), obj);
1064 co = heap_alloc( sizeof(*co) );
1065 if (!co) return E_OUTOFMEMORY;
1067 co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
1068 co->refs = 1;
1069 if (!name) co->name = NULL;
1070 else if (!(co->name = heap_strdupW( name )))
1072 heap_free( co );
1073 return E_OUTOFMEMORY;
1075 co->iter = iter;
1076 co->index = index;
1077 co->index_method = 0;
1078 co->index_property = 0;
1079 co->record = record;
1080 if (iter) IEnumWbemClassObject_AddRef( iter );
1082 *obj = &co->IWbemClassObject_iface;
1084 TRACE("returning iface %p\n", *obj);
1085 return S_OK;