| /* |
| * Copyright 2013 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 qualifier_set |
| { |
| IWbemQualifierSet IWbemQualifierSet_iface; |
| LONG refs; |
| WCHAR *class; |
| WCHAR *member; |
| }; |
| |
| static inline struct qualifier_set *impl_from_IWbemQualifierSet( |
| IWbemQualifierSet *iface ) |
| { |
| return CONTAINING_RECORD(iface, struct qualifier_set, IWbemQualifierSet_iface); |
| } |
| |
| static ULONG WINAPI qualifier_set_AddRef( |
| IWbemQualifierSet *iface ) |
| { |
| struct qualifier_set *set = impl_from_IWbemQualifierSet( iface ); |
| return InterlockedIncrement( &set->refs ); |
| } |
| |
| static ULONG WINAPI qualifier_set_Release( |
| IWbemQualifierSet *iface ) |
| { |
| struct qualifier_set *set = impl_from_IWbemQualifierSet( iface ); |
| LONG refs = InterlockedDecrement( &set->refs ); |
| if (!refs) |
| { |
| TRACE("destroying %p\n", set); |
| heap_free( set->class ); |
| heap_free( set->member ); |
| heap_free( set ); |
| } |
| return refs; |
| } |
| |
| static HRESULT WINAPI qualifier_set_QueryInterface( |
| IWbemQualifierSet *iface, |
| REFIID riid, |
| void **ppvObject ) |
| { |
| struct qualifier_set *set = impl_from_IWbemQualifierSet( iface ); |
| |
| TRACE("%p, %s, %p\n", set, debugstr_guid( riid ), ppvObject ); |
| |
| if ( IsEqualGUID( riid, &IID_IWbemQualifierSet ) || |
| IsEqualGUID( riid, &IID_IUnknown ) ) |
| { |
| *ppvObject = set; |
| } |
| else |
| { |
| FIXME("interface %s not implemented\n", debugstr_guid(riid)); |
| return E_NOINTERFACE; |
| } |
| IWbemQualifierSet_AddRef( iface ); |
| return S_OK; |
| } |
| |
| static HRESULT create_qualifier_enum( const WCHAR *class, const WCHAR *member, const WCHAR *name, |
| IEnumWbemClassObject **iter ) |
| { |
| static const WCHAR fmtW[] = |
| {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','_','_','Q','U','A','L', |
| 'I','F','I','E','R','S',' ','W','H','E','R','E',' ','C','l','a','s','s','=', |
| '\'','%','s','\'',' ','A','N','D',' ','M','e','m','b','e','r','=','\'','%','s','\'',' ', |
| 'A','N','D',' ','N','a','m','e','=','\'','%','s','\'',0}; |
| static const WCHAR fmt2W[] = |
| {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','_','_','Q','U','A','L', |
| 'I','F','I','E','R','S',' ','W','H','E','R','E',' ','C','l','a','s','s','=', |
| '\'','%','s','\'',' ','A','N','D',' ','M','e','m','b','e','r','=','\'','%','s','\'',0}; |
| static const WCHAR noneW[] = {'_','_','N','O','N','E',0}; |
| WCHAR *query; |
| HRESULT hr; |
| int len; |
| |
| if (!member) member = noneW; |
| len = strlenW( class ) + strlenW( member ); |
| if (name) len += strlenW( name ) + SIZEOF(fmtW); |
| else len += SIZEOF(fmt2W); |
| |
| if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY; |
| if (name) sprintfW( query, fmtW, class, member, name ); |
| else sprintfW( query, fmt2W, class, member ); |
| |
| hr = exec_query( query, iter ); |
| heap_free( query ); |
| return hr; |
| } |
| |
| static HRESULT get_qualifier_value( const WCHAR *class, const WCHAR *member, const WCHAR *name, |
| VARIANT *val, LONG *flavor ) |
| { |
| static const WCHAR qualifiersW[] = {'_','_','Q','U','A','L','I','F','I','E','R','S',0}; |
| static const WCHAR intvalueW[] = {'I','n','t','e','g','e','r','V','a','l','u','e',0}; |
| static const WCHAR strvalueW[] = {'S','t','r','i','n','g','V','a','l','u','e',0}; |
| static const WCHAR flavorW[] = {'F','l','a','v','o','r',0}; |
| static const WCHAR typeW[] = {'T','y','p','e',0}; |
| IEnumWbemClassObject *iter; |
| IWbemClassObject *obj; |
| VARIANT var; |
| HRESULT hr; |
| |
| hr = create_qualifier_enum( class, member, name, &iter ); |
| if (FAILED( hr )) return hr; |
| |
| hr = create_class_object( qualifiersW, iter, 0, NULL, &obj ); |
| IEnumWbemClassObject_Release( iter ); |
| if (FAILED( hr )) return hr; |
| |
| if (flavor) |
| { |
| hr = IWbemClassObject_Get( obj, flavorW, 0, &var, NULL, NULL ); |
| if (hr != S_OK) goto done; |
| *flavor = V_I4( &var ); |
| } |
| hr = IWbemClassObject_Get( obj, typeW, 0, &var, NULL, NULL ); |
| if (hr != S_OK) goto done; |
| switch (V_UI4( &var )) |
| { |
| case CIM_STRING: |
| hr = IWbemClassObject_Get( obj, strvalueW, 0, val, NULL, NULL ); |
| break; |
| case CIM_SINT32: |
| hr = IWbemClassObject_Get( obj, intvalueW, 0, val, NULL, NULL ); |
| break; |
| default: |
| ERR("unhandled type %u\n", V_UI4( &var )); |
| break; |
| } |
| |
| done: |
| IWbemClassObject_Release( obj ); |
| return hr; |
| } |
| |
| static HRESULT WINAPI qualifier_set_Get( |
| IWbemQualifierSet *iface, |
| LPCWSTR wszName, |
| LONG lFlags, |
| VARIANT *pVal, |
| LONG *plFlavor ) |
| { |
| struct qualifier_set *set = impl_from_IWbemQualifierSet( iface ); |
| |
| FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, plFlavor); |
| return get_qualifier_value( set->class, set->member, wszName, pVal, plFlavor ); |
| } |
| |
| static HRESULT WINAPI qualifier_set_Put( |
| IWbemQualifierSet *iface, |
| LPCWSTR wszName, |
| VARIANT *pVal, |
| LONG lFlavor ) |
| { |
| FIXME("%p, %s, %p, %d\n", iface, debugstr_w(wszName), pVal, lFlavor); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI qualifier_set_Delete( |
| IWbemQualifierSet *iface, |
| LPCWSTR wszName ) |
| { |
| FIXME("%p, %s\n", iface, debugstr_w(wszName)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI qualifier_set_GetNames( |
| IWbemQualifierSet *iface, |
| LONG lFlags, |
| SAFEARRAY **pNames ) |
| { |
| FIXME("%p, %08x, %p\n", iface, lFlags, pNames); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI qualifier_set_BeginEnumeration( |
| IWbemQualifierSet *iface, |
| LONG lFlags ) |
| { |
| FIXME("%p, %08x\n", iface, lFlags); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI qualifier_set_Next( |
| IWbemQualifierSet *iface, |
| LONG lFlags, |
| BSTR *pstrName, |
| VARIANT *pVal, |
| LONG *plFlavor ) |
| { |
| FIXME("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, pVal, plFlavor); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI qualifier_set_EndEnumeration( |
| IWbemQualifierSet *iface ) |
| { |
| FIXME("%p\n", iface); |
| return E_NOTIMPL; |
| } |
| |
| static const IWbemQualifierSetVtbl qualifier_set_vtbl = |
| { |
| qualifier_set_QueryInterface, |
| qualifier_set_AddRef, |
| qualifier_set_Release, |
| qualifier_set_Get, |
| qualifier_set_Put, |
| qualifier_set_Delete, |
| qualifier_set_GetNames, |
| qualifier_set_BeginEnumeration, |
| qualifier_set_Next, |
| qualifier_set_EndEnumeration |
| }; |
| |
| HRESULT WbemQualifierSet_create( |
| IUnknown *pUnkOuter, const WCHAR *class, const WCHAR *member, LPVOID *ppObj ) |
| { |
| struct qualifier_set *set; |
| |
| TRACE("%p, %p\n", pUnkOuter, ppObj); |
| |
| if (!(set = heap_alloc( sizeof(*set) ))) return E_OUTOFMEMORY; |
| |
| set->IWbemQualifierSet_iface.lpVtbl = &qualifier_set_vtbl; |
| if (!(set->class = heap_strdupW( class ))) |
| { |
| heap_free( set ); |
| return E_OUTOFMEMORY; |
| } |
| if (!member) set->member = NULL; |
| else if (!(set->member = heap_strdupW( member ))) |
| { |
| heap_free( set->class ); |
| heap_free( set ); |
| return E_OUTOFMEMORY; |
| } |
| set->refs = 1; |
| |
| *ppObj = &set->IWbemQualifierSet_iface; |
| |
| TRACE("returning iface %p\n", *ppObj); |
| return S_OK; |
| } |