wined3d: Don't use persistent BOs from the client thread if we might need to do verte...
[wine.git] / dlls / wbemprox / class.c
blob3715076981661676e6ab18876ba5d1a8f8d5f956
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;
39 enum wbm_namespace ns;
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 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 struct table *table;
118 static int once = 0;
119 HRESULT hr;
120 ULONG i, j;
122 TRACE( "%p, %ld, %lu, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned );
124 if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
125 if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
127 *puReturned = 0;
129 for (i = 0; i < uCount; i++)
131 if (ec->index >= view->result_count) return WBEM_S_FALSE;
132 table = get_view_table( view, ec->index );
133 hr = create_class_object( ec->ns, table->name, iface, ec->index, NULL, &apObjects[i] );
134 if (hr != S_OK)
136 for (j = 0; j < i; j++) IWbemClassObject_Release( apObjects[j] );
137 return hr;
139 ec->index++;
140 (*puReturned)++;
143 return WBEM_S_NO_ERROR;
146 static HRESULT WINAPI enum_class_object_NextAsync(
147 IEnumWbemClassObject *iface,
148 ULONG uCount,
149 IWbemObjectSink *pSink )
151 FIXME( "%p, %lu, %p\n", iface, uCount, pSink );
152 return E_NOTIMPL;
155 static HRESULT WINAPI enum_class_object_Clone(
156 IEnumWbemClassObject *iface,
157 IEnumWbemClassObject **ppEnum )
159 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
161 TRACE("%p, %p\n", iface, ppEnum);
163 return EnumWbemClassObject_create( ec->query, (void **)ppEnum );
166 static HRESULT WINAPI enum_class_object_Skip(
167 IEnumWbemClassObject *iface,
168 LONG lTimeout,
169 ULONG nCount )
171 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
172 struct view *view = ec->query->view;
173 static int once = 0;
175 TRACE( "%p, %ld, %lu\n", iface, lTimeout, nCount );
177 if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n");
179 if (!view->result_count) return WBEM_S_FALSE;
181 if (nCount > view->result_count - ec->index)
183 ec->index = view->result_count - 1;
184 return WBEM_S_FALSE;
186 ec->index += nCount;
187 return WBEM_S_NO_ERROR;
190 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
192 enum_class_object_QueryInterface,
193 enum_class_object_AddRef,
194 enum_class_object_Release,
195 enum_class_object_Reset,
196 enum_class_object_Next,
197 enum_class_object_NextAsync,
198 enum_class_object_Clone,
199 enum_class_object_Skip
202 HRESULT EnumWbemClassObject_create( struct query *query, LPVOID *ppObj )
204 struct enum_class_object *ec;
206 TRACE("%p\n", ppObj);
208 if (!(ec = malloc( sizeof(*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;
214 ec->ns = query->ns;
216 *ppObj = &ec->IEnumWbemClassObject_iface;
218 TRACE("returning iface %p\n", *ppObj);
219 return S_OK;
222 static struct record *create_record( struct table *table )
224 UINT i;
225 struct record *record;
227 if (!(record = malloc( sizeof(struct record) ))) return NULL;
228 if (!(record->fields = malloc( table->num_cols * sizeof(struct field) )))
230 free( record );
231 return NULL;
233 for (i = 0; i < table->num_cols; i++)
235 record->fields[i].type = table->columns[i].type;
236 record->fields[i].u.ival = 0;
238 record->count = table->num_cols;
239 record->table = addref_table( table );
240 return record;
243 void destroy_array( struct array *array, CIMTYPE type )
245 UINT i;
246 if (!array) return;
247 if (type == CIM_STRING || type == CIM_DATETIME || type == CIM_REFERENCE)
249 for (i = 0; i < array->count; i++) free( *(WCHAR **)((char *)array->ptr + i * array->elem_size) );
251 free( array->ptr );
252 free( array );
255 static void destroy_record( struct record *record )
257 UINT i;
259 if (!record) return;
260 release_table( record->table );
261 for (i = 0; i < record->count; i++)
263 if (record->fields[i].type == CIM_STRING ||
264 record->fields[i].type == CIM_DATETIME ||
265 record->fields[i].type == CIM_REFERENCE) free( record->fields[i].u.sval );
266 else if (record->fields[i].type & CIM_FLAG_ARRAY)
267 destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK );
269 free( record->fields );
270 free( record );
273 struct class_object
275 IWbemClassObject IWbemClassObject_iface;
276 LONG refs;
277 WCHAR *name;
278 IEnumWbemClassObject *iter;
279 UINT index;
280 UINT index_method;
281 UINT index_property;
282 enum wbm_namespace ns;
283 struct record *record; /* uncommitted instance */
286 static inline struct class_object *impl_from_IWbemClassObject(
287 IWbemClassObject *iface )
289 return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
292 static ULONG WINAPI class_object_AddRef(
293 IWbemClassObject *iface )
295 struct class_object *co = impl_from_IWbemClassObject( iface );
296 return InterlockedIncrement( &co->refs );
299 static ULONG WINAPI class_object_Release(
300 IWbemClassObject *iface )
302 struct class_object *co = impl_from_IWbemClassObject( iface );
303 LONG refs = InterlockedDecrement( &co->refs );
304 if (!refs)
306 TRACE("destroying %p\n", co);
307 if (co->iter) IEnumWbemClassObject_Release( co->iter );
308 destroy_record( co->record );
309 free( co->name );
310 free( co );
312 return refs;
315 static HRESULT WINAPI class_object_QueryInterface(
316 IWbemClassObject *iface,
317 REFIID riid,
318 void **ppvObject )
320 struct class_object *co = impl_from_IWbemClassObject( iface );
322 TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
324 if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
325 IsEqualGUID( riid, &IID_IUnknown ) )
327 *ppvObject = co;
329 else if (IsEqualGUID( riid, &IID_IClientSecurity ))
331 *ppvObject = &client_security;
332 return S_OK;
334 else
336 FIXME("interface %s not implemented\n", debugstr_guid(riid));
337 return E_NOINTERFACE;
339 IWbemClassObject_AddRef( iface );
340 return S_OK;
343 static HRESULT WINAPI class_object_GetQualifierSet(
344 IWbemClassObject *iface,
345 IWbemQualifierSet **ppQualSet )
347 struct class_object *co = impl_from_IWbemClassObject( iface );
349 TRACE("%p, %p\n", iface, ppQualSet);
351 return WbemQualifierSet_create( co->ns, co->name, NULL, (void **)ppQualSet );
354 static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type )
356 VARTYPE vartype = to_vartype( record->fields[index].type & CIM_TYPE_MASK );
358 if (type) *type = record->fields[index].type;
359 if (!var) return S_OK;
361 if (record->fields[index].type & CIM_FLAG_ARRAY)
363 V_VT( var ) = vartype | VT_ARRAY;
364 V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & CIM_TYPE_MASK );
365 return S_OK;
367 switch (record->fields[index].type)
369 case CIM_STRING:
370 case CIM_DATETIME:
371 case CIM_REFERENCE:
372 V_BSTR( var ) = SysAllocString( record->fields[index].u.sval );
373 break;
374 case CIM_SINT32:
375 V_I4( var ) = record->fields[index].u.ival;
376 break;
377 case CIM_UINT32:
378 V_UI4( var ) = record->fields[index].u.ival;
379 break;
380 default:
381 FIXME("unhandled type %u\n", record->fields[index].type);
382 return WBEM_E_INVALID_PARAMETER;
384 V_VT( var ) = vartype;
385 return S_OK;
388 static HRESULT WINAPI class_object_Get(
389 IWbemClassObject *iface,
390 LPCWSTR wszName,
391 LONG lFlags,
392 VARIANT *pVal,
393 CIMTYPE *pType,
394 LONG *plFlavor )
396 struct class_object *co = impl_from_IWbemClassObject( iface );
397 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
399 TRACE( "%p, %s, %#lx, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor );
401 if (co->record)
403 UINT index;
404 HRESULT hr;
406 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
407 return record_get_value( co->record, index, pVal, pType );
409 return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor );
412 static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var )
414 LONGLONG val;
415 CIMTYPE type;
416 HRESULT hr;
418 if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr;
419 if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH;
421 if (type & CIM_FLAG_ARRAY)
423 record->fields[index].u.aval = (struct array *)(INT_PTR)val;
424 return S_OK;
426 switch (type)
428 case CIM_STRING:
429 case CIM_DATETIME:
430 case CIM_REFERENCE:
431 record->fields[index].u.sval = (WCHAR *)(INT_PTR)val;
432 return S_OK;
433 case CIM_SINT16:
434 case CIM_UINT16:
435 case CIM_SINT32:
436 case CIM_UINT32:
437 record->fields[index].u.ival = val;
438 return S_OK;
439 default:
440 FIXME( "unhandled type %lu\n", type );
441 break;
443 return WBEM_E_INVALID_PARAMETER;
446 static HRESULT WINAPI class_object_Put(
447 IWbemClassObject *iface,
448 LPCWSTR wszName,
449 LONG lFlags,
450 VARIANT *pVal,
451 CIMTYPE Type )
453 struct class_object *co = impl_from_IWbemClassObject( iface );
454 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
456 TRACE( "%p, %s, %#lx, %p, %lu\n", iface, debugstr_w(wszName), lFlags, pVal, Type );
458 if (co->record)
460 UINT index;
461 HRESULT hr;
463 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
464 return record_set_value( co->record, index, pVal );
467 if (!ec) return S_OK;
469 return put_propval( ec->query->view, co->index, wszName, pVal, Type );
472 static HRESULT WINAPI class_object_Delete(
473 IWbemClassObject *iface,
474 LPCWSTR wszName )
476 FIXME("%p, %s\n", iface, debugstr_w(wszName));
477 return E_NOTIMPL;
480 static HRESULT WINAPI class_object_GetNames(
481 IWbemClassObject *iface,
482 LPCWSTR wszQualifierName,
483 LONG lFlags,
484 VARIANT *pQualifierVal,
485 SAFEARRAY **pNames )
487 struct class_object *co = impl_from_IWbemClassObject( iface );
488 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
490 TRACE( "%p, %s, %#lx, %s, %p\n", iface, debugstr_w(wszQualifierName), lFlags,
491 debugstr_variant(pQualifierVal), pNames);
493 if (!pNames)
494 return WBEM_E_INVALID_PARAMETER;
496 /* Combination used in a handful of broken apps */
497 if (lFlags == (WBEM_FLAG_ALWAYS | WBEM_MASK_CONDITION_ORIGIN))
498 lFlags = WBEM_FLAG_ALWAYS;
500 if (lFlags && (lFlags != WBEM_FLAG_ALWAYS &&
501 lFlags != WBEM_FLAG_NONSYSTEM_ONLY &&
502 lFlags != WBEM_FLAG_SYSTEM_ONLY))
504 FIXME( "flags %#lx not supported\n", lFlags );
505 return E_NOTIMPL;
508 if (wszQualifierName || pQualifierVal)
509 FIXME("qualifier not supported\n");
511 return get_properties( ec->query->view, co->index, lFlags, pNames );
514 static HRESULT WINAPI class_object_BeginEnumeration(
515 IWbemClassObject *iface,
516 LONG lEnumFlags )
518 struct class_object *co = impl_from_IWbemClassObject( iface );
520 TRACE( "%p, %#lx\n", iface, lEnumFlags );
522 if (lEnumFlags) FIXME( "flags %#lx not supported\n", lEnumFlags );
524 co->index_property = 0;
525 return S_OK;
528 static HRESULT WINAPI class_object_Next(
529 IWbemClassObject *iface,
530 LONG lFlags,
531 BSTR *strName,
532 VARIANT *pVal,
533 CIMTYPE *pType,
534 LONG *plFlavor )
536 struct class_object *obj = impl_from_IWbemClassObject( iface );
537 struct enum_class_object *iter = impl_from_IEnumWbemClassObject( obj->iter );
538 struct view *view = iter->query->view;
539 struct table *table = get_view_table( view, obj->index );
540 BSTR prop;
541 HRESULT hr;
542 UINT i;
544 TRACE( "%p, %#lx, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor );
546 for (i = obj->index_property; i < table->num_cols; i++)
548 if (is_method( table, i )) continue;
549 if (!is_result_prop( view, table->columns[i].name )) continue;
550 if (!(prop = SysAllocString( table->columns[i].name ))) return E_OUTOFMEMORY;
551 if (obj->record)
553 UINT index;
555 if ((hr = get_column_index( table, table->columns[i].name, &index )) == S_OK)
556 hr = record_get_value( obj->record, index, pVal, pType );
558 else
559 hr = get_propval( view, obj->index, prop, pVal, pType, plFlavor );
561 if (FAILED(hr))
563 SysFreeString( prop );
564 return hr;
567 obj->index_property = i + 1;
568 if (strName) *strName = prop;
569 else SysFreeString( prop );
571 return S_OK;
573 return WBEM_S_NO_MORE_DATA;
576 static HRESULT WINAPI class_object_EndEnumeration(
577 IWbemClassObject *iface )
579 struct class_object *co = impl_from_IWbemClassObject( iface );
581 TRACE("%p\n", iface);
583 co->index_property = 0;
584 return S_OK;
587 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
588 IWbemClassObject *iface,
589 LPCWSTR wszProperty,
590 IWbemQualifierSet **ppQualSet )
592 struct class_object *co = impl_from_IWbemClassObject( iface );
594 TRACE("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
596 return WbemQualifierSet_create( co->ns, co->name, wszProperty, (void **)ppQualSet );
599 static HRESULT WINAPI class_object_Clone(
600 IWbemClassObject *iface,
601 IWbemClassObject **ppCopy )
603 FIXME("%p, %p\n", iface, ppCopy);
604 return E_NOTIMPL;
607 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
609 BSTR value, ret;
610 WCHAR *p;
611 UINT i;
613 *len = 0;
614 for (i = 0; i < table->num_cols; i++)
616 if ((value = get_value_bstr( table, row, i )))
618 *len += ARRAY_SIZE( L"\n\t%s = %s;" );
619 *len += lstrlenW( table->columns[i].name );
620 *len += SysStringLen( value );
621 SysFreeString( value );
624 if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
625 p = ret;
626 for (i = 0; i < table->num_cols; i++)
628 if ((value = get_value_bstr( table, row, i )))
630 p += swprintf( p, *len - (p - ret), L"\n\t%s = %s;", table->columns[i].name, value );
631 SysFreeString( value );
634 return ret;
637 static BSTR get_object_text( const struct view *view, UINT index )
639 UINT len, len_body, row = view->result[index];
640 struct table *table = get_view_table( view, index );
641 BSTR ret, body;
643 len = ARRAY_SIZE( L"\ninstance of %s\n{%s\n};" );
644 len += lstrlenW( table->name );
645 if (!(body = get_body_text( table, row, &len_body ))) return NULL;
646 len += len_body;
648 if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
649 swprintf( ret, len, L"\ninstance of %s\n{%s\n};", table->name, body );
650 SysFreeString( body );
651 return ret;
654 static HRESULT WINAPI class_object_GetObjectText(
655 IWbemClassObject *iface,
656 LONG lFlags,
657 BSTR *pstrObjectText )
659 struct class_object *co = impl_from_IWbemClassObject( iface );
660 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
661 struct view *view = ec->query->view;
662 BSTR text;
664 TRACE( "%p, %#lx, %p\n", iface, lFlags, pstrObjectText );
666 if (lFlags) FIXME( "flags %#lx not implemented\n", lFlags );
668 if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
669 *pstrObjectText = text;
670 return S_OK;
673 static HRESULT WINAPI class_object_SpawnDerivedClass(
674 IWbemClassObject *iface,
675 LONG lFlags,
676 IWbemClassObject **ppNewClass )
678 FIXME( "%p, %#lx, %p\n", iface, lFlags, ppNewClass );
679 return E_NOTIMPL;
682 static HRESULT WINAPI class_object_SpawnInstance(
683 IWbemClassObject *iface,
684 LONG lFlags,
685 IWbemClassObject **ppNewInstance )
687 struct class_object *co = impl_from_IWbemClassObject( iface );
688 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
689 struct table *table = get_view_table( ec->query->view, co->index );
690 IEnumWbemClassObject *iter;
691 struct record *record;
692 HRESULT hr;
694 TRACE( "%p, %#lx, %p\n", iface, lFlags, ppNewInstance );
696 if (!(record = create_record( table ))) return E_OUTOFMEMORY;
697 if (FAILED(hr = IEnumWbemClassObject_Clone( co->iter, &iter )))
699 destroy_record( record );
700 return hr;
702 hr = create_class_object( co->ns, co->name, iter, 0, record, ppNewInstance );
703 IEnumWbemClassObject_Release( iter );
704 return hr;
707 static HRESULT WINAPI class_object_CompareTo(
708 IWbemClassObject *iface,
709 LONG lFlags,
710 IWbemClassObject *pCompareTo )
712 FIXME( "%p, %#lx, %p\n", iface, lFlags, pCompareTo );
713 return E_NOTIMPL;
716 static HRESULT WINAPI class_object_GetPropertyOrigin(
717 IWbemClassObject *iface,
718 LPCWSTR wszName,
719 BSTR *pstrClassName )
721 FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
722 return E_NOTIMPL;
725 static HRESULT WINAPI class_object_InheritsFrom(
726 IWbemClassObject *iface,
727 LPCWSTR strAncestor )
729 FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
730 return E_NOTIMPL;
733 static UINT count_instances( IEnumWbemClassObject *iter )
735 UINT count = 0;
736 while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
737 IEnumWbemClassObject_Reset( iter );
738 return count;
741 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
743 switch (type)
745 case CIM_SINT16:
746 *(INT16 *)ptr = val;
747 break;
748 case CIM_UINT16:
749 *(UINT16 *)ptr = val;
750 break;
751 case CIM_SINT32:
752 *(INT32 *)ptr = val;
753 break;
754 case CIM_UINT32:
755 *(UINT32 *)ptr = val;
756 break;
757 default:
758 FIXME( "unhandled type %lu\n", type );
759 break;
763 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
764 struct column **cols, BYTE **data )
766 struct column *columns;
767 BYTE *row;
768 IWbemClassObject *param;
769 VARIANT val;
770 HRESULT hr = E_OUTOFMEMORY;
771 UINT offset = 0;
772 ULONG count;
773 int i = 0;
775 count = count_instances( iter );
776 if (!(columns = malloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
777 if (!(row = calloc( count, sizeof(LONGLONG) ))) goto error;
779 for (;;)
781 IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
782 if (!count) break;
784 hr = IWbemClassObject_Get( param, L"Parameter", 0, &val, NULL, NULL );
785 if (hr != S_OK) goto error;
786 columns[i].name = heap_strdupW( V_BSTR( &val ) );
787 VariantClear( &val );
789 hr = IWbemClassObject_Get( param, L"Type", 0, &val, NULL, NULL );
790 if (hr != S_OK) goto error;
791 columns[i].type = V_UI4( &val );
793 hr = IWbemClassObject_Get( param, L"DefaultValue", 0, &val, NULL, NULL );
794 if (hr != S_OK) goto error;
795 if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
796 offset += get_type_size( columns[i].type );
798 IWbemClassObject_Release( param );
799 i++;
801 *num_cols = i;
802 *cols = columns;
803 *data = row;
804 return S_OK;
806 error:
807 for (; i >= 0; i--) free( (WCHAR *)columns[i].name );
808 free( columns );
809 free( row );
810 return hr;
813 static HRESULT create_signature_table( IEnumWbemClassObject *iter, enum wbm_namespace ns, WCHAR *name )
815 HRESULT hr;
816 struct table *table;
817 struct column *columns;
818 UINT num_cols;
819 BYTE *row;
821 hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
822 if (hr != S_OK) return hr;
824 if (!(table = create_table( name, num_cols, columns, 1, 1, row, NULL )))
826 free_columns( columns, num_cols );
827 free( row );
828 return E_OUTOFMEMORY;
830 if (!add_table( ns, table )) free_table( table ); /* already exists */
831 return S_OK;
834 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
836 UINT len = ARRAY_SIZE(L"__%s_%s_%s") + ARRAY_SIZE(L"OUT") + lstrlenW( class ) + lstrlenW( method );
837 WCHAR *ret;
839 if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL;
840 swprintf( ret, len, L"__%s_%s_%s", class, method, dir == PARAM_IN ? L"IN" : L"OUT" );
841 return wcsupr( ret );
844 HRESULT create_signature( enum wbm_namespace ns, const WCHAR *class, const WCHAR *method, enum param_direction dir,
845 IWbemClassObject **sig )
847 static const WCHAR selectW[] = L"SELECT * FROM __PARAMETERS WHERE Class='%s' AND Method='%s' AND Direction%s";
848 UINT len = ARRAY_SIZE(selectW) + ARRAY_SIZE(L">=0");
849 IEnumWbemClassObject *iter;
850 WCHAR *query, *name;
851 HRESULT hr;
853 len += lstrlenW( class ) + lstrlenW( method );
854 if (!(query = malloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
855 swprintf( query, len, selectW, class, method, dir >= 0 ? L">=0" : L"<=0" );
857 hr = exec_query( ns, query, &iter );
858 free( query );
859 if (hr != S_OK) return hr;
861 if (!count_instances( iter ))
863 *sig = NULL;
864 IEnumWbemClassObject_Release( iter );
865 return S_OK;
868 if (!(name = build_signature_table_name( class, method, dir )))
870 IEnumWbemClassObject_Release( iter );
871 return E_OUTOFMEMORY;
873 hr = create_signature_table( iter, ns, name );
874 IEnumWbemClassObject_Release( iter );
875 if (hr == S_OK)
876 hr = get_object( ns, name, sig );
878 free( name );
879 return hr;
882 static HRESULT WINAPI class_object_GetMethod(
883 IWbemClassObject *iface,
884 LPCWSTR wszName,
885 LONG lFlags,
886 IWbemClassObject **ppInSignature,
887 IWbemClassObject **ppOutSignature )
889 struct class_object *co = impl_from_IWbemClassObject( iface );
890 IWbemClassObject *in, *out;
891 struct table *table;
892 unsigned int i;
893 HRESULT hr;
895 TRACE( "%p, %s, %#lx, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature );
897 if (ppInSignature) *ppInSignature = NULL;
898 if (ppOutSignature) *ppOutSignature = NULL;
900 table = get_view_table( impl_from_IEnumWbemClassObject( co->iter )->query->view, co->index );
902 for (i = 0; i < table->num_cols; ++i)
904 if (is_method( table, i ) && !lstrcmpiW( table->columns[i].name, wszName )) break;
906 if (i == table->num_cols)
908 FIXME("Method %s not found in class %s.\n", debugstr_w(wszName), debugstr_w(co->name));
909 return WBEM_E_NOT_FOUND;
912 hr = create_signature( co->ns, co->name, wszName, PARAM_IN, &in );
913 if (hr != S_OK) return hr;
915 hr = create_signature( co->ns, co->name, wszName, PARAM_OUT, &out );
916 if (hr == S_OK)
918 if (ppInSignature) *ppInSignature = in;
919 else if (in) IWbemClassObject_Release( in );
920 if (ppOutSignature) *ppOutSignature = out;
921 else if (out) IWbemClassObject_Release( out );
923 else IWbemClassObject_Release( in );
924 return hr;
927 static HRESULT WINAPI class_object_PutMethod(
928 IWbemClassObject *iface,
929 LPCWSTR wszName,
930 LONG lFlags,
931 IWbemClassObject *pInSignature,
932 IWbemClassObject *pOutSignature )
934 FIXME( "%p, %s, %#lx, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature );
935 return E_NOTIMPL;
938 static HRESULT WINAPI class_object_DeleteMethod(
939 IWbemClassObject *iface,
940 LPCWSTR wszName )
942 FIXME("%p, %s\n", iface, debugstr_w(wszName));
943 return E_NOTIMPL;
946 static HRESULT WINAPI class_object_BeginMethodEnumeration(
947 IWbemClassObject *iface,
948 LONG lEnumFlags)
950 struct class_object *co = impl_from_IWbemClassObject( iface );
952 TRACE( "%p, %#lx\n", iface, lEnumFlags );
954 if (lEnumFlags) FIXME( "flags %#lx not supported\n", lEnumFlags );
956 co->index_method = 0;
957 return S_OK;
960 static HRESULT WINAPI class_object_NextMethod(
961 IWbemClassObject *iface,
962 LONG lFlags,
963 BSTR *pstrName,
964 IWbemClassObject **ppInSignature,
965 IWbemClassObject **ppOutSignature)
967 struct class_object *co = impl_from_IWbemClassObject( iface );
968 BSTR method;
969 HRESULT hr;
971 TRACE( "%p, %#lx, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature );
973 if (!(method = get_method_name( co->ns, co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
975 hr = create_signature( co->ns, co->name, method, PARAM_IN, ppInSignature );
976 if (hr != S_OK)
978 SysFreeString( method );
979 return hr;
981 hr = create_signature( co->ns, co->name, method, PARAM_OUT, ppOutSignature );
982 if (hr != S_OK)
984 SysFreeString( method );
985 if (*ppInSignature)
986 IWbemClassObject_Release( *ppInSignature );
988 else
990 *pstrName = method;
991 co->index_method++;
993 return hr;
996 static HRESULT WINAPI class_object_EndMethodEnumeration(
997 IWbemClassObject *iface )
999 struct class_object *co = impl_from_IWbemClassObject( iface );
1001 TRACE("%p\n", iface);
1003 co->index_method = 0;
1004 return S_OK;
1007 static HRESULT WINAPI class_object_GetMethodQualifierSet(
1008 IWbemClassObject *iface,
1009 LPCWSTR wszMethod,
1010 IWbemQualifierSet **ppQualSet)
1012 struct class_object *co = impl_from_IWbemClassObject( iface );
1014 TRACE("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
1016 return WbemQualifierSet_create( co->ns, co->name, wszMethod, (void **)ppQualSet );
1019 static HRESULT WINAPI class_object_GetMethodOrigin(
1020 IWbemClassObject *iface,
1021 LPCWSTR wszMethodName,
1022 BSTR *pstrClassName)
1024 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
1025 return E_NOTIMPL;
1028 static const IWbemClassObjectVtbl class_object_vtbl =
1030 class_object_QueryInterface,
1031 class_object_AddRef,
1032 class_object_Release,
1033 class_object_GetQualifierSet,
1034 class_object_Get,
1035 class_object_Put,
1036 class_object_Delete,
1037 class_object_GetNames,
1038 class_object_BeginEnumeration,
1039 class_object_Next,
1040 class_object_EndEnumeration,
1041 class_object_GetPropertyQualifierSet,
1042 class_object_Clone,
1043 class_object_GetObjectText,
1044 class_object_SpawnDerivedClass,
1045 class_object_SpawnInstance,
1046 class_object_CompareTo,
1047 class_object_GetPropertyOrigin,
1048 class_object_InheritsFrom,
1049 class_object_GetMethod,
1050 class_object_PutMethod,
1051 class_object_DeleteMethod,
1052 class_object_BeginMethodEnumeration,
1053 class_object_NextMethod,
1054 class_object_EndMethodEnumeration,
1055 class_object_GetMethodQualifierSet,
1056 class_object_GetMethodOrigin
1059 HRESULT create_class_object( enum wbm_namespace ns, const WCHAR *name, IEnumWbemClassObject *iter, UINT index,
1060 struct record *record, IWbemClassObject **obj )
1062 struct class_object *co;
1064 TRACE("%s, %p\n", debugstr_w(name), obj);
1066 if (!(co = malloc( sizeof(*co) ))) return E_OUTOFMEMORY;
1068 co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
1069 co->refs = 1;
1070 if (!name) co->name = NULL;
1071 else if (!(co->name = heap_strdupW( name )))
1073 free( co );
1074 return E_OUTOFMEMORY;
1076 co->iter = iter;
1077 co->index = index;
1078 co->index_method = 0;
1079 co->index_property = 0;
1080 co->record = record;
1081 co->ns = ns;
1082 if (iter) IEnumWbemClassObject_AddRef( iter );
1084 *obj = &co->IWbemClassObject_iface;
1086 TRACE("returning iface %p\n", *obj);
1087 return S_OK;