/* * Implementation of IEnumUnknown (for internal use). * * hidenori@a2.ctktv.ne.jp */ #include "config.h" #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "winerror.h" #include "wine/obj_base.h" #include "wine/obj_oleaut.h" #include "strmif.h" #include "control.h" #include "uuids.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "enumunk.h" #include "iunk.h" typedef struct IEnumUnknownImpl { ICOM_VFIELD(IEnumUnknown); } IEnumUnknownImpl; typedef struct { QUARTZ_IUnkImpl unk; IEnumUnknownImpl enumunk; struct QUARTZ_IFEntry IFEntries[1]; QUARTZ_CompList* pCompList; QUARTZ_CompListItem* pItemCur; } CEnumUnknown; #define CEnumUnknown_THIS(iface,member) CEnumUnknown* This = ((CEnumUnknown*)(((char*)iface)-offsetof(CEnumUnknown,member))) static HRESULT WINAPI IEnumUnknown_fnQueryInterface(IEnumUnknown* iface,REFIID riid,void** ppobj) { CEnumUnknown_THIS(iface,enumunk); TRACE("(%p)->()\n",This); return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj); } static ULONG WINAPI IEnumUnknown_fnAddRef(IEnumUnknown* iface) { CEnumUnknown_THIS(iface,enumunk); TRACE("(%p)->()\n",This); return IUnknown_AddRef(This->unk.punkControl); } static ULONG WINAPI IEnumUnknown_fnRelease(IEnumUnknown* iface) { CEnumUnknown_THIS(iface,enumunk); TRACE("(%p)->()\n",This); return IUnknown_Release(This->unk.punkControl); } static HRESULT WINAPI IEnumUnknown_fnNext(IEnumUnknown* iface,ULONG cReq,IUnknown** ppunk,ULONG* pcFetched) { CEnumUnknown_THIS(iface,enumunk); HRESULT hr; ULONG cFetched; TRACE("(%p)->(%lu,%p,%p)\n",This,cReq,ppunk,pcFetched); if ( pcFetched == NULL && cReq > 1 ) return E_INVALIDARG; if ( ppunk == NULL ) return E_POINTER; QUARTZ_CompList_Lock( This->pCompList ); hr = NOERROR; cFetched = 0; while ( cReq > 0 ) { if ( This->pItemCur == NULL ) { hr = S_FALSE; break; } ppunk[ cFetched ++ ] = QUARTZ_CompList_GetItemPtr( This->pItemCur ); IUnknown_AddRef( *ppunk ); This->pItemCur = QUARTZ_CompList_GetNext( This->pCompList, This->pItemCur ); cReq --; } QUARTZ_CompList_Unlock( This->pCompList ); if ( pcFetched != NULL ) *pcFetched = cFetched; return hr; } static HRESULT WINAPI IEnumUnknown_fnSkip(IEnumUnknown* iface,ULONG cSkip) { CEnumUnknown_THIS(iface,enumunk); HRESULT hr; TRACE("(%p)->()\n",This); QUARTZ_CompList_Lock( This->pCompList ); hr = NOERROR; while ( cSkip > 0 ) { if ( This->pItemCur == NULL ) { hr = S_FALSE; break; } This->pItemCur = QUARTZ_CompList_GetNext( This->pCompList, This->pItemCur ); cSkip --; } QUARTZ_CompList_Unlock( This->pCompList ); return hr; } static HRESULT WINAPI IEnumUnknown_fnReset(IEnumUnknown* iface) { CEnumUnknown_THIS(iface,enumunk); TRACE("(%p)->()\n",This); QUARTZ_CompList_Lock( This->pCompList ); This->pItemCur = QUARTZ_CompList_GetFirst( This->pCompList ); QUARTZ_CompList_Unlock( This->pCompList ); return NOERROR; } static HRESULT WINAPI IEnumUnknown_fnClone(IEnumUnknown* iface,IEnumUnknown** ppunk) { CEnumUnknown_THIS(iface,enumunk); HRESULT hr; TRACE("(%p)->()\n",This); if ( ppunk == NULL ) return E_POINTER; QUARTZ_CompList_Lock( This->pCompList ); hr = QUARTZ_CreateEnumUnknown( This->IFEntries[0].piid, (void**)ppunk, This->pCompList ); QUARTZ_CompList_Unlock( This->pCompList ); return hr; } static ICOM_VTABLE(IEnumUnknown) ienumunk = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE /* IUnknown fields */ IEnumUnknown_fnQueryInterface, IEnumUnknown_fnAddRef, IEnumUnknown_fnRelease, /* IEnumUnknown fields */ IEnumUnknown_fnNext, IEnumUnknown_fnSkip, IEnumUnknown_fnReset, IEnumUnknown_fnClone, }; void QUARTZ_DestroyEnumUnknown(IUnknown* punk) { CEnumUnknown_THIS(punk,unk); if ( This->pCompList != NULL ) QUARTZ_CompList_Free( This->pCompList ); } HRESULT QUARTZ_CreateEnumUnknown( REFIID riidEnum, void** ppobj, const QUARTZ_CompList* pCompList ) { CEnumUnknown* penum; QUARTZ_CompList* pCompListDup; TRACE("(%s,%p,%p)\n",debugstr_guid(riidEnum),ppobj,pCompList); pCompListDup = QUARTZ_CompList_Dup( pCompList, FALSE ); if ( pCompListDup == NULL ) return E_OUTOFMEMORY; penum = (CEnumUnknown*)QUARTZ_AllocObj( sizeof(CEnumUnknown) ); if ( penum == NULL ) { QUARTZ_CompList_Free( pCompListDup ); return E_OUTOFMEMORY; } QUARTZ_IUnkInit( &penum->unk, NULL ); ICOM_VTBL(&penum->enumunk) = &ienumunk; penum->IFEntries[0].piid = riidEnum; penum->IFEntries[0].ofsVTPtr = offsetof(CEnumUnknown,enumunk)-offsetof(CEnumUnknown,unk); penum->pCompList = pCompListDup; penum->pItemCur = QUARTZ_CompList_GetFirst( pCompListDup ); penum->unk.pEntries = penum->IFEntries; penum->unk.dwEntries = 1; penum->unk.pOnFinalRelease = QUARTZ_DestroyEnumUnknown; *ppobj = (void*)(&penum->enumunk); return S_OK; }