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