Module: wine Branch: master Commit: c245fb66f89da61818b743e1f1df9b00343968dc URL: http://source.winehq.org/git/wine.git/?a=commit;h=c245fb66f89da61818b743e1f1...
Author: Hans Leidekker hans@codeweavers.com Date: Wed Jan 14 15:36:16 2015 +0100
wbemdisp: Implement ISWbemObjectSet::get__NewEnum.
---
dlls/wbemdisp/locator.c | 156 +++++++++++++++++++++++++++++++++++++++-- dlls/wbemdisp/tests/wbemdisp.c | 69 ++++++++++++++++++ 2 files changed, 221 insertions(+), 4 deletions(-)
diff --git a/dlls/wbemdisp/locator.c b/dlls/wbemdisp/locator.c index 9731630..c3103fa 100644 --- a/dlls/wbemdisp/locator.c +++ b/dlls/wbemdisp/locator.c @@ -36,6 +36,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(wbemdisp);
+static HRESULT EnumVARIANT_create( ISWbemObjectSet *, IEnumVARIANT ** ); + enum type_id { ISWbemLocator_tid, @@ -401,8 +403,11 @@ static HRESULT WINAPI objectset_get__NewEnum( ISWbemObjectSet *iface, IUnknown **pUnk ) { - FIXME( "\n" ); - return E_NOTIMPL; + struct objectset *objectset = impl_from_ISWbemObjectSet( iface ); + + TRACE( "%p, %p\n", objectset, pUnk ); + + return EnumVARIANT_create( iface, (IEnumVARIANT **)pUnk ); }
static HRESULT WINAPI objectset_Item( @@ -420,12 +425,20 @@ static HRESULT WINAPI objectset_get_Count( LONG *iCount ) { struct objectset *objectset = impl_from_ISWbemObjectSet( iface ); + LONG count = 0, total = 0;
TRACE( "%p, %p\n", objectset, iCount );
- *iCount = 0; + while (IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, 1 ) == S_OK) count++; + IEnumWbemClassObject_Reset( objectset->objectenum ); - while (!IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, 1 )) (*iCount)++; + while (IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, 1 ) == S_OK) total++; + + count = total - count; + IEnumWbemClassObject_Reset( objectset->objectenum ); + while (count--) IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, 1 ); + + *iCount = total; return S_OK; }
@@ -479,6 +492,141 @@ static HRESULT SWbemObjectSet_create( IEnumWbemClassObject *wbem_objectenum, ISW return S_OK; }
+struct enumvar +{ + IEnumVARIANT IEnumVARIANT_iface; + LONG refs; + ISWbemObjectSet *objectset; +}; + +static inline struct enumvar *impl_from_IEnumVARIANT( + IEnumVARIANT *iface ) +{ + return CONTAINING_RECORD( iface, struct enumvar, IEnumVARIANT_iface ); +} + +static ULONG WINAPI enumvar_AddRef( + IEnumVARIANT *iface ) +{ + struct enumvar *enumvar = impl_from_IEnumVARIANT( iface ); + return InterlockedIncrement( &enumvar->refs ); +} + +static ULONG WINAPI enumvar_Release( + IEnumVARIANT *iface ) +{ + struct enumvar *enumvar = impl_from_IEnumVARIANT( iface ); + LONG refs = InterlockedDecrement( &enumvar->refs ); + if (!refs) + { + TRACE( "destroying %p\n", enumvar ); + ISWbemObjectSet_Release( enumvar->objectset ); + heap_free( enumvar ); + } + return refs; +} + +static HRESULT WINAPI enumvar_QueryInterface( + IEnumVARIANT *iface, + REFIID riid, + void **ppvObject ) +{ + struct enumvar *enumvar = impl_from_IEnumVARIANT( iface ); + + TRACE( "%p %s %p\n", enumvar, debugstr_guid(riid), ppvObject ); + + if (IsEqualGUID( riid, &IID_IEnumVARIANT ) || + IsEqualGUID( riid, &IID_IUnknown )) + { + *ppvObject = enumvar; + } + else + { + FIXME( "interface %s not implemented\n", debugstr_guid(riid) ); + return E_NOINTERFACE; + } + IEnumVARIANT_AddRef( iface ); + return S_OK; +} + +static HRESULT WINAPI enumvar_Next( IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched ) +{ + struct enumvar *enumvar = impl_from_IEnumVARIANT( iface ); + struct objectset *objectset = impl_from_ISWbemObjectSet( enumvar->objectset ); + IWbemClassObject *obj; + ULONG count = 0; + + TRACE( "%p, %u, %p, %p\n", iface, celt, var, fetched ); + + if (celt) IEnumWbemClassObject_Next( objectset->objectenum, WBEM_INFINITE, 1, &obj, &count ); + if (count) + { + ISWbemObject *sobj; + HRESULT hr; + + hr = SWbemObject_create( obj, &sobj ); + IWbemClassObject_Release( obj ); + if (FAILED( hr )) return hr; + + V_VT( var ) = VT_DISPATCH; + V_DISPATCH( var ) = (IDispatch *)sobj; + } + if (fetched) *fetched = count; + return (count < celt) ? S_FALSE : S_OK; +} + +static HRESULT WINAPI enumvar_Skip( IEnumVARIANT *iface, ULONG celt ) +{ + struct enumvar *enumvar = impl_from_IEnumVARIANT( iface ); + struct objectset *objectset = impl_from_ISWbemObjectSet( enumvar->objectset ); + + TRACE( "%p, %u\n", iface, celt ); + + return IEnumWbemClassObject_Skip( objectset->objectenum, WBEM_INFINITE, celt ); +} + +static HRESULT WINAPI enumvar_Reset( IEnumVARIANT *iface ) +{ + struct enumvar *enumvar = impl_from_IEnumVARIANT( iface ); + struct objectset *objectset = impl_from_ISWbemObjectSet( enumvar->objectset ); + + TRACE( "%p\n", iface ); + + return IEnumWbemClassObject_Reset( objectset->objectenum ); +} + +static HRESULT WINAPI enumvar_Clone( IEnumVARIANT *iface, IEnumVARIANT **penum ) +{ + FIXME( "%p, %p\n", iface, penum ); + return E_NOTIMPL; +} + +static const struct IEnumVARIANTVtbl enumvar_vtbl = +{ + enumvar_QueryInterface, + enumvar_AddRef, + enumvar_Release, + enumvar_Next, + enumvar_Skip, + enumvar_Reset, + enumvar_Clone +}; + +static HRESULT EnumVARIANT_create( ISWbemObjectSet *objectset, IEnumVARIANT **obj ) +{ + struct enumvar *enumvar; + + if (!(enumvar = heap_alloc( sizeof(*enumvar) ))) return E_OUTOFMEMORY; + enumvar->IEnumVARIANT_iface.lpVtbl = &enumvar_vtbl; + enumvar->refs = 1; + enumvar->objectset = objectset; + ISWbemObjectSet_AddRef( enumvar->objectset ); + + *obj = &enumvar->IEnumVARIANT_iface; + TRACE( "returning iface %p\n", *obj ); + return S_OK; +} + struct services { ISWbemServices ISWbemServices_iface; diff --git a/dlls/wbemdisp/tests/wbemdisp.c b/dlls/wbemdisp/tests/wbemdisp.c index 8c0b628..863115b 100644 --- a/dlls/wbemdisp/tests/wbemdisp.c +++ b/dlls/wbemdisp/tests/wbemdisp.c @@ -29,6 +29,7 @@ DEFINE_GUID(CLSID_WINMGMTS,0x172bddf8,0xceea,0x11d1,0x8b,0x05,0x00,0x60,0x08,0x0
static void test_ParseDisplayName(void) { + static const WCHAR biosW[] = {'W','i','n','3','2','_','B','i','o','s',0}; static const WCHAR name1[] = {'w','i','n','m','g','m','t','s',':',0}; static const WCHAR name2[] = @@ -90,6 +91,74 @@ static void test_ParseDisplayName(void) } }
+ str = SysAllocString( name1 ); + eaten = 0xdeadbeef; + moniker = NULL; + hr = IParseDisplayName_ParseDisplayName( displayname, NULL, str, &eaten, &moniker ); + SysFreeString( str ); + ok( hr == S_OK, "got %x\n", hr ); + ok( eaten == lstrlenW(name1), "got %u\n", eaten ); + if (moniker) + { + ISWbemServices *services = NULL; + + hr = IMoniker_BindToObject( moniker, ctx, NULL, &IID_IUnknown, (void **)&services ); + ok( hr == S_OK, "got %x\n", hr ); + if (services) + { + ISWbemObjectSet *objectset = NULL; + + str = SysAllocString( biosW ); + hr = ISWbemServices_InstancesOf( services, str, 0, NULL, &objectset ); + SysFreeString( str ); + ok( hr == S_OK, "got %x\n", hr ); + if (objectset) + { + hr = ISWbemObjectSet_get__NewEnum( objectset, &obj ); + ok( hr == S_OK, "got %x\n", hr ); + if (obj) + { + IEnumVARIANT *enumvar = NULL; + + hr = IUnknown_QueryInterface( obj, &IID_IEnumVARIANT, (void **)&enumvar ); + ok( hr == S_OK, "got %x\n", hr ); + + if (enumvar) + { + VARIANT var; + ULONG fetched; + + fetched = 0xdeadbeef; + hr = IEnumVARIANT_Next( enumvar, 0, &var, &fetched ); + ok( hr == S_OK, "got %x\n", hr ); + ok( !fetched, "got %u\n", fetched ); + + fetched = 0xdeadbeef; + V_VT( &var ) = VT_ERROR; + V_ERROR( &var ) = 0xdeadbeef; + hr = IEnumVARIANT_Next( enumvar, 1, &var, &fetched ); + ok( hr == S_OK, "got %x\n", hr ); + ok( fetched == 1, "got %u\n", fetched ); + ok( V_VT( &var ) == VT_DISPATCH, "got %u\n", V_VT( &var ) ); + ok( V_DISPATCH( &var ) != (IDispatch *)0xdeadbeef, "got %u\n", V_VT( &var ) ); + VariantClear( &var ); + + fetched = 0xdeadbeef; + hr = IEnumVARIANT_Next( enumvar, 1, &var, &fetched ); + ok( hr == S_FALSE, "got %x\n", hr ); + ok( !fetched, "got %u\n", fetched ); + + IEnumVARIANT_Release( enumvar ); + } + IUnknown_Release( obj ); + } + ISWbemObjectSet_Release( objectset ); + } + IUnknown_Release( services ); + } + IMoniker_Release( moniker ); + } + IBindCtx_Release( ctx ); IParseDisplayName_Release( displayname ); }