/* * Copyright 2012 Hans Leidekker for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define COBJMACROS #include #include "windef.h" #include "winbase.h" #include "objbase.h" #include "wbemcli.h" #include "wine/debug.h" #include "wbemprox_private.h" WINE_DEFAULT_DEBUG_CHANNEL(wbemprox); struct enum_class_object { IEnumWbemClassObject IEnumWbemClassObject_iface; LONG refs; struct query *query; UINT index; }; static inline struct enum_class_object *impl_from_IEnumWbemClassObject( IEnumWbemClassObject *iface ) { return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface); } static ULONG WINAPI enum_class_object_AddRef( IEnumWbemClassObject *iface ) { struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface ); return InterlockedIncrement( &ec->refs ); } static ULONG WINAPI enum_class_object_Release( IEnumWbemClassObject *iface ) { struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface ); LONG refs = InterlockedDecrement( &ec->refs ); if (!refs) { TRACE("destroying %p\n", ec); release_query( ec->query ); heap_free( ec ); } return refs; } static HRESULT WINAPI enum_class_object_QueryInterface( IEnumWbemClassObject *iface, REFIID riid, void **ppvObject ) { struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface ); TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject ); if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) || IsEqualGUID( riid, &IID_IUnknown ) ) { *ppvObject = ec; } else if ( IsEqualGUID( riid, &IID_IClientSecurity ) ) { *ppvObject = &client_security; return S_OK; } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); return E_NOINTERFACE; } IEnumWbemClassObject_AddRef( iface ); return S_OK; } static HRESULT WINAPI enum_class_object_Reset( IEnumWbemClassObject *iface ) { struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface ); TRACE("%p\n", iface); ec->index = 0; return WBEM_S_NO_ERROR; } static HRESULT WINAPI enum_class_object_Next( IEnumWbemClassObject *iface, LONG lTimeout, ULONG uCount, IWbemClassObject **apObjects, ULONG *puReturned ) { struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface ); struct view *view = ec->query->view; struct table *table; static int once = 0; HRESULT hr; ULONG i, j; TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned); if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER; if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n"); *puReturned = 0; for (i = 0; i < uCount; i++) { if (ec->index >= view->result_count) return WBEM_S_FALSE; table = get_view_table( view, ec->index ); hr = create_class_object( table->name, iface, ec->index, NULL, &apObjects[i] ); if (hr != S_OK) { for (j = 0; j < i; j++) IWbemClassObject_Release( apObjects[j] ); return hr; } ec->index++; (*puReturned)++; } return WBEM_S_NO_ERROR; } static HRESULT WINAPI enum_class_object_NextAsync( IEnumWbemClassObject *iface, ULONG uCount, IWbemObjectSink *pSink ) { FIXME("%p, %u, %p\n", iface, uCount, pSink); return E_NOTIMPL; } static HRESULT WINAPI enum_class_object_Clone( IEnumWbemClassObject *iface, IEnumWbemClassObject **ppEnum ) { struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface ); TRACE("%p, %p\n", iface, ppEnum); return EnumWbemClassObject_create( ec->query, (void **)ppEnum ); } static HRESULT WINAPI enum_class_object_Skip( IEnumWbemClassObject *iface, LONG lTimeout, ULONG nCount ) { struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface ); struct view *view = ec->query->view; static int once = 0; TRACE("%p, %d, %u\n", iface, lTimeout, nCount); if (lTimeout != WBEM_INFINITE && !once++) FIXME("timeout not supported\n"); if (!view->result_count) return WBEM_S_FALSE; if (nCount > view->result_count - ec->index) { ec->index = view->result_count - 1; return WBEM_S_FALSE; } ec->index += nCount; return WBEM_S_NO_ERROR; } static const IEnumWbemClassObjectVtbl enum_class_object_vtbl = { enum_class_object_QueryInterface, enum_class_object_AddRef, enum_class_object_Release, enum_class_object_Reset, enum_class_object_Next, enum_class_object_NextAsync, enum_class_object_Clone, enum_class_object_Skip }; HRESULT EnumWbemClassObject_create( struct query *query, LPVOID *ppObj ) { struct enum_class_object *ec; TRACE("%p\n", ppObj); ec = heap_alloc( sizeof(*ec) ); if (!ec) return E_OUTOFMEMORY; ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl; ec->refs = 1; ec->query = addref_query( query ); ec->index = 0; *ppObj = &ec->IEnumWbemClassObject_iface; TRACE("returning iface %p\n", *ppObj); return S_OK; } static struct record *create_record( struct table *table ) { UINT i; struct record *record; if (!(record = heap_alloc( sizeof(struct record) ))) return NULL; if (!(record->fields = heap_alloc( table->num_cols * sizeof(struct field) ))) { heap_free( record ); return NULL; } for (i = 0; i < table->num_cols; i++) { record->fields[i].type = table->columns[i].type; record->fields[i].u.ival = 0; } record->count = table->num_cols; record->table = addref_table( table ); return record; } void destroy_array( struct array *array, CIMTYPE type ) { UINT i; if (!array) return; if (type == CIM_STRING || type == CIM_DATETIME || type == CIM_REFERENCE) { for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * array->elem_size) ); } heap_free( array->ptr ); heap_free( array ); } static void destroy_record( struct record *record ) { UINT i; if (!record) return; release_table( record->table ); for (i = 0; i < record->count; i++) { if (record->fields[i].type == CIM_STRING || record->fields[i].type == CIM_DATETIME || record->fields[i].type == CIM_REFERENCE) heap_free( record->fields[i].u.sval ); else if (record->fields[i].type & CIM_FLAG_ARRAY) destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK ); } heap_free( record->fields ); heap_free( record ); } struct class_object { IWbemClassObject IWbemClassObject_iface; LONG refs; WCHAR *name; IEnumWbemClassObject *iter; UINT index; UINT index_method; UINT index_property; struct record *record; /* uncommitted instance */ }; static inline struct class_object *impl_from_IWbemClassObject( IWbemClassObject *iface ) { return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface); } static ULONG WINAPI class_object_AddRef( IWbemClassObject *iface ) { struct class_object *co = impl_from_IWbemClassObject( iface ); return InterlockedIncrement( &co->refs ); } static ULONG WINAPI class_object_Release( IWbemClassObject *iface ) { struct class_object *co = impl_from_IWbemClassObject( iface ); LONG refs = InterlockedDecrement( &co->refs ); if (!refs) { TRACE("destroying %p\n", co); if (co->iter) IEnumWbemClassObject_Release( co->iter ); destroy_record( co->record ); heap_free( co->name ); heap_free( co ); } return refs; } static HRESULT WINAPI class_object_QueryInterface( IWbemClassObject *iface, REFIID riid, void **ppvObject ) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject ); if ( IsEqualGUID( riid, &IID_IWbemClassObject ) || IsEqualGUID( riid, &IID_IUnknown ) ) { *ppvObject = co; } else if (IsEqualGUID( riid, &IID_IClientSecurity )) { *ppvObject = &client_security; return S_OK; } else { FIXME("interface %s not implemented\n", debugstr_guid(riid)); return E_NOINTERFACE; } IWbemClassObject_AddRef( iface ); return S_OK; } static HRESULT WINAPI class_object_GetQualifierSet( IWbemClassObject *iface, IWbemQualifierSet **ppQualSet ) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p, %p\n", iface, ppQualSet); return WbemQualifierSet_create( co->name, NULL, (void **)ppQualSet ); } static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type ) { VARTYPE vartype = to_vartype( record->fields[index].type & CIM_TYPE_MASK ); if (type) *type = record->fields[index].type; if (!var) return S_OK; if (record->fields[index].type & CIM_FLAG_ARRAY) { V_VT( var ) = vartype | VT_ARRAY; V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & CIM_TYPE_MASK ); return S_OK; } switch (record->fields[index].type) { case CIM_STRING: case CIM_DATETIME: case CIM_REFERENCE: V_BSTR( var ) = SysAllocString( record->fields[index].u.sval ); break; case CIM_SINT32: V_I4( var ) = record->fields[index].u.ival; break; case CIM_UINT32: V_UI4( var ) = record->fields[index].u.ival; break; default: FIXME("unhandled type %u\n", record->fields[index].type); return WBEM_E_INVALID_PARAMETER; } V_VT( var ) = vartype; return S_OK; } static HRESULT WINAPI class_object_Get( IWbemClassObject *iface, LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pType, LONG *plFlavor ) { struct class_object *co = impl_from_IWbemClassObject( iface ); struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter ); TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor); if (co->record) { UINT index; HRESULT hr; if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr; return record_get_value( co->record, index, pVal, pType ); } return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor ); } static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var ) { LONGLONG val; CIMTYPE type; HRESULT hr; if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr; if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH; if (type & CIM_FLAG_ARRAY) { record->fields[index].u.aval = (struct array *)(INT_PTR)val; return S_OK; } switch (type) { case CIM_STRING: case CIM_DATETIME: case CIM_REFERENCE: record->fields[index].u.sval = (WCHAR *)(INT_PTR)val; return S_OK; case CIM_SINT16: case CIM_UINT16: case CIM_SINT32: case CIM_UINT32: record->fields[index].u.ival = val; return S_OK; default: FIXME("unhandled type %u\n", type); break; } return WBEM_E_INVALID_PARAMETER; } static HRESULT WINAPI class_object_Put( IWbemClassObject *iface, LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE Type ) { struct class_object *co = impl_from_IWbemClassObject( iface ); struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter ); TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type); if (co->record) { UINT index; HRESULT hr; if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr; return record_set_value( co->record, index, pVal ); } if (!ec) return S_OK; return put_propval( ec->query->view, co->index, wszName, pVal, Type ); } static HRESULT WINAPI class_object_Delete( IWbemClassObject *iface, LPCWSTR wszName ) { FIXME("%p, %s\n", iface, debugstr_w(wszName)); return E_NOTIMPL; } static HRESULT WINAPI class_object_GetNames( IWbemClassObject *iface, LPCWSTR wszQualifierName, LONG lFlags, VARIANT *pQualifierVal, SAFEARRAY **pNames ) { struct class_object *co = impl_from_IWbemClassObject( iface ); struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter ); TRACE("%p, %s, %08x, %s, %p\n", iface, debugstr_w(wszQualifierName), lFlags, debugstr_variant(pQualifierVal), pNames); if (!pNames) return WBEM_E_INVALID_PARAMETER; /* Combination used in a handful of broken apps */ if (lFlags == (WBEM_FLAG_ALWAYS | WBEM_MASK_CONDITION_ORIGIN)) lFlags = WBEM_FLAG_ALWAYS; if (lFlags && (lFlags != WBEM_FLAG_ALWAYS && lFlags != WBEM_FLAG_NONSYSTEM_ONLY && lFlags != WBEM_FLAG_SYSTEM_ONLY)) { FIXME("flags %08x not supported\n", lFlags); return E_NOTIMPL; } if (wszQualifierName || pQualifierVal) FIXME("qualifier not supported\n"); return get_properties( ec->query->view, co->index, lFlags, pNames ); } static HRESULT WINAPI class_object_BeginEnumeration( IWbemClassObject *iface, LONG lEnumFlags ) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p, %08x\n", iface, lEnumFlags); if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags); co->index_property = 0; return S_OK; } static HRESULT WINAPI class_object_Next( IWbemClassObject *iface, LONG lFlags, BSTR *strName, VARIANT *pVal, CIMTYPE *pType, LONG *plFlavor ) { struct class_object *obj = impl_from_IWbemClassObject( iface ); struct enum_class_object *iter = impl_from_IEnumWbemClassObject( obj->iter ); struct view *view = iter->query->view; struct table *table = get_view_table( view, obj->index ); BSTR prop; HRESULT hr; UINT i; TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor); for (i = obj->index_property; i < table->num_cols; i++) { if (is_method( table, i )) continue; if (!is_result_prop( view, table->columns[i].name )) continue; if (!(prop = SysAllocString( table->columns[i].name ))) return E_OUTOFMEMORY; if ((hr = get_propval( view, obj->index, prop, pVal, pType, plFlavor )) != S_OK) { SysFreeString( prop ); return hr; } obj->index_property = i + 1; if (strName) *strName = prop; else SysFreeString( prop ); return S_OK; } return WBEM_S_NO_MORE_DATA; } static HRESULT WINAPI class_object_EndEnumeration( IWbemClassObject *iface ) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p\n", iface); co->index_property = 0; return S_OK; } static HRESULT WINAPI class_object_GetPropertyQualifierSet( IWbemClassObject *iface, LPCWSTR wszProperty, IWbemQualifierSet **ppQualSet ) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet); return WbemQualifierSet_create( co->name, wszProperty, (void **)ppQualSet ); } static HRESULT WINAPI class_object_Clone( IWbemClassObject *iface, IWbemClassObject **ppCopy ) { FIXME("%p, %p\n", iface, ppCopy); return E_NOTIMPL; } static BSTR get_body_text( const struct table *table, UINT row, UINT *len ) { BSTR value, ret; WCHAR *p; UINT i; *len = 0; for (i = 0; i < table->num_cols; i++) { if ((value = get_value_bstr( table, row, i ))) { *len += ARRAY_SIZE( L"\n\t%s = %s;" ); *len += lstrlenW( table->columns[i].name ); *len += SysStringLen( value ); SysFreeString( value ); } } if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL; p = ret; for (i = 0; i < table->num_cols; i++) { if ((value = get_value_bstr( table, row, i ))) { p += swprintf( p, *len - (p - ret), L"\n\t%s = %s;", table->columns[i].name, value ); SysFreeString( value ); } } return ret; } static BSTR get_object_text( const struct view *view, UINT index ) { UINT len, len_body, row = view->result[index]; struct table *table = get_view_table( view, index ); BSTR ret, body; len = ARRAY_SIZE( L"\ninstance of %s\n{%s\n};" ); len += lstrlenW( table->name ); if (!(body = get_body_text( table, row, &len_body ))) return NULL; len += len_body; if (!(ret = SysAllocStringLen( NULL, len ))) return NULL; swprintf( ret, len, L"\ninstance of %s\n{%s\n};", table->name, body ); SysFreeString( body ); return ret; } static HRESULT WINAPI class_object_GetObjectText( IWbemClassObject *iface, LONG lFlags, BSTR *pstrObjectText ) { struct class_object *co = impl_from_IWbemClassObject( iface ); struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter ); struct view *view = ec->query->view; BSTR text; TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText); if (lFlags) FIXME("flags %08x not implemented\n", lFlags); if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY; *pstrObjectText = text; return S_OK; } static HRESULT WINAPI class_object_SpawnDerivedClass( IWbemClassObject *iface, LONG lFlags, IWbemClassObject **ppNewClass ) { FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass); return E_NOTIMPL; } static HRESULT WINAPI class_object_SpawnInstance( IWbemClassObject *iface, LONG lFlags, IWbemClassObject **ppNewInstance ) { struct class_object *co = impl_from_IWbemClassObject( iface ); struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter ); struct table *table = get_view_table( ec->query->view, co->index ); IEnumWbemClassObject *iter; struct record *record; HRESULT hr; TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance); if (!(record = create_record( table ))) return E_OUTOFMEMORY; if (FAILED(hr = IEnumWbemClassObject_Clone( co->iter, &iter ))) { destroy_record( record ); return hr; } hr = create_class_object( co->name, iter, 0, record, ppNewInstance ); IEnumWbemClassObject_Release( iter ); return hr; } static HRESULT WINAPI class_object_CompareTo( IWbemClassObject *iface, LONG lFlags, IWbemClassObject *pCompareTo ) { FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo); return E_NOTIMPL; } static HRESULT WINAPI class_object_GetPropertyOrigin( IWbemClassObject *iface, LPCWSTR wszName, BSTR *pstrClassName ) { FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName); return E_NOTIMPL; } static HRESULT WINAPI class_object_InheritsFrom( IWbemClassObject *iface, LPCWSTR strAncestor ) { FIXME("%p, %s\n", iface, debugstr_w(strAncestor)); return E_NOTIMPL; } static UINT count_instances( IEnumWbemClassObject *iter ) { UINT count = 0; while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++; IEnumWbemClassObject_Reset( iter ); return count; } static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr ) { switch (type) { case CIM_SINT16: *(INT16 *)ptr = val; break; case CIM_UINT16: *(UINT16 *)ptr = val; break; case CIM_SINT32: *(INT32 *)ptr = val; break; case CIM_UINT32: *(UINT32 *)ptr = val; break; default: FIXME("unhandled type %u\n", type); break; } } static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols, struct column **cols, BYTE **data ) { struct column *columns; BYTE *row; IWbemClassObject *param; VARIANT val; HRESULT hr = E_OUTOFMEMORY; UINT offset = 0; ULONG count; int i = 0; count = count_instances( iter ); if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY; if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error; for (;;) { IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, ¶m, &count ); if (!count) break; hr = IWbemClassObject_Get( param, L"Parameter", 0, &val, NULL, NULL ); if (hr != S_OK) goto error; columns[i].name = heap_strdupW( V_BSTR( &val ) ); VariantClear( &val ); hr = IWbemClassObject_Get( param, L"Type", 0, &val, NULL, NULL ); if (hr != S_OK) goto error; columns[i].type = V_UI4( &val ); hr = IWbemClassObject_Get( param, L"DefaultValue", 0, &val, NULL, NULL ); if (hr != S_OK) goto error; if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset ); offset += get_type_size( columns[i].type ); IWbemClassObject_Release( param ); i++; } *num_cols = i; *cols = columns; *data = row; return S_OK; error: for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name ); heap_free( columns ); heap_free( row ); return hr; } static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name ) { HRESULT hr; struct table *table; struct column *columns; UINT num_cols; BYTE *row; hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row ); if (hr != S_OK) return hr; if (!(table = create_table( name, num_cols, columns, 1, 1, row, NULL ))) { free_columns( columns, num_cols ); heap_free( row ); return E_OUTOFMEMORY; } if (!add_table( table )) free_table( table ); /* already exists */ return S_OK; } static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir ) { UINT len = ARRAY_SIZE(L"__%s_%s_%s") + ARRAY_SIZE(L"OUT") + lstrlenW( class ) + lstrlenW( method ); WCHAR *ret; if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL; swprintf( ret, len, L"__%s_%s_%s", class, method, dir == PARAM_IN ? L"IN" : L"OUT" ); return wcsupr( ret ); } HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir, IWbemClassObject **sig ) { static const WCHAR selectW[] = L"SELECT * FROM __PARAMETERS WHERE Class='%s' AND Method='%s' AND Direction%s"; UINT len = ARRAY_SIZE(selectW) + ARRAY_SIZE(L">=0"); IEnumWbemClassObject *iter; WCHAR *query, *name; HRESULT hr; len += lstrlenW( class ) + lstrlenW( method ); if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY; swprintf( query, len, selectW, class, method, dir >= 0 ? L">=0" : L"<=0" ); hr = exec_query( query, &iter ); heap_free( query ); if (hr != S_OK) return hr; if (!count_instances( iter )) { *sig = NULL; IEnumWbemClassObject_Release( iter ); return S_OK; } if (!(name = build_signature_table_name( class, method, dir ))) { IEnumWbemClassObject_Release( iter ); return E_OUTOFMEMORY; } hr = create_signature_table( iter, name ); IEnumWbemClassObject_Release( iter ); if (hr == S_OK) hr = get_object( name, sig ); heap_free( name ); return hr; } static HRESULT WINAPI class_object_GetMethod( IWbemClassObject *iface, LPCWSTR wszName, LONG lFlags, IWbemClassObject **ppInSignature, IWbemClassObject **ppOutSignature ) { struct class_object *co = impl_from_IWbemClassObject( iface ); IWbemClassObject *in, *out; struct table *table; unsigned int i; HRESULT hr; TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature); if (ppInSignature) *ppInSignature = NULL; if (ppOutSignature) *ppOutSignature = NULL; table = get_view_table( impl_from_IEnumWbemClassObject( co->iter )->query->view, co->index ); for (i = 0; i < table->num_cols; ++i) { if (is_method( table, i ) && !lstrcmpiW( table->columns[i].name, wszName )) break; } if (i == table->num_cols) { FIXME("Method %s not found in class %s.\n", debugstr_w(wszName), debugstr_w(co->name)); return WBEM_E_NOT_FOUND; } hr = create_signature( co->name, wszName, PARAM_IN, &in ); if (hr != S_OK) return hr; hr = create_signature( co->name, wszName, PARAM_OUT, &out ); if (hr == S_OK) { if (ppInSignature) *ppInSignature = in; else if (in) IWbemClassObject_Release( in ); if (ppOutSignature) *ppOutSignature = out; else if (out) IWbemClassObject_Release( out ); } else IWbemClassObject_Release( in ); return hr; } static HRESULT WINAPI class_object_PutMethod( IWbemClassObject *iface, LPCWSTR wszName, LONG lFlags, IWbemClassObject *pInSignature, IWbemClassObject *pOutSignature ) { FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature); return E_NOTIMPL; } static HRESULT WINAPI class_object_DeleteMethod( IWbemClassObject *iface, LPCWSTR wszName ) { FIXME("%p, %s\n", iface, debugstr_w(wszName)); return E_NOTIMPL; } static HRESULT WINAPI class_object_BeginMethodEnumeration( IWbemClassObject *iface, LONG lEnumFlags) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p, %08x\n", iface, lEnumFlags); if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags); co->index_method = 0; return S_OK; } static HRESULT WINAPI class_object_NextMethod( IWbemClassObject *iface, LONG lFlags, BSTR *pstrName, IWbemClassObject **ppInSignature, IWbemClassObject **ppOutSignature) { struct class_object *co = impl_from_IWbemClassObject( iface ); BSTR method; HRESULT hr; TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature); if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA; hr = create_signature( co->name, method, PARAM_IN, ppInSignature ); if (hr != S_OK) { SysFreeString( method ); return hr; } hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature ); if (hr != S_OK) { SysFreeString( method ); if (*ppInSignature) IWbemClassObject_Release( *ppInSignature ); } else { *pstrName = method; co->index_method++; } return hr; } static HRESULT WINAPI class_object_EndMethodEnumeration( IWbemClassObject *iface ) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p\n", iface); co->index_method = 0; return S_OK; } static HRESULT WINAPI class_object_GetMethodQualifierSet( IWbemClassObject *iface, LPCWSTR wszMethod, IWbemQualifierSet **ppQualSet) { struct class_object *co = impl_from_IWbemClassObject( iface ); TRACE("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet); return WbemQualifierSet_create( co->name, wszMethod, (void **)ppQualSet ); } static HRESULT WINAPI class_object_GetMethodOrigin( IWbemClassObject *iface, LPCWSTR wszMethodName, BSTR *pstrClassName) { FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName); return E_NOTIMPL; } static const IWbemClassObjectVtbl class_object_vtbl = { class_object_QueryInterface, class_object_AddRef, class_object_Release, class_object_GetQualifierSet, class_object_Get, class_object_Put, class_object_Delete, class_object_GetNames, class_object_BeginEnumeration, class_object_Next, class_object_EndEnumeration, class_object_GetPropertyQualifierSet, class_object_Clone, class_object_GetObjectText, class_object_SpawnDerivedClass, class_object_SpawnInstance, class_object_CompareTo, class_object_GetPropertyOrigin, class_object_InheritsFrom, class_object_GetMethod, class_object_PutMethod, class_object_DeleteMethod, class_object_BeginMethodEnumeration, class_object_NextMethod, class_object_EndMethodEnumeration, class_object_GetMethodQualifierSet, class_object_GetMethodOrigin }; HRESULT create_class_object( const WCHAR *name, IEnumWbemClassObject *iter, UINT index, struct record *record, IWbemClassObject **obj ) { struct class_object *co; TRACE("%s, %p\n", debugstr_w(name), obj); co = heap_alloc( sizeof(*co) ); if (!co) return E_OUTOFMEMORY; co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl; co->refs = 1; if (!name) co->name = NULL; else if (!(co->name = heap_strdupW( name ))) { heap_free( co ); return E_OUTOFMEMORY; } co->iter = iter; co->index = index; co->index_method = 0; co->index_property = 0; co->record = record; if (iter) IEnumWbemClassObject_AddRef( iter ); *obj = &co->IWbemClassObject_iface; TRACE("returning iface %p\n", *obj); return S_OK; }