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