vbscript/tests: Add tests for the script TypeInfo's TypeComp binds.
[wine.git] / dlls / wbemprox / class.c
blob3ee5771e6b08bf7bf1a7ac0670e4514da7458be8
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;
120 TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
122 if (!uCount) return WBEM_S_FALSE;
123 if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
124 if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
126 *puReturned = 0;
127 if (ec->index >= view->result_count) return WBEM_S_FALSE;
129 table = get_view_table( view, ec->index );
130 hr = create_class_object( table->name, iface, ec->index, NULL, apObjects );
131 if (hr != S_OK) return hr;
133 ec->index++;
134 *puReturned = 1;
135 if (ec->index == view->result_count && uCount > 1) return WBEM_S_FALSE;
136 if (uCount > 1) return WBEM_S_TIMEDOUT;
137 return WBEM_S_NO_ERROR;
140 static HRESULT WINAPI enum_class_object_NextAsync(
141 IEnumWbemClassObject *iface,
142 ULONG uCount,
143 IWbemObjectSink *pSink )
145 FIXME("%p, %u, %p\n", iface, uCount, pSink);
146 return E_NOTIMPL;
149 static HRESULT WINAPI enum_class_object_Clone(
150 IEnumWbemClassObject *iface,
151 IEnumWbemClassObject **ppEnum )
153 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
155 TRACE("%p, %p\n", iface, ppEnum);
157 return EnumWbemClassObject_create( ec->query, (void **)ppEnum );
160 static HRESULT WINAPI enum_class_object_Skip(
161 IEnumWbemClassObject *iface,
162 LONG lTimeout,
163 ULONG nCount )
165 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
166 struct view *view = ec->query->view;
167 static int once = 0;
169 TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
171 if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
173 if (!view->result_count) return WBEM_S_FALSE;
175 if (nCount > view->result_count - ec->index)
177 ec->index = view->result_count - 1;
178 return WBEM_S_FALSE;
180 ec->index += nCount;
181 return WBEM_S_NO_ERROR;
184 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
186 enum_class_object_QueryInterface,
187 enum_class_object_AddRef,
188 enum_class_object_Release,
189 enum_class_object_Reset,
190 enum_class_object_Next,
191 enum_class_object_NextAsync,
192 enum_class_object_Clone,
193 enum_class_object_Skip
196 HRESULT EnumWbemClassObject_create( struct query *query, LPVOID *ppObj )
198 struct enum_class_object *ec;
200 TRACE("%p\n", ppObj);
202 ec = heap_alloc( sizeof(*ec) );
203 if (!ec) return E_OUTOFMEMORY;
205 ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
206 ec->refs = 1;
207 ec->query = addref_query( query );
208 ec->index = 0;
210 *ppObj = &ec->IEnumWbemClassObject_iface;
212 TRACE("returning iface %p\n", *ppObj);
213 return S_OK;
216 static struct record *create_record( struct table *table )
218 UINT i;
219 struct record *record;
221 if (!(record = heap_alloc( sizeof(struct record) ))) return NULL;
222 if (!(record->fields = heap_alloc( table->num_cols * sizeof(struct field) )))
224 heap_free( record );
225 return NULL;
227 for (i = 0; i < table->num_cols; i++)
229 record->fields[i].type = table->columns[i].type;
230 record->fields[i].u.ival = 0;
232 record->count = table->num_cols;
233 record->table = addref_table( table );
234 return record;
237 void destroy_array( struct array *array, CIMTYPE type )
239 UINT i;
240 if (!array) return;
241 if (type == CIM_STRING || type == CIM_DATETIME || type == CIM_REFERENCE)
243 for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * array->elem_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 ||
258 record->fields[i].type == CIM_DATETIME ||
259 record->fields[i].type == CIM_REFERENCE) heap_free( record->fields[i].u.sval );
260 else if (record->fields[i].type & CIM_FLAG_ARRAY)
261 destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK );
263 heap_free( record->fields );
264 heap_free( record );
267 struct class_object
269 IWbemClassObject IWbemClassObject_iface;
270 LONG refs;
271 WCHAR *name;
272 IEnumWbemClassObject *iter;
273 UINT index;
274 UINT index_method;
275 UINT index_property;
276 struct record *record; /* uncommitted instance */
279 static inline struct class_object *impl_from_IWbemClassObject(
280 IWbemClassObject *iface )
282 return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
285 static ULONG WINAPI class_object_AddRef(
286 IWbemClassObject *iface )
288 struct class_object *co = impl_from_IWbemClassObject( iface );
289 return InterlockedIncrement( &co->refs );
292 static ULONG WINAPI class_object_Release(
293 IWbemClassObject *iface )
295 struct class_object *co = impl_from_IWbemClassObject( iface );
296 LONG refs = InterlockedDecrement( &co->refs );
297 if (!refs)
299 TRACE("destroying %p\n", co);
300 if (co->iter) IEnumWbemClassObject_Release( co->iter );
301 destroy_record( co->record );
302 heap_free( co->name );
303 heap_free( co );
305 return refs;
308 static HRESULT WINAPI class_object_QueryInterface(
309 IWbemClassObject *iface,
310 REFIID riid,
311 void **ppvObject )
313 struct class_object *co = impl_from_IWbemClassObject( iface );
315 TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
317 if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
318 IsEqualGUID( riid, &IID_IUnknown ) )
320 *ppvObject = co;
322 else if (IsEqualGUID( riid, &IID_IClientSecurity ))
324 *ppvObject = &client_security;
325 return S_OK;
327 else
329 FIXME("interface %s not implemented\n", debugstr_guid(riid));
330 return E_NOINTERFACE;
332 IWbemClassObject_AddRef( iface );
333 return S_OK;
336 static HRESULT WINAPI class_object_GetQualifierSet(
337 IWbemClassObject *iface,
338 IWbemQualifierSet **ppQualSet )
340 struct class_object *co = impl_from_IWbemClassObject( iface );
342 TRACE("%p, %p\n", iface, ppQualSet);
344 return WbemQualifierSet_create( co->name, NULL, (void **)ppQualSet );
347 static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type )
349 VARTYPE vartype = to_vartype( record->fields[index].type & CIM_TYPE_MASK );
351 if (type) *type = record->fields[index].type;
353 if (record->fields[index].type & CIM_FLAG_ARRAY)
355 V_VT( var ) = vartype | VT_ARRAY;
356 V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & CIM_TYPE_MASK );
357 return S_OK;
359 switch (record->fields[index].type)
361 case CIM_STRING:
362 case CIM_DATETIME:
363 case CIM_REFERENCE:
364 V_BSTR( var ) = SysAllocString( record->fields[index].u.sval );
365 break;
366 case CIM_SINT32:
367 V_I4( var ) = record->fields[index].u.ival;
368 break;
369 case CIM_UINT32:
370 V_UI4( var ) = record->fields[index].u.ival;
371 break;
372 default:
373 FIXME("unhandled type %u\n", record->fields[index].type);
374 return WBEM_E_INVALID_PARAMETER;
376 V_VT( var ) = vartype;
377 return S_OK;
380 static HRESULT WINAPI class_object_Get(
381 IWbemClassObject *iface,
382 LPCWSTR wszName,
383 LONG lFlags,
384 VARIANT *pVal,
385 CIMTYPE *pType,
386 LONG *plFlavor )
388 struct class_object *co = impl_from_IWbemClassObject( iface );
389 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
391 TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
393 if (co->record)
395 UINT index;
396 HRESULT hr;
398 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
399 return record_get_value( co->record, index, pVal, pType );
401 return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor );
404 static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var )
406 LONGLONG val;
407 CIMTYPE type;
408 HRESULT hr;
410 if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr;
411 if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH;
413 if (type & CIM_FLAG_ARRAY)
415 record->fields[index].u.aval = (struct array *)(INT_PTR)val;
416 return S_OK;
418 switch (type)
420 case CIM_STRING:
421 case CIM_DATETIME:
422 case CIM_REFERENCE:
423 record->fields[index].u.sval = (WCHAR *)(INT_PTR)val;
424 return S_OK;
425 case CIM_SINT16:
426 case CIM_UINT16:
427 case CIM_SINT32:
428 case CIM_UINT32:
429 record->fields[index].u.ival = val;
430 return S_OK;
431 default:
432 FIXME("unhandled type %u\n", type);
433 break;
435 return WBEM_E_INVALID_PARAMETER;
438 static HRESULT WINAPI class_object_Put(
439 IWbemClassObject *iface,
440 LPCWSTR wszName,
441 LONG lFlags,
442 VARIANT *pVal,
443 CIMTYPE Type )
445 struct class_object *co = impl_from_IWbemClassObject( iface );
446 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
448 TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
450 if (co->record)
452 UINT index;
453 HRESULT hr;
455 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
456 return record_set_value( co->record, index, pVal );
458 return put_propval( ec->query->view, co->index, wszName, pVal, Type );
461 static HRESULT WINAPI class_object_Delete(
462 IWbemClassObject *iface,
463 LPCWSTR wszName )
465 FIXME("%p, %s\n", iface, debugstr_w(wszName));
466 return E_NOTIMPL;
469 static HRESULT WINAPI class_object_GetNames(
470 IWbemClassObject *iface,
471 LPCWSTR wszQualifierName,
472 LONG lFlags,
473 VARIANT *pQualifierVal,
474 SAFEARRAY **pNames )
476 struct class_object *co = impl_from_IWbemClassObject( iface );
477 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
479 TRACE("%p, %s, %08x, %s, %p\n", iface, debugstr_w(wszQualifierName), lFlags,
480 debugstr_variant(pQualifierVal), pNames);
482 if (lFlags != WBEM_FLAG_ALWAYS &&
483 lFlags != WBEM_FLAG_NONSYSTEM_ONLY &&
484 lFlags != WBEM_FLAG_SYSTEM_ONLY)
486 FIXME("flags %08x not supported\n", lFlags);
487 return E_NOTIMPL;
489 if (wszQualifierName || pQualifierVal)
490 FIXME("qualifier not supported\n");
492 return get_properties( ec->query->view, co->index, lFlags, pNames );
495 static HRESULT WINAPI class_object_BeginEnumeration(
496 IWbemClassObject *iface,
497 LONG lEnumFlags )
499 struct class_object *co = impl_from_IWbemClassObject( iface );
501 TRACE("%p, %08x\n", iface, lEnumFlags);
503 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
505 co->index_property = 0;
506 return S_OK;
509 static HRESULT WINAPI class_object_Next(
510 IWbemClassObject *iface,
511 LONG lFlags,
512 BSTR *strName,
513 VARIANT *pVal,
514 CIMTYPE *pType,
515 LONG *plFlavor )
517 struct class_object *obj = impl_from_IWbemClassObject( iface );
518 struct enum_class_object *iter = impl_from_IEnumWbemClassObject( obj->iter );
519 struct view *view = iter->query->view;
520 struct table *table = get_view_table( view, obj->index );
521 BSTR prop;
522 HRESULT hr;
523 UINT i;
525 TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
527 for (i = obj->index_property; i < table->num_cols; i++)
529 if (is_method( table, i )) continue;
530 if (!is_result_prop( view, table->columns[i].name )) continue;
531 if (!(prop = SysAllocString( table->columns[i].name ))) return E_OUTOFMEMORY;
532 if ((hr = get_propval( view, obj->index, prop, pVal, pType, plFlavor )) != S_OK)
534 SysFreeString( prop );
535 return hr;
538 obj->index_property = i + 1;
539 if (strName) *strName = prop;
540 else SysFreeString( prop );
542 return S_OK;
544 return WBEM_S_NO_MORE_DATA;
547 static HRESULT WINAPI class_object_EndEnumeration(
548 IWbemClassObject *iface )
550 struct class_object *co = impl_from_IWbemClassObject( iface );
552 TRACE("%p\n", iface);
554 co->index_property = 0;
555 return S_OK;
558 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
559 IWbemClassObject *iface,
560 LPCWSTR wszProperty,
561 IWbemQualifierSet **ppQualSet )
563 struct class_object *co = impl_from_IWbemClassObject( iface );
565 TRACE("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
567 return WbemQualifierSet_create( co->name, wszProperty, (void **)ppQualSet );
570 static HRESULT WINAPI class_object_Clone(
571 IWbemClassObject *iface,
572 IWbemClassObject **ppCopy )
574 FIXME("%p, %p\n", iface, ppCopy);
575 return E_NOTIMPL;
578 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
580 static const WCHAR fmtW[] = {'\n','\t','%','s',' ','=',' ','%','s',';',0};
581 BSTR value, ret;
582 WCHAR *p;
583 UINT i;
585 *len = 0;
586 for (i = 0; i < table->num_cols; i++)
588 if ((value = get_value_bstr( table, row, i )))
590 *len += ARRAY_SIZE( fmtW );
591 *len += lstrlenW( table->columns[i].name );
592 *len += SysStringLen( value );
593 SysFreeString( value );
596 if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
597 p = ret;
598 for (i = 0; i < table->num_cols; i++)
600 if ((value = get_value_bstr( table, row, i )))
602 p += swprintf( p, *len - (p - ret), fmtW, table->columns[i].name, value );
603 SysFreeString( value );
606 return ret;
609 static BSTR get_object_text( const struct view *view, UINT index )
611 static const WCHAR fmtW[] =
612 {'\n','i','n','s','t','a','n','c','e',' ','o','f',' ','%','s','\n','{','%','s','\n','}',';',0};
613 UINT len, len_body, row = view->result[index];
614 struct table *table = get_view_table( view, index );
615 BSTR ret, body;
617 len = ARRAY_SIZE( fmtW );
618 len += lstrlenW( table->name );
619 if (!(body = get_body_text( table, row, &len_body ))) return NULL;
620 len += len_body;
622 if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
623 swprintf( ret, len, fmtW, table->name, body );
624 SysFreeString( body );
625 return ret;
628 static HRESULT WINAPI class_object_GetObjectText(
629 IWbemClassObject *iface,
630 LONG lFlags,
631 BSTR *pstrObjectText )
633 struct class_object *co = impl_from_IWbemClassObject( iface );
634 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
635 struct view *view = ec->query->view;
636 BSTR text;
638 TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
640 if (lFlags) FIXME("flags %08x not implemented\n", lFlags);
642 if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
643 *pstrObjectText = text;
644 return S_OK;
647 static HRESULT WINAPI class_object_SpawnDerivedClass(
648 IWbemClassObject *iface,
649 LONG lFlags,
650 IWbemClassObject **ppNewClass )
652 FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
653 return E_NOTIMPL;
656 static HRESULT WINAPI class_object_SpawnInstance(
657 IWbemClassObject *iface,
658 LONG lFlags,
659 IWbemClassObject **ppNewInstance )
661 struct class_object *co = impl_from_IWbemClassObject( iface );
662 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
663 struct table *table = get_view_table( ec->query->view, co->index );
664 struct record *record;
666 TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
668 if (!(record = create_record( table ))) return E_OUTOFMEMORY;
670 return create_class_object( co->name, NULL, 0, record, ppNewInstance );
673 static HRESULT WINAPI class_object_CompareTo(
674 IWbemClassObject *iface,
675 LONG lFlags,
676 IWbemClassObject *pCompareTo )
678 FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
679 return E_NOTIMPL;
682 static HRESULT WINAPI class_object_GetPropertyOrigin(
683 IWbemClassObject *iface,
684 LPCWSTR wszName,
685 BSTR *pstrClassName )
687 FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
688 return E_NOTIMPL;
691 static HRESULT WINAPI class_object_InheritsFrom(
692 IWbemClassObject *iface,
693 LPCWSTR strAncestor )
695 FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
696 return E_NOTIMPL;
699 static UINT count_instances( IEnumWbemClassObject *iter )
701 UINT count = 0;
702 while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
703 IEnumWbemClassObject_Reset( iter );
704 return count;
707 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
709 switch (type)
711 case CIM_SINT16:
712 *(INT16 *)ptr = val;
713 break;
714 case CIM_UINT16:
715 *(UINT16 *)ptr = val;
716 break;
717 case CIM_SINT32:
718 *(INT32 *)ptr = val;
719 break;
720 case CIM_UINT32:
721 *(UINT32 *)ptr = val;
722 break;
723 default:
724 FIXME("unhandled type %u\n", type);
725 break;
729 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
730 struct column **cols, BYTE **data )
732 static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
733 static const WCHAR typeW[] = {'T','y','p','e',0};
734 static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0};
735 struct column *columns;
736 BYTE *row;
737 IWbemClassObject *param;
738 VARIANT val;
739 HRESULT hr = E_OUTOFMEMORY;
740 UINT offset = 0;
741 ULONG count;
742 int i = 0;
744 count = count_instances( iter );
745 if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
746 if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
748 for (;;)
750 IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
751 if (!count) break;
753 hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL );
754 if (hr != S_OK) goto error;
755 columns[i].name = heap_strdupW( V_BSTR( &val ) );
756 VariantClear( &val );
758 hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL );
759 if (hr != S_OK) goto error;
760 columns[i].type = V_UI4( &val );
762 hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
763 if (hr != S_OK) goto error;
764 if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
765 offset += get_type_size( columns[i].type );
767 IWbemClassObject_Release( param );
768 i++;
770 *num_cols = i;
771 *cols = columns;
772 *data = row;
773 return S_OK;
775 error:
776 for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
777 heap_free( columns );
778 heap_free( row );
779 return hr;
782 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
784 HRESULT hr;
785 struct table *table;
786 struct column *columns;
787 UINT num_cols;
788 BYTE *row;
790 hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
791 if (hr != S_OK) return hr;
793 if (!(table = create_table( name, num_cols, columns, 1, 1, row, NULL )))
795 free_columns( columns, num_cols );
796 heap_free( row );
797 return E_OUTOFMEMORY;
799 if (!add_table( table )) free_table( table ); /* already exists */
800 return S_OK;
803 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
805 static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
806 static const WCHAR outW[] = {'O','U','T',0};
807 static const WCHAR inW[] = {'I','N',0};
808 UINT len = ARRAY_SIZE(fmtW) + ARRAY_SIZE(outW) + lstrlenW( class ) + lstrlenW( method );
809 WCHAR *ret;
811 if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
812 swprintf( ret, len, fmtW, class, method, dir == PARAM_IN ? inW : outW );
813 return wcsupr( ret );
816 HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
817 IWbemClassObject **sig )
819 static const WCHAR selectW[] =
820 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
821 '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
822 'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
823 'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
824 'D','i','r','e','c','t','i','o','n','%','s',0};
825 static const WCHAR geW[] = {'>','=','0',0};
826 static const WCHAR leW[] = {'<','=','0',0};
827 UINT len = ARRAY_SIZE(selectW) + ARRAY_SIZE(geW);
828 IEnumWbemClassObject *iter;
829 WCHAR *query, *name;
830 HRESULT hr;
832 len += lstrlenW( class ) + lstrlenW( method );
833 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
834 swprintf( query, len, selectW, class, method, dir >= 0 ? geW : leW );
836 hr = exec_query( query, &iter );
837 heap_free( query );
838 if (hr != S_OK) return hr;
840 if (!count_instances( iter ))
842 *sig = NULL;
843 IEnumWbemClassObject_Release( iter );
844 return S_OK;
847 if (!(name = build_signature_table_name( class, method, dir )))
849 IEnumWbemClassObject_Release( iter );
850 return E_OUTOFMEMORY;
852 hr = create_signature_table( iter, name );
853 IEnumWbemClassObject_Release( iter );
854 if (hr == S_OK)
855 hr = get_object( name, sig );
857 heap_free( name );
858 return hr;
861 static HRESULT WINAPI class_object_GetMethod(
862 IWbemClassObject *iface,
863 LPCWSTR wszName,
864 LONG lFlags,
865 IWbemClassObject **ppInSignature,
866 IWbemClassObject **ppOutSignature )
868 struct class_object *co = impl_from_IWbemClassObject( iface );
869 IWbemClassObject *in, *out;
870 HRESULT hr;
872 TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
874 hr = create_signature( co->name, wszName, PARAM_IN, &in );
875 if (hr != S_OK) return hr;
877 hr = create_signature( co->name, wszName, PARAM_OUT, &out );
878 if (hr == S_OK)
880 if (ppInSignature) *ppInSignature = in;
881 else if (in) IWbemClassObject_Release( in );
882 if (ppOutSignature) *ppOutSignature = out;
883 else if (out) IWbemClassObject_Release( out );
885 else IWbemClassObject_Release( in );
886 return hr;
889 static HRESULT WINAPI class_object_PutMethod(
890 IWbemClassObject *iface,
891 LPCWSTR wszName,
892 LONG lFlags,
893 IWbemClassObject *pInSignature,
894 IWbemClassObject *pOutSignature )
896 FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
897 return E_NOTIMPL;
900 static HRESULT WINAPI class_object_DeleteMethod(
901 IWbemClassObject *iface,
902 LPCWSTR wszName )
904 FIXME("%p, %s\n", iface, debugstr_w(wszName));
905 return E_NOTIMPL;
908 static HRESULT WINAPI class_object_BeginMethodEnumeration(
909 IWbemClassObject *iface,
910 LONG lEnumFlags)
912 struct class_object *co = impl_from_IWbemClassObject( iface );
914 TRACE("%p, %08x\n", iface, lEnumFlags);
916 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
918 co->index_method = 0;
919 return S_OK;
922 static HRESULT WINAPI class_object_NextMethod(
923 IWbemClassObject *iface,
924 LONG lFlags,
925 BSTR *pstrName,
926 IWbemClassObject **ppInSignature,
927 IWbemClassObject **ppOutSignature)
929 struct class_object *co = impl_from_IWbemClassObject( iface );
930 BSTR method;
931 HRESULT hr;
933 TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
935 if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
937 hr = create_signature( co->name, method, PARAM_IN, ppInSignature );
938 if (hr != S_OK)
940 SysFreeString( method );
941 return hr;
943 hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature );
944 if (hr != S_OK)
946 SysFreeString( method );
947 if (*ppInSignature)
948 IWbemClassObject_Release( *ppInSignature );
950 else
952 *pstrName = method;
953 co->index_method++;
955 return hr;
958 static HRESULT WINAPI class_object_EndMethodEnumeration(
959 IWbemClassObject *iface )
961 struct class_object *co = impl_from_IWbemClassObject( iface );
963 TRACE("%p\n", iface);
965 co->index_method = 0;
966 return S_OK;
969 static HRESULT WINAPI class_object_GetMethodQualifierSet(
970 IWbemClassObject *iface,
971 LPCWSTR wszMethod,
972 IWbemQualifierSet **ppQualSet)
974 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
975 return E_NOTIMPL;
978 static HRESULT WINAPI class_object_GetMethodOrigin(
979 IWbemClassObject *iface,
980 LPCWSTR wszMethodName,
981 BSTR *pstrClassName)
983 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
984 return E_NOTIMPL;
987 static const IWbemClassObjectVtbl class_object_vtbl =
989 class_object_QueryInterface,
990 class_object_AddRef,
991 class_object_Release,
992 class_object_GetQualifierSet,
993 class_object_Get,
994 class_object_Put,
995 class_object_Delete,
996 class_object_GetNames,
997 class_object_BeginEnumeration,
998 class_object_Next,
999 class_object_EndEnumeration,
1000 class_object_GetPropertyQualifierSet,
1001 class_object_Clone,
1002 class_object_GetObjectText,
1003 class_object_SpawnDerivedClass,
1004 class_object_SpawnInstance,
1005 class_object_CompareTo,
1006 class_object_GetPropertyOrigin,
1007 class_object_InheritsFrom,
1008 class_object_GetMethod,
1009 class_object_PutMethod,
1010 class_object_DeleteMethod,
1011 class_object_BeginMethodEnumeration,
1012 class_object_NextMethod,
1013 class_object_EndMethodEnumeration,
1014 class_object_GetMethodQualifierSet,
1015 class_object_GetMethodOrigin
1018 HRESULT create_class_object( const WCHAR *name, IEnumWbemClassObject *iter, UINT index,
1019 struct record *record, IWbemClassObject **obj )
1021 struct class_object *co;
1023 TRACE("%s, %p\n", debugstr_w(name), obj);
1025 co = heap_alloc( sizeof(*co) );
1026 if (!co) return E_OUTOFMEMORY;
1028 co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
1029 co->refs = 1;
1030 if (!name) co->name = NULL;
1031 else if (!(co->name = heap_strdupW( name )))
1033 heap_free( co );
1034 return E_OUTOFMEMORY;
1036 co->iter = iter;
1037 co->index = index;
1038 co->index_method = 0;
1039 co->index_property = 0;
1040 co->record = record;
1041 if (iter) IEnumWbemClassObject_AddRef( iter );
1043 *obj = &co->IWbemClassObject_iface;
1045 TRACE("returning iface %p\n", *obj);
1046 return S_OK;