Update shell xxxAW wrapper prototypes for fixed SHLWAPI functions.
[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,fmap3)-offsetof(CFilterMapper2,unk) },
662   { &IID_IFilterMapper3, offsetof(CFilterMapper2,fmap3)-offsetof(CFilterMapper2,unk) },
663 };
664
665
666 static void QUARTZ_DestroyFilterMapper2(IUnknown* punk)
667 {
668         CFilterMapper2_THIS(punk,unk);
669
670         CFilterMapper2_UninitIFilterMapper3( This );
671 }
672
673 HRESULT QUARTZ_CreateFilterMapper2(IUnknown* punkOuter,void** ppobj)
674 {
675         CFilterMapper2* pfm;
676         HRESULT hr;
677
678         TRACE("(%p,%p)\n",punkOuter,ppobj);
679
680         pfm = (CFilterMapper2*)QUARTZ_AllocObj( sizeof(CFilterMapper2) );
681         if ( pfm == NULL )
682                 return E_OUTOFMEMORY;
683
684         QUARTZ_IUnkInit( &pfm->unk, punkOuter );
685         hr = CFilterMapper2_InitIFilterMapper3( pfm );
686         if ( FAILED(hr) )
687         {
688                 QUARTZ_FreeObj( pfm );
689                 return hr;
690         }
691
692         pfm->unk.pEntries = FMap2IFEntries;
693         pfm->unk.dwEntries = sizeof(FMap2IFEntries)/sizeof(FMap2IFEntries[0]);
694         pfm->unk.pOnFinalRelease = QUARTZ_DestroyFilterMapper2;
695
696         *ppobj = (void*)(&pfm->unk);
697
698         return S_OK;
699 }
700
701 /***************************************************************************
702  *
703  *      CLSID_FilterMapper2::IFilterMapper3
704  *
705  */
706
707
708 static HRESULT WINAPI
709 IFilterMapper3_fnQueryInterface(IFilterMapper3* iface,REFIID riid,void** ppobj)
710 {
711         CFilterMapper2_THIS(iface,fmap3);
712
713         TRACE("(%p)->()\n",This);
714
715         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
716 }
717
718 static ULONG WINAPI
719 IFilterMapper3_fnAddRef(IFilterMapper3* iface)
720 {
721         CFilterMapper2_THIS(iface,fmap3);
722
723         TRACE("(%p)->()\n",This);
724
725         return IUnknown_AddRef(This->unk.punkControl);
726 }
727
728 static ULONG WINAPI
729 IFilterMapper3_fnRelease(IFilterMapper3* iface)
730 {
731         CFilterMapper2_THIS(iface,fmap3);
732
733         TRACE("(%p)->()\n",This);
734
735         return IUnknown_Release(This->unk.punkControl);
736 }
737
738 static HRESULT WINAPI
739 IFilterMapper3_fnCreateCategory(IFilterMapper3* iface,REFCLSID rclsidCategory,DWORD dwMerit,LPCWSTR lpwszDesc)
740 {
741         CFilterMapper2_THIS(iface,fmap3);
742
743         FIXME("(%p)->(%s,%lu,%s) stub!\n",This,
744                 debugstr_guid(rclsidCategory),
745                 (unsigned long)dwMerit,debugstr_w(lpwszDesc));
746
747         return E_NOTIMPL;
748 }
749
750
751 static HRESULT WINAPI
752 IFilterMapper3_fnUnregisterFilter(IFilterMapper3* iface,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,REFCLSID rclsidFilter)
753 {
754         CFilterMapper2_THIS(iface,fmap3);
755         WCHAR*  pwszPath = NULL;
756         HRESULT hr;
757
758         TRACE("(%p)->(%s,%s,%s)\n",This,
759                 debugstr_guid(pclsidCategory),
760                 debugstr_w(lpwszInst),
761                 debugstr_guid(rclsidFilter));
762
763         if ( pclsidCategory == NULL )
764                 pclsidCategory = &CLSID_LegacyAmFilterCategory;
765
766         hr = QUARTZ_GetFilterRegPath(
767                 &pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
768         if ( FAILED(hr) )
769                 return hr;
770
771         hr = QUARTZ_RegDeleteKey(HKEY_CLASSES_ROOT,pwszPath);
772         QUARTZ_FreeMem(pwszPath);
773
774         return hr;
775 }
776
777
778 static HRESULT WINAPI
779 IFilterMapper3_fnRegisterFilter(IFilterMapper3* iface,REFCLSID rclsidFilter,LPCWSTR lpName,IMoniker** ppMoniker,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,const REGFILTER2* pRF2)
780 {
781         CFilterMapper2_THIS(iface,fmap3);
782         WCHAR*  pwszPath = NULL;
783         IMoniker*       pMoniker = NULL;
784         BYTE*   pFilterData = NULL;
785         DWORD   cbFilterData = 0;
786         HRESULT hr;
787
788         TRACE( "(%p)->(%s,%s,%p,%s,%s,%p) stub!\n",This,
789                 debugstr_guid(rclsidFilter),debugstr_w(lpName),
790                 ppMoniker,debugstr_guid(pclsidCategory),
791                 debugstr_w(lpwszInst),pRF2 );
792
793         if ( lpName == NULL || pRF2 == NULL )
794                 return E_POINTER;
795
796         if ( ppMoniker != NULL && *ppMoniker != NULL )
797         {
798                 FIXME( "ppMoniker != NULL - not implemented! *ppMoniker = %p\n",*ppMoniker );
799                 return E_NOTIMPL;
800         }
801
802         if ( pclsidCategory == NULL )
803                 pclsidCategory = &CLSID_LegacyAmFilterCategory;
804
805         if ( pMoniker == NULL )
806         {
807                 hr = QUARTZ_GetFilterRegPath(
808                         &pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
809                 if ( FAILED(hr) )
810                         return hr;
811                 hr = QUARTZ_CreateDeviceMoniker(
812                         HKEY_CLASSES_ROOT,pwszPath,&pMoniker);
813                 QUARTZ_FreeMem(pwszPath);
814                 if ( FAILED(hr) )
815                         return hr;
816         }
817
818         pFilterData = QUARTZ_RegFilterToFilterData( pRF2, &cbFilterData );
819         if ( pFilterData == NULL || cbFilterData == 0 )
820         {
821                 hr = E_FAIL;
822                 goto err;
823         }
824
825         hr = QUARTZ_RegisterFilterToMoniker(
826                 pMoniker, rclsidFilter, lpName, pFilterData, cbFilterData );
827         if ( FAILED(hr) )
828                 goto err;
829
830         if ( ppMoniker != NULL )
831         {
832                 *ppMoniker = pMoniker;
833                 pMoniker = NULL;
834         }
835 err:
836         if ( pFilterData != NULL )
837                 QUARTZ_FreeMem(pFilterData);
838         if ( pMoniker != NULL )
839                 IMoniker_Release(pMoniker);
840
841         return hr;
842 }
843
844
845 static HRESULT WINAPI
846 IFilterMapper3_fnEnumMatchingFilters(IFilterMapper3* iface,
847         IEnumMoniker** ppEnumMoniker,DWORD dwFlags,BOOL bExactMatch,DWORD dwMerit,
848         BOOL bInputNeeded,DWORD cInputTypes,const GUID* pguidInputTypes,const REGPINMEDIUM* pPinMediumIn,const CLSID* pPinCategoryIn,BOOL bRender,
849         BOOL bOutputNeeded,DWORD cOutputTypes,const GUID* pguidOutputTypes,const REGPINMEDIUM* pPinMediumOut,const CLSID* pPinCategoryOut)
850 {
851         CFilterMapper2_THIS(iface,fmap3);
852         ICreateDevEnum* pEnum = NULL;
853         IEnumMoniker*   pCategories = NULL;
854         IMoniker*       pCat = NULL;
855         DWORD   dwCatMerit;
856         IEnumMoniker*   pCatFilters = NULL;
857         IMoniker*       pFilter = NULL;
858         CLSID   clsid;
859         ULONG   cReturned;
860         BYTE*   pbFilterData = NULL;
861         DWORD   cbFilterData = 0;
862         REGFILTER2*     prf2 = NULL;
863         QUARTZ_CompList*        pList = NULL;
864         const REGFILTERPINS2*   pRegFilterPin;
865         DWORD   n;
866         BOOL    bMatch;
867         HRESULT hr;
868
869         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);
870
871         if ( ppEnumMoniker == NULL )
872                 return E_POINTER;
873         *ppEnumMoniker = NULL;
874         if ( dwFlags != 0 )
875                 return E_INVALIDARG;
876
877         hr = CoCreateInstance(
878                 &CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
879                 &IID_ICreateDevEnum, (void**)&pEnum );
880         if ( FAILED(hr) )
881                 goto err;
882
883         hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&CLSID_ActiveMovieCategories,&pCategories,0);
884         if ( hr != S_OK )
885                 goto err;
886
887         while ( 1 )
888         {
889                 if ( pCat != NULL )
890                 {
891                         IMoniker_Release(pCat);
892                         pCat = NULL;
893                 }
894                 hr = IEnumMoniker_Next(pCategories,1,&pCat,&cReturned);
895                 if ( FAILED(hr) )
896                         goto err;
897                 if ( hr != S_OK )
898                         break;
899                 hr = QUARTZ_GetMeritFromMoniker(pCat,&dwCatMerit);
900                 if ( hr != S_OK || dwMerit > dwCatMerit )
901                         continue;
902                 hr = QUARTZ_GetCLSIDFromMoniker(pCat,&clsid);
903                 if ( hr != S_OK )
904                         continue;
905
906                 if ( pCatFilters != NULL )
907                 {
908                         IEnumMoniker_Release(pCatFilters);
909                         pCatFilters = NULL;
910                 }
911                 hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&clsid,&pCatFilters,0);
912                 if ( FAILED(hr) )
913                         goto err;
914                 if ( hr != S_OK )
915                         continue;
916
917                 while ( 1 )
918                 {
919                         if ( pFilter != NULL )
920                         {
921                                 IMoniker_Release(pFilter);
922                                 pFilter = NULL;
923                         }
924                         hr = IEnumMoniker_Next(pCatFilters,1,&pFilter,&cReturned);
925                         if ( FAILED(hr) )
926                                 goto err;
927                         if ( hr != S_OK )
928                                 break;
929                         if ( pbFilterData != NULL )
930                         {
931                                 QUARTZ_FreeMem(pbFilterData);
932                                 pbFilterData = NULL;
933                         }
934                         if(TRACE_ON(quartz))
935                         {
936                                 CLSID clsidTrace;
937                                 if (SUCCEEDED(QUARTZ_GetCLSIDFromMoniker(pFilter,&clsidTrace)))
938                                 {
939                                         TRACE("moniker clsid %s\n",debugstr_guid(&clsidTrace));
940                                 }
941                         }
942                         hr = QUARTZ_GetFilterDataFromMoniker(pFilter,&pbFilterData,&cbFilterData);
943                         if ( hr != S_OK )
944                                 continue;
945
946                         if ( prf2 != NULL )
947                         {
948                                 QUARTZ_FreeMem(prf2);
949                                 prf2 = NULL;
950                         }
951                         prf2 = QUARTZ_RegFilterV2FromFilterData(pbFilterData,cbFilterData);
952                         if ( prf2 == NULL )
953                                 continue;
954                         TRACE("prf2 %p, Merit %08lx\n",prf2,prf2->dwMerit);
955                         if ( prf2->dwMerit < dwMerit || prf2->dwVersion != 2 )
956                                 continue;
957
958                         /* check input pins. */
959                         if ( bInputNeeded )
960                         {
961                                 bMatch = FALSE;
962                                 for ( n = 0; n < prf2->u.s2.cPins2; n++ )
963                                 {
964                                         pRegFilterPin = &prf2->u.s2.rgPins2[n];
965                                         if ( pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT )
966                                                 continue;
967                                         bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cInputTypes, pguidInputTypes, pPinMediumIn, pPinCategoryIn, bRender );
968                                         if ( bMatch )
969                                                 break;
970                                 }
971                                 if ( !bMatch )
972                                 {
973                                         TRACE("no matching input pin\n");
974                                         continue;
975                                 }
976                         }
977
978                         /* check output pins. */
979                         if ( bOutputNeeded )
980                         {
981                                 bMatch = FALSE;
982                                 for ( n = 0; n < prf2->u.s2.cPins2; n++ )
983                                 {
984                                         pRegFilterPin = &prf2->u.s2.rgPins2[n];
985                                         if ( !(pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT) )
986                                                 continue;
987                                         bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cOutputTypes, pguidOutputTypes, pPinMediumOut, pPinCategoryOut, FALSE );
988                                         if ( bMatch )
989                                                 break;
990                                 }
991                                 if ( !bMatch )
992                                 {
993                                         TRACE("no matching output pin\n");
994                                         continue;
995                                 }
996                         }
997
998                         /* matched - add pFilter to the list. */
999                         if ( pList == NULL )
1000                         {
1001                                 pList = QUARTZ_CompList_Alloc();
1002                                 if ( pList == NULL )
1003                                 {
1004                                         hr = E_OUTOFMEMORY;
1005                                         goto err;
1006                                 }
1007                         }
1008                         TRACE("matched\n");
1009                         hr = QUARTZ_CompList_AddComp(
1010                                 pList, (IUnknown*)pFilter, NULL, 0 );
1011                         if ( FAILED(hr) )
1012                                 goto err;
1013                 }
1014         }
1015
1016         if ( pList == NULL )
1017         {
1018                 hr = S_FALSE;
1019                 goto err;
1020         }
1021
1022         FIXME("create IEnumMoniker - not sorted\n");
1023         /* FIXME - should be sorted?(in Merit order) */
1024         hr = QUARTZ_CreateEnumUnknown( &IID_IEnumMoniker, (void**)ppEnumMoniker, pList );
1025         if ( FAILED(hr) )
1026                 goto err;
1027
1028         hr = S_OK;
1029 err:
1030         if ( pEnum != NULL )
1031                 ICreateDevEnum_Release(pEnum);
1032         if ( pCategories != NULL )
1033                 IEnumMoniker_Release(pCategories);
1034         if ( pCat != NULL )
1035                 IMoniker_Release(pCat);
1036         if ( pCatFilters != NULL )
1037                 IEnumMoniker_Release(pCatFilters);
1038         if ( pFilter != NULL )
1039                 IMoniker_Release(pFilter);
1040         if ( pbFilterData != NULL )
1041                 QUARTZ_FreeMem(pbFilterData);
1042         if ( prf2 != NULL )
1043                 QUARTZ_FreeMem(prf2);
1044         if ( pList != NULL )
1045                 QUARTZ_CompList_Free( pList );
1046
1047         TRACE("returns %08lx\n",hr);
1048
1049         return hr;
1050 }
1051
1052 static HRESULT WINAPI
1053 IFilterMapper3_fnGetICreateDevEnum(IFilterMapper3* iface,ICreateDevEnum** ppDevEnum)
1054 {
1055         CFilterMapper2_THIS(iface,fmap3);
1056
1057         /* undocumented */
1058         FIXME("(%p)->() stub!\n",This);
1059
1060         return E_NOTIMPL;
1061 }
1062
1063
1064
1065
1066 static ICOM_VTABLE(IFilterMapper3) ifmap3 =
1067 {
1068         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1069         /* IUnknown fields */
1070         IFilterMapper3_fnQueryInterface,
1071         IFilterMapper3_fnAddRef,
1072         IFilterMapper3_fnRelease,
1073         /* IFilterMapper2 fields */
1074         IFilterMapper3_fnCreateCategory,
1075         IFilterMapper3_fnUnregisterFilter,
1076         IFilterMapper3_fnRegisterFilter,
1077         IFilterMapper3_fnEnumMatchingFilters,
1078         /* IFilterMapper3 fields */
1079         IFilterMapper3_fnGetICreateDevEnum,
1080 };
1081
1082
1083 HRESULT CFilterMapper2_InitIFilterMapper3( CFilterMapper2* pfm )
1084 {
1085         TRACE("(%p)\n",pfm);
1086         ICOM_VTBL(&pfm->fmap3) = &ifmap3;
1087
1088         return NOERROR;
1089 }
1090
1091 void CFilterMapper2_UninitIFilterMapper3( CFilterMapper2* pfm )
1092 {
1093         TRACE("(%p)\n",pfm);
1094 }
1095