Changed the GDI driver interface to pass an opaque PHYSDEV pointer
[wine] / dlls / quartz / fmap.c
1 /*
2  * Implementation of CLSID_FilterMapper and CLSID_FilterMapper2.
3  *
4  * FIXME - stub.
5  *
6  * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "winerror.h"
31 #include "strmif.h"
32 #include "uuids.h"
33
34 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
36
37 #include "quartz_private.h"
38 #include "fmap.h"
39 #include "regsvr.h"
40 #include "devenum.h"
41 #include "complist.h"
42 #include "enumunk.h"
43
44 /***************************************************************************/
45
46 typedef struct QUARTZ_REGFILTERDATA
47 {
48         DWORD   dwVersion; /* =2 */
49         DWORD   dwMerit;
50         DWORD   cPins; /* count of pins */
51         DWORD   dwZero; /* padding??? */
52 } QUARTZ_REGFILTERDATA;
53
54 typedef struct QUARTZ_REGPINDATA
55 {
56         CHAR    id[4]; /* '0pi3', '1pi3', ... */
57         DWORD   dwFlags; /* flags */
58         UINT    cInstances; /* FIXME - is this correct? */
59         UINT    nMediaTypes; /* count of media types('0ty3') */
60         UINT    nMediums; /* FIXME - is this correct? */
61         UINT    nOfsClsPinCategory; /* FIXME - is this correct? */
62 } QUARTZ_REGPINDATA;
63
64 typedef struct QUARTZ_REGMEDIATYPE
65 {
66         CHAR    id[4]; /* '0ty3', '1ty3', ... */
67         DWORD   nZero; /* padding??? */
68         UINT    nOfsMajorType;
69         UINT    nOfsMinorType;
70 } QUARTZ_REGMEDIATYPE;
71
72
73
74 /***************************************************************************/
75
76 static
77 REGFILTER2* QUARTZ_RegFilterV2FromFilterData(
78         const BYTE* pData, DWORD cbData )
79 {
80         REGFILTER2*     pFilter;
81         REGFILTERPINS2* pPin;
82         REGPINTYPES*    pTypes;
83         BYTE* pDst;
84         const QUARTZ_REGFILTERDATA*     pRegFilter;
85         const QUARTZ_REGPINDATA*        pRegPin;
86         const QUARTZ_REGMEDIATYPE*      pRegMediaType;
87         DWORD   cPins;
88         DWORD   cbBufSize;
89         UINT    n;
90
91         TRACE("(%p,%lu)\n",pData,cbData);
92
93         if ( cbData < sizeof(QUARTZ_REGFILTERDATA) )
94                 return NULL;
95
96         pRegFilter = (QUARTZ_REGFILTERDATA*)pData;
97
98         if ( pRegFilter->dwVersion != 2 ) return NULL; /* FIXME */
99
100         if ( cbData < (sizeof(QUARTZ_REGFILTERDATA)+sizeof(QUARTZ_REGPINDATA)*pRegFilter->cPins) )
101                 return NULL;
102
103         cbBufSize = sizeof(REGFILTER2);
104         cPins = pRegFilter->cPins;
105         pRegPin = (const QUARTZ_REGPINDATA*)(pRegFilter+1);
106         while ( cPins-- > 0 )
107         {
108                 if ( pRegPin->nMediums != 0 ||
109                          pRegPin->nOfsClsPinCategory != 0 )
110                         return NULL; /* FIXME */
111
112                 cbBufSize += sizeof(REGFILTERPINS2) +
113                         pRegPin->nMediaTypes * (sizeof(REGPINTYPES) + sizeof(GUID)*2) +
114                         pRegPin->nMediums * sizeof(REGPINMEDIUM) +
115                         sizeof(CLSID);
116                 pRegPin = (const QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
117                         sizeof(QUARTZ_REGPINDATA) +
118                         sizeof(QUARTZ_REGMEDIATYPE) * pRegPin->nMediaTypes );
119         }
120
121         pFilter = (REGFILTER2*)QUARTZ_AllocMem( cbBufSize );
122         if ( pFilter == NULL ) return NULL;
123         ZeroMemory( pFilter, cbBufSize );
124         pPin = (REGFILTERPINS2*)(pFilter+1);
125         pDst = (BYTE*)(pPin + pRegFilter->cPins);
126
127         pFilter->dwVersion = 2;
128         pFilter->dwMerit = pRegFilter->dwMerit;
129         pFilter->u.s2.cPins2 = pRegFilter->cPins;
130         pFilter->u.s2.rgPins2 = pPin;
131
132         cPins = pRegFilter->cPins;
133         TRACE("cPins = %lu\n",cPins);
134
135         pRegPin = (const QUARTZ_REGPINDATA*)(pRegFilter+1);
136         while ( cPins-- > 0 )
137         {
138                 pPin->dwFlags = pRegPin->dwFlags;
139                 pPin->cInstances = pRegPin->cInstances;
140                 pPin->nMediaTypes = pRegPin->nMediaTypes;
141                 pPin->lpMediaType = NULL;
142                 pPin->nMediums = pRegPin->nMediums;
143                 pPin->lpMedium = NULL;
144                 pPin->clsPinCategory = NULL;
145
146                 pTypes = (REGPINTYPES*)pDst;
147                 pPin->lpMediaType = pTypes;
148                 pDst += sizeof(REGPINTYPES) * pRegPin->nMediaTypes;
149
150                 pRegPin = (const QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
151                         sizeof(QUARTZ_REGPINDATA) );
152
153                 for ( n = 0; n < pPin->nMediaTypes; n++ )
154                 {
155                         pRegMediaType = ((const QUARTZ_REGMEDIATYPE*)pRegPin);
156                         TRACE("ofsMajor = %u, ofsMinor = %u\n", pRegMediaType->nOfsMajorType, pRegMediaType->nOfsMinorType);
157                         memcpy( pDst, pData+pRegMediaType->nOfsMajorType, sizeof(GUID) );
158                         pTypes->clsMajorType = (const GUID*)pDst; pDst += sizeof(GUID);
159                         memcpy( pDst, pData+pRegMediaType->nOfsMinorType, sizeof(GUID) );
160                         pTypes->clsMinorType = (const GUID*)pDst; pDst += sizeof(GUID);
161
162                         pRegPin = (const QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
163                                 sizeof(QUARTZ_REGMEDIATYPE) );
164                         pTypes ++;
165                 }
166
167                 /* FIXME - pPin->lpMedium */
168                 /* FIXME - pPin->clsPinCategory */
169
170                 pPin ++;
171         }
172
173         return pFilter;
174 }
175
176 static
177 BYTE* QUARTZ_RegFilterV2ToFilterData(
178         const REGFILTER2* pFilter, DWORD* pcbData )
179 {
180         DWORD   cbData;
181         DWORD   cbPinData;
182         DWORD   cPins;
183         const REGFILTERPINS2*   pPin;
184         const REGPINTYPES*      pTypes;
185         BYTE*   pRet = NULL;
186         BYTE*   pDst;
187         QUARTZ_REGFILTERDATA*   pRegFilter;
188         QUARTZ_REGPINDATA*      pRegPin;
189         QUARTZ_REGMEDIATYPE*    pRegMediaType;
190         UINT    n;
191
192         if ( pFilter->dwVersion != 2 ) return NULL; /* FIXME */
193
194         cbData = sizeof(QUARTZ_REGFILTERDATA);
195         cPins = pFilter->u.s2.cPins2;
196         pPin = pFilter->u.s2.rgPins2;
197         if ( cPins > 10 ) return NULL; /* FIXME */
198
199         cbPinData = 0;
200         while ( cPins-- > 0 )
201         {
202                 if ( pPin->cInstances != 0 ||
203                          pPin->nMediaTypes > 10 ||
204                          pPin->nMediums != 0 ||
205                          pPin->clsPinCategory != 0 )
206                 {
207                         FIXME( "not implemented.\n" );
208                         return NULL; /* FIXME */
209                 }
210
211                 cbPinData += sizeof(QUARTZ_REGPINDATA) +
212                         pPin->nMediaTypes * sizeof(QUARTZ_REGMEDIATYPE);
213                 cbData += pPin->nMediaTypes * (sizeof(GUID)*2);
214                 pPin ++;
215         }
216         cbData += cbPinData;
217         TRACE("cbData %lu, cbPinData %lu\n",cbData,cbPinData);
218
219         pRet = (BYTE*)QUARTZ_AllocMem( cbData );
220         if ( pRet == NULL ) return NULL;
221         ZeroMemory( pRet, cbData );
222         pDst = pRet;
223
224         pRegFilter = (QUARTZ_REGFILTERDATA*)pDst;
225         pDst += sizeof(QUARTZ_REGFILTERDATA);
226
227         pRegFilter->dwVersion = 2;
228         pRegFilter->dwMerit = pFilter->dwMerit;
229         pRegFilter->cPins = pFilter->u.s2.cPins2;
230
231         pRegPin = (QUARTZ_REGPINDATA*)pDst;
232         pDst += cbPinData;
233
234         pPin = pFilter->u.s2.rgPins2;
235         for ( cPins = 0; cPins < pFilter->u.s2.cPins2; cPins++ )
236         {
237                 pRegPin->id[0] = '0'+cPins;
238                 pRegPin->id[1] = 'p';
239                 pRegPin->id[2] = 'i';
240                 pRegPin->id[3] = '3';
241                 pRegPin->dwFlags = pPin->dwFlags; /* flags */
242                 pRegPin->cInstances = pPin->cInstances;
243                 pRegPin->nMediaTypes = pPin->nMediaTypes;
244                 pRegPin->nMediums = pPin->nMediums;
245                 pRegPin->nOfsClsPinCategory = 0; /* FIXME */
246
247                 pTypes = pPin->lpMediaType;
248                 pRegPin = (QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
249                         sizeof(QUARTZ_REGPINDATA) );
250                 for ( n = 0; n < pPin->nMediaTypes; n++ )
251                 {
252                         pRegMediaType = ((QUARTZ_REGMEDIATYPE*)pRegPin);
253
254                         pRegMediaType->id[0] = '0'+n;
255                         pRegMediaType->id[1] = 't';
256                         pRegMediaType->id[2] = 'y';
257                         pRegMediaType->id[3] = '3';
258
259                         /* FIXME - CLSID should be shared. */
260                         pRegMediaType->nOfsMajorType = pDst - pRet;
261                         memcpy( pDst, pTypes->clsMajorType, sizeof(GUID) );
262                         pDst += sizeof(GUID);
263                         pRegMediaType->nOfsMinorType = pDst - pRet;
264                         memcpy( pDst, pTypes->clsMinorType, sizeof(GUID) );
265                         pDst += sizeof(GUID);
266
267                         pRegPin = (QUARTZ_REGPINDATA*)( ((const BYTE*)pRegPin) +
268                                 sizeof(QUARTZ_REGMEDIATYPE) );
269                         pTypes ++;
270                 }
271                 pPin ++;
272         }
273
274         *pcbData = pDst - pRet;
275         TRACE("cbData %lu/%lu\n",*pcbData,cbData);
276
277         return pRet;
278 }
279
280 static
281 REGFILTER2* QUARTZ_RegFilterV1ToV2( const REGFILTER2* prfV1 )
282 {
283         REGFILTER2*     prfV2;
284         const REGFILTERPINS*    pPinV1;
285         REGFILTERPINS2* pPinV2;
286         DWORD   cPins;
287
288         if ( prfV1->dwVersion != 1 ) return NULL;
289
290         prfV2 = (REGFILTER2*)QUARTZ_AllocMem(
291                 sizeof(REGFILTER2) + sizeof(REGFILTERPINS2) * prfV1->u.s1.cPins );
292         if ( prfV2 == NULL ) return NULL;
293         ZeroMemory( prfV2, sizeof(REGFILTER2) + sizeof(REGFILTERPINS2) * prfV1->u.s1.cPins );
294         pPinV1 = prfV1->u.s1.rgPins;
295         pPinV2 = (REGFILTERPINS2*)(prfV2+1);
296         prfV2->dwVersion = 2;
297         prfV2->dwMerit = prfV1->dwMerit;
298         prfV2->u.s2.cPins2 = prfV1->u.s1.cPins;
299         prfV2->u.s2.rgPins2 = pPinV2;
300
301         cPins = prfV1->u.s1.cPins;
302         while ( cPins-- > 0 )
303         {
304                 pPinV2->dwFlags = 0;
305                 pPinV2->cInstances = 0;
306                 pPinV2->nMediaTypes = pPinV1->nMediaTypes;
307                 pPinV2->lpMediaType = pPinV1->lpMediaType;
308                 pPinV2->nMediums = 0;
309                 pPinV2->lpMedium = NULL;
310                 pPinV2->clsPinCategory = NULL;
311
312                 if ( pPinV1->bRendered )
313                         pPinV2->dwFlags |= REG_PINFLAG_B_RENDERER;
314                 if ( pPinV1->bOutput )
315                         pPinV2->dwFlags |= REG_PINFLAG_B_OUTPUT;
316                 if ( pPinV1->bZero )
317                         pPinV2->dwFlags |= REG_PINFLAG_B_ZERO;
318                 if ( pPinV1->bMany )
319                         pPinV2->dwFlags |= REG_PINFLAG_B_MANY;
320
321                 pPinV1 ++;
322                 pPinV2 ++;
323         }
324
325         return prfV2;
326 }
327
328 static
329 BYTE* QUARTZ_RegFilterToFilterData(
330         const REGFILTER2* pFilter, DWORD* pcbData )
331 {
332         REGFILTER2*     prfV2;
333         BYTE*   pRet = NULL;
334
335         *pcbData = 0;
336         switch ( pFilter->dwVersion )
337         {
338         case 1:
339                 prfV2 = QUARTZ_RegFilterV1ToV2( pFilter );
340                 if ( prfV2 != NULL )
341                 {
342                         pRet = QUARTZ_RegFilterV2ToFilterData( prfV2, pcbData );
343                         QUARTZ_FreeMem( prfV2 );
344                 }
345                 break;
346         case 2:
347                 pRet = QUARTZ_RegFilterV2ToFilterData( pFilter, pcbData );
348                 break;
349         default:
350                 FIXME( "unknown REGFILTER2 version - %08lu\n", pFilter->dwVersion );
351                 break;
352         }
353
354         return pRet;
355 }
356
357 /***************************************************************************/
358
359 static
360 BOOL QUARTZ_CheckPinType( BOOL bExactMatch, const REGFILTERPINS2* pPin, DWORD cTypes, const GUID* pTypes, const REGPINMEDIUM* pMedium, const CLSID* pCategory, BOOL bRender )
361 {
362         DWORD   n1, n2;
363         BOOL    bMatch;
364
365         if ( cTypes > 0 && pTypes != NULL )
366         {
367                 bMatch = FALSE;
368                 for ( n1 = 0; n1 < pPin->nMediaTypes; n1++ )
369                 {
370                         for ( n2 = 0; n2 < cTypes; n2++ )
371                         {
372                                 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)) )
373                                 {
374                                         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)) )
375                                         {
376                                                 bMatch = TRUE;
377                                                 break;
378                                         }
379                                 }
380                         }
381                 }
382                 TRACE("Check media type %d\n",(int)bMatch);
383                 if ( !bMatch )
384                         return FALSE;
385         }
386
387         if ( pMedium != NULL )
388         {
389                 bMatch = FALSE;
390                 for ( n1 = 0; n1 < pPin->nMediums; n1++ )
391                 {
392                         if ( IsEqualGUID( &pPin->lpMedium[n1].clsMedium, &pMedium->clsMedium ) && pPin->lpMedium[n1].dw1 == pMedium->dw1 && pPin->lpMedium[n1].dw2 == pMedium->dw2 )
393                         {
394                                 bMatch = TRUE;
395                                 break;
396                         }
397                 }
398                 TRACE("Check medium %d\n",(int)bMatch);
399                 if ( !bMatch )
400                         return FALSE;
401         }
402
403         if ( pCategory != NULL )
404         {
405                 if ( pPin->clsPinCategory == NULL )
406                         return FALSE;
407                 if ( (!bExactMatch && IsEqualGUID(pCategory,&GUID_NULL)) || IsEqualGUID(pCategory,pPin->clsPinCategory) )
408                         return TRUE;
409                 return FALSE;
410         }
411
412         if ( bRender && (!(pPin->dwFlags & REG_PINFLAG_B_RENDERER)) )
413         {
414                 TRACE("not a renderer\n");
415                 return FALSE;
416         }
417
418         return TRUE;
419 }
420
421
422
423
424 /***************************************************************************
425  *
426  *      new/delete for CLSID_FilterMapper
427  *
428  */
429
430 /* can I use offsetof safely? - FIXME? */
431 static QUARTZ_IFEntry FMapIFEntries[] =
432 {
433   { &IID_IFilterMapper, offsetof(CFilterMapper,fmap)-offsetof(CFilterMapper,unk) },
434 };
435
436
437 static void QUARTZ_DestroyFilterMapper(IUnknown* punk)
438 {
439         CFilterMapper_THIS(punk,unk);
440
441         CFilterMapper_UninitIFilterMapper( This );
442 }
443
444 HRESULT QUARTZ_CreateFilterMapper(IUnknown* punkOuter,void** ppobj)
445 {
446         CFilterMapper*  pfm;
447         HRESULT hr;
448
449         TRACE("(%p,%p)\n",punkOuter,ppobj);
450
451         pfm = (CFilterMapper*)QUARTZ_AllocObj( sizeof(CFilterMapper) );
452         if ( pfm == NULL )
453                 return E_OUTOFMEMORY;
454
455         QUARTZ_IUnkInit( &pfm->unk, punkOuter );
456         hr = CFilterMapper_InitIFilterMapper( pfm );
457         if ( FAILED(hr) )
458         {
459                 QUARTZ_FreeObj( pfm );
460                 return hr;
461         }
462
463         pfm->unk.pEntries = FMapIFEntries;
464         pfm->unk.dwEntries = sizeof(FMapIFEntries)/sizeof(FMapIFEntries[0]);
465         pfm->unk.pOnFinalRelease = QUARTZ_DestroyFilterMapper;
466
467         *ppobj = (void*)(&pfm->unk);
468
469         return S_OK;
470 }
471
472 /***************************************************************************
473  *
474  *      CLSID_FilterMapper::IFilterMapper
475  *
476  */
477
478 static HRESULT WINAPI
479 IFilterMapper_fnQueryInterface(IFilterMapper* iface,REFIID riid,void** ppobj)
480 {
481         CFilterMapper_THIS(iface,fmap);
482
483         TRACE("(%p)->()\n",This);
484
485         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
486 }
487
488 static ULONG WINAPI
489 IFilterMapper_fnAddRef(IFilterMapper* iface)
490 {
491         CFilterMapper_THIS(iface,fmap);
492
493         TRACE("(%p)->()\n",This);
494
495         return IUnknown_AddRef(This->unk.punkControl);
496 }
497
498 static ULONG WINAPI
499 IFilterMapper_fnRelease(IFilterMapper* iface)
500 {
501         CFilterMapper_THIS(iface,fmap);
502
503         TRACE("(%p)->()\n",This);
504
505         return IUnknown_Release(This->unk.punkControl);
506 }
507
508
509 static HRESULT WINAPI
510 IFilterMapper_fnRegisterFilter(IFilterMapper* iface,CLSID clsid,LPCWSTR lpwszName,DWORD dwMerit)
511 {
512         CFilterMapper_THIS(iface,fmap);
513
514         FIXME("(%p)->(%s,%s,%08lx)\n",This,
515                 debugstr_guid(&clsid),debugstr_w(lpwszName),dwMerit);
516
517         /* FIXME */
518         /* FIXME - handle dwMerit! */
519         return QUARTZ_RegisterAMovieFilter(
520                 &CLSID_LegacyAmFilterCategory,
521                 &clsid,
522                 NULL, 0,
523                 lpwszName, NULL, TRUE );
524 }
525
526 static HRESULT WINAPI
527 IFilterMapper_fnRegisterFilterInstance(IFilterMapper* iface,CLSID clsid,LPCWSTR lpwszName,CLSID* pclsidMedia)
528 {
529         CFilterMapper_THIS(iface,fmap);
530         HRESULT hr;
531
532         FIXME("(%p)->()\n",This);
533
534         if ( pclsidMedia == NULL )
535                 return E_POINTER;
536         hr = CoCreateGuid(pclsidMedia);
537         if ( FAILED(hr) )
538                 return hr;
539
540         /* FIXME */
541         /* this doesn't work. */
542         /* return IFilterMapper_RegisterFilter(iface,
543                 *pclsidMedia,lpwszName,0x60000000); */
544
545         return E_NOTIMPL;
546 }
547
548 static HRESULT WINAPI
549 IFilterMapper_fnRegisterPin(IFilterMapper* iface,CLSID clsidFilter,LPCWSTR lpwszName,BOOL bRendered,BOOL bOutput,BOOL bZero,BOOL bMany,CLSID clsidReserved,LPCWSTR lpwszReserved)
550 {
551         CFilterMapper_THIS(iface,fmap);
552
553         FIXME("(%p)->() stub!\n",This);
554
555         return E_NOTIMPL;
556 }
557
558 static HRESULT WINAPI
559 IFilterMapper_fnRegisterPinType(IFilterMapper* iface,CLSID clsidFilter,LPCWSTR lpwszName,CLSID clsidMajorType,CLSID clsidSubType)
560 {
561         CFilterMapper_THIS(iface,fmap);
562
563         FIXME("(%p)->() stub!\n",This);
564
565         return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI
569 IFilterMapper_fnUnregisterFilter(IFilterMapper* iface,CLSID clsidFilter)
570 {
571         CFilterMapper_THIS(iface,fmap);
572
573         FIXME("(%p)->(%s)\n",This,debugstr_guid(&clsidFilter));
574
575         /* FIXME */
576         return QUARTZ_RegisterAMovieFilter(
577                 &CLSID_LegacyAmFilterCategory,
578                 &clsidFilter,
579                 NULL, 0, NULL, NULL, FALSE );
580 }
581
582 static HRESULT WINAPI
583 IFilterMapper_fnUnregisterFilterInstance(IFilterMapper* iface,CLSID clsidMedia)
584 {
585         CFilterMapper_THIS(iface,fmap);
586
587         FIXME("(%p)->(%s)\n",This,debugstr_guid(&clsidMedia));
588
589         /* FIXME */
590         /* this doesn't work. */
591         /* return IFilterMapper_UnregisterFilter(iface,clsidMedia); */
592
593         return E_NOTIMPL;
594 }
595
596 static HRESULT WINAPI
597 IFilterMapper_fnUnregisterPin(IFilterMapper* iface,CLSID clsidPin,LPCWSTR lpwszName)
598 {
599         CFilterMapper_THIS(iface,fmap);
600
601         FIXME("(%p)->(%s,%s) stub!\n",This,
602                 debugstr_guid(&clsidPin),debugstr_w(lpwszName));
603
604         return E_NOTIMPL;
605 }
606
607 static HRESULT WINAPI
608 IFilterMapper_fnEnumMatchingFilters(IFilterMapper* iface,IEnumRegFilters** ppobj,DWORD dwMerit,BOOL bInputNeeded,CLSID clsInMajorType,CLSID clsidSubType,BOOL bRender,BOOL bOutputNeeded,CLSID clsOutMajorType,CLSID clsOutSubType)
609 {
610         CFilterMapper_THIS(iface,fmap);
611
612         FIXME("(%p)->() stub!\n",This);
613
614         return E_NOTIMPL;
615 }
616
617
618
619 static ICOM_VTABLE(IFilterMapper) ifmap =
620 {
621         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
622         /* IUnknown fields */
623         IFilterMapper_fnQueryInterface,
624         IFilterMapper_fnAddRef,
625         IFilterMapper_fnRelease,
626         /* IFilterMapper fields */
627         IFilterMapper_fnRegisterFilter,
628         IFilterMapper_fnRegisterFilterInstance,
629         IFilterMapper_fnRegisterPin,
630         IFilterMapper_fnRegisterPinType,
631         IFilterMapper_fnUnregisterFilter,
632         IFilterMapper_fnUnregisterFilterInstance,
633         IFilterMapper_fnUnregisterPin,
634         IFilterMapper_fnEnumMatchingFilters,
635 };
636
637
638 HRESULT CFilterMapper_InitIFilterMapper( CFilterMapper* pfm )
639 {
640         TRACE("(%p)\n",pfm);
641         ICOM_VTBL(&pfm->fmap) = &ifmap;
642
643         return NOERROR;
644 }
645
646 void CFilterMapper_UninitIFilterMapper( CFilterMapper* pfm )
647 {
648         TRACE("(%p)\n",pfm);
649 }
650
651
652 /***************************************************************************
653  *
654  *      new/delete for CLSID_FilterMapper2
655  *
656  */
657
658 /* can I use offsetof safely? - FIXME? */
659 static QUARTZ_IFEntry FMap2IFEntries[] =
660 {
661   { &IID_IFilterMapper2, offsetof(CFilterMapper2,fmap2)-offsetof(CFilterMapper2,unk) },
662 };
663
664
665 static void QUARTZ_DestroyFilterMapper2(IUnknown* punk)
666 {
667         CFilterMapper2_THIS(punk,unk);
668
669         CFilterMapper2_UninitIFilterMapper2( This );
670 }
671
672 HRESULT QUARTZ_CreateFilterMapper2(IUnknown* punkOuter,void** ppobj)
673 {
674         CFilterMapper2* pfm;
675         HRESULT hr;
676
677         TRACE("(%p,%p)\n",punkOuter,ppobj);
678
679         pfm = (CFilterMapper2*)QUARTZ_AllocObj( sizeof(CFilterMapper2) );
680         if ( pfm == NULL )
681                 return E_OUTOFMEMORY;
682
683         QUARTZ_IUnkInit( &pfm->unk, punkOuter );
684         hr = CFilterMapper2_InitIFilterMapper2( pfm );
685         if ( FAILED(hr) )
686         {
687                 QUARTZ_FreeObj( pfm );
688                 return hr;
689         }
690
691         pfm->unk.pEntries = FMap2IFEntries;
692         pfm->unk.dwEntries = sizeof(FMap2IFEntries)/sizeof(FMap2IFEntries[0]);
693         pfm->unk.pOnFinalRelease = QUARTZ_DestroyFilterMapper2;
694
695         *ppobj = (void*)(&pfm->unk);
696
697         return S_OK;
698 }
699
700 /***************************************************************************
701  *
702  *      CLSID_FilterMapper2::IFilterMapper2
703  *
704  */
705
706
707 static HRESULT WINAPI
708 IFilterMapper2_fnQueryInterface(IFilterMapper2* iface,REFIID riid,void** ppobj)
709 {
710         CFilterMapper2_THIS(iface,fmap2);
711
712         TRACE("(%p)->()\n",This);
713
714         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
715 }
716
717 static ULONG WINAPI
718 IFilterMapper2_fnAddRef(IFilterMapper2* iface)
719 {
720         CFilterMapper2_THIS(iface,fmap2);
721
722         TRACE("(%p)->()\n",This);
723
724         return IUnknown_AddRef(This->unk.punkControl);
725 }
726
727 static ULONG WINAPI
728 IFilterMapper2_fnRelease(IFilterMapper2* iface)
729 {
730         CFilterMapper2_THIS(iface,fmap2);
731
732         TRACE("(%p)->()\n",This);
733
734         return IUnknown_Release(This->unk.punkControl);
735 }
736
737 static HRESULT WINAPI
738 IFilterMapper2_fnCreateCategory(IFilterMapper2* iface,REFCLSID rclsidCategory,DWORD dwMerit,LPCWSTR lpwszDesc)
739 {
740         CFilterMapper2_THIS(iface,fmap2);
741
742         FIXME("(%p)->(%s,%lu,%s) stub!\n",This,
743                 debugstr_guid(rclsidCategory),
744                 (unsigned long)dwMerit,debugstr_w(lpwszDesc));
745
746         return E_NOTIMPL;
747 }
748
749
750 static HRESULT WINAPI
751 IFilterMapper2_fnUnregisterFilter(IFilterMapper2* iface,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,REFCLSID rclsidFilter)
752 {
753         CFilterMapper2_THIS(iface,fmap2);
754         WCHAR*  pwszPath = NULL;
755         HRESULT hr;
756
757         TRACE("(%p)->(%s,%s,%s)\n",This,
758                 debugstr_guid(pclsidCategory),
759                 debugstr_w(lpwszInst),
760                 debugstr_guid(rclsidFilter));
761
762         if ( pclsidCategory == NULL )
763                 pclsidCategory = &CLSID_LegacyAmFilterCategory;
764
765         hr = QUARTZ_GetFilterRegPath(
766                 &pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
767         if ( FAILED(hr) )
768                 return hr;
769
770         hr = QUARTZ_RegDeleteKey(HKEY_CLASSES_ROOT,pwszPath);
771         QUARTZ_FreeMem(pwszPath);
772
773         return hr;
774 }
775
776
777 static HRESULT WINAPI
778 IFilterMapper2_fnRegisterFilter(IFilterMapper2* iface,REFCLSID rclsidFilter,LPCWSTR lpName,IMoniker** ppMoniker,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,const REGFILTER2* pRF2)
779 {
780         CFilterMapper2_THIS(iface,fmap2);
781         WCHAR*  pwszPath = NULL;
782         IMoniker*       pMoniker = NULL;
783         BYTE*   pFilterData = NULL;
784         DWORD   cbFilterData = 0;
785         HRESULT hr;
786
787         TRACE( "(%p)->(%s,%s,%p,%s,%s,%p) stub!\n",This,
788                 debugstr_guid(rclsidFilter),debugstr_w(lpName),
789                 ppMoniker,debugstr_guid(pclsidCategory),
790                 debugstr_w(lpwszInst),pRF2 );
791
792         if ( lpName == NULL || pRF2 == NULL )
793                 return E_POINTER;
794
795         if ( ppMoniker != NULL && *ppMoniker != NULL )
796         {
797                 FIXME( "ppMoniker != NULL - not implemented! *ppMoniker = %p\n",*ppMoniker );
798                 return E_NOTIMPL;
799         }
800
801         if ( pclsidCategory == NULL )
802                 pclsidCategory = &CLSID_LegacyAmFilterCategory;
803
804         if ( pMoniker == NULL )
805         {
806                 hr = QUARTZ_GetFilterRegPath(
807                         &pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
808                 if ( FAILED(hr) )
809                         return hr;
810                 hr = QUARTZ_CreateDeviceMoniker(
811                         HKEY_CLASSES_ROOT,pwszPath,&pMoniker);
812                 QUARTZ_FreeMem(pwszPath);
813                 if ( FAILED(hr) )
814                         return hr;
815         }
816
817         pFilterData = QUARTZ_RegFilterToFilterData( pRF2, &cbFilterData );
818         if ( pFilterData == NULL || cbFilterData == 0 )
819         {
820                 hr = E_FAIL;
821                 goto err;
822         }
823
824         hr = QUARTZ_RegisterFilterToMoniker(
825                 pMoniker, rclsidFilter, lpName, pFilterData, cbFilterData );
826         if ( FAILED(hr) )
827                 goto err;
828
829         if ( ppMoniker != NULL )
830         {
831                 *ppMoniker = pMoniker;
832                 pMoniker = NULL;
833         }
834 err:
835         if ( pFilterData != NULL )
836                 QUARTZ_FreeMem(pFilterData);
837         if ( pMoniker != NULL )
838                 IMoniker_Release(pMoniker);
839
840         return hr;
841 }
842
843
844 static HRESULT WINAPI
845 IFilterMapper2_fnEnumMatchingFilters(IFilterMapper2* iface,
846         IEnumMoniker** ppEnumMoniker,DWORD dwFlags,BOOL bExactMatch,DWORD dwMerit,
847         BOOL bInputNeeded,DWORD cInputTypes,const GUID* pguidInputTypes,const REGPINMEDIUM* pPinMediumIn,const CLSID* pPinCategoryIn,BOOL bRender,
848         BOOL bOutputNeeded,DWORD cOutputTypes,const GUID* pguidOutputTypes,const REGPINMEDIUM* pPinMediumOut,const CLSID* pPinCategoryOut)
849 {
850         CFilterMapper2_THIS(iface,fmap2);
851         ICreateDevEnum* pEnum = NULL;
852         IEnumMoniker*   pCategories = NULL;
853         IMoniker*       pCat = NULL;
854         DWORD   dwCatMerit;
855         IEnumMoniker*   pCatFilters = NULL;
856         IMoniker*       pFilter = NULL;
857         CLSID   clsid;
858         ULONG   cReturned;
859         BYTE*   pbFilterData = NULL;
860         DWORD   cbFilterData = 0;
861         REGFILTER2*     prf2 = NULL;
862         QUARTZ_CompList*        pList = NULL;
863         const REGFILTERPINS2*   pRegFilterPin;
864         DWORD   n;
865         BOOL    bMatch;
866         HRESULT hr;
867
868         FIXME("(%p)->(%p,%08lx,%d,%08lx,%d,%lu,%p,%p,%p,%d,%d,%lu,%p,%p,%p)\n",This,ppEnumMoniker,dwFlags,bExactMatch,dwMerit,bInputNeeded,cInputTypes,pguidInputTypes,pPinMediumIn,pPinCategoryIn,bRender,bOutputNeeded,cOutputTypes,pguidOutputTypes,pPinMediumOut,pPinCategoryOut);
869
870         if ( ppEnumMoniker == NULL )
871                 return E_POINTER;
872         *ppEnumMoniker = NULL;
873         if ( dwFlags != 0 )
874                 return E_INVALIDARG;
875
876         hr = CoCreateInstance(
877                 &CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
878                 &IID_ICreateDevEnum, (void**)&pEnum );
879         if ( FAILED(hr) )
880                 goto err;
881
882         hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&CLSID_ActiveMovieCategories,&pCategories,0);
883         if ( hr != S_OK )
884                 goto err;
885
886         while ( 1 )
887         {
888                 if ( pCat != NULL )
889                 {
890                         IMoniker_Release(pCat);
891                         pCat = NULL;
892                 }
893                 hr = IEnumMoniker_Next(pCategories,1,&pCat,&cReturned);
894                 if ( FAILED(hr) )
895                         goto err;
896                 if ( hr != S_OK )
897                         break;
898                 hr = QUARTZ_GetMeritFromMoniker(pCat,&dwCatMerit);
899                 if ( hr != S_OK || dwMerit > dwCatMerit )
900                         continue;
901                 hr = QUARTZ_GetCLSIDFromMoniker(pCat,&clsid);
902                 if ( hr != S_OK )
903                         continue;
904
905                 if ( pCatFilters != NULL )
906                 {
907                         IEnumMoniker_Release(pCatFilters);
908                         pCatFilters = NULL;
909                 }
910                 hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&clsid,&pCatFilters,0);
911                 if ( FAILED(hr) )
912                         goto err;
913                 if ( hr != S_OK )
914                         continue;
915
916                 while ( 1 )
917                 {
918                         if ( pFilter != NULL )
919                         {
920                                 IMoniker_Release(pFilter);
921                                 pFilter = NULL;
922                         }
923                         hr = IEnumMoniker_Next(pCatFilters,1,&pFilter,&cReturned);
924                         if ( FAILED(hr) )
925                                 goto err;
926                         if ( hr != S_OK )
927                                 break;
928                         if ( pbFilterData != NULL )
929                         {
930                                 QUARTZ_FreeMem(pbFilterData);
931                                 pbFilterData = NULL;
932                         }
933                         if(TRACE_ON(quartz))
934                         {
935                                 CLSID clsidTrace;
936                                 if (SUCCEEDED(QUARTZ_GetCLSIDFromMoniker(pFilter,&clsidTrace)))
937                                 {
938                                         TRACE("moniker clsid %s\n",debugstr_guid(&clsidTrace));
939                                 }
940                         }
941                         hr = QUARTZ_GetFilterDataFromMoniker(pFilter,&pbFilterData,&cbFilterData);
942                         if ( hr != S_OK )
943                                 continue;
944
945                         if ( prf2 != NULL )
946                         {
947                                 QUARTZ_FreeMem(prf2);
948                                 prf2 = NULL;
949                         }
950                         prf2 = QUARTZ_RegFilterV2FromFilterData(pbFilterData,cbFilterData);
951                         if ( prf2 == NULL )
952                                 continue;
953                         TRACE("prf2 %p, Merit %08lx\n",prf2,prf2->dwMerit);
954                         if ( prf2->dwMerit < dwMerit || prf2->dwVersion != 2 )
955                                 continue;
956
957                         /* check input pins. */
958                         if ( bInputNeeded )
959                         {
960                                 bMatch = FALSE;
961                                 for ( n = 0; n < prf2->u.s2.cPins2; n++ )
962                                 {
963                                         pRegFilterPin = &prf2->u.s2.rgPins2[n];
964                                         if ( pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT )
965                                                 continue;
966                                         bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cInputTypes, pguidInputTypes, pPinMediumIn, pPinCategoryIn, bRender );
967                                         if ( bMatch )
968                                                 break;
969                                 }
970                                 if ( !bMatch )
971                                 {
972                                         TRACE("no matching input pin\n");
973                                         continue;
974                                 }
975                         }
976
977                         /* check output pins. */
978                         if ( bOutputNeeded )
979                         {
980                                 bMatch = FALSE;
981                                 for ( n = 0; n < prf2->u.s2.cPins2; n++ )
982                                 {
983                                         pRegFilterPin = &prf2->u.s2.rgPins2[n];
984                                         if ( !(pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT) )
985                                                 continue;
986                                         bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cOutputTypes, pguidOutputTypes, pPinMediumOut, pPinCategoryOut, FALSE );
987                                         if ( bMatch )
988                                                 break;
989                                 }
990                                 if ( !bMatch )
991                                 {
992                                         TRACE("no matching output pin\n");
993                                         continue;
994                                 }
995                         }
996
997                         /* matched - add pFilter to the list. */
998                         if ( pList == NULL )
999                         {
1000                                 pList = QUARTZ_CompList_Alloc();
1001                                 if ( pList == NULL )
1002                                 {
1003                                         hr = E_OUTOFMEMORY;
1004                                         goto err;
1005                                 }
1006                         }
1007                         TRACE("matched\n");
1008                         hr = QUARTZ_CompList_AddComp(
1009                                 pList, (IUnknown*)pFilter, NULL, 0 );
1010                         if ( FAILED(hr) )
1011                                 goto err;
1012                 }
1013         }
1014
1015         if ( pList == NULL )
1016         {
1017                 hr = S_FALSE;
1018                 goto err;
1019         }
1020
1021         FIXME("create IEnumMoniker - not sorted\n");
1022         /* FIXME - should be sorted?(in Merit order) */
1023         hr = QUARTZ_CreateEnumUnknown( &IID_IEnumMoniker, (void**)ppEnumMoniker, pList );
1024         if ( FAILED(hr) )
1025                 goto err;
1026
1027         hr = S_OK;
1028 err:
1029         if ( pEnum != NULL )
1030                 ICreateDevEnum_Release(pEnum);
1031         if ( pCategories != NULL )
1032                 IEnumMoniker_Release(pCategories);
1033         if ( pCat != NULL )
1034                 IMoniker_Release(pCat);
1035         if ( pCatFilters != NULL )
1036                 IEnumMoniker_Release(pCatFilters);
1037         if ( pFilter != NULL )
1038                 IMoniker_Release(pFilter);
1039         if ( pbFilterData != NULL )
1040                 QUARTZ_FreeMem(pbFilterData);
1041         if ( prf2 != NULL )
1042                 QUARTZ_FreeMem(prf2);
1043         if ( pList != NULL )
1044                 QUARTZ_CompList_Free( pList );
1045
1046         TRACE("returns %08lx\n",hr);
1047
1048         return hr;
1049 }
1050
1051
1052
1053
1054 static ICOM_VTABLE(IFilterMapper2) ifmap2 =
1055 {
1056         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1057         /* IUnknown fields */
1058         IFilterMapper2_fnQueryInterface,
1059         IFilterMapper2_fnAddRef,
1060         IFilterMapper2_fnRelease,
1061         /* IFilterMapper2 fields */
1062         IFilterMapper2_fnCreateCategory,
1063         IFilterMapper2_fnUnregisterFilter,
1064         IFilterMapper2_fnRegisterFilter,
1065         IFilterMapper2_fnEnumMatchingFilters,
1066 };
1067
1068
1069 HRESULT CFilterMapper2_InitIFilterMapper2( CFilterMapper2* pfm )
1070 {
1071         TRACE("(%p)\n",pfm);
1072         ICOM_VTBL(&pfm->fmap2) = &ifmap2;
1073
1074         return NOERROR;
1075 }
1076
1077 void CFilterMapper2_UninitIFilterMapper2( CFilterMapper2* pfm )
1078 {
1079         TRACE("(%p)\n",pfm);
1080 }
1081