Added LGPL standard comment, and copyright notices where necessary.
[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                 if ( !bMatch )
383                         return FALSE;
384         }
385
386         if ( pMedium != NULL )
387         {
388                 bMatch = FALSE;
389                 for ( n1 = 0; n1 < pPin->nMediums; n1++ )
390                 {
391                         if ( IsEqualGUID( &pPin->lpMedium[n1].clsMedium, &pMedium->clsMedium ) && pPin->lpMedium[n1].dw1 == pMedium->dw1 && pPin->lpMedium[n1].dw2 == pMedium->dw2 )
392                         {
393                                 bMatch = TRUE;
394                                 break;
395                         }
396                 }
397                 if ( !bMatch )
398                         return FALSE;
399         }
400
401         if ( pCategory != NULL )
402         {
403                 if ( pPin->clsPinCategory == NULL )
404                         return FALSE;
405                 if ( (!bExactMatch && IsEqualGUID(pCategory,&GUID_NULL)) || IsEqualGUID(pCategory,pPin->clsPinCategory) )
406                         return TRUE;
407                 return FALSE;
408         }
409
410         if ( bRender && (!(pPin->dwFlags & REG_PINFLAG_B_RENDERER)) )
411                 return FALSE;
412
413         return TRUE;
414 }
415
416
417
418
419 /***************************************************************************
420  *
421  *      new/delete for CLSID_FilterMapper
422  *
423  */
424
425 /* can I use offsetof safely? - FIXME? */
426 static QUARTZ_IFEntry FMapIFEntries[] =
427 {
428   { &IID_IFilterMapper, offsetof(CFilterMapper,fmap)-offsetof(CFilterMapper,unk) },
429 };
430
431
432 static void QUARTZ_DestroyFilterMapper(IUnknown* punk)
433 {
434         CFilterMapper_THIS(punk,unk);
435
436         CFilterMapper_UninitIFilterMapper( This );
437 }
438
439 HRESULT QUARTZ_CreateFilterMapper(IUnknown* punkOuter,void** ppobj)
440 {
441         CFilterMapper*  pfm;
442         HRESULT hr;
443
444         TRACE("(%p,%p)\n",punkOuter,ppobj);
445
446         pfm = (CFilterMapper*)QUARTZ_AllocObj( sizeof(CFilterMapper) );
447         if ( pfm == NULL )
448                 return E_OUTOFMEMORY;
449
450         QUARTZ_IUnkInit( &pfm->unk, punkOuter );
451         hr = CFilterMapper_InitIFilterMapper( pfm );
452         if ( FAILED(hr) )
453         {
454                 QUARTZ_FreeObj( pfm );
455                 return hr;
456         }
457
458         pfm->unk.pEntries = FMapIFEntries;
459         pfm->unk.dwEntries = sizeof(FMapIFEntries)/sizeof(FMapIFEntries[0]);
460         pfm->unk.pOnFinalRelease = QUARTZ_DestroyFilterMapper;
461
462         *ppobj = (void*)(&pfm->unk);
463
464         return S_OK;
465 }
466
467 /***************************************************************************
468  *
469  *      CLSID_FilterMapper::IFilterMapper
470  *
471  */
472
473 static HRESULT WINAPI
474 IFilterMapper_fnQueryInterface(IFilterMapper* iface,REFIID riid,void** ppobj)
475 {
476         CFilterMapper_THIS(iface,fmap);
477
478         TRACE("(%p)->()\n",This);
479
480         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
481 }
482
483 static ULONG WINAPI
484 IFilterMapper_fnAddRef(IFilterMapper* iface)
485 {
486         CFilterMapper_THIS(iface,fmap);
487
488         TRACE("(%p)->()\n",This);
489
490         return IUnknown_AddRef(This->unk.punkControl);
491 }
492
493 static ULONG WINAPI
494 IFilterMapper_fnRelease(IFilterMapper* iface)
495 {
496         CFilterMapper_THIS(iface,fmap);
497
498         TRACE("(%p)->()\n",This);
499
500         return IUnknown_Release(This->unk.punkControl);
501 }
502
503
504 static HRESULT WINAPI
505 IFilterMapper_fnRegisterFilter(IFilterMapper* iface,CLSID clsid,LPCWSTR lpwszName,DWORD dwMerit)
506 {
507         CFilterMapper_THIS(iface,fmap);
508
509         FIXME("(%p)->(%s,%s,%08lx)\n",This,
510                 debugstr_guid(&clsid),debugstr_w(lpwszName),dwMerit);
511
512         /* FIXME */
513         /* FIXME - handle dwMerit! */
514         return QUARTZ_RegisterAMovieFilter(
515                 &CLSID_LegacyAmFilterCategory,
516                 &clsid,
517                 NULL, 0,
518                 lpwszName, NULL, TRUE );
519 }
520
521 static HRESULT WINAPI
522 IFilterMapper_fnRegisterFilterInstance(IFilterMapper* iface,CLSID clsid,LPCWSTR lpwszName,CLSID* pclsidMedia)
523 {
524         CFilterMapper_THIS(iface,fmap);
525         HRESULT hr;
526
527         FIXME("(%p)->()\n",This);
528
529         if ( pclsidMedia == NULL )
530                 return E_POINTER;
531         hr = CoCreateGuid(pclsidMedia);
532         if ( FAILED(hr) )
533                 return hr;
534
535         /* FIXME */
536         /* this doesn't work. */
537         /* return IFilterMapper_RegisterFilter(iface,
538                 *pclsidMedia,lpwszName,0x60000000); */
539
540         return E_NOTIMPL;
541 }
542
543 static HRESULT WINAPI
544 IFilterMapper_fnRegisterPin(IFilterMapper* iface,CLSID clsidFilter,LPCWSTR lpwszName,BOOL bRendered,BOOL bOutput,BOOL bZero,BOOL bMany,CLSID clsidReserved,LPCWSTR lpwszReserved)
545 {
546         CFilterMapper_THIS(iface,fmap);
547
548         FIXME("(%p)->() stub!\n",This);
549
550         return E_NOTIMPL;
551 }
552
553 static HRESULT WINAPI
554 IFilterMapper_fnRegisterPinType(IFilterMapper* iface,CLSID clsidFilter,LPCWSTR lpwszName,CLSID clsidMajorType,CLSID clsidSubType)
555 {
556         CFilterMapper_THIS(iface,fmap);
557
558         FIXME("(%p)->() stub!\n",This);
559
560         return E_NOTIMPL;
561 }
562
563 static HRESULT WINAPI
564 IFilterMapper_fnUnregisterFilter(IFilterMapper* iface,CLSID clsidFilter)
565 {
566         CFilterMapper_THIS(iface,fmap);
567
568         FIXME("(%p)->(%s)\n",This,debugstr_guid(&clsidFilter));
569
570         /* FIXME */
571         return QUARTZ_RegisterAMovieFilter(
572                 &CLSID_LegacyAmFilterCategory,
573                 &clsidFilter,
574                 NULL, 0, NULL, NULL, FALSE );
575 }
576
577 static HRESULT WINAPI
578 IFilterMapper_fnUnregisterFilterInstance(IFilterMapper* iface,CLSID clsidMedia)
579 {
580         CFilterMapper_THIS(iface,fmap);
581
582         FIXME("(%p)->(%s)\n",This,debugstr_guid(&clsidMedia));
583
584         /* FIXME */
585         /* this doesn't work. */
586         /* return IFilterMapper_UnregisterFilter(iface,clsidMedia); */
587
588         return E_NOTIMPL;
589 }
590
591 static HRESULT WINAPI
592 IFilterMapper_fnUnregisterPin(IFilterMapper* iface,CLSID clsidPin,LPCWSTR lpwszName)
593 {
594         CFilterMapper_THIS(iface,fmap);
595
596         FIXME("(%p)->(%s,%s) stub!\n",This,
597                 debugstr_guid(&clsidPin),debugstr_w(lpwszName));
598
599         return E_NOTIMPL;
600 }
601
602 static HRESULT WINAPI
603 IFilterMapper_fnEnumMatchingFilters(IFilterMapper* iface,IEnumRegFilters** ppobj,DWORD dwMerit,BOOL bInputNeeded,CLSID clsInMajorType,CLSID clsidSubType,BOOL bRender,BOOL bOutputNeeded,CLSID clsOutMajorType,CLSID clsOutSubType)
604 {
605         CFilterMapper_THIS(iface,fmap);
606
607         FIXME("(%p)->() stub!\n",This);
608
609         return E_NOTIMPL;
610 }
611
612
613
614 static ICOM_VTABLE(IFilterMapper) ifmap =
615 {
616         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
617         /* IUnknown fields */
618         IFilterMapper_fnQueryInterface,
619         IFilterMapper_fnAddRef,
620         IFilterMapper_fnRelease,
621         /* IFilterMapper fields */
622         IFilterMapper_fnRegisterFilter,
623         IFilterMapper_fnRegisterFilterInstance,
624         IFilterMapper_fnRegisterPin,
625         IFilterMapper_fnRegisterPinType,
626         IFilterMapper_fnUnregisterFilter,
627         IFilterMapper_fnUnregisterFilterInstance,
628         IFilterMapper_fnUnregisterPin,
629         IFilterMapper_fnEnumMatchingFilters,
630 };
631
632
633 HRESULT CFilterMapper_InitIFilterMapper( CFilterMapper* pfm )
634 {
635         TRACE("(%p)\n",pfm);
636         ICOM_VTBL(&pfm->fmap) = &ifmap;
637
638         return NOERROR;
639 }
640
641 void CFilterMapper_UninitIFilterMapper( CFilterMapper* pfm )
642 {
643         TRACE("(%p)\n",pfm);
644 }
645
646
647 /***************************************************************************
648  *
649  *      new/delete for CLSID_FilterMapper2
650  *
651  */
652
653 /* can I use offsetof safely? - FIXME? */
654 static QUARTZ_IFEntry FMap2IFEntries[] =
655 {
656   { &IID_IFilterMapper2, offsetof(CFilterMapper2,fmap3)-offsetof(CFilterMapper2,unk) },
657   { &IID_IFilterMapper3, offsetof(CFilterMapper2,fmap3)-offsetof(CFilterMapper2,unk) },
658 };
659
660
661 static void QUARTZ_DestroyFilterMapper2(IUnknown* punk)
662 {
663         CFilterMapper2_THIS(punk,unk);
664
665         CFilterMapper2_UninitIFilterMapper3( This );
666 }
667
668 HRESULT QUARTZ_CreateFilterMapper2(IUnknown* punkOuter,void** ppobj)
669 {
670         CFilterMapper2* pfm;
671         HRESULT hr;
672
673         TRACE("(%p,%p)\n",punkOuter,ppobj);
674
675         pfm = (CFilterMapper2*)QUARTZ_AllocObj( sizeof(CFilterMapper2) );
676         if ( pfm == NULL )
677                 return E_OUTOFMEMORY;
678
679         QUARTZ_IUnkInit( &pfm->unk, punkOuter );
680         hr = CFilterMapper2_InitIFilterMapper3( pfm );
681         if ( FAILED(hr) )
682         {
683                 QUARTZ_FreeObj( pfm );
684                 return hr;
685         }
686
687         pfm->unk.pEntries = FMap2IFEntries;
688         pfm->unk.dwEntries = sizeof(FMap2IFEntries)/sizeof(FMap2IFEntries[0]);
689         pfm->unk.pOnFinalRelease = QUARTZ_DestroyFilterMapper2;
690
691         *ppobj = (void*)(&pfm->unk);
692
693         return S_OK;
694 }
695
696 /***************************************************************************
697  *
698  *      CLSID_FilterMapper2::IFilterMapper3
699  *
700  */
701
702
703 static HRESULT WINAPI
704 IFilterMapper3_fnQueryInterface(IFilterMapper3* iface,REFIID riid,void** ppobj)
705 {
706         CFilterMapper2_THIS(iface,fmap3);
707
708         TRACE("(%p)->()\n",This);
709
710         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
711 }
712
713 static ULONG WINAPI
714 IFilterMapper3_fnAddRef(IFilterMapper3* iface)
715 {
716         CFilterMapper2_THIS(iface,fmap3);
717
718         TRACE("(%p)->()\n",This);
719
720         return IUnknown_AddRef(This->unk.punkControl);
721 }
722
723 static ULONG WINAPI
724 IFilterMapper3_fnRelease(IFilterMapper3* iface)
725 {
726         CFilterMapper2_THIS(iface,fmap3);
727
728         TRACE("(%p)->()\n",This);
729
730         return IUnknown_Release(This->unk.punkControl);
731 }
732
733 static HRESULT WINAPI
734 IFilterMapper3_fnCreateCategory(IFilterMapper3* iface,REFCLSID rclsidCategory,DWORD dwMerit,LPCWSTR lpwszDesc)
735 {
736         CFilterMapper2_THIS(iface,fmap3);
737
738         FIXME("(%p)->(%s,%lu,%s) stub!\n",This,
739                 debugstr_guid(rclsidCategory),
740                 (unsigned long)dwMerit,debugstr_w(lpwszDesc));
741
742         return E_NOTIMPL;
743 }
744
745
746 static HRESULT WINAPI
747 IFilterMapper3_fnUnregisterFilter(IFilterMapper3* iface,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,REFCLSID rclsidFilter)
748 {
749         CFilterMapper2_THIS(iface,fmap3);
750         WCHAR*  pwszPath = NULL;
751         HRESULT hr;
752
753         TRACE("(%p)->(%s,%s,%s)\n",This,
754                 debugstr_guid(pclsidCategory),
755                 debugstr_w(lpwszInst),
756                 debugstr_guid(rclsidFilter));
757
758         if ( pclsidCategory == NULL )
759                 pclsidCategory = &CLSID_LegacyAmFilterCategory;
760
761         hr = QUARTZ_GetFilterRegPath(
762                 &pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
763         if ( FAILED(hr) )
764                 return hr;
765
766         hr = QUARTZ_RegDeleteKey(HKEY_CLASSES_ROOT,pwszPath);
767         QUARTZ_FreeMem(pwszPath);
768
769         return hr;
770 }
771
772
773 static HRESULT WINAPI
774 IFilterMapper3_fnRegisterFilter(IFilterMapper3* iface,REFCLSID rclsidFilter,LPCWSTR lpName,IMoniker** ppMoniker,const CLSID* pclsidCategory,const OLECHAR* lpwszInst,const REGFILTER2* pRF2)
775 {
776         CFilterMapper2_THIS(iface,fmap3);
777         WCHAR*  pwszPath = NULL;
778         IMoniker*       pMoniker = NULL;
779         BYTE*   pFilterData = NULL;
780         DWORD   cbFilterData = 0;
781         HRESULT hr;
782
783         TRACE( "(%p)->(%s,%s,%p,%s,%s,%p) stub!\n",This,
784                 debugstr_guid(rclsidFilter),debugstr_w(lpName),
785                 ppMoniker,debugstr_guid(pclsidCategory),
786                 debugstr_w(lpwszInst),pRF2 );
787
788         if ( lpName == NULL || pRF2 == NULL )
789                 return E_POINTER;
790
791         if ( ppMoniker != NULL && *ppMoniker != NULL )
792         {
793                 FIXME( "ppMoniker != NULL - not implemented! *ppMoniker = %p\n",*ppMoniker );
794                 return E_NOTIMPL;
795         }
796
797         if ( pclsidCategory == NULL )
798                 pclsidCategory = &CLSID_LegacyAmFilterCategory;
799
800         if ( pMoniker == NULL )
801         {
802                 hr = QUARTZ_GetFilterRegPath(
803                         &pwszPath, pclsidCategory, rclsidFilter, lpwszInst );
804                 if ( FAILED(hr) )
805                         return hr;
806                 hr = QUARTZ_CreateDeviceMoniker(
807                         HKEY_CLASSES_ROOT,pwszPath,&pMoniker);
808                 QUARTZ_FreeMem(pwszPath);
809                 if ( FAILED(hr) )
810                         return hr;
811         }
812
813         pFilterData = QUARTZ_RegFilterToFilterData( pRF2, &cbFilterData );
814         if ( pFilterData == NULL || cbFilterData == 0 )
815         {
816                 hr = E_FAIL;
817                 goto err;
818         }
819
820         hr = QUARTZ_RegisterFilterToMoniker(
821                 pMoniker, rclsidFilter, lpName, pFilterData, cbFilterData );
822         if ( FAILED(hr) )
823                 goto err;
824
825         if ( ppMoniker != NULL )
826         {
827                 *ppMoniker = pMoniker;
828                 pMoniker = NULL;
829         }
830 err:
831         if ( pFilterData != NULL )
832                 QUARTZ_FreeMem(pFilterData);
833         if ( pMoniker != NULL )
834                 IMoniker_Release(pMoniker);
835
836         return hr;
837 }
838
839
840 static HRESULT WINAPI
841 IFilterMapper3_fnEnumMatchingFilters(IFilterMapper3* iface,
842         IEnumMoniker** ppEnumMoniker,DWORD dwFlags,BOOL bExactMatch,DWORD dwMerit,
843         BOOL bInputNeeded,DWORD cInputTypes,const GUID* pguidInputTypes,const REGPINMEDIUM* pPinMediumIn,const CLSID* pPinCategoryIn,BOOL bRender,
844         BOOL bOutputNeeded,DWORD cOutputTypes,const GUID* pguidOutputTypes,const REGPINMEDIUM* pPinMediumOut,const CLSID* pPinCategoryOut)
845 {
846         CFilterMapper2_THIS(iface,fmap3);
847         ICreateDevEnum* pEnum = NULL;
848         IEnumMoniker*   pCategories = NULL;
849         IMoniker*       pCat = NULL;
850         DWORD   dwCatMerit;
851         IEnumMoniker*   pCatFilters = NULL;
852         IMoniker*       pFilter = NULL;
853         CLSID   clsid;
854         ULONG   cReturned;
855         BYTE*   pbFilterData = NULL;
856         DWORD   cbFilterData = 0;
857         REGFILTER2*     prf2 = NULL;
858         QUARTZ_CompList*        pList = NULL;
859         const REGFILTERPINS2*   pRegFilterPin;
860         DWORD   n;
861         BOOL    bMatch;
862         HRESULT hr;
863
864         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);
865
866         if ( ppEnumMoniker == NULL )
867                 return E_POINTER;
868         *ppEnumMoniker = NULL;
869         if ( dwFlags != 0 )
870                 return E_INVALIDARG;
871
872         hr = CoCreateInstance(
873                 &CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
874                 &IID_ICreateDevEnum, (void**)&pEnum );
875         if ( FAILED(hr) )
876                 goto err;
877
878         hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&CLSID_ActiveMovieCategories,&pCategories,0);
879         if ( hr != S_OK )
880                 goto err;
881
882         while ( 1 )
883         {
884                 if ( pCat != NULL )
885                 {
886                         IMoniker_Release(pCat);
887                         pCat = NULL;
888                 }
889                 hr = IEnumMoniker_Next(pCategories,1,&pCat,&cReturned);
890                 if ( FAILED(hr) )
891                         goto err;
892                 if ( hr != S_OK )
893                         break;
894                 hr = QUARTZ_GetMeritFromMoniker(pCat,&dwCatMerit);
895                 if ( hr != S_OK || dwMerit > dwCatMerit )
896                         continue;
897                 hr = QUARTZ_GetCLSIDFromMoniker(pCat,&clsid);
898                 if ( hr != S_OK )
899                         continue;
900
901                 if ( pCatFilters != NULL )
902                 {
903                         IEnumMoniker_Release(pCatFilters);
904                         pCatFilters = NULL;
905                 }
906                 hr = ICreateDevEnum_CreateClassEnumerator(pEnum,&clsid,&pCatFilters,0);
907                 if ( FAILED(hr) )
908                         goto err;
909                 if ( hr != S_OK )
910                         continue;
911
912                 while ( 1 )
913                 {
914                         if ( pFilter != NULL )
915                         {
916                                 IMoniker_Release(pFilter);
917                                 pFilter = NULL;
918                         }
919                         hr = IEnumMoniker_Next(pCatFilters,1,&pFilter,&cReturned);
920                         if ( FAILED(hr) )
921                                 goto err;
922                         if ( hr != S_OK )
923                                 break;
924                         if ( pbFilterData != NULL )
925                         {
926                                 QUARTZ_FreeMem(pbFilterData);
927                                 pbFilterData = NULL;
928                         }
929                         hr = QUARTZ_GetFilterDataFromMoniker(pFilter,&pbFilterData,&cbFilterData);
930                         if ( hr != S_OK )
931                                 continue;
932
933                         if ( prf2 != NULL )
934                         {
935                                 QUARTZ_FreeMem(prf2);
936                                 prf2 = NULL;
937                         }
938                         prf2 = QUARTZ_RegFilterV2FromFilterData(pbFilterData,cbFilterData);
939                         if ( prf2 == NULL )
940                                 continue;
941                         TRACE("prf2 %p, Merit %lu\n",prf2,prf2->dwMerit);
942                         if ( prf2->dwMerit < dwMerit || prf2->dwVersion != 2 )
943                                 continue;
944
945                         /* check input pins. */
946                         if ( bInputNeeded )
947                         {
948                                 bMatch = FALSE;
949                                 for ( n = 0; n < prf2->u.s2.cPins2; n++ )
950                                 {
951                                         pRegFilterPin = &prf2->u.s2.rgPins2[n];
952                                         if ( pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT )
953                                                 continue;
954                                         bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cInputTypes, pguidInputTypes, pPinMediumIn, pPinCategoryIn, bRender );
955                                         if ( bMatch )
956                                                 break;
957                                 }
958                                 if ( !bMatch )
959                                         continue;
960                         }
961
962                         /* check output pins. */
963                         if ( bOutputNeeded )
964                         {
965                                 bMatch = FALSE;
966                                 for ( n = 0; n < prf2->u.s2.cPins2; n++ )
967                                 {
968                                         pRegFilterPin = &prf2->u.s2.rgPins2[n];
969                                         if ( !(pRegFilterPin->dwFlags & REG_PINFLAG_B_OUTPUT) )
970                                                 continue;
971                                         bMatch = QUARTZ_CheckPinType( bExactMatch, pRegFilterPin, cOutputTypes, pguidOutputTypes, pPinMediumOut, pPinCategoryOut, FALSE );
972                                         if ( bMatch )
973                                                 break;
974                                 }
975                                 if ( !bMatch )
976                                         continue;
977                         }
978
979                         /* matched - add pFilter to the list. */
980                         if ( pList == NULL )
981                         {
982                                 pList = QUARTZ_CompList_Alloc();
983                                 if ( pList == NULL )
984                                 {
985                                         hr = E_OUTOFMEMORY;
986                                         goto err;
987                                 }
988                         }
989                         hr = QUARTZ_CompList_AddComp(
990                                 pList, (IUnknown*)pFilter, NULL, 0 );
991                         if ( FAILED(hr) )
992                                 goto err;
993                 }
994         }
995
996         if ( pList == NULL )
997         {
998                 hr = S_FALSE;
999                 goto err;
1000         }
1001
1002         FIXME("create IEnumMoniker - not sorted\n");
1003         /* FIXME - should be sorted?(in Merit order) */
1004         hr = QUARTZ_CreateEnumUnknown( &IID_IEnumMoniker, (void**)ppEnumMoniker, pList );
1005         if ( FAILED(hr) )
1006                 goto err;
1007
1008         hr = S_OK;
1009 err:
1010         if ( pEnum != NULL )
1011                 ICreateDevEnum_Release(pEnum);
1012         if ( pCategories != NULL )
1013                 IEnumMoniker_Release(pCategories);
1014         if ( pCat != NULL )
1015                 IMoniker_Release(pCat);
1016         if ( pCatFilters != NULL )
1017                 IEnumMoniker_Release(pCatFilters);
1018         if ( pFilter != NULL )
1019                 IMoniker_Release(pFilter);
1020         if ( pbFilterData != NULL )
1021                 QUARTZ_FreeMem(pbFilterData);
1022         if ( prf2 != NULL )
1023                 QUARTZ_FreeMem(prf2);
1024         if ( pList != NULL )
1025                 QUARTZ_CompList_Free( pList );
1026
1027         TRACE("returns %08lx\n",hr);
1028
1029         return hr;
1030 }
1031
1032 static HRESULT WINAPI
1033 IFilterMapper3_fnGetICreateDevEnum(IFilterMapper3* iface,ICreateDevEnum** ppDevEnum)
1034 {
1035         CFilterMapper2_THIS(iface,fmap3);
1036
1037         /* undocumented */
1038         FIXME("(%p)->() stub!\n",This);
1039
1040         return E_NOTIMPL;
1041 }
1042
1043
1044
1045
1046 static ICOM_VTABLE(IFilterMapper3) ifmap3 =
1047 {
1048         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1049         /* IUnknown fields */
1050         IFilterMapper3_fnQueryInterface,
1051         IFilterMapper3_fnAddRef,
1052         IFilterMapper3_fnRelease,
1053         /* IFilterMapper2 fields */
1054         IFilterMapper3_fnCreateCategory,
1055         IFilterMapper3_fnUnregisterFilter,
1056         IFilterMapper3_fnRegisterFilter,
1057         IFilterMapper3_fnEnumMatchingFilters,
1058         /* IFilterMapper3 fields */
1059         IFilterMapper3_fnGetICreateDevEnum,
1060 };
1061
1062
1063 HRESULT CFilterMapper2_InitIFilterMapper3( CFilterMapper2* pfm )
1064 {
1065         TRACE("(%p)\n",pfm);
1066         ICOM_VTBL(&pfm->fmap3) = &ifmap3;
1067
1068         return NOERROR;
1069 }
1070
1071 void CFilterMapper2_UninitIFilterMapper3( CFilterMapper2* pfm )
1072 {
1073         TRACE("(%p)\n",pfm);
1074 }
1075