wine/dlls/quartz/fmap.c
Hidenori Takeshima 912f899c96 Fixed some bugs.
Added stubs.
Remove harmless FIXMEs.
2002-04-14 19:32:31 +00:00

1126 lines
27 KiB
C

/*
* Implementation of CLSID_FilterMapper and CLSID_FilterMapper2.
*
* FIXME - some stubs
*
* Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "winerror.h"
#include "strmif.h"
#include "uuids.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
#include "quartz_private.h"
#include "fmap.h"
#include "regsvr.h"
#include "devenum.h"
#include "complist.h"
#include "enumunk.h"
/***************************************************************************/
typedef struct QUARTZ_REGFILTERDATA
{
DWORD dwVersion; /* =2 */
DWORD dwMerit;
DWORD cPins; /* count of pins */
DWORD dwZero; /* padding??? */
} QUARTZ_REGFILTERDATA;
typedef struct QUARTZ_REGPINDATA
{
CHAR id[4]; /* '0pi3', '1pi3', ... */
DWORD dwFlags; /* flags */
UINT cInstances; /* FIXME - is this correct? */
UINT nMediaTypes; /* count of media types('0ty3') */
UINT nMediums; /* FIXME - is this correct? */
UINT nOfsClsPinCategory; /* FIXME - is this correct? */
} QUARTZ_REGPINDATA;
typedef struct QUARTZ_REGMEDIATYPE
{
CHAR id[4]; /* '0ty3', '1ty3', ... */
DWORD nZero; /* padding??? */
UINT nOfsMajorType;
UINT nOfsMinorType;
} QUARTZ_REGMEDIATYPE;
/***************************************************************************/
static
REGFILTER2* QUARTZ_RegFilterV2FromFilterData(
const BYTE* pData, DWORD cbData )
{
REGFILTER2* pFilter;
REGFILTERPINS2* pPin;
REGPINTYPES* pTypes;
BYTE* pDst;
const QUARTZ_REGFILTERDATA* pRegFilter;
const QUARTZ_REGPINDATA* pRegPin;
const QUARTZ_REGMEDIATYPE* pRegMediaType;
DWORD cPins;
DWORD cbBufSize;
UINT n;
TRACE("(%p,%lu)\n",pData,cbData);
if ( cbData < sizeof(QUARTZ_REGFILTERDATA) )
return NULL;
pRegFilter = (QUARTZ_REGFILTERDATA*)pData;
if ( pRegFilter->dwVersion != 2 ) return NULL; /* FIXME */
if ( cbData < (sizeof(QUARTZ_REGFILTERDATA)+sizeof(QUARTZ_REGPINDATA)*pRegFilter->cPins) )
return NULL;
cbBufSize = sizeof(REGFILTER2);
cPins = pRegFilter->cPins;
pRegPin = (const QUARTZ_REGPINDATA*)(pRegFilter+1);
while ( cPins-- > 0 )
{
if ( pRegPin->nMediums != 0 ||
pRegPin->nOfsClsPinCategory != 0 )
return NULL; /* FIXME */
cbBufSize += sizeof(REGFILTERPINS2) +
pRegPin->nMediaTypes * (sizeof(REGPINTYPES) + sizeof(GUID)*2) +
pRegPin->nMediums * sizeof(REGPINMEDIUM) +
sizeof(CLSID);
pRegPin = (const QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
sizeof(QUARTZ_REGPINDATA) +
sizeof(QUARTZ_REGMEDIATYPE) * pRegPin->nMediaTypes );
}
pFilter = (REGFILTER2*)QUARTZ_AllocMem( cbBufSize );
if ( pFilter == NULL ) return NULL;
ZeroMemory( pFilter, cbBufSize );
pPin = (REGFILTERPINS2*)(pFilter+1);
pDst = (BYTE*)(pPin + pRegFilter->cPins);
pFilter->dwVersion = 2;
pFilter->dwMerit = pRegFilter->dwMerit;
pFilter->u.s2.cPins2 = pRegFilter->cPins;
pFilter->u.s2.rgPins2 = pPin;
cPins = pRegFilter->cPins;
TRACE("cPins = %lu\n",cPins);
pRegPin = (const QUARTZ_REGPINDATA*)(pRegFilter+1);
while ( cPins-- > 0 )
{
pPin->dwFlags = pRegPin->dwFlags;
pPin->cInstances = pRegPin->cInstances;
pPin->nMediaTypes = pRegPin->nMediaTypes;
pPin->lpMediaType = NULL;
pPin->nMediums = pRegPin->nMediums;
pPin->lpMedium = NULL;
pPin->clsPinCategory = NULL;
pTypes = (REGPINTYPES*)pDst;
pPin->lpMediaType = pTypes;
pDst += sizeof(REGPINTYPES) * pRegPin->nMediaTypes;
pRegPin = (const QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
sizeof(QUARTZ_REGPINDATA) );
for ( n = 0; n < pPin->nMediaTypes; n++ )
{
pRegMediaType = ((const QUARTZ_REGMEDIATYPE*)pRegPin);
TRACE("ofsMajor = %u, ofsMinor = %u\n", pRegMediaType->nOfsMajorType, pRegMediaType->nOfsMinorType);
memcpy( pDst, pData+pRegMediaType->nOfsMajorType, sizeof(GUID) );
pTypes->clsMajorType = (const GUID*)pDst; pDst += sizeof(GUID);
memcpy( pDst, pData+pRegMediaType->nOfsMinorType, sizeof(GUID) );
pTypes->clsMinorType = (const GUID*)pDst; pDst += sizeof(GUID);
pRegPin = (const QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
sizeof(QUARTZ_REGMEDIATYPE) );
pTypes ++;
}
/* FIXME - pPin->lpMedium */
/* FIXME - pPin->clsPinCategory */
pPin ++;
}
return pFilter;
}
static
BYTE* QUARTZ_RegFilterV2ToFilterData(
const REGFILTER2* pFilter, DWORD* pcbData )
{
DWORD cbData;
DWORD cbPinData;
DWORD cPins;
const REGFILTERPINS2* pPin;
const REGPINTYPES* pTypes;
BYTE* pRet = NULL;
BYTE* pDst;
QUARTZ_REGFILTERDATA* pRegFilter;
QUARTZ_REGPINDATA* pRegPin;
QUARTZ_REGMEDIATYPE* pRegMediaType;
UINT n;
if ( pFilter->dwVersion != 2 ) return NULL; /* FIXME */
cbData = sizeof(QUARTZ_REGFILTERDATA);
cPins = pFilter->u.s2.cPins2;
pPin = pFilter->u.s2.rgPins2;
if ( cPins > 10 ) return NULL; /* FIXME */
cbPinData = 0;
while ( cPins-- > 0 )
{
if ( pPin->cInstances != 0 ||
pPin->nMediaTypes > 10 ||
pPin->nMediums != 0 ||
pPin->clsPinCategory != 0 )
{
FIXME( "not implemented.\n" );
return NULL; /* FIXME */
}
cbPinData += sizeof(QUARTZ_REGPINDATA) +
pPin->nMediaTypes * sizeof(QUARTZ_REGMEDIATYPE);
cbData += pPin->nMediaTypes * (sizeof(GUID)*2);
pPin ++;
}
cbData += cbPinData;
TRACE("cbData %lu, cbPinData %lu\n",cbData,cbPinData);
pRet = (BYTE*)QUARTZ_AllocMem( cbData );
if ( pRet == NULL ) return NULL;
ZeroMemory( pRet, cbData );
pDst = pRet;
pRegFilter = (QUARTZ_REGFILTERDATA*)pDst;
pDst += sizeof(QUARTZ_REGFILTERDATA);
pRegFilter->dwVersion = 2;
pRegFilter->dwMerit = pFilter->dwMerit;
pRegFilter->cPins = pFilter->u.s2.cPins2;
pRegPin = (QUARTZ_REGPINDATA*)pDst;
pDst += cbPinData;
pPin = pFilter->u.s2.rgPins2;
for ( cPins = 0; cPins < pFilter->u.s2.cPins2; cPins++ )
{
pRegPin->id[0] = '0'+cPins;
pRegPin->id[1] = 'p';
pRegPin->id[2] = 'i';
pRegPin->id[3] = '3';
pRegPin->dwFlags = pPin->dwFlags; /* flags */
pRegPin->cInstances = pPin->cInstances;
pRegPin->nMediaTypes = pPin->nMediaTypes;
pRegPin->nMediums = pPin->nMediums;
pRegPin->nOfsClsPinCategory = 0; /* FIXME */
pTypes = pPin->lpMediaType;
pRegPin = (QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
sizeof(QUARTZ_REGPINDATA) );
for ( n = 0; n < pPin->nMediaTypes; n++ )
{
pRegMediaType = ((QUARTZ_REGMEDIATYPE*)pRegPin);
pRegMediaType->id[0] = '0'+n;
pRegMediaType->id[1] = 't';
pRegMediaType->id[2] = 'y';
pRegMediaType->id[3] = '3';
/* FIXME - CLSID should be shared. */
pRegMediaType->nOfsMajorType = pDst - pRet;
memcpy( pDst, pTypes->clsMajorType, sizeof(GUID) );
pDst += sizeof(GUID);
pRegMediaType->nOfsMinorType = pDst - pRet;
memcpy( pDst, pTypes->clsMinorType, sizeof(GUID) );
pDst += sizeof(GUID);
pRegPin = (QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
sizeof(QUARTZ_REGMEDIATYPE) );
pTypes ++;
}
pPin ++;
}
*pcbData = pDst - pRet;
TRACE("cbData %lu/%lu\n",*pcbData,cbData);
return pRet;
}
static
REGFILTER2* QUARTZ_RegFilterV1ToV2( const REGFILTER2* prfV1 )
{
REGFILTER2* prfV2;
const REGFILTERPINS* pPinV1;
REGFILTERPINS2* pPinV2;
DWORD cPins;
if ( prfV1->dwVersion != 1 ) return NULL;
prfV2 = (REGFILTER2*)QUARTZ_AllocMem(
sizeof(REGFILTER2) + sizeof(REGFILTERPINS2) * prfV1->u.s1.cPins );
if ( prfV2 == NULL ) return NULL;
ZeroMemory( prfV2, sizeof(REGFILTER2) + sizeof(REGFILTERPINS2) * prfV1->u.s1.cPins );
pPinV1 = prfV1->u.s1.rgPins;
pPinV2 = (REGFILTERPINS2*)(prfV2+1);
prfV2->dwVersion = 2;
prfV2->dwMerit = prfV1->dwMerit;
prfV2->u.s2.cPins2 = prfV1->u.s1.cPins;
prfV2->u.s2.rgPins2 = pPinV2;
cPins = prfV1->u.s1.cPins;
while ( cPins-- > 0 )
{
pPinV2->dwFlags = 0;
pPinV2->cInstances = 0;
pPinV2->nMediaTypes = pPinV1->nMediaTypes;
pPinV2->lpMediaType = pPinV1->lpMediaType;
pPinV2->nMediums = 0;
pPinV2->lpMedium = NULL;
pPinV2->clsPinCategory = NULL;
if ( pPinV1->bRendered )
pPinV2->dwFlags |= REG_PINFLAG_B_RENDERER;
if ( pPinV1->bOutput )
pPinV2->dwFlags |= REG_PINFLAG_B_OUTPUT;
if ( pPinV1->bZero )
pPinV2->dwFlags |= REG_PINFLAG_B_ZERO;
if ( pPinV1->bMany )
pPinV2->dwFlags |= REG_PINFLAG_B_MANY;
pPinV1 ++;
pPinV2 ++;
}
return prfV2;
}
static
BYTE* QUARTZ_RegFilterToFilterData(
const REGFILTER2* pFilter, DWORD* pcbData )
{
REGFILTER2* prfV2;
BYTE* pRet = NULL;
*pcbData = 0;
switch ( pFilter->dwVersion )
{
case 1:
prfV2 = QUARTZ_RegFilterV1ToV2( pFilter );
if ( prfV2 != NULL )
{
pRet = QUARTZ_RegFilterV2ToFilterData( prfV2, pcbData );
QUARTZ_FreeMem( prfV2 );
}
break;
case 2:
pRet = QUARTZ_RegFilterV2ToFilterData( pFilter, pcbData );
break;
default:
FIXME( "unknown REGFILTER2 version - %08lu\n", pFilter->dwVersion );
break;
}
return pRet;
}
/***************************************************************************/
static
BOOL QUARTZ_CheckPinType( BOOL bExactMatch, const REGFILTERPINS2* pPin, DWORD cTypes, const GUID* pTypes, const REGPINMEDIUM* pMedium, const CLSID* pCategory, BOOL bRender )
{
DWORD n1, n2;
BOOL bMatch;
if ( cTypes > 0 && pTypes != NULL )
{
bMatch = FALSE;
for ( n1 = 0; n1 < pPin->nMediaTypes; n1++ )
{
for ( n2 = 0; n2 < cTypes; n2++ )
{
if ( IsEqualGUID(pPin->lpMediaType[n1].clsMajorType,&GUID_NULL) || IsEqualGUID(pPin->lpMediaType[n1].clsMajorType, &pTypes[n2*2+0]) || (!bExactMatch && IsEqualGUID(pPin->lpMediaType[n1].clsMajorType,&GUID_NULL)) )
{
if ( IsEqualGUID(pPin->lpMediaType[n1].clsMinorType,&GUID_NULL) || IsEqualGUID(pPin->lpMediaType[n1].clsMinorType, &pTypes[n2*2+1]) || (!bExactMatch && IsEqualGUID(pPin->lpMediaType[n1].clsMinorType,&GUID_NULL)) )
{
bMatch = TRUE;
break;
}
}
}
}
TRACE("Check media type %d\n",(int)bMatch);
if ( !bMatch )
return FALSE;
}
if ( pMedium != NULL )
{
bMatch = FALSE;
for ( n1 = 0; n1 < pPin->nMediums; n1++ )
{
if ( IsEqualGUID( &pPin->lpMedium[n1].clsMedium, &pMedium->clsMedium ) && pPin->lpMedium[n1].dw1 == pMedium->dw1 && pPin->lpMedium[n1].dw2 == pMedium->dw2 )
{
bMatch = TRUE;
break;
}
}
TRACE("Check medium %d\n",(int)bMatch);
if ( !bMatch )
return FALSE;
}
if ( pCategory != NULL )
{
if ( pPin->clsPinCategory == NULL )
return FALSE;
if ( (!bExactMatch && IsEqualGUID(pCategory,&GUID_NULL)) || IsEqualGUID(pCategory,pPin->clsPinCategory) )
return TRUE;
return FALSE;
}
if ( bRender && (!(pPin->dwFlags & REG_PINFLAG_B_RENDERER)) )
{
TRACE("not a renderer\n");
return FALSE;
}
return TRUE;
}
/***************************************************************************
*
* new/delete for CLSID_FilterMapper
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry FMapIFEntries[] =
{
{ &IID_IFilterMapper, offsetof(CFilterMapper,fmap)-offsetof(CFilterMapper,unk) },
};
static void QUARTZ_DestroyFilterMapper(IUnknown* punk)
{
CFilterMapper_THIS(punk,unk);
CFilterMapper_UninitIFilterMapper( This );
}
HRESULT QUARTZ_CreateFilterMapper(IUnknown* punkOuter,void** ppobj)
{
CFilterMapper* pfm;
HRESULT hr;
TRACE("(%p,%p)\n",punkOuter,ppobj);
pfm = (CFilterMapper*)QUARTZ_AllocObj( sizeof(CFilterMapper) );
if ( pfm == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &pfm->unk, punkOuter );
hr = CFilterMapper_InitIFilterMapper( pfm );
if ( FAILED(hr) )
{
QUARTZ_FreeObj( pfm );
return hr;
}
pfm->unk.pEntries = FMapIFEntries;
pfm->unk.dwEntries = sizeof(FMapIFEntries)/sizeof(FMapIFEntries[0]);
pfm->unk.pOnFinalRelease = QUARTZ_DestroyFilterMapper;
*ppobj = (void*)(&pfm->unk);
return S_OK;
}
/***************************************************************************
*
* CLSID_FilterMapper::IFilterMapper
*
*/
static HRESULT WINAPI
IFilterMapper_fnQueryInterface(IFilterMapper* iface,REFIID riid,void** ppobj)
{
CFilterMapper_THIS(iface,fmap);
TRACE("(%p)->()\n",This);
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
}
static ULONG WINAPI
IFilterMapper_fnAddRef(IFilterMapper* iface)
{
CFilterMapper_THIS(iface,fmap);
TRACE("(%p)->()\n",This);
return IUnknown_AddRef(This->unk.punkControl);
}
static ULONG WINAPI
IFilterMapper_fnRelease(IFilterMapper* iface)
{
CFilterMapper_THIS(iface,fmap);
TRACE("(%p)->()\n",This);
return IUnknown_Release(This->unk.punkControl);
}
static HRESULT WINAPI
IFilterMapper_fnRegisterFilter(IFilterMapper* iface,CLSID clsid,LPCWSTR lpwszName,DWORD dwMerit)
{
CFilterMapper_THIS(iface,fmap);
FIXME("(%p)->(%s,%s,%08lx)\n",This,
debugstr_guid(&clsid),debugstr_w(lpwszName),dwMerit);
/* FIXME */
/* FIXME - handle dwMerit! */
return QUARTZ_RegisterAMovieFilter(
&CLSID_LegacyAmFilterCategory,
&clsid,
NULL, 0,
lpwszName, NULL, TRUE );
}
static HRESULT WINAPI
IFilterMapper_fnRegisterFilterInstance(IFilterMapper* iface,CLSID clsid,LPCWSTR lpwszName,CLSID* pclsidMedia)
{
CFilterMapper_THIS(iface,fmap);
HRESULT hr;
FIXME("(%p)->()\n",This);
if ( pclsidMedia == NULL )
return E_POINTER;
hr = CoCreateGuid(pclsidMedia);
if ( FAILED(hr) )
return hr;
/* FIXME */
/* this doesn't work. */
/* return IFilterMapper_RegisterFilter(iface,
*pclsidMedia,lpwszName,0x60000000); */
return E_NOTIMPL;
}
static HRESULT WINAPI
IFilterMapper_fnRegisterPin(IFilterMapper* iface,CLSID clsidFilter,LPCWSTR lpwszName,BOOL bRendered,BOOL bOutput,BOOL bZero,BOOL bMany,CLSID clsidReserved,LPCWSTR lpwszReserved)
{
CFilterMapper_THIS(iface,fmap);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IFilterMapper_fnRegisterPinType(IFilterMapper* iface,CLSID clsidFilter,LPCWSTR lpwszName,CLSID clsidMajorType,CLSID clsidSubType)
{
CFilterMapper_THIS(iface,fmap);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI
IFilterMapper_fnUnregisterFilter(IFilterMapper* iface,CLSID clsidFilter)
{
CFilterMapper_THIS(iface,fmap);
FIXME("(%p)->(%s)\n",This,debugstr_guid(&clsidFilter));
/* FIXME */
return QUARTZ_RegisterAMovieFilter(
&CLSID_LegacyAmFilterCategory,
&clsidFilter,
NULL, 0, NULL, NULL, FALSE );
}
static HRESULT WINAPI
IFilterMapper_fnUnregisterFilterInstance(IFilterMapper* iface,CLSID clsidMedia)
{
CFilterMapper_THIS(iface,fmap);
FIXME("(%p)->(%s)\n",This,debugstr_guid(&clsidMedia));
/* FIXME */
/* this doesn't work. */
/* return IFilterMapper_UnregisterFilter(iface,clsidMedia); */
return E_NOTIMPL;
}
static HRESULT WINAPI
IFilterMapper_fnUnregisterPin(IFilterMapper* iface,CLSID clsidPin,LPCWSTR lpwszName)
{
CFilterMapper_THIS(iface,fmap);
FIXME("(%p)->(%s,%s) stub!\n",This,
debugstr_guid(&clsidPin),debugstr_w(lpwszName));
return E_NOTIMPL;
}
static HRESULT WINAPI
IFilterMapper_fnEnumMatchingFilters(IFilterMapper* iface,IEnumRegFilters** ppobj,DWORD dwMerit,BOOL bInputNeeded,CLSID clsInMajorType,CLSID clsidSubType,BOOL bRender,BOOL bOutputNeeded,CLSID clsOutMajorType,CLSID clsOutSubType)
{
CFilterMapper_THIS(iface,fmap);
FIXME("(%p)->() stub!\n",This);
return E_NOTIMPL;
}
static ICOM_VTABLE(IFilterMapper) ifmap =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown fields */
IFilterMapper_fnQueryInterface,
IFilterMapper_fnAddRef,
IFilterMapper_fnRelease,
/* IFilterMapper fields */
IFilterMapper_fnRegisterFilter,
IFilterMapper_fnRegisterFilterInstance,
IFilterMapper_fnRegisterPin,
IFilterMapper_fnRegisterPinType,
IFilterMapper_fnUnregisterFilter,
IFilterMapper_fnUnregisterFilterInstance,
IFilterMapper_fnUnregisterPin,
IFilterMapper_fnEnumMatchingFilters,
};
HRESULT CFilterMapper_InitIFilterMapper( CFilterMapper* pfm )
{
TRACE("(%p)\n",pfm);
ICOM_VTBL(&pfm->fmap) = &ifmap;
return NOERROR;
}
void CFilterMapper_UninitIFilterMapper( CFilterMapper* pfm )
{
TRACE("(%p)\n",pfm);
}
/***************************************************************************
*
* new/delete for CLSID_FilterMapper2
*
*/
/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry FMap2IFEntries[] =
{
{ &IID_IFilterMapper2, offsetof(CFilterMapper2,fmap2)-offsetof(CFilterMapper2,unk) },
};
static void QUARTZ_DestroyFilterMapper2(IUnknown* punk)
{
CFilterMapper2_THIS(punk,unk);
CFilterMapper2_UninitIFilterMapper2( This );
}
HRESULT QUARTZ_CreateFilterMapper2(IUnknown* punkOuter,void** ppobj)
{
CFilterMapper2* pfm;
HRESULT hr;
TRACE("(%p,%p)\n",punkOuter,ppobj);
pfm = (CFilterMapper2*)QUARTZ_AllocObj( sizeof(CFilterMapper2) );
if ( pfm == NULL )
return E_OUTOFMEMORY;
QUARTZ_IUnkInit( &pfm->unk, punkOuter );
hr = CFilterMapper2_InitIFilterMapper2( pfm );
if ( FAILED(hr) )
{
QUARTZ_FreeObj( pfm );
return hr;
}
pfm->unk.pEntries = FMap2IFEntries;
pfm->unk.dwEntries = sizeof(FMap2IFEntries)/sizeof(FMap2IFEntries[0]);
pfm->unk.pOnFinalRelease = QUARTZ_DestroyFilterMapper2;
*ppobj = (void*)(&pfm->unk);
return S_OK;
}
/***************************************************************************
*
* CLSID_FilterMapper2::IFilterMapper2
*
*/
static HRESULT WINAPI
IFilterMapper2_fnQueryInterface(IFilterMapper2* iface,REFIID riid,void** ppobj)
{
CFilterMapper2_THIS(iface,fmap2);
TRACE("(%p)->()\n",This);
return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
}
static ULONG WINAPI
IFilterMapper2_fnAddRef(IFilterMapper2* iface)
{
CFilterMapper2_THIS(iface,fmap2);
TRACE("(%p)->()\n",This);
return IUnknown_AddRef(This->unk.punkControl);
}
static ULONG WINAPI
IFilterMapper2_fnRelease(IFilterMapper2* iface)
{
CFilterMapper2_THIS(iface,fmap2);
TRACE("(%p)->()\n",This);
return IUnknown_Release(This->unk.punkControl);
}
static HRESULT WINAPI
IFilterMapper2_fnCreateCategory(IFilterMapper2* iface,REFCLSID rclsidCategory,DWORD dwMerit,LPCWSTR lpwszDesc)
{
CFilterMapper2_THIS(iface,fmap2);
FIXME("(%p)->(%s,%lu,%s) stub!\n",This,
debugstr_guid(rclsidCategory),
(unsigned long)dwMerit,debugstr_w(lpwszDesc));
return E_NOTIMPL;
}
static HRESULT WINAPI
IFilterMapper2_fnUnregisterFilter(IFilterMapper2* iface,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,REFCLSID rclsidFilter)
{
CFilterMapper2_THIS(iface,fmap2);
WCHAR* pwszPath = NULL;
HRESULT hr;
TRACE("(%p)->(%s,%s,%s)\n",This,
debugstr_guid(pclsidCategory),
debugstr_w(lpwszInst),
debugstr_guid(rclsidFilter));
if ( pclsidCategory == NULL )
pclsidCategory = &CLSID_LegacyAmFilterCategory;
hr = QUARTZ_GetFilterRegPath(
&pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
if ( FAILED(hr) )
return hr;
hr = QUARTZ_RegDeleteKey(HKEY_CLASSES_ROOT,pwszPath);
QUARTZ_FreeMem(pwszPath);
return hr;
}
static HRESULT WINAPI
IFilterMapper2_fnRegisterFilter(IFilterMapper2* iface,REFCLSID rclsidFilter,LPCWSTR lpName,IMoniker** ppMoniker,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,const REGFILTER2* pRF2)
{
CFilterMapper2_THIS(iface,fmap2);
WCHAR* pwszPath = NULL;
IMoniker* pMoniker = NULL;
BYTE* pFilterData = NULL;
DWORD cbFilterData = 0;
HRESULT hr;
TRACE( "(%p)->(%s,%s,%p,%s,%s,%p) stub!\n",This,
debugstr_guid(rclsidFilter),debugstr_w(lpName),
ppMoniker,debugstr_guid(pclsidCategory),
debugstr_w(lpwszInst),pRF2 );
if ( lpName == NULL || pRF2 == NULL )
return E_POINTER;
if ( ppMoniker != NULL && *ppMoniker != NULL )
{
FIXME( "ppMoniker != NULL - not implemented! *ppMoniker = %p\n",*ppMoniker );
return E_NOTIMPL;
}
if ( pclsidCategory == NULL )
pclsidCategory = &CLSID_LegacyAmFilterCategory;
if ( pMoniker == NULL )
{
hr = QUARTZ_GetFilterRegPath(
&pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
if ( FAILED(hr) )
return hr;
hr = QUARTZ_CreateDeviceMoniker(
HKEY_CLASSES_ROOT,pwszPath,&pMoniker);
QUARTZ_FreeMem(pwszPath);
if ( FAILED(hr) )
return hr;
}
pFilterData = QUARTZ_RegFilterToFilterData( pRF2, &cbFilterData );
if ( pFilterData == NULL || cbFilterData == 0 )
{
hr = E_FAIL;
goto err;
}
hr = QUARTZ_RegisterFilterToMoniker(
pMoniker, rclsidFilter, lpName, pFilterData, cbFilterData );
if ( FAILED(hr) )
goto err;
if ( ppMoniker != NULL )
{
*ppMoniker = pMoniker;
pMoniker = NULL;
}
err:
if ( pFilterData != NULL )
QUARTZ_FreeMem(pFilterData);
if ( pMoniker != NULL )
IMoniker_Release(pMoniker);
return hr;
}
struct MATCHED_ITEM
{
IMoniker* pMonFilter;
DWORD dwMerit;
};
static int sort_comp_merit(const void* p1,const void* p2)
{
const struct MATCHED_ITEM* pItem1 = (const struct MATCHED_ITEM*)p1;
const struct MATCHED_ITEM* pItem2 = (const struct MATCHED_ITEM*)p2;
return (int)pItem2->dwMerit - (int)pItem1->dwMerit;
}
static HRESULT WINAPI
IFilterMapper2_fnEnumMatchingFilters(IFilterMapper2* iface,
IEnumMoniker** ppEnumMoniker,DWORD dwFlags,BOOL bExactMatch,DWORD dwMerit,
BOOL bInputNeeded,DWORD cInputTypes,const GUID* pguidInputTypes,const REGPINMEDIUM* pPinMediumIn,const CLSID* pPinCategoryIn,BOOL bRender,
BOOL bOutputNeeded,DWORD cOutputTypes,const GUID* pguidOutputTypes,const REGPINMEDIUM* pPinMediumOut,const CLSID* pPinCategoryOut)
{
CFilterMapper2_THIS(iface,fmap2);
ICreateDevEnum* pEnum = NULL;
IEnumMoniker* pCategories = NULL;
IMoniker* pCat = NULL;
DWORD dwCatMerit;
IEnumMoniker* pCatFilters = NULL;
IMoniker* pFilter = NULL;
CLSID clsid;
ULONG cReturned;
BYTE* pbFilterData = NULL;
DWORD cbFilterData = 0;
REGFILTER2* prf2 = NULL;
QUARTZ_CompList* pListFilters = NULL;
struct MATCHED_ITEM* pItems = NULL;
struct MATCHED_ITEM* pItemsTmp;
int cItems = 0;
const REGFILTERPINS2* pRegFilterPin;
DWORD n;
BOOL bMatch;
HRESULT hr;
WARN("(%p)->(%p,%08lx,%d,%08lx,%d,%lu,%p,%p,%p,%d,%d,%lu,%p,%p,%p) some features are not implemented\n",
This,ppEnumMoniker,dwFlags,bExactMatch,dwMerit,
bInputNeeded,cInputTypes,pguidInputTypes,
pPinMediumIn,pPinCategoryIn,
bRender,
bOutputNeeded,cOutputTypes,pguidOutputTypes,
pPinMediumOut,pPinCategoryOut);
if ( ppEnumMoniker == NULL )
return E_POINTER;
*ppEnumMoniker = NULL;
if ( dwFlags != 0 )
return E_INVALIDARG;
hr = CoCreateInstance(
&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
&IID_ICreateDevEnum, (void**)&pEnum );
if ( FAILED(hr) )
goto err;
hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&CLSID_ActiveMovieCategories,&pCategories,0);
if ( hr != S_OK )
goto err;
while ( 1 )
{
if ( pCat != NULL )
{
IMoniker_Release(pCat);
pCat = NULL;
}
hr = IEnumMoniker_Next(pCategories,1,&pCat,&cReturned);
if ( FAILED(hr) )
goto err;
if ( hr != S_OK )
break;
hr = QUARTZ_GetMeritFromMoniker(pCat,&dwCatMerit);
if ( hr != S_OK || dwMerit > dwCatMerit )
continue;
hr = QUARTZ_GetCLSIDFromMoniker(pCat,&clsid);
if ( hr != S_OK )
continue;
if ( pCatFilters != NULL )
{
IEnumMoniker_Release(pCatFilters);
pCatFilters = NULL;
}
hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&clsid,&pCatFilters,0);
if ( FAILED(hr) )
goto err;
if ( hr != S_OK )
continue;
while ( 1 )
{
if ( pFilter != NULL )
{
IMoniker_Release(pFilter);
pFilter = NULL;
}
hr = IEnumMoniker_Next(pCatFilters,1,&pFilter,&cReturned);
if ( FAILED(hr) )
goto err;
if ( hr != S_OK )
break;
if ( pbFilterData != NULL )
{
QUARTZ_FreeMem(pbFilterData);
pbFilterData = NULL;
}
if(TRACE_ON(quartz))
{
CLSID clsidTrace;
if (SUCCEEDED(QUARTZ_GetCLSIDFromMoniker(pFilter,&clsidTrace)))
{
TRACE("moniker clsid %s\n",debugstr_guid(&clsidTrace));
}
}
hr = QUARTZ_GetFilterDataFromMoniker(pFilter,&pbFilterData,&cbFilterData);
if ( hr != S_OK )
continue;
if ( prf2 != NULL )
{
QUARTZ_FreeMem(prf2);
prf2 = NULL;
}
prf2 = QUARTZ_RegFilterV2FromFilterData(pbFilterData,cbFilterData);
if ( prf2 == NULL )
continue;
TRACE("prf2 %p, Merit %08lx\n",prf2,prf2->dwMerit);
if ( prf2->dwMerit < dwMerit || prf2->dwVersion != 2 )
continue;
/* check input pins. */
if ( bInputNeeded )
{
bMatch = FALSE;
for ( n = 0; n < prf2->u.s2.cPins2; n++ )
{
pRegFilterPin = &prf2->u.s2.rgPins2[n];
if ( pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT )
continue;
bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cInputTypes, pguidInputTypes, pPinMediumIn, pPinCategoryIn, bRender );
if ( bMatch )
break;
}
if ( !bMatch )
{
TRACE("no matching input pin\n");
continue;
}
}
/* check output pins. */
if ( bOutputNeeded )
{
bMatch = FALSE;
for ( n = 0; n < prf2->u.s2.cPins2; n++ )
{
pRegFilterPin = &prf2->u.s2.rgPins2[n];
if ( !(pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT) )
continue;
bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cOutputTypes, pguidOutputTypes, pPinMediumOut, pPinCategoryOut, FALSE );
if ( bMatch )
break;
}
if ( !bMatch )
{
TRACE("no matching output pin\n");
continue;
}
}
/* matched - add pFilter to the list. */
pItemsTmp = QUARTZ_ReallocMem( pItems, sizeof(struct MATCHED_ITEM) * (cItems+1) );
if ( pItemsTmp == NULL )
{
hr = E_OUTOFMEMORY;
goto err;
}
pItems = pItemsTmp;
pItemsTmp = pItems + cItems; cItems ++;
pItemsTmp->pMonFilter = pFilter; pFilter = NULL;
pItemsTmp->dwMerit = prf2->dwMerit;
}
}
if ( pItems == NULL || cItems == 0 )
{
hr = S_FALSE;
goto err;
}
/* FIXME - sort in Merit order */
TRACE("sort in Merit order\n");
qsort( pItems, cItems, sizeof(struct MATCHED_ITEM), sort_comp_merit );
pListFilters = QUARTZ_CompList_Alloc();
if ( pListFilters == NULL )
{
hr = E_OUTOFMEMORY;
goto err;
}
for ( n = 0; n < cItems; n++ )
{
TRACE("merit %08lx\n",pItems[n].dwMerit);
hr = QUARTZ_CompList_AddComp( pListFilters, (IUnknown*)pItems[n].pMonFilter, NULL, 0 );
if ( FAILED(hr) )
goto err;
}
hr = QUARTZ_CreateEnumUnknown( &IID_IEnumMoniker, (void**)ppEnumMoniker, pListFilters );
if ( FAILED(hr) )
goto err;
hr = S_OK;
err:
if ( pEnum != NULL )
ICreateDevEnum_Release(pEnum);
if ( pCategories != NULL )
IEnumMoniker_Release(pCategories);
if ( pCat != NULL )
IMoniker_Release(pCat);
if ( pCatFilters != NULL )
IEnumMoniker_Release(pCatFilters);
if ( pFilter != NULL )
IMoniker_Release(pFilter);
if ( pbFilterData != NULL )
QUARTZ_FreeMem(pbFilterData);
if ( prf2 != NULL )
QUARTZ_FreeMem(prf2);
if ( pItems != NULL && cItems > 0 )
{
for ( n = 0; n < cItems; n++ )
{
if ( pItems[n].pMonFilter != NULL )
IMoniker_Release(pItems[n].pMonFilter);
}
QUARTZ_FreeMem(pItems);
}
if ( pListFilters != NULL )
QUARTZ_CompList_Free( pListFilters );
TRACE("returns %08lx\n",hr);
return hr;
}
static ICOM_VTABLE(IFilterMapper2) ifmap2 =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown fields */
IFilterMapper2_fnQueryInterface,
IFilterMapper2_fnAddRef,
IFilterMapper2_fnRelease,
/* IFilterMapper2 fields */
IFilterMapper2_fnCreateCategory,
IFilterMapper2_fnUnregisterFilter,
IFilterMapper2_fnRegisterFilter,
IFilterMapper2_fnEnumMatchingFilters,
};
HRESULT CFilterMapper2_InitIFilterMapper2( CFilterMapper2* pfm )
{
TRACE("(%p)\n",pfm);
ICOM_VTBL(&pfm->fmap2) = &ifmap2;
return NOERROR;
}
void CFilterMapper2_UninitIFilterMapper2( CFilterMapper2* pfm )
{
TRACE("(%p)\n",pfm);
}