nkobj: Use an internal header.
[wine] / dlls / quartz / filtergraph.c
1 /*              DirectShow FilterGraph object (QUARTZ.DLL)
2  *
3  * Copyright 2002 Lionel Ulmer
4  * Copyright 2004 Christian Costa
5  *
6  * This file contains the (internal) driver registration functions,
7  * driver enumeration APIs and DirectDraw creation functions.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25 #include <stdarg.h>
26
27 #define COBJMACROS
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "dshow.h"
33 #include "wine/debug.h"
34 #include "quartz_private.h"
35 #include "ole2.h"
36 #include "olectl.h"
37 #include "strmif.h"
38 #include "vfwmsgs.h"
39 #include "evcode.h"
40 #include "wine/unicode.h"
41
42
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
44
45 typedef struct {
46     HWND hWnd;      /* Target window */
47     long msg;       /* User window message */
48     long instance;  /* User data */
49     int  disabled;  /* Disabled messages posting */
50 } WndNotify;
51
52 typedef struct {
53     long lEventCode;   /* Event code */
54     LONG_PTR lParam1;  /* Param1 */
55     LONG_PTR lParam2;  /* Param2 */
56 } Event;
57
58 /* messages ring implementation for queuing events (taken from winmm) */
59 #define EVENTS_RING_BUFFER_INCREMENT      64
60 typedef struct {
61     Event* messages;
62     int ring_buffer_size;
63     int msg_tosave;
64     int msg_toget;
65     CRITICAL_SECTION msg_crst;
66     HANDLE msg_event; /* Signaled for no empty queue */
67 } EventsQueue;
68
69 static int EventsQueue_Init(EventsQueue* omr)
70 {
71     omr->msg_toget = 0;
72     omr->msg_tosave = 0;
73     omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
74     omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
75     omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event));
76     ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
77
78     InitializeCriticalSection(&omr->msg_crst);
79     omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst");
80     return TRUE;
81 }
82
83 static int EventsQueue_Destroy(EventsQueue* omr)
84 {
85     CloseHandle(omr->msg_event);
86     CoTaskMemFree(omr->messages);
87     omr->msg_crst.DebugInfo->Spare[0] = 0;
88     DeleteCriticalSection(&omr->msg_crst);
89     return TRUE;
90 }
91
92 static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt)
93 {
94     EnterCriticalSection(&omr->msg_crst);
95     if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
96     {
97         int old_ring_buffer_size = omr->ring_buffer_size;
98         omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
99         TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
100         omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event));
101         /* Now we need to rearrange the ring buffer so that the new
102            buffers just allocated are in between omr->msg_tosave and
103            omr->msg_toget.
104         */
105         if (omr->msg_tosave < omr->msg_toget)
106         {
107             memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
108                     &(omr->messages[omr->msg_toget]),
109                     sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
110                     );
111             omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
112         }
113     }
114     omr->messages[omr->msg_tosave] = *evt;
115     SetEvent(omr->msg_event);
116     omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
117     LeaveCriticalSection(&omr->msg_crst);
118     return TRUE;
119 }
120
121 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, long msTimeOut)
122 {
123     if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
124         return FALSE;
125         
126     EnterCriticalSection(&omr->msg_crst);
127
128     if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
129     {
130         LeaveCriticalSection(&omr->msg_crst);
131         return FALSE;
132     }
133
134     *evt = omr->messages[omr->msg_toget];
135     omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
136
137     /* Mark the buffer as empty if needed */
138     if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
139         ResetEvent(omr->msg_event);
140
141     LeaveCriticalSection(&omr->msg_crst);
142     return TRUE;
143 }
144
145 #define MAX_ITF_CACHE_ENTRIES 3
146 typedef struct _ITF_CACHE_ENTRY {
147    const IID* riid;
148    IBaseFilter* filter;
149    IUnknown* iface;
150 } ITF_CACHE_ENTRY;
151
152 typedef struct _IFilterGraphImpl {
153     const IGraphBuilderVtbl *IGraphBuilder_vtbl;
154     const IMediaControlVtbl *IMediaControl_vtbl;
155     const IMediaSeekingVtbl *IMediaSeeking_vtbl;
156     const IBasicAudioVtbl *IBasicAudio_vtbl;
157     const IBasicVideoVtbl *IBasicVideo_vtbl;
158     const IVideoWindowVtbl *IVideoWindow_vtbl;
159     const IMediaEventExVtbl *IMediaEventEx_vtbl;
160     const IMediaFilterVtbl *IMediaFilter_vtbl;
161     const IMediaEventSinkVtbl *IMediaEventSink_vtbl;
162     const IGraphConfigVtbl *IGraphConfig_vtbl;
163     const IMediaPositionVtbl *IMediaPosition_vtbl;
164     /* IAMGraphStreams */
165     /* IAMStats */
166     /* IBasicVideo2 */
167     /* IFilterChain */
168     /* IFilterGraph2 */
169     /* IFilterMapper2 */
170     /* IGraphVersion */
171     /* IQueueCommand */
172     /* IRegisterServiceProvider */
173     /* IResourceMananger */
174     /* IServiceProvider */
175     /* IVideoFrameStep */
176
177     LONG ref;
178     IFilterMapper2 * pFilterMapper2;
179     IBaseFilter ** ppFiltersInGraph;
180     LPWSTR * pFilterNames;
181     int nFilters;
182     int filterCapacity;
183     long nameIndex;
184     IReferenceClock *refClock;
185     EventsQueue evqueue;
186     HANDLE hEventCompletion;
187     int CompletionStatus;
188     WndNotify notif;
189     int nRenderers;
190     int EcCompleteCount;
191     int HandleEcComplete;
192     int HandleEcRepaint;
193     int HandleEcClockChanged;
194     OAFilterState state;
195     CRITICAL_SECTION cs;
196     ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES];
197     int nItfCacheEntries;
198 } IFilterGraphImpl;
199
200
201 static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This,
202                                           REFIID riid,
203                                           LPVOID *ppvObj) {
204     TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
205     
206     if (IsEqualGUID(&IID_IUnknown, riid) ||
207         IsEqualGUID(&IID_IFilterGraph, riid) ||
208         IsEqualGUID(&IID_IGraphBuilder, riid)) {
209         *ppvObj = &(This->IGraphBuilder_vtbl);
210         TRACE("   returning IGraphBuilder interface (%p)\n", *ppvObj);
211     } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
212         *ppvObj = &(This->IMediaControl_vtbl);
213         TRACE("   returning IMediaControl interface (%p)\n", *ppvObj);
214     } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
215         *ppvObj = &(This->IMediaSeeking_vtbl);
216         TRACE("   returning IMediaSeeking interface (%p)\n", *ppvObj);
217     } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
218         *ppvObj = &(This->IBasicAudio_vtbl);
219         TRACE("   returning IBasicAudio interface (%p)\n", *ppvObj);
220     } else if (IsEqualGUID(&IID_IBasicVideo, riid)) {
221         *ppvObj = &(This->IBasicVideo_vtbl);
222         TRACE("   returning IBasicVideo interface (%p)\n", *ppvObj);
223     } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
224         *ppvObj = &(This->IVideoWindow_vtbl);
225         TRACE("   returning IVideoWindow interface (%p)\n", *ppvObj);
226     } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
227            IsEqualGUID(&IID_IMediaEventEx, riid)) {
228         *ppvObj = &(This->IMediaEventEx_vtbl);
229         TRACE("   returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
230     } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
231           IsEqualGUID(&IID_IPersist, riid)) {
232         *ppvObj = &(This->IMediaFilter_vtbl);
233         TRACE("   returning IMediaFilter interface (%p)\n", *ppvObj);
234     } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
235         *ppvObj = &(This->IMediaEventSink_vtbl);
236         TRACE("   returning IMediaEventSink interface (%p)\n", *ppvObj);
237     } else if (IsEqualGUID(&IID_IGraphConfig, riid)) {
238         *ppvObj = &(This->IGraphConfig_vtbl);
239         TRACE("   returning IGraphConfig interface (%p)\n", *ppvObj);
240     } else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
241         *ppvObj = &(This->IMediaPosition_vtbl);
242         TRACE("   returning IMediaPosition interface (%p)\n", *ppvObj);
243     } else {
244         *ppvObj = NULL;
245         FIXME("unknown interface %s\n", debugstr_guid(riid));
246         return E_NOINTERFACE;
247     }
248
249     InterlockedIncrement(&This->ref);
250     return S_OK;
251 }
252
253 static ULONG Filtergraph_AddRef(IFilterGraphImpl *This) {
254     ULONG ref = InterlockedIncrement(&This->ref);
255
256     TRACE("(%p)->(): new ref = %d\n", This, ref);
257     
258     return ref;
259 }
260
261 static ULONG Filtergraph_Release(IFilterGraphImpl *This) {
262     ULONG ref = InterlockedDecrement(&This->ref);
263     
264     TRACE("(%p)->(): new ref = %d\n", This, ref);
265     
266     if (ref == 0) {
267         int i;
268
269         if (This->refClock)
270             IReferenceClock_Release(This->refClock);
271
272         for (i = 0; i < This->nFilters; i++)
273         {
274             IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], NULL);
275             IBaseFilter_Release(This->ppFiltersInGraph[i]);
276         }
277         for (i = 0; i < This->nItfCacheEntries; i++)
278         {
279             if (This->ItfCacheEntries[i].iface)
280                 IUnknown_Release(This->ItfCacheEntries[i].iface);
281         }
282         IFilterMapper2_Release(This->pFilterMapper2);
283         CloseHandle(This->hEventCompletion);
284         EventsQueue_Destroy(&This->evqueue);
285         This->cs.DebugInfo->Spare[0] = 0;
286         DeleteCriticalSection(&This->cs);
287         CoTaskMemFree(This->ppFiltersInGraph);
288         CoTaskMemFree(This->pFilterNames);
289         CoTaskMemFree(This);
290     }
291     return ref;
292 }
293
294
295 /*** IUnknown methods ***/
296 static HRESULT WINAPI GraphBuilder_QueryInterface(IGraphBuilder *iface,
297                                                   REFIID riid,
298                                                   LPVOID*ppvObj) {
299     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
300     
301     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
302     return Filtergraph_QueryInterface(This, riid, ppvObj);
303 }
304
305 static ULONG WINAPI GraphBuilder_AddRef(IGraphBuilder *iface) {
306     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
307     
308     TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
309     
310     return Filtergraph_AddRef(This);
311 }
312
313 static ULONG WINAPI GraphBuilder_Release(IGraphBuilder *iface) {
314     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
315     
316     TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
317
318     return Filtergraph_Release(This);
319 }
320
321 /*** IFilterGraph methods ***/
322 static HRESULT WINAPI GraphBuilder_AddFilter(IGraphBuilder *iface,
323                                              IBaseFilter *pFilter,
324                                              LPCWSTR pName) {
325     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
326     HRESULT hr;
327     int i,j;
328     WCHAR* wszFilterName = NULL;
329     int duplicate_name = FALSE;
330
331     TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
332
333     wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
334
335     if (pName)
336     {
337         /* Check if name already exists */
338         for(i = 0; i < This->nFilters; i++)
339             if (!strcmpW(This->pFilterNames[i], pName))
340             {
341                 duplicate_name = TRUE;
342                 break;
343             }
344     }
345
346     /* If no name given or name already existing, generate one */
347     if (!pName || duplicate_name)
348     {
349         static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
350         static const WCHAR wszFmt2[] = {'%','0','4','d',0};
351
352         for (j = 0; j < 10000 ; j++)
353         {
354             /* Create name */
355             if (pName)
356                 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
357             else
358                 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
359             TRACE("Generated name %s\n", debugstr_w(wszFilterName));
360
361             /* Check if the generated name already exists */
362             for(i = 0; i < This->nFilters; i++)
363                 if (!strcmpW(This->pFilterNames[i], wszFilterName))
364                     break;
365
366             /* Compute next index and exit if generated name is suitable */
367             if (This->nameIndex++ == 10000)
368                 This->nameIndex = 1;
369             if (i == This->nFilters)
370                 break;
371         }
372         /* Unable to find a suitable name */
373         if (j == 10000)
374         {
375             CoTaskMemFree(wszFilterName);
376             return VFW_E_DUPLICATE_NAME;
377         }
378     }
379     else
380         memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
381
382     if (This->nFilters + 1 > This->filterCapacity)
383     {
384         int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
385         IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
386         LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
387         memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
388         memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
389         if (!This->filterCapacity)
390         {
391             CoTaskMemFree(This->ppFiltersInGraph);
392             CoTaskMemFree(This->pFilterNames);
393         }
394         This->ppFiltersInGraph = ppNewFilters;
395         This->pFilterNames = pNewNames;
396         This->filterCapacity = newCapacity;
397     }
398
399     hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
400
401     if (SUCCEEDED(hr))
402     {
403         IBaseFilter_AddRef(pFilter);
404         This->ppFiltersInGraph[This->nFilters] = pFilter;
405         This->pFilterNames[This->nFilters] = wszFilterName;
406         This->nFilters++;
407         IBaseFilter_SetSyncSource(pFilter, This->refClock);
408     }
409     else
410         CoTaskMemFree(wszFilterName);
411
412     if (SUCCEEDED(hr) && duplicate_name)
413         return VFW_S_DUPLICATE_NAME;
414         
415     return hr;
416 }
417
418 static HRESULT WINAPI GraphBuilder_RemoveFilter(IGraphBuilder *iface,
419                                                 IBaseFilter *pFilter) {
420     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
421     int i;
422     HRESULT hr = E_FAIL;
423
424     TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
425
426     /* FIXME: check graph is stopped */
427
428     for (i = 0; i < This->nFilters; i++)
429     {
430         if (This->ppFiltersInGraph[i] == pFilter)
431         {
432             IEnumPins *penumpins;
433             hr = IBaseFilter_EnumPins(pFilter, &penumpins);
434             if (SUCCEEDED(hr)) {
435                 IPin *ppin;
436                 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK) {
437                     IPin_Disconnect(ppin);
438                     IPin_Release(ppin);
439                 }
440                 IEnumPins_Release(penumpins);
441             }
442
443             hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
444             if (SUCCEEDED(hr))
445             {
446                 IBaseFilter_SetSyncSource(pFilter, NULL);
447                 IBaseFilter_Release(pFilter);
448                 CoTaskMemFree(This->pFilterNames[i]);
449                 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
450                 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
451                 This->nFilters--;
452                 /* Invalidate interfaces in the cache */
453                 for (i = 0; i < This->nItfCacheEntries; i++)
454                     if (pFilter == This->ItfCacheEntries[i].filter)
455                     {
456                         IUnknown_Release(This->ItfCacheEntries[i].iface);
457                         This->ItfCacheEntries[i].iface = NULL;
458                         This->ItfCacheEntries[i].filter = NULL;
459                     }
460                 return S_OK;
461             }
462             break;
463         }
464     }
465
466     return hr; /* FIXME: check this error code */
467 }
468
469 static HRESULT WINAPI GraphBuilder_EnumFilters(IGraphBuilder *iface,
470                                               IEnumFilters **ppEnum) {
471     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
472
473     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
474
475     return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
476 }
477
478 static HRESULT WINAPI GraphBuilder_FindFilterByName(IGraphBuilder *iface,
479                                                     LPCWSTR pName,
480                                                     IBaseFilter **ppFilter) {
481     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
482     int i;
483
484     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
485
486     *ppFilter = NULL;
487
488     for (i = 0; i < This->nFilters; i++)
489     {
490         if (!strcmpW(pName, This->pFilterNames[i]))
491         {
492             *ppFilter = This->ppFiltersInGraph[i];
493             IBaseFilter_AddRef(*ppFilter);
494             return S_OK;
495         }
496     }
497
498     return E_FAIL; /* FIXME: check this error code */
499 }
500
501 /* NOTE: despite the implication, it doesn't matter which
502  * way round you put in the input and output pins */
503 static HRESULT WINAPI GraphBuilder_ConnectDirect(IGraphBuilder *iface,
504                                                  IPin *ppinIn,
505                                                  IPin *ppinOut,
506                                                  const AM_MEDIA_TYPE *pmt) {
507     PIN_DIRECTION dir;
508     HRESULT hr;
509
510     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
511
512     TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
513
514     /* FIXME: check pins are in graph */
515
516     if (TRACE_ON(quartz))
517     {
518         PIN_INFO PinInfo;
519
520         hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
521         if (FAILED(hr))
522             return hr;
523
524         TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
525         IBaseFilter_Release(PinInfo.pFilter);
526
527         hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
528         if (FAILED(hr))
529             return hr;
530
531         TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
532         IBaseFilter_Release(PinInfo.pFilter);
533     }
534
535     hr = IPin_QueryDirection(ppinIn, &dir);
536     if (SUCCEEDED(hr))
537     {
538         if (dir == PINDIR_INPUT)
539             hr = IPin_Connect(ppinOut, ppinIn, pmt);
540         else
541             hr = IPin_Connect(ppinIn, ppinOut, pmt);
542     }
543
544     return hr;
545 }
546
547 static HRESULT WINAPI GraphBuilder_Reconnect(IGraphBuilder *iface,
548                                              IPin *ppin) {
549     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
550     IPin *pConnectedTo = NULL;
551     HRESULT hr;
552     PIN_DIRECTION pindir;
553
554     IPin_QueryDirection(ppin, &pindir);
555     hr = IPin_ConnectedTo(ppin, &pConnectedTo);
556     if (FAILED(hr)) {
557         TRACE("Querying connected to failed: %x\n", hr);
558         return hr; 
559     }
560     IPin_Disconnect(ppin);
561     IPin_Disconnect(pConnectedTo);
562     if (pindir == PINDIR_INPUT)
563         hr = IPin_Connect(pConnectedTo, ppin, NULL);
564     else
565         hr = IPin_Connect(ppin, pConnectedTo, NULL);
566     IPin_Release(pConnectedTo);
567     if (FAILED(hr))
568         ERR("Reconnecting pins failed, pins are not connected now..\n");
569     TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr);
570     return hr;
571 }
572
573 static HRESULT WINAPI GraphBuilder_Disconnect(IGraphBuilder *iface,
574                                               IPin *ppin) {
575     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
576
577     TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
578
579     return IPin_Disconnect(ppin);
580 }
581
582 static HRESULT WINAPI GraphBuilder_SetDefaultSyncSource(IGraphBuilder *iface) {
583     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
584
585     TRACE("(%p/%p)->(): stub !!!\n", iface, This);
586
587     return S_OK;
588 }
589
590 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
591 {
592     static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
593     static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
594     IPropertyBag * pPropBagCat = NULL;
595     HRESULT hr;
596
597     VariantInit(pvar);
598     V_VT(pvar) = VT_BSTR;
599
600     hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
601
602     if (SUCCEEDED(hr))
603         hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
604
605     if (SUCCEEDED(hr))
606         hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
607
608     if (SUCCEEDED(hr))
609         hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
610
611     if (SUCCEEDED(hr))
612         TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
613
614     if (pPropBagCat)
615         IPropertyBag_Release(pPropBagCat);
616
617     return hr;
618 }
619
620 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
621 {
622     HRESULT hr;
623     ULONG nb = 0;
624
625     TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
626     hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
627     if (hr == S_OK) {
628         /* Rendered input */
629     } else if (hr == S_FALSE) {
630         *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
631         hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
632         if (hr != S_OK) {
633             ERR("Error (%x)\n", hr);
634         }
635     } else if (hr == E_NOTIMPL) {
636         /* Input connected to all outputs */
637         IEnumPins* penumpins;
638         IPin* ppin;
639         int i = 0;
640         TRACE("E_NOTIMPL\n");
641         hr = IBaseFilter_EnumPins(pfilter, &penumpins);
642         if (FAILED(hr)) {
643             ERR("filter Enumpins failed (%x)\n", hr);
644             return hr;
645         }
646         i = 0;
647         /* Count output pins */
648         while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
649             PIN_DIRECTION pindir;
650             IPin_QueryDirection(ppin, &pindir);
651             if (pindir == PINDIR_OUTPUT)
652                 i++;
653             IPin_Release(ppin);
654         }
655         *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
656         /* Retrieve output pins */
657         IEnumPins_Reset(penumpins);
658         i = 0;
659         while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
660             PIN_DIRECTION pindir;
661             IPin_QueryDirection(ppin, &pindir);
662             if (pindir == PINDIR_OUTPUT)
663                 (*pppins)[i++] = ppin;
664             else
665                 IPin_Release(ppin);
666         }
667         IEnumPins_Release(penumpins);
668         nb = i;
669         if (FAILED(hr)) {
670             ERR("Next failed (%x)\n", hr);
671             return hr;
672         }
673     } else if (FAILED(hr)) {
674         ERR("Cannot get internal connection (%x)\n", hr);
675         return hr;
676     }
677
678     *pnb = nb;
679     return S_OK;
680 }
681
682 /*** IGraphBuilder methods ***/
683 static HRESULT WINAPI GraphBuilder_Connect(IGraphBuilder *iface,
684                                            IPin *ppinOut,
685                                            IPin *ppinIn) {
686     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
687     HRESULT hr;
688     AM_MEDIA_TYPE* mt;
689     IEnumMediaTypes* penummt;
690     ULONG nbmt;
691     IEnumPins* penumpins;
692     IEnumMoniker* pEnumMoniker;
693     GUID tab[2];
694     ULONG nb;
695     IMoniker* pMoniker;
696     ULONG pin;
697     PIN_INFO PinInfo;
698     CLSID FilterCLSID;
699
700     TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
701
702     if (TRACE_ON(quartz))
703     {
704         hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
705         if (FAILED(hr))
706             return hr;
707
708         TRACE("Filter owning first pin => %p\n", PinInfo.pFilter);
709         IBaseFilter_Release(PinInfo.pFilter);
710
711         hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
712         if (FAILED(hr))
713             return hr;
714
715         TRACE("Filter owning second pin => %p\n", PinInfo.pFilter);
716         IBaseFilter_Release(PinInfo.pFilter);
717     }
718
719     /* Try direct connection first */
720     hr = IPin_Connect(ppinOut, ppinIn, NULL);
721     if (SUCCEEDED(hr)) {
722         return S_OK;
723     }
724     TRACE("Direct connection failed, trying to insert other filters\n");
725
726     hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
727     if (FAILED(hr))
728        return hr;
729
730     hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
731     IBaseFilter_Release(PinInfo.pFilter);
732     if (FAILED(hr))
733        return hr;
734
735     /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream 
736      * filter to the minor mediatype of input pin of the renderer */
737     hr = IPin_EnumMediaTypes(ppinOut, &penummt);
738     if (FAILED(hr)) {
739         ERR("EnumMediaTypes (%x)\n", hr);
740         return hr;
741     }
742
743     hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
744     if (FAILED(hr)) {
745         ERR("IEnumMediaTypes_Next (%x)\n", hr);
746         return hr;
747     }
748
749     if (!nbmt) {
750         ERR("No media type found!\n");
751         return S_OK;
752     }
753     TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
754     TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
755
756     /* Try to find a suitable filter that can connect to the pin to render */
757     tab[0] = mt->majortype;
758     tab[1] = mt->subtype;
759     hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
760     if (FAILED(hr)) {
761         ERR("Unable to enum filters (%x)\n", hr);
762         return hr;
763     }
764     
765     while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
766     {
767         VARIANT var;
768         GUID clsid;
769         IPin** ppins;
770         IPin* ppinfilter = NULL;
771         IBaseFilter* pfilter = NULL;
772
773         hr = GetFilterInfo(pMoniker, &clsid, &var);
774         IMoniker_Release(pMoniker);
775         if (FAILED(hr)) {
776             ERR("Unable to retrieve filter info (%x)\n", hr);
777             goto error;
778         }
779
780         if (IsEqualGUID(&clsid, &FilterCLSID)) {
781             /* Skip filter (same as the one the output pin belongs to) */
782             goto error;
783         }
784
785         hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
786         if (FAILED(hr)) {
787             ERR("Unable to create filter (%x), trying next one\n", hr);
788             goto error;
789         }
790
791         hr = IGraphBuilder_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
792         if (FAILED(hr)) {
793             ERR("Unable to add filter (%x)\n", hr);
794             IBaseFilter_Release(pfilter);
795             pfilter = NULL;
796             goto error;
797         }
798
799         hr = IBaseFilter_EnumPins(pfilter, &penumpins);
800         if (FAILED(hr)) {
801             ERR("Enumpins (%x)\n", hr);
802             goto error;
803         }
804
805         hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
806         IEnumPins_Release(penumpins);
807
808         if (FAILED(hr)) {
809             ERR("Next (%x)\n", hr);
810             goto error;
811         }
812         if (pin == 0) {
813             ERR("No Pin\n");
814             goto error;
815         }
816
817         hr = IPin_Connect(ppinOut, ppinfilter, NULL);
818         if (FAILED(hr)) {
819             TRACE("Cannot connect to filter (%x), trying next one\n", hr);
820             goto error;
821         }
822         TRACE("Successfully connected to filter, follow chain...\n");
823
824         /* Render all output pins of the filter by calling IGraphBuilder_Render on each of them */
825         hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
826
827         if (SUCCEEDED(hr)) {
828             int i;
829             if (nb == 0) {
830                 IPin_Disconnect(ppinOut);
831                 goto error;
832             }
833             TRACE("pins to consider: %d\n", nb);
834             for(i = 0; i < nb; i++) {
835                 TRACE("Processing pin %d\n", i);
836                 hr = IGraphBuilder_Connect(iface, ppins[i], ppinIn);
837                 if (FAILED(hr)) {
838                    TRACE("Cannot render pin %p (%x)\n", ppinfilter, hr);
839                 }
840                 IPin_Release(ppins[i]);
841                 if (SUCCEEDED(hr)) break;
842             }
843             while (++i < nb) IPin_Release(ppins[i]);
844             CoTaskMemFree(ppins);
845             IPin_Release(ppinfilter);
846             IBaseFilter_Release(pfilter);
847             break;
848         }
849
850 error:
851         if (ppinfilter) IPin_Release(ppinfilter);
852         if (pfilter) {
853             IGraphBuilder_RemoveFilter(iface, pfilter);
854             IBaseFilter_Release(pfilter);
855         }
856     }
857
858     IEnumMediaTypes_Release(penummt);
859     DeleteMediaType(mt);
860     
861     return S_OK;
862 }
863
864 static HRESULT WINAPI GraphBuilder_Render(IGraphBuilder *iface,
865                                           IPin *ppinOut) {
866     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
867     IEnumMediaTypes* penummt;
868     AM_MEDIA_TYPE* mt;
869     ULONG nbmt;
870     HRESULT hr;
871
872     IEnumMoniker* pEnumMoniker;
873     GUID tab[2];
874     ULONG nb;
875     IMoniker* pMoniker;
876
877     TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
878
879     if (TRACE_ON(quartz))
880     {
881         PIN_INFO PinInfo;
882
883         hr = IPin_QueryPinInfo(ppinOut, &PinInfo);
884         if (FAILED(hr))
885             return hr;
886
887         TRACE("Filter owning pin => %p\n", PinInfo.pFilter);
888         IBaseFilter_Release(PinInfo.pFilter);
889     }
890
891     hr = IPin_EnumMediaTypes(ppinOut, &penummt);
892     if (FAILED(hr)) {
893         ERR("EnumMediaTypes (%x)\n", hr);
894         return hr;
895     }
896
897     while(1)
898     {
899         hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
900         if (FAILED(hr)) {
901             ERR("IEnumMediaTypes_Next (%x)\n", hr);
902             return hr;
903         }
904         if (!nbmt)
905             break;
906         TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
907         TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
908
909         /* Try to find a suitable renderer with the same media type */
910         tab[0] = mt->majortype;
911         tab[1] = GUID_NULL;
912         hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL);
913         if (FAILED(hr)) {
914             ERR("Unable to enum filters (%x)\n", hr);
915             return hr;
916         }
917
918         while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
919         {
920             VARIANT var;
921             GUID clsid;
922             IPin* ppinfilter;
923             IBaseFilter* pfilter = NULL;
924             IEnumPins* penumpins;
925             ULONG pin;
926
927             hr = GetFilterInfo(pMoniker, &clsid, &var);
928             IMoniker_Release(pMoniker);
929             if (FAILED(hr)) {
930                 ERR("Unable to retrieve filter info (%x)\n", hr);
931                 goto error;
932             }
933
934             hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
935             if (FAILED(hr)) {
936                ERR("Unable to create filter (%x), trying next one\n", hr);
937                goto error;
938             }
939
940             hr = IGraphBuilder_AddFilter(iface, pfilter, V_UNION(&var, bstrVal));
941             if (FAILED(hr)) {
942                 ERR("Unable to add filter (%x)\n", hr);
943                 IBaseFilter_Release(pfilter);
944                 pfilter = NULL;
945                 goto error;
946             }
947
948             hr = IBaseFilter_EnumPins(pfilter, &penumpins);
949             if (FAILED(hr)) {
950                 ERR("Splitter Enumpins (%x)\n", hr);
951                 goto error;
952             }
953             hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
954             IEnumPins_Release(penumpins);
955             if (FAILED(hr)) {
956                ERR("Next (%x)\n", hr);
957                goto error;
958             }
959             if (pin == 0) {
960                ERR("No Pin\n");
961                goto error;
962             }
963
964             /* Connect the pin to render to the renderer */
965             hr = IGraphBuilder_Connect(iface, ppinOut, ppinfilter);
966             if (FAILED(hr)) {
967                 TRACE("Unable to connect to renderer (%x)\n", hr);
968                 IPin_Release(ppinfilter);
969                 goto error;
970             }
971             IPin_Release(ppinfilter);
972             IBaseFilter_Release(pfilter);
973             pfilter = NULL;
974             break;
975
976 error:
977             if (pfilter) {
978                 IGraphBuilder_RemoveFilter(iface, pfilter);
979                 IBaseFilter_Release(pfilter);
980             }
981         }
982        
983         DeleteMediaType(mt);
984         break;  
985     }
986
987     IEnumMediaTypes_Release(penummt);
988     
989     return S_OK;
990 }
991
992 static HRESULT WINAPI GraphBuilder_RenderFile(IGraphBuilder *iface,
993                                               LPCWSTR lpcwstrFile,
994                                               LPCWSTR lpcwstrPlayList) {
995     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
996     static const WCHAR string[] = {'R','e','a','d','e','r',0};
997     IBaseFilter* preader = NULL;
998     IBaseFilter* psplitter = NULL;
999     IPin* ppinreader = NULL;
1000     IPin* ppinsplitter = NULL;
1001     IEnumPins* penumpins;
1002     ULONG pin;
1003     HRESULT hr;
1004     IEnumMoniker* pEnumMoniker = NULL;
1005     GUID tab[2];
1006     IPin** ppins = NULL;
1007     ULONG nb;
1008     IMoniker* pMoniker;
1009     IFileSourceFilter* pfile = NULL;
1010     AM_MEDIA_TYPE mt;
1011     WCHAR* filename;
1012
1013     TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
1014
1015     if (lpcwstrPlayList != NULL)
1016         return E_INVALIDARG;
1017
1018     hr = IGraphBuilder_AddSourceFilter(iface, lpcwstrFile, string, &preader);
1019
1020     /* Retrieve file media type */
1021     if (SUCCEEDED(hr))
1022         hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1023     if (SUCCEEDED(hr)) {
1024         hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1025         IFileSourceFilter_Release(pfile);
1026     }
1027
1028     if (SUCCEEDED(hr))
1029         hr = IBaseFilter_EnumPins(preader, &penumpins);
1030     if (SUCCEEDED(hr)) {
1031         hr = IEnumPins_Next(penumpins, 1, &ppinreader, &pin);
1032         IEnumPins_Release(penumpins);
1033     }
1034
1035     if (SUCCEEDED(hr)) {
1036         tab[0] = mt.majortype;
1037         tab[1] = mt.subtype;
1038         hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
1039     }
1040
1041     if (FAILED(hr))
1042     {
1043         if (ppinreader)
1044             IPin_Release(ppinreader);
1045         if (pEnumMoniker)
1046             IEnumMoniker_Release(pEnumMoniker);
1047         if (preader) {
1048              IGraphBuilder_RemoveFilter(iface, preader);
1049              IBaseFilter_Release(preader);
1050         }
1051         return hr;
1052     }
1053
1054     hr = VFW_E_CANNOT_RENDER;
1055     while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
1056     {
1057         VARIANT var;
1058         GUID clsid;
1059
1060         hr = GetFilterInfo(pMoniker, &clsid, &var);
1061         IMoniker_Release(pMoniker);
1062         if (FAILED(hr)) {
1063             ERR("Unable to retrieve filter info (%x)\n", hr);
1064             continue;
1065         }
1066
1067         hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&psplitter);
1068         if (FAILED(hr)) {
1069            ERR("Unable to create filter (%x), trying next one\n", hr);
1070            continue;
1071         }
1072
1073         hr = IGraphBuilder_AddFilter(iface, psplitter, V_UNION(&var, bstrVal));
1074         if (FAILED(hr)) {
1075             ERR("Unable add filter (%x)\n", hr);
1076             IBaseFilter_Release(psplitter);
1077             continue;
1078         }
1079
1080         /* Connect file source and splitter filters together */
1081         /* Make the splitter analyze incoming data */
1082
1083         hr = IBaseFilter_EnumPins(psplitter, &penumpins);
1084         if (SUCCEEDED(hr)) {
1085             hr = IEnumPins_Next(penumpins, 1, &ppinsplitter, &pin);
1086             IEnumPins_Release(penumpins);
1087         }
1088
1089         if (SUCCEEDED(hr))
1090             hr = IPin_Connect(ppinreader, ppinsplitter, NULL);
1091
1092         /* Make sure there's some output pins in the filter */
1093         if (SUCCEEDED(hr))
1094             hr = GetInternalConnections(psplitter, ppinsplitter, &ppins, &nb);
1095         if (SUCCEEDED(hr)) {
1096             if(nb == 0) {
1097                 IPin_Disconnect(ppinreader);
1098                 TRACE("No output pins found in filter\n");
1099                 hr = VFW_E_CANNOT_RENDER;
1100             }
1101         }
1102
1103         if (ppinsplitter)
1104             IPin_Release(ppinsplitter);
1105         ppinsplitter = NULL;
1106
1107         if (SUCCEEDED(hr)) {
1108             TRACE("Successfully connected to filter\n");
1109             break;
1110         }
1111
1112         TRACE("Cannot connect to filter (%x), trying next one\n", hr);
1113
1114         if (ppins) {
1115             CoTaskMemFree(ppins);
1116             ppins = NULL;
1117         }
1118         IGraphBuilder_RemoveFilter(iface, psplitter);
1119         IBaseFilter_Release(psplitter);
1120         psplitter = NULL;
1121     }
1122
1123     /* Render all output pin of the splitter by calling IGraphBuilder_Render on each of them */
1124     if (SUCCEEDED(hr)) {
1125         int partial = 0;
1126         int i;
1127         TRACE("pins to consider: %d\n", nb);
1128         for(i = 0; i < nb; i++) {
1129             TRACE("Processing pin %d\n", i);
1130             hr = IGraphBuilder_Render(iface, ppins[i]);
1131             if (FAILED(hr)) {
1132                 ERR("Cannot render pin %p (%x)\n", ppins[i], hr);
1133                 partial = 1;
1134             }
1135             IPin_Release(ppins[i]);
1136         }
1137         CoTaskMemFree(ppins);
1138
1139         hr = (partial ? VFW_S_PARTIAL_RENDER : S_OK);
1140     }
1141
1142     IPin_Release(ppinreader);
1143     IBaseFilter_Release(preader);
1144     if (psplitter)
1145         IBaseFilter_Release(psplitter);
1146
1147     return hr;
1148 }
1149
1150 static HRESULT WINAPI GraphBuilder_AddSourceFilter(IGraphBuilder *iface,
1151                                                    LPCWSTR lpcwstrFileName,
1152                                                    LPCWSTR lpcwstrFilterName,
1153                                                    IBaseFilter **ppFilter) {
1154     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1155     HRESULT hr;
1156     IBaseFilter* preader;
1157     IFileSourceFilter* pfile = NULL;
1158     AM_MEDIA_TYPE mt;
1159     WCHAR* filename;
1160
1161     TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
1162
1163     /* Instantiate a file source filter */ 
1164     hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
1165     if (FAILED(hr)) {
1166         ERR("Unable to create file source filter (%x)\n", hr);
1167         return hr;
1168     }
1169
1170     hr = IGraphBuilder_AddFilter(iface, preader, lpcwstrFilterName);
1171     if (FAILED(hr)) {
1172         ERR("Unable add filter (%x)\n", hr);
1173         IBaseFilter_Release(preader);
1174         return hr;
1175     }
1176
1177     hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1178     if (FAILED(hr)) {
1179         ERR("Unable to get IFileSourceInterface (%x)\n", hr);
1180         goto error;
1181     }
1182
1183     /* Load the file in the file source filter */
1184     hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1185     if (FAILED(hr)) {
1186         ERR("Load (%x)\n", hr);
1187         goto error;
1188     }
1189     
1190     IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1191     if (FAILED(hr)) {
1192         ERR("GetCurFile (%x)\n", hr);
1193         goto error;
1194     }
1195     TRACE("File %s\n", debugstr_w(filename));
1196     TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1197     TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1198
1199     if (ppFilter)
1200         *ppFilter = preader;
1201     IFileSourceFilter_Release(pfile);
1202
1203     return S_OK;
1204     
1205 error:
1206     if (pfile)
1207         IFileSourceFilter_Release(pfile);
1208     IGraphBuilder_RemoveFilter(iface, preader);
1209     IBaseFilter_Release(preader);
1210        
1211     return hr;
1212 }
1213
1214 static HRESULT WINAPI GraphBuilder_SetLogFile(IGraphBuilder *iface,
1215                                               DWORD_PTR hFile) {
1216     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1217
1218     TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile);
1219
1220     return S_OK;
1221 }
1222
1223 static HRESULT WINAPI GraphBuilder_Abort(IGraphBuilder *iface) {
1224     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1225
1226     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1227
1228     return S_OK;
1229 }
1230
1231 static HRESULT WINAPI GraphBuilder_ShouldOperationContinue(IGraphBuilder *iface) {
1232     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1233
1234     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1235
1236     return S_OK;
1237 }
1238
1239
1240 static const IGraphBuilderVtbl IGraphBuilder_VTable =
1241 {
1242     GraphBuilder_QueryInterface,
1243     GraphBuilder_AddRef,
1244     GraphBuilder_Release,
1245     GraphBuilder_AddFilter,
1246     GraphBuilder_RemoveFilter,
1247     GraphBuilder_EnumFilters,
1248     GraphBuilder_FindFilterByName,
1249     GraphBuilder_ConnectDirect,
1250     GraphBuilder_Reconnect,
1251     GraphBuilder_Disconnect,
1252     GraphBuilder_SetDefaultSyncSource,
1253     GraphBuilder_Connect,
1254     GraphBuilder_Render,
1255     GraphBuilder_RenderFile,
1256     GraphBuilder_AddSourceFilter,
1257     GraphBuilder_SetLogFile,
1258     GraphBuilder_Abort,
1259     GraphBuilder_ShouldOperationContinue
1260 };
1261
1262 /*** IUnknown methods ***/
1263 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface,
1264                                                   REFIID riid,
1265                                                   LPVOID*ppvObj) {
1266     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1267
1268     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1269
1270     return Filtergraph_QueryInterface(This, riid, ppvObj);
1271 }
1272
1273 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) {
1274     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1275
1276     TRACE("(%p/%p)->()\n", This, iface);
1277
1278     return Filtergraph_AddRef(This);
1279 }
1280
1281 static ULONG WINAPI MediaControl_Release(IMediaControl *iface) {
1282     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1283
1284     TRACE("(%p/%p)->()\n", This, iface);
1285
1286     return Filtergraph_Release(This);
1287
1288 }
1289
1290 /*** IDispatch methods ***/
1291 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface,
1292                                                     UINT*pctinfo) {
1293     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1294
1295     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1296
1297     return S_OK;
1298 }
1299
1300 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface,
1301                                                UINT iTInfo,
1302                                                LCID lcid,
1303                                                ITypeInfo**ppTInfo) {
1304     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1305
1306     TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1307
1308     return S_OK;
1309 }
1310
1311 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface,
1312                                                  REFIID riid,
1313                                                  LPOLESTR*rgszNames,
1314                                                  UINT cNames,
1315                                                  LCID lcid,
1316                                                  DISPID*rgDispId) {
1317     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1318
1319     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1320
1321     return S_OK;
1322 }
1323
1324 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface,
1325                                           DISPID dispIdMember,
1326                                           REFIID riid,
1327                                           LCID lcid,
1328                                           WORD wFlags,
1329                                           DISPPARAMS*pDispParams,
1330                                           VARIANT*pVarResult,
1331                                           EXCEPINFO*pExepInfo,
1332                                           UINT*puArgErr) {
1333     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1334
1335     TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1336
1337     return S_OK;
1338 }
1339
1340 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *);
1341
1342 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter)
1343 {
1344     HRESULT hr;
1345     IPin* pInputPin;
1346     IPin** ppPins;
1347     ULONG nb;
1348     ULONG i;
1349     PIN_INFO PinInfo;
1350
1351     TRACE("%p %p\n", pGraph, pOutputPin);
1352     PinInfo.pFilter = NULL;
1353
1354     hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1355
1356     if (SUCCEEDED(hr))
1357     {
1358         hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1359         if (SUCCEEDED(hr))
1360             hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1361         IPin_Release(pInputPin);
1362     }
1363
1364     if (SUCCEEDED(hr))
1365     {
1366         if (nb == 0)
1367         {
1368             TRACE("Reached a renderer\n");
1369             /* Count renderers for end of stream notification */
1370             pGraph->nRenderers++;
1371         }
1372         else
1373         {
1374             for(i = 0; i < nb; i++)
1375             {
1376                 /* Explore the graph downstream from this pin
1377                  * FIXME: We should prevent exploring from a pin more than once. This can happens when
1378                  * several input pins are connected to the same output (a MUX for instance). */
1379                 ExploreGraph(pGraph, ppPins[i], FoundFilter);
1380                 IPin_Release(ppPins[i]);
1381             }
1382
1383             CoTaskMemFree(ppPins);
1384         }
1385         TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
1386         FoundFilter(PinInfo.pFilter);
1387     }
1388
1389     if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
1390     return hr;
1391 }
1392
1393 static HRESULT WINAPI SendRun(IBaseFilter *pFilter) {
1394    return IBaseFilter_Run(pFilter, 0);
1395 }
1396
1397 static HRESULT WINAPI SendPause(IBaseFilter *pFilter) {
1398    return IBaseFilter_Pause(pFilter);
1399 }
1400
1401 static HRESULT WINAPI SendStop(IBaseFilter *pFilter) {
1402    return IBaseFilter_Stop(pFilter);
1403 }
1404
1405 static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter) {
1406     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1407     int i;
1408     IBaseFilter* pfilter;
1409     IEnumPins* pEnum;
1410     HRESULT hr;
1411     IPin* pPin;
1412     DWORD dummy;
1413     PIN_DIRECTION dir;
1414     TRACE("(%p/%p)->()\n", This, iface);
1415
1416     /* Explorer the graph from source filters to renderers, determine renderers
1417      * number and run filters from renderers to source filters */
1418     This->nRenderers = 0;  
1419     ResetEvent(This->hEventCompletion);
1420
1421     for(i = 0; i < This->nFilters; i++)
1422     {
1423         BOOL source = TRUE;
1424         pfilter = This->ppFiltersInGraph[i];
1425         hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1426         if (hr != S_OK)
1427         {
1428             ERR("Enum pins failed %x\n", hr);
1429             continue;
1430         }
1431         /* Check if it is a source filter */
1432         while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1433         {
1434             IPin_QueryDirection(pPin, &dir);
1435             IPin_Release(pPin);
1436             if (dir == PINDIR_INPUT)
1437             {
1438                 source = FALSE;
1439                 break;
1440             }
1441         }
1442         if (source)
1443         {
1444             TRACE("Found a source filter %p\n", pfilter);
1445             IEnumPins_Reset(pEnum);
1446             while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1447             {
1448                 /* Explore the graph downstream from this pin */
1449                 ExploreGraph(This, pPin, FoundFilter);
1450                 IPin_Release(pPin);
1451             }
1452             FoundFilter(pfilter);
1453         }
1454         IEnumPins_Release(pEnum);
1455     }
1456
1457     return S_FALSE;
1458 }
1459
1460 /*** IMediaControl methods ***/
1461 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) {
1462     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1463     TRACE("(%p/%p)->()\n", This, iface);
1464
1465     if (This->state == State_Running) return S_OK;
1466
1467     EnterCriticalSection(&This->cs);
1468     SendFilterMessage(iface, SendRun);
1469     This->state = State_Running;
1470     LeaveCriticalSection(&This->cs);
1471     return S_FALSE;
1472 }
1473
1474 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) {
1475     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1476     TRACE("(%p/%p)->()\n", This, iface);
1477
1478     if (This->state == State_Paused) return S_OK;
1479
1480     EnterCriticalSection(&This->cs);
1481     SendFilterMessage(iface, SendPause);
1482     This->state = State_Paused;
1483     LeaveCriticalSection(&This->cs);
1484     return S_FALSE;
1485 }
1486
1487 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) {
1488     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1489     TRACE("(%p/%p)->()\n", This, iface);
1490
1491     if (This->state == State_Stopped) return S_OK;
1492
1493     EnterCriticalSection(&This->cs);
1494     if (This->state == State_Running) SendFilterMessage(iface, SendPause);
1495     SendFilterMessage(iface, SendStop);
1496     This->state = State_Stopped;
1497     LeaveCriticalSection(&This->cs);
1498     return S_FALSE;
1499 }
1500
1501 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,
1502                                             LONG msTimeout,
1503                                             OAFilterState *pfs) {
1504     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1505
1506     TRACE("(%p/%p)->(%d, %p): semi-stub !!!\n", This, iface, msTimeout, pfs);
1507
1508     EnterCriticalSection(&This->cs);
1509
1510     *pfs = This->state;
1511
1512     LeaveCriticalSection(&This->cs);
1513
1514     return S_OK;
1515 }
1516
1517 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface,
1518                                               BSTR strFilename) {
1519     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1520
1521     TRACE("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
1522
1523     return S_OK;
1524 }
1525
1526 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface,
1527                                                    BSTR strFilename,
1528                                                    IDispatch **ppUnk) {
1529     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1530
1531     TRACE("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
1532
1533     return S_OK;
1534 }
1535
1536 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface,
1537                                                         IDispatch **ppUnk) {
1538     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1539
1540     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1541
1542     return S_OK;
1543 }
1544
1545 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface,
1546                                                            IDispatch **ppUnk) {
1547     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1548
1549     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1550
1551     return S_OK;
1552 }
1553
1554 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) {
1555     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1556
1557     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1558
1559     return S_OK;
1560 }
1561
1562
1563 static const IMediaControlVtbl IMediaControl_VTable =
1564 {
1565     MediaControl_QueryInterface,
1566     MediaControl_AddRef,
1567     MediaControl_Release,
1568     MediaControl_GetTypeInfoCount,
1569     MediaControl_GetTypeInfo,
1570     MediaControl_GetIDsOfNames,
1571     MediaControl_Invoke,
1572     MediaControl_Run,
1573     MediaControl_Pause,
1574     MediaControl_Stop,
1575     MediaControl_GetState,
1576     MediaControl_RenderFile,
1577     MediaControl_AddSourceFilter,
1578     MediaControl_get_FilterCollection,
1579     MediaControl_get_RegFilterCollection,
1580     MediaControl_StopWhenReady
1581 };
1582
1583
1584 /*** IUnknown methods ***/
1585 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface,
1586                                                   REFIID riid,
1587                                                   LPVOID*ppvObj) {
1588     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1589
1590     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1591
1592     return Filtergraph_QueryInterface(This, riid, ppvObj);
1593 }
1594
1595 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) {
1596     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1597
1598     TRACE("(%p/%p)->()\n", This, iface);
1599
1600     return Filtergraph_AddRef(This);
1601 }
1602
1603 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) {
1604     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1605
1606     TRACE("(%p/%p)->()\n", This, iface);
1607
1608     return Filtergraph_Release(This);
1609 }
1610
1611 /*** IMediaSeeking methods ***/
1612 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface,
1613                                                    DWORD *pCapabilities) {
1614     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1615
1616     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCapabilities);
1617
1618     return S_OK;
1619 }
1620
1621 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface,
1622                                                      DWORD *pCapabilities) {
1623     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1624
1625     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCapabilities);
1626
1627     return S_OK;
1628 }
1629
1630 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface,
1631                                                      const GUID *pFormat) {
1632     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1633
1634     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1635
1636     return S_OK;
1637 }
1638
1639 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface,
1640                                                         GUID *pFormat) {
1641     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1642
1643     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1644
1645     return S_OK;
1646 }
1647
1648 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface,
1649                                                  GUID *pFormat) {
1650     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1651
1652     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1653
1654     return S_OK;
1655 }
1656
1657 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface,
1658                                                      const GUID *pFormat) {
1659     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1660
1661     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1662
1663     return S_OK;
1664 }
1665
1666 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface,
1667                                                  const GUID *pFormat) {
1668     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1669
1670     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1671
1672     return S_OK;
1673 }
1674
1675 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface,
1676                                                LONGLONG *pDuration) {
1677     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1678
1679     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDuration);
1680
1681     return S_OK;
1682 }
1683
1684 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface,
1685                                                    LONGLONG *pStop) {
1686     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1687
1688     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pStop);
1689
1690     return S_OK;
1691 }
1692
1693 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface,
1694                                                       LONGLONG *pCurrent) {
1695     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1696
1697     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCurrent);
1698
1699     return S_OK;
1700 }
1701
1702 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface,
1703                                                      LONGLONG *pTarget,
1704                                                      const GUID *pTargetFormat,
1705                                                      LONGLONG Source,
1706                                                      const GUID *pSourceFormat) {
1707     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1708
1709     TRACE("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
1710         pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
1711
1712     return S_OK;
1713 }
1714
1715 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface,
1716                                                 LONGLONG *pCurrent,
1717                                                 DWORD dwCurrentFlags,
1718                                                 LONGLONG *pStop,
1719                                                 DWORD dwStopFlags) {
1720     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1721
1722     TRACE("(%p/%p)->(%p, %08x, %p, %08x): stub !!!\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
1723
1724     return S_OK;
1725 }
1726
1727 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface,
1728                                                 LONGLONG *pCurrent,
1729                                                 LONGLONG *pStop) {
1730     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1731
1732     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pCurrent, pStop);
1733
1734     return S_OK;
1735 }
1736
1737 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface,
1738                                                 LONGLONG *pEarliest,
1739                                                 LONGLONG *pLatest) {
1740     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1741
1742     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
1743
1744     return S_OK;
1745 }
1746
1747 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface,
1748                                            double dRate) {
1749     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1750
1751     TRACE("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
1752
1753     return S_OK;
1754 }
1755
1756 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface,
1757                                            double *pdRate) {
1758     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1759
1760     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
1761
1762     return S_OK;
1763 }
1764
1765 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface,
1766                                               LONGLONG *pllPreroll) {
1767     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1768
1769     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
1770
1771     return S_OK;
1772 }
1773
1774
1775 static const IMediaSeekingVtbl IMediaSeeking_VTable =
1776 {
1777     MediaSeeking_QueryInterface,
1778     MediaSeeking_AddRef,
1779     MediaSeeking_Release,
1780     MediaSeeking_GetCapabilities,
1781     MediaSeeking_CheckCapabilities,
1782     MediaSeeking_IsFormatSupported,
1783     MediaSeeking_QueryPreferredFormat,
1784     MediaSeeking_GetTimeFormat,
1785     MediaSeeking_IsUsingTimeFormat,
1786     MediaSeeking_SetTimeFormat,
1787     MediaSeeking_GetDuration,
1788     MediaSeeking_GetStopPosition,
1789     MediaSeeking_GetCurrentPosition,
1790     MediaSeeking_ConvertTimeFormat,
1791     MediaSeeking_SetPositions,
1792     MediaSeeking_GetPositions,
1793     MediaSeeking_GetAvailable,
1794     MediaSeeking_SetRate,
1795     MediaSeeking_GetRate,
1796     MediaSeeking_GetPreroll
1797 };
1798
1799 /*** IUnknown methods ***/
1800 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj){
1801     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
1802
1803     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1804
1805     return Filtergraph_QueryInterface(This, riid, ppvObj);
1806 }
1807
1808 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface){
1809     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
1810
1811     TRACE("(%p/%p)->()\n", This, iface);
1812
1813     return Filtergraph_AddRef(This);
1814 }
1815
1816 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface){
1817     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
1818
1819     TRACE("(%p/%p)->()\n", This, iface);
1820
1821     return Filtergraph_Release(This);
1822 }
1823
1824 /*** IDispatch methods ***/
1825 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
1826     FIXME("(%p) stub!\n", iface);
1827     return E_NOTIMPL;
1828 }
1829
1830 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
1831     FIXME("(%p) stub!\n", iface);
1832     return E_NOTIMPL;
1833 }
1834
1835 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
1836     FIXME("(%p) stub!\n", iface);
1837     return E_NOTIMPL;
1838 }
1839
1840 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
1841     FIXME("(%p) stub!\n", iface);
1842     return E_NOTIMPL;
1843 }
1844
1845 /*** IMediaPosition methods ***/
1846 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength){
1847     FIXME("(%p)->(%p) stub!\n", iface, plength);
1848     return E_NOTIMPL;
1849 }
1850
1851 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime){
1852     FIXME("(%p)->(%f) stub!\n", iface, llTime);
1853     return E_NOTIMPL;
1854 }
1855
1856 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime){
1857     FIXME("(%p)->(%p) stub!\n", iface, pllTime);
1858     return E_NOTIMPL;
1859 }
1860
1861 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime){
1862     FIXME("(%p)->(%p) stub!\n", iface, pllTime);
1863     return E_NOTIMPL;
1864 }
1865
1866 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime){
1867     FIXME("(%p)->(%f) stub!\n", iface, llTime);
1868     return E_NOTIMPL;
1869 }
1870
1871 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
1872     FIXME("(%p)->(%p) stub!\n", iface, pllTime);
1873     return E_NOTIMPL;
1874 }
1875
1876 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
1877     FIXME("(%p)->(%f) stub!\n", iface, llTime);
1878     return E_NOTIMPL;
1879 }
1880
1881 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate){
1882     FIXME("(%p)->(%f) stub!\n", iface, dRate);
1883     return E_NOTIMPL;
1884 }
1885
1886 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate){
1887     FIXME("(%p)->(%p) stub!\n", iface, pdRate);
1888     return E_NOTIMPL;
1889 }
1890
1891 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
1892     FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
1893     return E_NOTIMPL;
1894 }
1895
1896 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
1897     FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
1898     return E_NOTIMPL;
1899 }
1900
1901
1902 static const IMediaPositionVtbl IMediaPosition_VTable =
1903 {
1904     MediaPosition_QueryInterface,
1905     MediaPosition_AddRef,
1906     MediaPosition_Release,
1907     MediaPosition_GetTypeInfoCount,
1908     MediaPosition_GetTypeInfo,
1909     MediaPosition_GetIDsOfNames,
1910     MediaPosition_Invoke,
1911     MediaPosition_get_Duration,
1912     MediaPosition_put_CurrentPosition,
1913     MediaPosition_get_CurrentPosition,
1914     MediaPosition_get_StopTime,
1915     MediaPosition_put_StopTime,
1916     MediaPosition_get_PrerollTime,
1917     MediaPosition_put_PrerollTime,
1918     MediaPosition_put_Rate,
1919     MediaPosition_get_Rate,
1920     MediaPosition_CanSeekForward,
1921     MediaPosition_CanSeekBackward
1922 };
1923
1924 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
1925 {
1926     HRESULT hr = E_NOINTERFACE;
1927     int i;
1928     int entry;
1929
1930     /* Check if the interface type is already registered */
1931     for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
1932         if (riid == pGraph->ItfCacheEntries[entry].riid)
1933         {
1934             if (pGraph->ItfCacheEntries[entry].iface)
1935             {
1936                 /* Return the interface if available */
1937                 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
1938                 return S_OK;
1939             }
1940             break;
1941         }
1942
1943     if (entry >= MAX_ITF_CACHE_ENTRIES)
1944     {
1945         FIXME("Not enough space to store interface in the cache\n");
1946         return E_OUTOFMEMORY;
1947     }
1948
1949     /* Find a filter supporting the requested interface */
1950     for (i = 0; i < pGraph->nFilters; i++)
1951     {
1952         hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
1953         if (hr == S_OK)
1954         {
1955             pGraph->ItfCacheEntries[entry].riid = riid;
1956             pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
1957             pGraph->ItfCacheEntries[entry].iface = (IUnknown*)*ppvObj;
1958             if (entry >= pGraph->nItfCacheEntries)
1959                 pGraph->nItfCacheEntries++;
1960             return S_OK;
1961         }
1962         if (hr != E_NOINTERFACE)
1963             return hr;
1964     }
1965
1966     return hr;
1967 }
1968
1969 /*** IUnknown methods ***/
1970 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface,
1971                                                 REFIID riid,
1972                                                 LPVOID*ppvObj) {
1973     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1974
1975     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1976
1977     return Filtergraph_QueryInterface(This, riid, ppvObj);
1978 }
1979
1980 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) {
1981     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1982
1983     TRACE("(%p/%p)->()\n", This, iface);
1984
1985     return Filtergraph_AddRef(This);
1986 }
1987
1988 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) {
1989     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1990
1991     TRACE("(%p/%p)->()\n", This, iface);
1992
1993     return Filtergraph_Release(This);
1994 }
1995
1996 /*** IDispatch methods ***/
1997 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface,
1998                                                   UINT*pctinfo) {
1999     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2000     IBasicAudio* pBasicAudio;
2001     HRESULT hr;
2002
2003     TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2004
2005     EnterCriticalSection(&This->cs);
2006
2007     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2008
2009     if (hr == S_OK)
2010         hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2011
2012     LeaveCriticalSection(&This->cs);
2013
2014     return hr;
2015 }
2016
2017 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface,
2018                                              UINT iTInfo,
2019                                              LCID lcid,
2020                                              ITypeInfo**ppTInfo) {
2021     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2022     IBasicAudio* pBasicAudio;
2023     HRESULT hr;
2024
2025     TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2026
2027     EnterCriticalSection(&This->cs);
2028
2029     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2030
2031     if (hr == S_OK)
2032         hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2033
2034     LeaveCriticalSection(&This->cs);
2035
2036     return hr;
2037 }
2038
2039 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface,
2040                                                REFIID riid,
2041                                                LPOLESTR*rgszNames,
2042                                                UINT cNames,
2043                                                LCID lcid,
2044                                                DISPID*rgDispId) {
2045     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2046     IBasicAudio* pBasicAudio;
2047     HRESULT hr;
2048
2049     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2050
2051     EnterCriticalSection(&This->cs);
2052
2053     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2054
2055     if (hr == S_OK)
2056         hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
2057
2058     LeaveCriticalSection(&This->cs);
2059
2060     return hr;
2061 }
2062
2063 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface,
2064                                         DISPID dispIdMember,
2065                                         REFIID riid,
2066                                         LCID lcid,
2067                                         WORD wFlags,
2068                                         DISPPARAMS*pDispParams,
2069                                         VARIANT*pVarResult,
2070                                         EXCEPINFO*pExepInfo,
2071                                         UINT*puArgErr) {
2072     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2073     IBasicAudio* pBasicAudio;
2074     HRESULT hr;
2075
2076     TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2077
2078     EnterCriticalSection(&This->cs);
2079
2080     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2081
2082     if (hr == S_OK)
2083         hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2084
2085     LeaveCriticalSection(&This->cs);
2086
2087     return hr;
2088 }
2089
2090 /*** IBasicAudio methods ***/
2091 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface,
2092                                             long lVolume) {
2093     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2094     IBasicAudio* pBasicAudio;
2095     HRESULT hr;
2096
2097     TRACE("(%p/%p)->(%ld)\n", This, iface, lVolume);
2098
2099     EnterCriticalSection(&This->cs);
2100
2101     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2102
2103     if (hr == S_OK)
2104         hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
2105
2106     LeaveCriticalSection(&This->cs);
2107
2108     return hr;
2109 }
2110
2111 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface,
2112                                             long *plVolume) {
2113     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2114     IBasicAudio* pBasicAudio;
2115     HRESULT hr;
2116
2117     TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
2118
2119     EnterCriticalSection(&This->cs);
2120
2121     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2122
2123     if (hr == S_OK)
2124         hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
2125
2126     LeaveCriticalSection(&This->cs);
2127
2128     return hr;
2129 }
2130
2131 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface,
2132                                              long lBalance) {
2133     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2134     IBasicAudio* pBasicAudio;
2135     HRESULT hr;
2136
2137     TRACE("(%p/%p)->(%ld)\n", This, iface, lBalance);
2138
2139     EnterCriticalSection(&This->cs);
2140
2141     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2142
2143     if (hr == S_OK)
2144         hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
2145
2146     LeaveCriticalSection(&This->cs);
2147
2148     return hr;
2149 }
2150
2151 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface,
2152                                              long *plBalance) {
2153     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2154     IBasicAudio* pBasicAudio;
2155     HRESULT hr;
2156
2157     TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
2158
2159     EnterCriticalSection(&This->cs);
2160
2161     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2162
2163     if (hr == S_OK)
2164         hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
2165
2166     LeaveCriticalSection(&This->cs);
2167
2168     return hr;
2169 }
2170
2171 static const IBasicAudioVtbl IBasicAudio_VTable =
2172 {
2173     BasicAudio_QueryInterface,
2174     BasicAudio_AddRef,
2175     BasicAudio_Release,
2176     BasicAudio_GetTypeInfoCount,
2177     BasicAudio_GetTypeInfo,
2178     BasicAudio_GetIDsOfNames,
2179     BasicAudio_Invoke,
2180     BasicAudio_put_Volume,
2181     BasicAudio_get_Volume,
2182     BasicAudio_put_Balance,
2183     BasicAudio_get_Balance
2184 };
2185
2186 /*** IUnknown methods ***/
2187 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface,
2188                                                 REFIID riid,
2189                                                 LPVOID*ppvObj) {
2190     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2191
2192     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2193
2194     return Filtergraph_QueryInterface(This, riid, ppvObj);
2195 }
2196
2197 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface) {
2198     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2199
2200     TRACE("(%p/%p)->()\n", This, iface);
2201
2202     return Filtergraph_AddRef(This);
2203 }
2204
2205 static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface) {
2206     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2207
2208     TRACE("(%p/%p)->()\n", This, iface);
2209
2210     return Filtergraph_Release(This);
2211 }
2212
2213 /*** IDispatch methods ***/
2214 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo *iface,
2215                                                   UINT*pctinfo) {
2216     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2217     IBasicVideo* pBasicVideo;
2218     HRESULT hr;
2219
2220     TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2221
2222     EnterCriticalSection(&This->cs);
2223
2224     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2225
2226     if (hr == S_OK)
2227         hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
2228
2229     LeaveCriticalSection(&This->cs);
2230
2231     return hr;
2232 }
2233
2234 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo *iface,
2235                                              UINT iTInfo,
2236                                              LCID lcid,
2237                                              ITypeInfo**ppTInfo) {
2238     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2239     IBasicVideo* pBasicVideo;
2240     HRESULT hr;
2241
2242     TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2243
2244     EnterCriticalSection(&This->cs);
2245
2246     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2247
2248     if (hr == S_OK)
2249         hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
2250
2251     LeaveCriticalSection(&This->cs);
2252
2253     return hr;
2254 }
2255
2256 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo *iface,
2257                                                REFIID riid,
2258                                                LPOLESTR*rgszNames,
2259                                                UINT cNames,
2260                                                LCID lcid,
2261                                                DISPID*rgDispId) {
2262     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2263     IBasicVideo* pBasicVideo;
2264     HRESULT hr;
2265
2266     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2267
2268     EnterCriticalSection(&This->cs);
2269
2270     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2271
2272     if (hr == S_OK)
2273         hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
2274
2275     LeaveCriticalSection(&This->cs);
2276
2277     return hr;
2278 }
2279
2280 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo *iface,
2281                                         DISPID dispIdMember,
2282                                         REFIID riid,
2283                                         LCID lcid,
2284                                         WORD wFlags,
2285                                         DISPPARAMS*pDispParams,
2286                                         VARIANT*pVarResult,
2287                                         EXCEPINFO*pExepInfo,
2288                                         UINT*puArgErr) {
2289     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2290     IBasicVideo* pBasicVideo;
2291     HRESULT hr;
2292
2293     TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2294
2295     EnterCriticalSection(&This->cs);
2296
2297     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2298
2299     if (hr == S_OK)
2300         hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2301
2302     LeaveCriticalSection(&This->cs);
2303
2304     return hr;
2305 }
2306
2307 /*** IBasicVideo methods ***/
2308 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo *iface,
2309                                                      REFTIME *pAvgTimePerFrame) {
2310     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2311     IBasicVideo* pBasicVideo;
2312     HRESULT hr;
2313
2314     TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
2315
2316     EnterCriticalSection(&This->cs);
2317
2318     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2319
2320     if (hr == S_OK)
2321         hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
2322
2323     LeaveCriticalSection(&This->cs);
2324
2325     return hr;
2326 }
2327
2328 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo *iface,
2329                                              long *pBitRate) {
2330     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2331     IBasicVideo* pBasicVideo;
2332     HRESULT hr;
2333
2334     TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
2335
2336     EnterCriticalSection(&This->cs);
2337
2338     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2339
2340     if (hr == S_OK)
2341         hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
2342
2343     LeaveCriticalSection(&This->cs);
2344
2345     return hr;
2346 }
2347
2348 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo *iface,
2349                                                   long *pBitErrorRate) {
2350     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2351     IBasicVideo* pBasicVideo;
2352     HRESULT hr;
2353
2354     TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
2355
2356     EnterCriticalSection(&This->cs);
2357
2358     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2359
2360     if (hr == S_OK)
2361         hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
2362
2363     LeaveCriticalSection(&This->cs);
2364
2365     return hr;
2366 }
2367
2368 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo *iface,
2369                                                 long *pVideoWidth) {
2370     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2371     IBasicVideo* pBasicVideo;
2372     HRESULT hr;
2373
2374     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
2375
2376     EnterCriticalSection(&This->cs);
2377
2378     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2379
2380     if (hr == S_OK)
2381         hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
2382
2383     LeaveCriticalSection(&This->cs);
2384
2385     return hr;
2386 }
2387
2388 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo *iface,
2389                                                  long *pVideoHeight) {
2390     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2391     IBasicVideo* pBasicVideo;
2392     HRESULT hr;
2393
2394     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
2395
2396     EnterCriticalSection(&This->cs);
2397
2398     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2399
2400     if (hr == S_OK)
2401         hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
2402
2403     LeaveCriticalSection(&This->cs);
2404
2405     return hr;
2406 }
2407
2408 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo *iface,
2409                                                 long SourceLeft) {
2410     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2411     IBasicVideo* pBasicVideo;
2412     HRESULT hr;
2413
2414     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
2415
2416     EnterCriticalSection(&This->cs);
2417
2418     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2419
2420     if (hr == S_OK)
2421         hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
2422
2423     LeaveCriticalSection(&This->cs);
2424
2425     return hr;
2426 }
2427
2428 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo *iface,
2429                                                 long *pSourceLeft) {
2430     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2431     IBasicVideo* pBasicVideo;
2432     HRESULT hr;
2433
2434     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
2435
2436     EnterCriticalSection(&This->cs);
2437
2438     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2439
2440     if (hr == S_OK)
2441         hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
2442
2443     LeaveCriticalSection(&This->cs);
2444
2445     return hr;
2446 }
2447
2448 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo *iface,
2449                                                  long SourceWidth) {
2450     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2451     IBasicVideo* pBasicVideo;
2452     HRESULT hr;
2453
2454     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
2455
2456     EnterCriticalSection(&This->cs);
2457
2458     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2459
2460     if (hr == S_OK)
2461         hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
2462
2463     LeaveCriticalSection(&This->cs);
2464
2465     return hr;
2466 }
2467
2468 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo *iface,
2469                                                  long *pSourceWidth) {
2470     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2471     IBasicVideo* pBasicVideo;
2472     HRESULT hr;
2473
2474     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
2475
2476     EnterCriticalSection(&This->cs);
2477
2478     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2479
2480     if (hr == S_OK)
2481         hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
2482
2483     LeaveCriticalSection(&This->cs);
2484
2485     return hr;
2486 }
2487
2488 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo *iface,
2489                                                long SourceTop) {
2490     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2491     IBasicVideo* pBasicVideo;
2492     HRESULT hr;
2493
2494     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
2495
2496     EnterCriticalSection(&This->cs);
2497
2498     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2499
2500     if (hr == S_OK)
2501         hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
2502
2503     LeaveCriticalSection(&This->cs);
2504
2505     return hr;
2506 }
2507
2508 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo *iface,
2509                                                long *pSourceTop) {
2510     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2511     IBasicVideo* pBasicVideo;
2512     HRESULT hr;
2513
2514     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
2515
2516     EnterCriticalSection(&This->cs);
2517
2518     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2519
2520     if (hr == S_OK)
2521         hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
2522
2523     LeaveCriticalSection(&This->cs);
2524
2525     return hr;
2526 }
2527
2528 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo *iface,
2529                                                   long SourceHeight) {
2530     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2531     IBasicVideo* pBasicVideo;
2532     HRESULT hr;
2533
2534     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
2535
2536     EnterCriticalSection(&This->cs);
2537
2538     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2539
2540     if (hr == S_OK)
2541         hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
2542
2543     LeaveCriticalSection(&This->cs);
2544
2545     return hr;
2546 }
2547
2548 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo *iface,
2549                                                   long *pSourceHeight) {
2550     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2551     IBasicVideo* pBasicVideo;
2552     HRESULT hr;
2553
2554     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
2555
2556     EnterCriticalSection(&This->cs);
2557
2558     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2559
2560     if (hr == S_OK)
2561         hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
2562
2563     LeaveCriticalSection(&This->cs);
2564
2565     return hr;
2566 }
2567
2568 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo *iface,
2569                                                      long DestinationLeft) {
2570     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2571     IBasicVideo* pBasicVideo;
2572     HRESULT hr;
2573
2574     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
2575
2576     EnterCriticalSection(&This->cs);
2577
2578     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2579
2580     if (hr == S_OK)
2581         hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
2582
2583     LeaveCriticalSection(&This->cs);
2584
2585     return hr;
2586 }
2587
2588 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo *iface,
2589                                                      long *pDestinationLeft) {
2590     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2591     IBasicVideo* pBasicVideo;
2592     HRESULT hr;
2593
2594     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
2595
2596     EnterCriticalSection(&This->cs);
2597
2598     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2599
2600     if (hr == S_OK)
2601         hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
2602
2603     LeaveCriticalSection(&This->cs);
2604
2605     return hr;
2606 }
2607
2608 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo *iface,
2609                                                       long DestinationWidth) {
2610     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2611     IBasicVideo* pBasicVideo;
2612     HRESULT hr;
2613
2614     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
2615
2616     EnterCriticalSection(&This->cs);
2617
2618     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2619
2620     if (hr == S_OK)
2621         hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
2622
2623     LeaveCriticalSection(&This->cs);
2624
2625     return hr;
2626 }
2627
2628 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo *iface,
2629                                                       long *pDestinationWidth) {
2630     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2631     IBasicVideo* pBasicVideo;
2632     HRESULT hr;
2633
2634     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
2635
2636     EnterCriticalSection(&This->cs);
2637
2638     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2639
2640     if (hr == S_OK)
2641         hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
2642
2643     LeaveCriticalSection(&This->cs);
2644
2645     return hr;
2646 }
2647
2648 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo *iface,
2649                                                     long DestinationTop) {
2650     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2651     IBasicVideo* pBasicVideo;
2652     HRESULT hr;
2653
2654     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
2655
2656     EnterCriticalSection(&This->cs);
2657
2658     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2659
2660     if (hr == S_OK)
2661         hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
2662
2663     LeaveCriticalSection(&This->cs);
2664
2665     return hr;
2666 }
2667
2668 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo *iface,
2669                                                     long *pDestinationTop) {
2670     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2671     IBasicVideo* pBasicVideo;
2672     HRESULT hr;
2673
2674     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
2675
2676     EnterCriticalSection(&This->cs);
2677
2678     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2679
2680     if (hr == S_OK)
2681         hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
2682
2683     LeaveCriticalSection(&This->cs);
2684
2685     return hr;
2686 }
2687
2688 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo *iface,
2689                                                        long DestinationHeight) {
2690     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2691     IBasicVideo* pBasicVideo;
2692     HRESULT hr;
2693
2694     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
2695
2696     EnterCriticalSection(&This->cs);
2697
2698     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2699
2700     if (hr == S_OK)
2701         hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
2702
2703     LeaveCriticalSection(&This->cs);
2704
2705     return hr;
2706 }
2707
2708 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo *iface,
2709                                                        long *pDestinationHeight) {
2710     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2711     IBasicVideo* pBasicVideo;
2712     HRESULT hr;
2713
2714     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
2715
2716     EnterCriticalSection(&This->cs);
2717
2718     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2719
2720     if (hr == S_OK)
2721         hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
2722
2723     LeaveCriticalSection(&This->cs);
2724
2725     return hr;
2726 }
2727
2728 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo *iface,
2729                                                    long Left,
2730                                                    long Top,
2731                                                    long Width,
2732                                                    long Height) {
2733     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2734     IBasicVideo* pBasicVideo;
2735     HRESULT hr;
2736
2737     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
2738
2739     EnterCriticalSection(&This->cs);
2740
2741     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2742
2743     if (hr == S_OK)
2744         hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
2745
2746     LeaveCriticalSection(&This->cs);
2747
2748     return hr;
2749 }
2750
2751 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo *iface,
2752                                                    long *pLeft,
2753                                                    long *pTop,
2754                                                    long *pWidth,
2755                                                    long *pHeight) {
2756     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2757     IBasicVideo* pBasicVideo;
2758     HRESULT hr;
2759
2760     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
2761
2762     EnterCriticalSection(&This->cs);
2763
2764     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2765
2766     if (hr == S_OK)
2767         hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
2768
2769     LeaveCriticalSection(&This->cs);
2770
2771     return hr;
2772 }
2773
2774 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo *iface) {
2775     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2776     IBasicVideo* pBasicVideo;
2777     HRESULT hr;
2778
2779     TRACE("(%p/%p)->()\n", This, iface);
2780
2781     EnterCriticalSection(&This->cs);
2782
2783     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2784
2785     if (hr == S_OK)
2786         hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
2787
2788     LeaveCriticalSection(&This->cs);
2789
2790     return hr;
2791 }
2792
2793 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo *iface,
2794                                                         long Left,
2795                                                         long Top,
2796                                                         long Width,
2797                                                         long Height) {
2798     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2799     IBasicVideo* pBasicVideo;
2800     HRESULT hr;
2801
2802     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
2803
2804     EnterCriticalSection(&This->cs);
2805
2806     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2807
2808     if (hr == S_OK)
2809         hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
2810
2811     LeaveCriticalSection(&This->cs);
2812
2813     return hr;
2814 }
2815
2816 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo *iface,
2817                                                         long *pLeft,
2818                                                         long *pTop,
2819                                                         long *pWidth,
2820                                                         long *pHeight) {
2821     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2822     IBasicVideo* pBasicVideo;
2823     HRESULT hr;
2824
2825     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
2826
2827     EnterCriticalSection(&This->cs);
2828
2829     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2830
2831     if (hr == S_OK)
2832         hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
2833
2834     LeaveCriticalSection(&This->cs);
2835
2836     return hr;
2837 }
2838
2839 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
2840     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2841     IBasicVideo* pBasicVideo;
2842     HRESULT hr;
2843
2844     TRACE("(%p/%p)->()\n", This, iface);
2845
2846     EnterCriticalSection(&This->cs);
2847
2848     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2849
2850     if (hr == S_OK)
2851         hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
2852
2853     LeaveCriticalSection(&This->cs);
2854
2855     return hr;
2856 }
2857
2858 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo *iface,
2859                                               long *pWidth,
2860                                               long *pHeight) {
2861     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2862     IBasicVideo* pBasicVideo;
2863     HRESULT hr;
2864
2865     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
2866
2867     EnterCriticalSection(&This->cs);
2868
2869     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2870
2871     if (hr == S_OK)
2872         hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
2873
2874     LeaveCriticalSection(&This->cs);
2875
2876     return hr;
2877 }
2878
2879 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo *iface,
2880                                                         long StartIndex,
2881                                                         long Entries,
2882                                                         long *pRetrieved,
2883                                                         long *pPalette) {
2884     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2885     IBasicVideo* pBasicVideo;
2886     HRESULT hr;
2887
2888     TRACE("(%p/%p)->(%ld, %ld, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
2889
2890     EnterCriticalSection(&This->cs);
2891
2892     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2893
2894     if (hr == S_OK)
2895         hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
2896
2897     LeaveCriticalSection(&This->cs);
2898
2899     return hr;
2900 }
2901
2902 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo *iface,
2903                                                  long *pBufferSize,
2904                                                  long *pDIBImage) {
2905     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2906     IBasicVideo* pBasicVideo;
2907     HRESULT hr;
2908
2909     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
2910
2911     EnterCriticalSection(&This->cs);
2912
2913     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2914
2915     if (hr == S_OK)
2916         hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
2917
2918     LeaveCriticalSection(&This->cs);
2919
2920     return hr;
2921 }
2922
2923 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo *iface) {
2924     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2925     IBasicVideo* pBasicVideo;
2926     HRESULT hr;
2927
2928     TRACE("(%p/%p)->()\n", This, iface);
2929
2930     EnterCriticalSection(&This->cs);
2931
2932     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2933
2934     if (hr == S_OK)
2935         hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
2936
2937     LeaveCriticalSection(&This->cs);
2938
2939     return hr;
2940 }
2941
2942 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo *iface) {
2943     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2944     IBasicVideo* pBasicVideo;
2945     HRESULT hr;
2946
2947     TRACE("(%p/%p)->()\n", This, iface);
2948
2949     EnterCriticalSection(&This->cs);
2950
2951     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2952
2953     if (hr == S_OK)
2954         hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
2955
2956     LeaveCriticalSection(&This->cs);
2957
2958     return hr;
2959 }
2960
2961
2962 static const IBasicVideoVtbl IBasicVideo_VTable =
2963 {
2964     BasicVideo_QueryInterface,
2965     BasicVideo_AddRef,
2966     BasicVideo_Release,
2967     BasicVideo_GetTypeInfoCount,
2968     BasicVideo_GetTypeInfo,
2969     BasicVideo_GetIDsOfNames,
2970     BasicVideo_Invoke,
2971     BasicVideo_get_AvgTimePerFrame,
2972     BasicVideo_get_BitRate,
2973     BasicVideo_get_BitErrorRate,
2974     BasicVideo_get_VideoWidth,
2975     BasicVideo_get_VideoHeight,
2976     BasicVideo_put_SourceLeft,
2977     BasicVideo_get_SourceLeft,
2978     BasicVideo_put_SourceWidth,
2979     BasicVideo_get_SourceWidth,
2980     BasicVideo_put_SourceTop,
2981     BasicVideo_get_SourceTop,
2982     BasicVideo_put_SourceHeight,
2983     BasicVideo_get_SourceHeight,
2984     BasicVideo_put_DestinationLeft,
2985     BasicVideo_get_DestinationLeft,
2986     BasicVideo_put_DestinationWidth,
2987     BasicVideo_get_DestinationWidth,
2988     BasicVideo_put_DestinationTop,
2989     BasicVideo_get_DestinationTop,
2990     BasicVideo_put_DestinationHeight,
2991     BasicVideo_get_DestinationHeight,
2992     BasicVideo_SetSourcePosition,
2993     BasicVideo_GetSourcePosition,
2994     BasicVideo_SetDefaultSourcePosition,
2995     BasicVideo_SetDestinationPosition,
2996     BasicVideo_GetDestinationPosition,
2997     BasicVideo_SetDefaultDestinationPosition,
2998     BasicVideo_GetVideoSize,
2999     BasicVideo_GetVideoPaletteEntries,
3000     BasicVideo_GetCurrentImage,
3001     BasicVideo_IsUsingDefaultSource,
3002     BasicVideo_IsUsingDefaultDestination
3003 };
3004
3005
3006 /*** IUnknown methods ***/
3007 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface,
3008                                                  REFIID riid,
3009                                                  LPVOID*ppvObj) {
3010     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3011
3012     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3013
3014     return Filtergraph_QueryInterface(This, riid, ppvObj);
3015 }
3016
3017 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) {
3018     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3019
3020     TRACE("(%p/%p)->()\n", This, iface);
3021
3022     return Filtergraph_AddRef(This);
3023 }
3024
3025 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) {
3026     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3027
3028     TRACE("(%p/%p)->()\n", This, iface);
3029
3030     return Filtergraph_Release(This);
3031 }
3032
3033 /*** IDispatch methods ***/
3034 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface,
3035                                                    UINT*pctinfo) {
3036     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3037     IVideoWindow* pVideoWindow;
3038     HRESULT hr;
3039
3040     TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3041
3042     EnterCriticalSection(&This->cs);
3043
3044     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3045
3046     if (hr == S_OK)
3047         hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
3048
3049     LeaveCriticalSection(&This->cs);
3050
3051     return hr;
3052 }
3053
3054 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface,
3055                                               UINT iTInfo,
3056                                               LCID lcid,
3057                                               ITypeInfo**ppTInfo) {
3058     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3059     IVideoWindow* pVideoWindow;
3060     HRESULT hr;
3061
3062     TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3063
3064     EnterCriticalSection(&This->cs);
3065
3066     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3067
3068     if (hr == S_OK)
3069         hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
3070
3071     LeaveCriticalSection(&This->cs);
3072
3073     return hr;
3074 }
3075
3076 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface,
3077                                                 REFIID riid,
3078                                                 LPOLESTR*rgszNames,
3079                                                 UINT cNames,
3080                                                 LCID lcid,
3081                                                 DISPID*rgDispId) {
3082     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3083     IVideoWindow* pVideoWindow;
3084     HRESULT hr;
3085
3086     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3087
3088     EnterCriticalSection(&This->cs);
3089
3090     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3091
3092     if (hr == S_OK)
3093         hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
3094
3095     LeaveCriticalSection(&This->cs);
3096
3097     return hr;
3098 }
3099
3100 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface,
3101                                          DISPID dispIdMember,
3102                                          REFIID riid,
3103                                          LCID lcid,
3104                                          WORD wFlags,
3105                                          DISPPARAMS*pDispParams,
3106                                          VARIANT*pVarResult,
3107                                          EXCEPINFO*pExepInfo,
3108                                          UINT*puArgErr) {
3109     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3110     IVideoWindow* pVideoWindow;
3111     HRESULT hr;
3112
3113     TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3114
3115     EnterCriticalSection(&This->cs);
3116
3117     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3118
3119     if (hr == S_OK)
3120         hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3121
3122     LeaveCriticalSection(&This->cs);
3123
3124     return hr;
3125 }
3126
3127
3128 /*** IVideoWindow methods ***/
3129 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface,
3130                                               BSTR strCaption) {
3131     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3132     IVideoWindow* pVideoWindow;
3133     HRESULT hr;
3134     
3135     TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
3136
3137     EnterCriticalSection(&This->cs);
3138
3139     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3140
3141     if (hr == S_OK)
3142         hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
3143
3144     LeaveCriticalSection(&This->cs);
3145
3146     return hr;
3147 }
3148
3149 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface,
3150                                               BSTR *strCaption) {
3151     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3152     IVideoWindow* pVideoWindow;
3153     HRESULT hr;
3154
3155     TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
3156
3157     EnterCriticalSection(&This->cs);
3158
3159     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3160
3161     if (hr == S_OK)
3162         hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
3163
3164     LeaveCriticalSection(&This->cs);
3165
3166     return hr;
3167 }
3168
3169 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface,
3170                                                   long WindowStyle) {
3171     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3172     IVideoWindow* pVideoWindow;
3173     HRESULT hr;
3174
3175     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyle);
3176
3177     EnterCriticalSection(&This->cs);
3178
3179     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3180
3181     if (hr == S_OK)
3182         hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
3183
3184     LeaveCriticalSection(&This->cs);
3185
3186     return hr;
3187 }
3188
3189 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface,
3190                                                   long *WindowStyle) {
3191     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3192     IVideoWindow* pVideoWindow;
3193     HRESULT hr;
3194
3195     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
3196
3197     EnterCriticalSection(&This->cs);
3198
3199     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3200
3201     if (hr == S_OK)
3202         hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
3203
3204     LeaveCriticalSection(&This->cs);
3205
3206     return hr;
3207 }
3208
3209 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface,
3210                                                     long WindowStyleEx) {
3211     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3212     IVideoWindow* pVideoWindow;
3213     HRESULT hr;
3214
3215     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
3216
3217     EnterCriticalSection(&This->cs);
3218
3219     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3220
3221     if (hr == S_OK)
3222         hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
3223
3224     LeaveCriticalSection(&This->cs);
3225
3226     return hr;
3227 }
3228
3229 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface,
3230                                                     long *WindowStyleEx) {
3231     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3232     IVideoWindow* pVideoWindow;
3233     HRESULT hr;
3234
3235     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
3236
3237     EnterCriticalSection(&This->cs);
3238
3239     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3240
3241     if (hr == S_OK)
3242         hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
3243
3244     LeaveCriticalSection(&This->cs);
3245
3246     return hr;
3247 }
3248
3249 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface,
3250                                                long AutoShow) {
3251     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3252     IVideoWindow* pVideoWindow;
3253     HRESULT hr;
3254
3255     TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
3256
3257     EnterCriticalSection(&This->cs);
3258
3259     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3260
3261     if (hr == S_OK)
3262         hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
3263
3264     LeaveCriticalSection(&This->cs);
3265
3266     return hr;
3267 }
3268
3269 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface,
3270                                                long *AutoShow) {
3271     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3272     IVideoWindow* pVideoWindow;
3273     HRESULT hr;
3274
3275     TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
3276
3277     EnterCriticalSection(&This->cs);
3278
3279     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3280
3281     if (hr == S_OK)
3282         hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
3283
3284     LeaveCriticalSection(&This->cs);
3285
3286     return hr;
3287 }
3288
3289 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface,
3290                                                   long WindowState) {
3291     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3292     IVideoWindow* pVideoWindow;
3293     HRESULT hr;
3294
3295     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowState);
3296
3297     EnterCriticalSection(&This->cs);
3298
3299     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3300
3301     if (hr == S_OK)
3302         hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
3303
3304     LeaveCriticalSection(&This->cs);
3305
3306     return hr;
3307 }
3308
3309 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface,
3310                                                   long *WindowState) {
3311     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3312     IVideoWindow* pVideoWindow;
3313     HRESULT hr;
3314
3315     TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
3316
3317     EnterCriticalSection(&This->cs);
3318
3319     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3320
3321     if (hr == S_OK)
3322         hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
3323
3324     LeaveCriticalSection(&This->cs);
3325
3326     return hr;
3327 }
3328
3329 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface,
3330                                                         long BackgroundPalette) {
3331     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3332     IVideoWindow* pVideoWindow;
3333     HRESULT hr;
3334
3335     TRACE("(%p/%p)->(%ld)\n", This, iface, BackgroundPalette);
3336
3337     EnterCriticalSection(&This->cs);
3338
3339     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3340
3341     if (hr == S_OK)
3342         hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
3343
3344     LeaveCriticalSection(&This->cs);
3345
3346     return hr;
3347 }
3348
3349 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
3350                                                         long *pBackgroundPalette) {
3351     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3352     IVideoWindow* pVideoWindow;
3353     HRESULT hr;
3354
3355     TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
3356
3357     EnterCriticalSection(&This->cs);
3358
3359     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3360
3361     if (hr == S_OK)
3362         hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
3363
3364     LeaveCriticalSection(&This->cs);
3365
3366     return hr;
3367 }
3368
3369 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface,
3370                                               long Visible) {
3371     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3372     IVideoWindow* pVideoWindow;
3373     HRESULT hr;
3374
3375     TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
3376
3377     EnterCriticalSection(&This->cs);
3378
3379     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3380
3381     if (hr == S_OK)
3382         hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
3383
3384     LeaveCriticalSection(&This->cs);
3385
3386     return hr;
3387 }
3388
3389 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface,
3390                                               long *pVisible) {
3391     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3392     IVideoWindow* pVideoWindow;
3393     HRESULT hr;
3394
3395     TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
3396
3397     EnterCriticalSection(&This->cs);
3398
3399     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3400
3401     if (hr == S_OK)
3402         hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
3403
3404     LeaveCriticalSection(&This->cs);
3405
3406     return hr;
3407 }
3408
3409 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface,
3410                                            long Left) {
3411     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3412     IVideoWindow* pVideoWindow;
3413     HRESULT hr;
3414
3415     TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
3416
3417     EnterCriticalSection(&This->cs);
3418
3419     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3420
3421     if (hr == S_OK)
3422         hr = IVideoWindow_put_Left(pVideoWindow, Left);
3423
3424     LeaveCriticalSection(&This->cs);
3425
3426     return hr;
3427 }
3428
3429 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface,
3430                                            long *pLeft) {
3431     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3432     IVideoWindow* pVideoWindow;
3433     HRESULT hr;
3434
3435     TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
3436
3437     EnterCriticalSection(&This->cs);
3438
3439     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3440
3441     if (hr == S_OK)
3442         hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
3443
3444     LeaveCriticalSection(&This->cs);
3445
3446     return hr;
3447 }
3448
3449 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface,
3450                                             long Width) {
3451     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3452     IVideoWindow* pVideoWindow;
3453     HRESULT hr;
3454
3455     TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
3456
3457     EnterCriticalSection(&This->cs);
3458
3459     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3460
3461     if (hr == S_OK)
3462         hr = IVideoWindow_put_Width(pVideoWindow, Width);
3463
3464     LeaveCriticalSection(&This->cs);
3465
3466     return hr;
3467 }
3468
3469 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface,
3470                                             long *pWidth) {
3471     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3472     IVideoWindow* pVideoWindow;
3473     HRESULT hr;
3474
3475     TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
3476
3477     EnterCriticalSection(&This->cs);
3478
3479     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3480
3481     if (hr == S_OK)
3482         hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
3483
3484     LeaveCriticalSection(&This->cs);
3485
3486     return hr;
3487 }
3488
3489 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface,
3490                                           long Top) {
3491     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3492     IVideoWindow* pVideoWindow;
3493     HRESULT hr;
3494
3495     TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
3496
3497     EnterCriticalSection(&This->cs);
3498
3499     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3500
3501     if (hr == S_OK)
3502         hr = IVideoWindow_put_Top(pVideoWindow, Top);
3503
3504     LeaveCriticalSection(&This->cs);
3505
3506     return hr;
3507 }
3508
3509 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface,
3510                                           long *pTop) {
3511     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3512     IVideoWindow* pVideoWindow;
3513     HRESULT hr;
3514
3515     TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
3516
3517     EnterCriticalSection(&This->cs);
3518
3519     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3520
3521     if (hr == S_OK)
3522         hr = IVideoWindow_get_Top(pVideoWindow, pTop);
3523
3524     LeaveCriticalSection(&This->cs);
3525
3526     return hr;
3527 }
3528
3529 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface,
3530                                              long Height) {
3531     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3532     IVideoWindow* pVideoWindow;
3533     HRESULT hr;
3534
3535     TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
3536
3537     EnterCriticalSection(&This->cs);
3538
3539     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3540
3541     if (hr == S_OK)
3542         hr = IVideoWindow_put_Height(pVideoWindow, Height);
3543
3544     LeaveCriticalSection(&This->cs);
3545
3546     return hr;
3547 }
3548
3549 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface,
3550                                              long *pHeight) {
3551     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3552     IVideoWindow* pVideoWindow;
3553     HRESULT hr;
3554
3555     TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
3556
3557     EnterCriticalSection(&This->cs);
3558
3559     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3560
3561     if (hr == S_OK)
3562         hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
3563
3564     LeaveCriticalSection(&This->cs);
3565
3566     return hr;
3567 }
3568
3569 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface,
3570                                             OAHWND Owner) {
3571     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3572     IVideoWindow* pVideoWindow;
3573     HRESULT hr;
3574
3575     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
3576
3577     EnterCriticalSection(&This->cs);
3578
3579     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3580
3581     if (hr == S_OK)
3582         hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
3583
3584     LeaveCriticalSection(&This->cs);
3585
3586     return hr;
3587 }
3588
3589 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface,
3590                                             OAHWND *Owner) {
3591     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3592     IVideoWindow* pVideoWindow;
3593     HRESULT hr;
3594
3595     TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
3596
3597     EnterCriticalSection(&This->cs);
3598
3599     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3600
3601     if (hr == S_OK)
3602         hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
3603
3604     LeaveCriticalSection(&This->cs);
3605
3606     return hr;
3607 }
3608
3609 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface,
3610                                                    OAHWND Drain) {
3611     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3612     IVideoWindow* pVideoWindow;
3613     HRESULT hr;
3614
3615     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
3616
3617     EnterCriticalSection(&This->cs);
3618
3619     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3620
3621     if (hr == S_OK)
3622         hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
3623
3624     LeaveCriticalSection(&This->cs);
3625
3626     return hr;
3627 }
3628
3629 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface,
3630                                                    OAHWND *Drain) {
3631     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3632     IVideoWindow* pVideoWindow;
3633     HRESULT hr;
3634
3635     TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
3636
3637     EnterCriticalSection(&This->cs);
3638
3639     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3640
3641     if (hr == S_OK)
3642         hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
3643
3644     LeaveCriticalSection(&This->cs);
3645
3646     return hr;
3647 }
3648
3649 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface,
3650                                                   long *Color) {
3651     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3652     IVideoWindow* pVideoWindow;
3653     HRESULT hr;
3654
3655     TRACE("(%p/%p)->(%p)\n", This, iface, Color);
3656
3657     EnterCriticalSection(&This->cs);
3658
3659     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3660
3661     if (hr == S_OK)
3662         hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
3663
3664     LeaveCriticalSection(&This->cs);
3665
3666     return hr;
3667 }
3668
3669 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface,
3670                                                   long Color) {
3671     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3672     IVideoWindow* pVideoWindow;
3673     HRESULT hr;
3674
3675     TRACE("(%p/%p)->(%ld)\n", This, iface, Color);
3676
3677     EnterCriticalSection(&This->cs);
3678
3679     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3680
3681     if (hr == S_OK)
3682         hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
3683
3684     LeaveCriticalSection(&This->cs);
3685
3686     return hr;
3687 }
3688
3689 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
3690                                                      long *FullScreenMode) {
3691     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3692     IVideoWindow* pVideoWindow;
3693     HRESULT hr;
3694
3695     TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
3696
3697     EnterCriticalSection(&This->cs);
3698
3699     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3700
3701     if (hr == S_OK)
3702         hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
3703
3704     LeaveCriticalSection(&This->cs);
3705
3706     return hr;
3707 }
3708
3709 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface,
3710                                                      long FullScreenMode) {
3711     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3712     IVideoWindow* pVideoWindow;
3713     HRESULT hr;
3714
3715     TRACE("(%p/%p)->(%ld)\n", This, iface, FullScreenMode);
3716
3717     EnterCriticalSection(&This->cs);
3718
3719     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3720
3721     if (hr == S_OK)
3722         hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
3723
3724     LeaveCriticalSection(&This->cs);
3725
3726     return hr;
3727 }
3728
3729 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface,
3730                                                       long Focus) {
3731     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3732     IVideoWindow* pVideoWindow;
3733     HRESULT hr;
3734
3735     TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
3736
3737     EnterCriticalSection(&This->cs);
3738
3739     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3740
3741     if (hr == S_OK)
3742         hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
3743
3744     LeaveCriticalSection(&This->cs);
3745
3746     return hr;
3747 }
3748
3749 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface,
3750                                                      OAHWND hwnd,
3751                                                      long uMsg,
3752                                                      LONG_PTR wParam,
3753                                                      LONG_PTR lParam) {
3754     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3755     IVideoWindow* pVideoWindow;
3756     HRESULT hr;
3757
3758     TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
3759
3760     EnterCriticalSection(&This->cs);
3761
3762     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3763
3764     if (hr == S_OK)
3765         hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
3766
3767     LeaveCriticalSection(&This->cs);
3768
3769     return hr;
3770 }
3771
3772 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface,
3773                                                     long Left,
3774                                                     long Top,
3775                                                     long Width,
3776                                                     long Height) {
3777     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3778     IVideoWindow* pVideoWindow;
3779     HRESULT hr;
3780     
3781     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3782
3783     EnterCriticalSection(&This->cs);
3784
3785     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3786
3787     if (hr == S_OK)
3788         hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
3789
3790     LeaveCriticalSection(&This->cs);
3791
3792     return hr;
3793 }
3794
3795 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface,
3796                                                     long *pLeft,
3797                                                     long *pTop,
3798                                                     long *pWidth,
3799                                                     long *pHeight) {
3800     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3801     IVideoWindow* pVideoWindow;
3802     HRESULT hr;
3803
3804     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3805
3806     EnterCriticalSection(&This->cs);
3807
3808     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3809
3810     if (hr == S_OK)
3811         hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
3812
3813     LeaveCriticalSection(&This->cs);
3814
3815     return hr;
3816 }
3817
3818 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface,
3819                                                        long *pWidth,
3820                                                        long *pHeight) {
3821     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3822     IVideoWindow* pVideoWindow;
3823     HRESULT hr;
3824
3825     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3826
3827     EnterCriticalSection(&This->cs);
3828
3829     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3830
3831     if (hr == S_OK)
3832         hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
3833
3834     LeaveCriticalSection(&This->cs);
3835
3836     return hr;
3837 }
3838
3839 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface,
3840                                                        long *pWidth,
3841                                                        long *pHeight) {
3842     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3843     IVideoWindow* pVideoWindow;
3844     HRESULT hr;
3845
3846     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3847
3848     EnterCriticalSection(&This->cs);
3849
3850     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3851
3852     if (hr == S_OK)
3853         hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
3854
3855     LeaveCriticalSection(&This->cs);
3856
3857     return hr;
3858 }
3859
3860 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface,
3861                                                      long *pLeft,
3862                                                      long *pTop,
3863                                                      long *pWidth,
3864                                                      long *pHeight) {
3865     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3866     IVideoWindow* pVideoWindow;
3867     HRESULT hr;
3868
3869     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3870
3871     EnterCriticalSection(&This->cs);
3872
3873     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3874
3875     if (hr == S_OK)
3876         hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
3877
3878     LeaveCriticalSection(&This->cs);
3879
3880     return hr;
3881 }
3882
3883 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface,
3884                                              long HideCursor) {
3885     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3886     IVideoWindow* pVideoWindow;
3887     HRESULT hr;
3888
3889     TRACE("(%p/%p)->(%ld)\n", This, iface, HideCursor);
3890
3891     EnterCriticalSection(&This->cs);
3892
3893     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3894
3895     if (hr == S_OK)
3896         hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
3897
3898     LeaveCriticalSection(&This->cs);
3899
3900     return hr;
3901 }
3902
3903 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface,
3904                                                  long *CursorHidden) {
3905     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3906     IVideoWindow* pVideoWindow;
3907     HRESULT hr;
3908
3909     TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
3910
3911     EnterCriticalSection(&This->cs);
3912
3913     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3914
3915     if (hr == S_OK)
3916         hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
3917
3918     LeaveCriticalSection(&This->cs);
3919
3920     return hr;
3921 }
3922
3923
3924 static const IVideoWindowVtbl IVideoWindow_VTable =
3925 {
3926     VideoWindow_QueryInterface,
3927     VideoWindow_AddRef,
3928     VideoWindow_Release,
3929     VideoWindow_GetTypeInfoCount,
3930     VideoWindow_GetTypeInfo,
3931     VideoWindow_GetIDsOfNames,
3932     VideoWindow_Invoke,
3933     VideoWindow_put_Caption,
3934     VideoWindow_get_Caption,
3935     VideoWindow_put_WindowStyle,
3936     VideoWindow_get_WindowStyle,
3937     VideoWindow_put_WindowStyleEx,
3938     VideoWindow_get_WindowStyleEx,
3939     VideoWindow_put_AutoShow,
3940     VideoWindow_get_AutoShow,
3941     VideoWindow_put_WindowState,
3942     VideoWindow_get_WindowState,
3943     VideoWindow_put_BackgroundPalette,
3944     VideoWindow_get_BackgroundPalette,
3945     VideoWindow_put_Visible,
3946     VideoWindow_get_Visible,
3947     VideoWindow_put_Left,
3948     VideoWindow_get_Left,
3949     VideoWindow_put_Width,
3950     VideoWindow_get_Width,
3951     VideoWindow_put_Top,
3952     VideoWindow_get_Top,
3953     VideoWindow_put_Height,
3954     VideoWindow_get_Height,
3955     VideoWindow_put_Owner,
3956     VideoWindow_get_Owner,
3957     VideoWindow_put_MessageDrain,
3958     VideoWindow_get_MessageDrain,
3959     VideoWindow_get_BorderColor,
3960     VideoWindow_put_BorderColor,
3961     VideoWindow_get_FullScreenMode,
3962     VideoWindow_put_FullScreenMode,
3963     VideoWindow_SetWindowForeground,
3964     VideoWindow_NotifyOwnerMessage,
3965     VideoWindow_SetWindowPosition,
3966     VideoWindow_GetWindowPosition,
3967     VideoWindow_GetMinIdealImageSize,
3968     VideoWindow_GetMaxIdealImageSize,
3969     VideoWindow_GetRestorePosition,
3970     VideoWindow_HideCursor,
3971     VideoWindow_IsCursorHidden
3972 };
3973
3974
3975 /*** IUnknown methods ***/
3976 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface,
3977                                                 REFIID riid,
3978                                                 LPVOID*ppvObj) {
3979     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
3980
3981     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3982
3983     return Filtergraph_QueryInterface(This, riid, ppvObj);
3984 }
3985
3986 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) {
3987     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
3988
3989     TRACE("(%p/%p)->()\n", This, iface);
3990
3991     return Filtergraph_AddRef(This);
3992 }
3993
3994 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) {
3995     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
3996
3997     TRACE("(%p/%p)->()\n", This, iface);
3998
3999     return Filtergraph_Release(This);
4000 }
4001
4002 /*** IDispatch methods ***/
4003 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface,
4004                                                   UINT*pctinfo) {
4005     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4006
4007     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4008
4009     return S_OK;
4010 }
4011
4012 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface,
4013                                              UINT iTInfo,
4014                                              LCID lcid,
4015                                              ITypeInfo**ppTInfo) {
4016     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4017
4018     TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4019
4020     return S_OK;
4021 }
4022
4023 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface,
4024                                                REFIID riid,
4025                                                LPOLESTR*rgszNames,
4026                                                UINT cNames,
4027                                                LCID lcid,
4028                                                DISPID*rgDispId) {
4029     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4030
4031     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4032
4033     return S_OK;
4034 }
4035
4036 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface,
4037                                         DISPID dispIdMember,
4038                                         REFIID riid,
4039                                         LCID lcid,
4040                                         WORD wFlags,
4041                                         DISPPARAMS*pDispParams,
4042                                         VARIANT*pVarResult,
4043                                         EXCEPINFO*pExepInfo,
4044                                         UINT*puArgErr) {
4045     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4046
4047     TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
4048
4049     return S_OK;
4050 }
4051
4052 /*** IMediaEvent methods ***/
4053 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface,
4054                                                 OAEVENT *hEvent) {
4055     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4056
4057     TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
4058
4059     *hEvent = (OAEVENT)This->evqueue.msg_event;
4060
4061     return S_OK;
4062 }
4063
4064 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface,
4065                                           long *lEventCode,
4066                                           LONG_PTR *lParam1,
4067                                           LONG_PTR *lParam2,
4068                                           long msTimeout) {
4069     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4070     Event evt;
4071
4072     TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
4073
4074     if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
4075     {
4076         *lEventCode = evt.lEventCode;
4077         *lParam1 = evt.lParam1;
4078         *lParam2 = evt.lParam2;
4079         return S_OK;
4080     }
4081
4082     *lEventCode = 0;
4083     return E_ABORT;
4084 }
4085
4086 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface,
4087                                                    long msTimeout,
4088                                                    long *pEvCode) {
4089     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4090
4091     TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
4092
4093     if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
4094     {
4095         *pEvCode = This->CompletionStatus;
4096         return S_OK;
4097     }
4098
4099     *pEvCode = 0;
4100     return E_ABORT;
4101 }
4102
4103 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface,
4104                                                        long lEvCode) {
4105     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4106
4107     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4108
4109     if (lEvCode == EC_COMPLETE)
4110         This->HandleEcComplete = FALSE;
4111     else if (lEvCode == EC_REPAINT)
4112         This->HandleEcRepaint = FALSE;
4113     else if (lEvCode == EC_CLOCK_CHANGED)
4114         This->HandleEcClockChanged = FALSE;
4115     else
4116         return S_FALSE;
4117
4118     return S_OK;
4119 }
4120
4121 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface,
4122                                                         long lEvCode) {
4123     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4124
4125     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4126
4127     if (lEvCode == EC_COMPLETE)
4128         This->HandleEcComplete = TRUE;
4129     else if (lEvCode == EC_REPAINT)
4130         This->HandleEcRepaint = TRUE;
4131     else if (lEvCode == EC_CLOCK_CHANGED)
4132         This->HandleEcClockChanged = TRUE;
4133     else
4134         return S_FALSE;
4135
4136     return S_OK;
4137 }
4138
4139 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface,
4140                                                  long lEvCode,
4141                                                  LONG_PTR lParam1,
4142                                                  LONG_PTR lParam2) {
4143     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4144
4145     TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
4146
4147     return S_OK;
4148 }
4149
4150 /*** IMediaEventEx methods ***/
4151 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface,
4152                                                  OAHWND hwnd,
4153                                                  long lMsg,
4154                                                  LONG_PTR lInstanceData) {
4155     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4156
4157     TRACE("(%p/%p)->(%08x, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
4158
4159     This->notif.hWnd = (HWND)hwnd;
4160     This->notif.msg = lMsg;
4161     This->notif.instance = (long) lInstanceData;
4162
4163     return S_OK;
4164 }
4165
4166 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface,
4167                                                 long lNoNotifyFlags) {
4168     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4169
4170     TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
4171
4172     if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
4173         return E_INVALIDARG;
4174
4175     This->notif.disabled = lNoNotifyFlags;
4176
4177     return S_OK;
4178 }
4179
4180 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface,
4181                                                 long *lplNoNotifyFlags) {
4182     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4183
4184     TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
4185
4186     if (!lplNoNotifyFlags)
4187         return E_POINTER;
4188
4189     *lplNoNotifyFlags = This->notif.disabled;
4190
4191     return S_OK;
4192 }
4193
4194
4195 static const IMediaEventExVtbl IMediaEventEx_VTable =
4196 {
4197     MediaEvent_QueryInterface,
4198     MediaEvent_AddRef,
4199     MediaEvent_Release,
4200     MediaEvent_GetTypeInfoCount,
4201     MediaEvent_GetTypeInfo,
4202     MediaEvent_GetIDsOfNames,
4203     MediaEvent_Invoke,
4204     MediaEvent_GetEventHandle,
4205     MediaEvent_GetEvent,
4206     MediaEvent_WaitForCompletion,
4207     MediaEvent_CancelDefaultHandling,
4208     MediaEvent_RestoreDefaultHandling,
4209     MediaEvent_FreeEventParams,
4210     MediaEvent_SetNotifyWindow,
4211     MediaEvent_SetNotifyFlags,
4212     MediaEvent_GetNotifyFlags
4213 };
4214
4215
4216 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
4217 {
4218     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4219
4220     return Filtergraph_QueryInterface(This, riid, ppv);
4221 }
4222
4223 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
4224 {
4225     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4226
4227     return Filtergraph_AddRef(This);
4228 }
4229
4230 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
4231 {
4232     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4233
4234     return Filtergraph_Release(This);
4235 }
4236
4237 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
4238 {
4239     FIXME("(%p): stub\n", pClassID);
4240
4241     return E_NOTIMPL;
4242 }
4243
4244 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
4245 {
4246     FIXME("(): stub\n");
4247
4248     return E_NOTIMPL;
4249 }
4250
4251 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
4252 {
4253     FIXME("(): stub\n");
4254
4255     return E_NOTIMPL;
4256 }
4257
4258 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
4259 {
4260     FIXME("(0x%s): stub\n", wine_dbgstr_longlong(tStart));
4261
4262     return E_NOTIMPL;
4263 }
4264
4265 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
4266 {
4267     FIXME("(%d, %p): stub\n", dwMsTimeout, pState);
4268
4269     return E_NOTIMPL;
4270 }
4271
4272 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
4273 {
4274     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4275     HRESULT hr = S_OK;
4276     int i;
4277
4278     TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
4279
4280     EnterCriticalSection(&This->cs);
4281     {
4282         for (i = 0;i < This->nFilters;i++)
4283         {
4284             hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
4285             if (FAILED(hr))
4286                 break;
4287         }
4288
4289         if (FAILED(hr))
4290         {
4291             for(;i >= 0;i--)
4292                 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
4293         }
4294         else
4295         {
4296             if (This->refClock)
4297                 IReferenceClock_Release(This->refClock);
4298             This->refClock = pClock;
4299             if (This->refClock)
4300                 IReferenceClock_AddRef(This->refClock);
4301
4302             if (This->HandleEcClockChanged)
4303             {
4304                 IMediaEventSink *pEventSink;
4305                 HRESULT eshr;
4306
4307                 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
4308                 if (SUCCEEDED(eshr))
4309                 {
4310                     IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
4311                     IMediaEventSink_Release(pEventSink);
4312                 }
4313             }
4314         }
4315     }
4316     LeaveCriticalSection(&This->cs);
4317
4318     return hr;
4319 }
4320
4321 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
4322 {
4323     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4324
4325     TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
4326
4327     if (!ppClock)
4328         return E_POINTER;
4329
4330     EnterCriticalSection(&This->cs);
4331     {
4332         *ppClock = This->refClock;
4333         if (*ppClock)
4334             IReferenceClock_AddRef(*ppClock);
4335     }
4336     LeaveCriticalSection(&This->cs);
4337
4338     return S_OK;
4339 }
4340
4341 static const IMediaFilterVtbl IMediaFilter_VTable =
4342 {
4343     MediaFilter_QueryInterface,
4344     MediaFilter_AddRef,
4345     MediaFilter_Release,
4346     MediaFilter_GetClassID,
4347     MediaFilter_Stop,
4348     MediaFilter_Pause,
4349     MediaFilter_Run,
4350     MediaFilter_GetState,
4351     MediaFilter_SetSyncSource,
4352     MediaFilter_GetSyncSource
4353 };
4354
4355 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
4356 {
4357     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4358
4359     return Filtergraph_QueryInterface(This, riid, ppv);
4360 }
4361
4362 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
4363 {
4364     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4365
4366     return Filtergraph_AddRef(This);
4367 }
4368
4369 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
4370 {
4371     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4372
4373     return Filtergraph_Release(This);
4374 }
4375
4376 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
4377 {
4378     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4379     Event evt;
4380
4381     TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
4382
4383     /* We need thread safety here, let's use the events queue's one */
4384     EnterCriticalSection(&This->evqueue.msg_crst);
4385
4386     if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
4387     {
4388         TRACE("Process EC_COMPLETE notification\n");
4389         if (++This->EcCompleteCount == This->nRenderers)
4390         {
4391             evt.lEventCode = EC_COMPLETE;
4392             evt.lParam1 = S_OK;
4393             evt.lParam2 = 0;
4394             TRACE("Send EC_COMPLETE to app\n");
4395             EventsQueue_PutEvent(&This->evqueue, &evt);
4396             if (!This->notif.disabled && This->notif.hWnd)
4397             {
4398                 TRACE("Send Window message\n");
4399                 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4400             }
4401             This->CompletionStatus = EC_COMPLETE;
4402             SetEvent(This->hEventCompletion);
4403         }
4404     }
4405     else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
4406     {
4407         /* FIXME: Not handled yet */
4408     }
4409     else
4410     {
4411         evt.lEventCode = EventCode;
4412         evt.lParam1 = EventParam1;
4413         evt.lParam2 = EventParam2;
4414         EventsQueue_PutEvent(&This->evqueue, &evt);
4415         if (!This->notif.disabled && This->notif.hWnd)
4416             PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4417     }
4418
4419     LeaveCriticalSection(&This->evqueue.msg_crst);
4420     return S_OK;
4421 }
4422
4423 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
4424 {
4425     MediaEventSink_QueryInterface,
4426     MediaEventSink_AddRef,
4427     MediaEventSink_Release,
4428     MediaEventSink_Notify
4429 };
4430
4431 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
4432 {
4433     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4434
4435     return Filtergraph_QueryInterface(This, riid, ppv);
4436 }
4437
4438 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
4439 {
4440     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4441
4442     return Filtergraph_AddRef(This);
4443 }
4444
4445 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
4446 {
4447     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4448
4449     return Filtergraph_Release(This);
4450 }
4451
4452 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface,
4453                                             IPin* pOutputPin,
4454                                             IPin* pInputPin,
4455                                             const AM_MEDIA_TYPE* pmtFirstConnection,
4456                                             IBaseFilter* pUsingFilter,
4457                                             HANDLE hAbortEvent,
4458                                             DWORD dwFlags)
4459 {
4460     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4461
4462     FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
4463     
4464     return E_NOTIMPL;
4465 }
4466
4467 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface,
4468                                               IGraphConfigCallback* pCallback,
4469                                               PVOID pvContext,
4470                                               DWORD dwFlags,
4471                                               HANDLE hAbortEvent)
4472 {
4473     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4474
4475     FIXME("(%p)->(%p, %p, %x, %p): stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
4476     
4477     return E_NOTIMPL;
4478 }
4479
4480 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface,
4481                                                    IBaseFilter* pFilter)
4482 {
4483     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4484
4485     FIXME("(%p)->(%p): stub!\n", This, pFilter);
4486     
4487     return E_NOTIMPL;
4488 }
4489
4490 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface,
4491                                                   IEnumFilters** pEnum)
4492 {
4493     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4494
4495     FIXME("(%p)->(%p): stub!\n", This, pEnum);
4496     
4497     return E_NOTIMPL;
4498 }
4499
4500 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface,
4501                                                         IBaseFilter* pFilter)
4502 {
4503     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4504
4505     FIXME("(%p)->(%p): stub!\n", This, pFilter);
4506     
4507     return E_NOTIMPL;
4508 }
4509
4510 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface,
4511                                                REFERENCE_TIME* prtStart)
4512 {
4513     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4514
4515     FIXME("(%p)->(%p): stub!\n", This, prtStart);
4516     
4517     return E_NOTIMPL;
4518 }
4519
4520 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface,
4521                                                   IPin* pOutputPin,
4522                                                   IPinConnection* pConnection,
4523                                                   HANDLE hEventAbort)
4524 {
4525     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4526
4527     FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
4528     
4529     return E_NOTIMPL;
4530 }
4531
4532 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface,
4533                                                  IBaseFilter* pFilter,
4534                                                  DWORD dwFlags)
4535 {
4536     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4537
4538     FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4539     
4540     return E_NOTIMPL;
4541 }
4542
4543 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface,
4544                                                  IBaseFilter* pFilter,
4545                                                  DWORD* dwFlags)
4546 {
4547     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4548
4549     FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
4550     
4551     return E_NOTIMPL;
4552 }
4553
4554 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface,
4555                                                  IBaseFilter* pFilter,
4556                                                  DWORD dwFlags)
4557 {
4558     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4559
4560     FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4561     
4562     return E_NOTIMPL;
4563 }
4564
4565 static const IGraphConfigVtbl IGraphConfig_VTable =
4566 {
4567     GraphConfig_QueryInterface,
4568     GraphConfig_AddRef,
4569     GraphConfig_Release,
4570     GraphConfig_Reconnect,
4571     GraphConfig_Reconfigure,
4572     GraphConfig_AddFilterToCache,
4573     GraphConfig_EnumCacheFilter,
4574     GraphConfig_RemoveFilterFromCache,
4575     GraphConfig_GetStartTime,
4576     GraphConfig_PushThroughData,
4577     GraphConfig_SetFilterFlags,
4578     GraphConfig_GetFilterFlags,
4579     GraphConfig_RemoveFilterEx
4580 };
4581
4582 /* This is the only function that actually creates a FilterGraph class... */
4583 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
4584 {
4585     IFilterGraphImpl *fimpl;
4586     HRESULT hr;
4587
4588     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
4589
4590     if( pUnkOuter )
4591         return CLASS_E_NOAGGREGATION;
4592
4593     fimpl = CoTaskMemAlloc(sizeof(*fimpl));
4594     fimpl->IGraphBuilder_vtbl = &IGraphBuilder_VTable;
4595     fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
4596     fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
4597     fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
4598     fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
4599     fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
4600     fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
4601     fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
4602     fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
4603     fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable;
4604     fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable;
4605     fimpl->ref = 1;
4606     fimpl->ppFiltersInGraph = NULL;
4607     fimpl->pFilterNames = NULL;
4608     fimpl->nFilters = 0;
4609     fimpl->filterCapacity = 0;
4610     fimpl->nameIndex = 1;
4611     fimpl->refClock = NULL;
4612     fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
4613     fimpl->HandleEcComplete = TRUE;
4614     fimpl->HandleEcRepaint = TRUE;
4615     fimpl->HandleEcClockChanged = TRUE;
4616     fimpl->notif.hWnd = 0;
4617     fimpl->notif.disabled = FALSE;
4618     fimpl->nRenderers = 0;
4619     fimpl->EcCompleteCount = 0;
4620     fimpl->state = State_Stopped;
4621     EventsQueue_Init(&fimpl->evqueue);
4622     InitializeCriticalSection(&fimpl->cs);
4623     fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
4624     fimpl->nItfCacheEntries = 0;
4625
4626     hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
4627     if (FAILED(hr)) {
4628         ERR("Unable to create filter mapper (%x)\n", hr);
4629         return hr;
4630     }
4631
4632     *ppObj = fimpl;
4633     return S_OK;
4634 }
4635
4636 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
4637 {
4638     FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
4639     return FilterGraph_create(pUnkOuter, ppObj);
4640 }