| /* |
| * 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 "config.h" |
| #include <stdarg.h> |
| |
| #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; |
| HRESULT hr; |
| |
| TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned); |
| |
| if (!uCount) return WBEM_S_FALSE; |
| if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER; |
| if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n"); |
| |
| *puReturned = 0; |
| if (ec->index + uCount > view->count) return WBEM_S_FALSE; |
| |
| hr = create_class_object( view->table->name, iface, ec->index, NULL, apObjects ); |
| if (hr != S_OK) return hr; |
| |
| ec->index++; |
| *puReturned = 1; |
| if (ec->index == view->count) return WBEM_S_FALSE; |
| if (uCount > 1) return WBEM_S_TIMEDOUT; |
| 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( NULL, 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; |
| |
| TRACE("%p, %d, %u\n", iface, lTimeout, nCount); |
| |
| if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n"); |
| |
| if (!view->count) return WBEM_S_FALSE; |
| |
| if (nCount > view->count - ec->index) |
| { |
| ec->index = view->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( |
| IUnknown *pUnkOuter, struct query *query, LPVOID *ppObj ) |
| { |
| struct enum_class_object *ec; |
| |
| TRACE("%p, %p\n", pUnkOuter, 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].vartype = table->columns[i].vartype; |
| 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, size; |
| |
| if (!array) return; |
| if (type == CIM_STRING || type == CIM_DATETIME) |
| { |
| size = get_type_size( type ); |
| for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * 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) |
| 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 ) |
| { |
| FIXME("%p, %p\n", iface, ppQualSet); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type ) |
| { |
| VARTYPE vartype = record->fields[index].vartype; |
| |
| if (type) *type = record->fields[index].type; |
| |
| if (record->fields[index].type & CIM_FLAG_ARRAY) |
| { |
| V_VT( var ) = vartype ? vartype : to_vartype( record->fields[index].type & CIM_TYPE_MASK ) | 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: |
| if (!vartype) vartype = VT_BSTR; |
| V_BSTR( var ) = SysAllocString( record->fields[index].u.sval ); |
| break; |
| case CIM_SINT32: |
| if (!vartype) vartype = VT_I4; |
| V_I4( var ) = record->fields[index].u.ival; |
| break; |
| case CIM_UINT32: |
| if (!vartype) vartype = VT_UI4; |
| 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: |
| 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 ); |
| } |
| 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, %p, %p\n", iface, debugstr_w(wszQualifierName), lFlags, pQualifierVal, pNames); |
| |
| if (wszQualifierName || pQualifierVal) |
| { |
| FIXME("qualifier not supported\n"); |
| return E_NOTIMPL; |
| } |
| if (lFlags != WBEM_FLAG_ALWAYS) |
| { |
| FIXME("flags %08x not supported\n", lFlags); |
| return E_NOTIMPL; |
| } |
| return get_properties( ec->query->view, 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 *co = impl_from_IWbemClassObject( iface ); |
| struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter ); |
| struct view *view = ec->query->view; |
| BSTR property; |
| HRESULT hr; |
| |
| TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor); |
| |
| if (!(property = get_property_name( co->name, co->index_property ))) return WBEM_S_NO_MORE_DATA; |
| if ((hr = get_propval( view, co->index, property, pVal, pType, plFlavor ) != S_OK)) |
| { |
| SysFreeString( property ); |
| return hr; |
| } |
| *strName = property; |
| co->index_property++; |
| return S_OK; |
| } |
| |
| 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 ) |
| { |
| FIXME("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet); |
| return E_NOTIMPL; |
| } |
| |
| 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 ) |
| { |
| static const WCHAR fmtW[] = {'\n','\t','%','s',' ','=',' ','%','s',';',0}; |
| 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 += sizeof(fmtW) / sizeof(fmtW[0]); |
| *len += strlenW( 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 += sprintfW( p, fmtW, table->columns[i].name, value ); |
| SysFreeString( value ); |
| } |
| } |
| return ret; |
| } |
| |
| static BSTR get_object_text( const struct view *view, UINT index ) |
| { |
| static const WCHAR fmtW[] = |
| {'\n','i','n','s','t','a','n','c','e',' ','o','f',' ','%','s','\n','{','%','s','\n','}',';',0}; |
| UINT len, len_body, row = view->result[index]; |
| BSTR ret, body; |
| |
| len = sizeof(fmtW) / sizeof(fmtW[0]); |
| len += strlenW( view->table->name ); |
| if (!(body = get_body_text( view->table, row, &len_body ))) return NULL; |
| len += len_body; |
| |
| if (!(ret = SysAllocStringLen( NULL, len ))) return NULL; |
| sprintfW( ret, fmtW, view->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 view *view = ec->query->view; |
| struct record *record; |
| |
| TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance); |
| |
| if (!(record = create_record( view->table ))) return E_OUTOFMEMORY; |
| |
| return create_class_object( co->name, NULL, 0, record, ppNewInstance ); |
| } |
| |
| 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 ) |
| { |
| static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0}; |
| static const WCHAR typeW[] = {'T','y','p','e',0}; |
| static const WCHAR varianttypeW[] = {'V','a','r','i','a','n','t','T','y','p','e',0}; |
| static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0}; |
| 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, parameterW, 0, &val, NULL, NULL ); |
| if (hr != S_OK) goto error; |
| columns[i].name = heap_strdupW( V_BSTR( &val ) ); |
| VariantClear( &val ); |
| |
| hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL ); |
| if (hr != S_OK) goto error; |
| columns[i].type = V_UI4( &val ); |
| |
| hr = IWbemClassObject_Get( param, varianttypeW, 0, &val, NULL, NULL ); |
| if (hr != S_OK) goto error; |
| columns[i].vartype = V_UI4( &val ); |
| |
| hr = IWbemClassObject_Get( param, defaultvalueW, 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, 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 ) |
| { |
| static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0}; |
| static const WCHAR outW[] = {'O','U','T',0}; |
| static const WCHAR inW[] = {'I','N',0}; |
| UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method ); |
| WCHAR *ret; |
| |
| if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL; |
| sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW ); |
| return struprW( ret ); |
| } |
| |
| HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir, |
| IWbemClassObject **sig ) |
| { |
| static const WCHAR selectW[] = |
| {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', |
| '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ', |
| 'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ', |
| 'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ', |
| 'D','i','r','e','c','t','i','o','n','%','s',0}; |
| static const WCHAR geW[] = {'>','=','0',0}; |
| static const WCHAR leW[] = {'<','=','0',0}; |
| UINT len = SIZEOF(selectW) + SIZEOF(geW); |
| IEnumWbemClassObject *iter; |
| WCHAR *query, *name; |
| HRESULT hr; |
| |
| len += strlenW( class ) + strlenW( method ); |
| if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY; |
| sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW ); |
| |
| hr = exec_query( query, &iter ); |
| heap_free( query ); |
| if (hr != S_OK) return hr; |
| |
| 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) |
| { |
| heap_free( name ); |
| return hr; |
| } |
| return get_object( name, sig ); |
| } |
| |
| static HRESULT WINAPI class_object_GetMethod( |
| IWbemClassObject *iface, |
| LPCWSTR wszName, |
| LONG lFlags, |
| IWbemClassObject **ppInSignature, |
| IWbemClassObject **ppOutSignature ) |
| { |
| struct class_object *co = impl_from_IWbemClassObject( iface ); |
| HRESULT hr; |
| |
| TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature); |
| |
| hr = create_signature( co->name, wszName, PARAM_IN, ppInSignature ); |
| if (hr != S_OK || !ppOutSignature) return hr; |
| |
| hr = create_signature( co->name, wszName, PARAM_OUT, ppOutSignature ); |
| if (hr != S_OK) IWbemClassObject_Release( *ppInSignature ); |
| 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); |
| |
| if (co->iter) |
| { |
| WARN("not allowed on instance\n"); |
| return WBEM_E_ILLEGAL_OPERATION; |
| } |
| 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 ); |
| 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) |
| { |
| FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet); |
| return E_NOTIMPL; |
| } |
| |
| 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; |
| co->name = heap_strdupW( name ); |
| if (!co->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; |
| } |