quartz: Pass the reference time + small delay on on begin of playback.
[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? */
1918     if (!*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 = 0;
1936     hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
1937     LeaveCriticalSection(&This->cs);
1938
1939     return hr;
1940 }
1941
1942 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface,
1943                                                    LONGLONG *pStop) {
1944     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1945
1946     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pStop);
1947
1948     return S_OK;
1949 }
1950
1951 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface,
1952                                                       LONGLONG *pCurrent) {
1953     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1954
1955     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pCurrent);
1956
1957     return S_OK;
1958 }
1959
1960 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface,
1961                                                      LONGLONG *pTarget,
1962                                                      const GUID *pTargetFormat,
1963                                                      LONGLONG Source,
1964                                                      const GUID *pSourceFormat) {
1965     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1966
1967     FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget,
1968         pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat);
1969
1970     return S_OK;
1971 }
1972
1973 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface,
1974                                                 LONGLONG *pCurrent,
1975                                                 DWORD dwCurrentFlags,
1976                                                 LONGLONG *pStop,
1977                                                 DWORD dwStopFlags) {
1978     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1979
1980     FIXME("(%p/%p)->(%p, %08x, %p, %08x): stub !!!\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
1981
1982     return S_OK;
1983 }
1984
1985 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface,
1986                                                 LONGLONG *pCurrent,
1987                                                 LONGLONG *pStop) {
1988     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1989
1990     FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pCurrent, pStop);
1991
1992     return S_OK;
1993 }
1994
1995 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface,
1996                                                 LONGLONG *pEarliest,
1997                                                 LONGLONG *pLatest) {
1998     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1999
2000     FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
2001
2002     return S_OK;
2003 }
2004
2005 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface,
2006                                            double dRate) {
2007     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2008
2009     FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
2010
2011     return S_OK;
2012 }
2013
2014 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface,
2015                                            double *pdRate) {
2016     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2017
2018     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
2019
2020     return S_OK;
2021 }
2022
2023 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface,
2024                                               LONGLONG *pllPreroll) {
2025     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
2026
2027     FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
2028
2029     return S_OK;
2030 }
2031
2032
2033 static const IMediaSeekingVtbl IMediaSeeking_VTable =
2034 {
2035     MediaSeeking_QueryInterface,
2036     MediaSeeking_AddRef,
2037     MediaSeeking_Release,
2038     MediaSeeking_GetCapabilities,
2039     MediaSeeking_CheckCapabilities,
2040     MediaSeeking_IsFormatSupported,
2041     MediaSeeking_QueryPreferredFormat,
2042     MediaSeeking_GetTimeFormat,
2043     MediaSeeking_IsUsingTimeFormat,
2044     MediaSeeking_SetTimeFormat,
2045     MediaSeeking_GetDuration,
2046     MediaSeeking_GetStopPosition,
2047     MediaSeeking_GetCurrentPosition,
2048     MediaSeeking_ConvertTimeFormat,
2049     MediaSeeking_SetPositions,
2050     MediaSeeking_GetPositions,
2051     MediaSeeking_GetAvailable,
2052     MediaSeeking_SetRate,
2053     MediaSeeking_GetRate,
2054     MediaSeeking_GetPreroll
2055 };
2056
2057 /*** IUnknown methods ***/
2058 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj){
2059     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2060
2061     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2062
2063     return Filtergraph_QueryInterface(This, riid, ppvObj);
2064 }
2065
2066 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface){
2067     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2068
2069     TRACE("(%p/%p)->()\n", This, iface);
2070
2071     return Filtergraph_AddRef(This);
2072 }
2073
2074 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface){
2075     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaPosition_vtbl, iface);
2076
2077     TRACE("(%p/%p)->()\n", This, iface);
2078
2079     return Filtergraph_Release(This);
2080 }
2081
2082 /*** IDispatch methods ***/
2083 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){
2084     FIXME("(%p) stub!\n", iface);
2085     return E_NOTIMPL;
2086 }
2087
2088 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){
2089     FIXME("(%p) stub!\n", iface);
2090     return E_NOTIMPL;
2091 }
2092
2093 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){
2094     FIXME("(%p) stub!\n", iface);
2095     return E_NOTIMPL;
2096 }
2097
2098 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){
2099     FIXME("(%p) stub!\n", iface);
2100     return E_NOTIMPL;
2101 }
2102
2103 /*** IMediaPosition methods ***/
2104 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength){
2105     FIXME("(%p)->(%p) stub!\n", iface, plength);
2106     return E_NOTIMPL;
2107 }
2108
2109 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime){
2110     FIXME("(%p)->(%f) stub!\n", iface, llTime);
2111     return E_NOTIMPL;
2112 }
2113
2114 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime){
2115     FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2116     return E_NOTIMPL;
2117 }
2118
2119 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime){
2120     FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2121     return E_NOTIMPL;
2122 }
2123
2124 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime){
2125     FIXME("(%p)->(%f) stub!\n", iface, llTime);
2126     return E_NOTIMPL;
2127 }
2128
2129 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){
2130     FIXME("(%p)->(%p) stub!\n", iface, pllTime);
2131     return E_NOTIMPL;
2132 }
2133
2134 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){
2135     FIXME("(%p)->(%f) stub!\n", iface, llTime);
2136     return E_NOTIMPL;
2137 }
2138
2139 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate){
2140     FIXME("(%p)->(%f) stub!\n", iface, dRate);
2141     return E_NOTIMPL;
2142 }
2143
2144 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate){
2145     FIXME("(%p)->(%p) stub!\n", iface, pdRate);
2146     return E_NOTIMPL;
2147 }
2148
2149 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){
2150     FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward);
2151     return E_NOTIMPL;
2152 }
2153
2154 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){
2155     FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward);
2156     return E_NOTIMPL;
2157 }
2158
2159
2160 static const IMediaPositionVtbl IMediaPosition_VTable =
2161 {
2162     MediaPosition_QueryInterface,
2163     MediaPosition_AddRef,
2164     MediaPosition_Release,
2165     MediaPosition_GetTypeInfoCount,
2166     MediaPosition_GetTypeInfo,
2167     MediaPosition_GetIDsOfNames,
2168     MediaPosition_Invoke,
2169     MediaPosition_get_Duration,
2170     MediaPosition_put_CurrentPosition,
2171     MediaPosition_get_CurrentPosition,
2172     MediaPosition_get_StopTime,
2173     MediaPosition_put_StopTime,
2174     MediaPosition_get_PrerollTime,
2175     MediaPosition_put_PrerollTime,
2176     MediaPosition_put_Rate,
2177     MediaPosition_get_Rate,
2178     MediaPosition_CanSeekForward,
2179     MediaPosition_CanSeekBackward
2180 };
2181
2182 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
2183 {
2184     HRESULT hr = E_NOINTERFACE;
2185     int i;
2186     int entry;
2187
2188     /* Check if the interface type is already registered */
2189     for (entry = 0; entry < pGraph->nItfCacheEntries; entry++)
2190         if (riid == pGraph->ItfCacheEntries[entry].riid)
2191         {
2192             if (pGraph->ItfCacheEntries[entry].iface)
2193             {
2194                 /* Return the interface if available */
2195                 *ppvObj = pGraph->ItfCacheEntries[entry].iface;
2196                 return S_OK;
2197             }
2198             break;
2199         }
2200
2201     if (entry >= MAX_ITF_CACHE_ENTRIES)
2202     {
2203         FIXME("Not enough space to store interface in the cache\n");
2204         return E_OUTOFMEMORY;
2205     }
2206
2207     /* Find a filter supporting the requested interface */
2208     for (i = 0; i < pGraph->nFilters; i++)
2209     {
2210         hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
2211         if (hr == S_OK)
2212         {
2213             pGraph->ItfCacheEntries[entry].riid = riid;
2214             pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
2215             pGraph->ItfCacheEntries[entry].iface = (IUnknown*)*ppvObj;
2216             if (entry >= pGraph->nItfCacheEntries)
2217                 pGraph->nItfCacheEntries++;
2218             return S_OK;
2219         }
2220         if (hr != E_NOINTERFACE)
2221             return hr;
2222     }
2223
2224     return hr;
2225 }
2226
2227 /*** IUnknown methods ***/
2228 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface,
2229                                                 REFIID riid,
2230                                                 LPVOID*ppvObj) {
2231     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2232
2233     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2234
2235     return Filtergraph_QueryInterface(This, riid, ppvObj);
2236 }
2237
2238 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) {
2239     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2240
2241     TRACE("(%p/%p)->()\n", This, iface);
2242
2243     return Filtergraph_AddRef(This);
2244 }
2245
2246 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) {
2247     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2248
2249     TRACE("(%p/%p)->()\n", This, iface);
2250
2251     return Filtergraph_Release(This);
2252 }
2253
2254 /*** IDispatch methods ***/
2255 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface,
2256                                                   UINT*pctinfo) {
2257     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2258     IBasicAudio* pBasicAudio;
2259     HRESULT hr;
2260
2261     TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2262
2263     EnterCriticalSection(&This->cs);
2264
2265     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2266
2267     if (hr == S_OK)
2268         hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo);
2269
2270     LeaveCriticalSection(&This->cs);
2271
2272     return hr;
2273 }
2274
2275 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface,
2276                                              UINT iTInfo,
2277                                              LCID lcid,
2278                                              ITypeInfo**ppTInfo) {
2279     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2280     IBasicAudio* pBasicAudio;
2281     HRESULT hr;
2282
2283     TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2284
2285     EnterCriticalSection(&This->cs);
2286
2287     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2288
2289     if (hr == S_OK)
2290         hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo);
2291
2292     LeaveCriticalSection(&This->cs);
2293
2294     return hr;
2295 }
2296
2297 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface,
2298                                                REFIID riid,
2299                                                LPOLESTR*rgszNames,
2300                                                UINT cNames,
2301                                                LCID lcid,
2302                                                DISPID*rgDispId) {
2303     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2304     IBasicAudio* pBasicAudio;
2305     HRESULT hr;
2306
2307     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2308
2309     EnterCriticalSection(&This->cs);
2310
2311     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2312
2313     if (hr == S_OK)
2314         hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId);
2315
2316     LeaveCriticalSection(&This->cs);
2317
2318     return hr;
2319 }
2320
2321 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface,
2322                                         DISPID dispIdMember,
2323                                         REFIID riid,
2324                                         LCID lcid,
2325                                         WORD wFlags,
2326                                         DISPPARAMS*pDispParams,
2327                                         VARIANT*pVarResult,
2328                                         EXCEPINFO*pExepInfo,
2329                                         UINT*puArgErr) {
2330     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2331     IBasicAudio* pBasicAudio;
2332     HRESULT hr;
2333
2334     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);
2335
2336     EnterCriticalSection(&This->cs);
2337
2338     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2339
2340     if (hr == S_OK)
2341         hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2342
2343     LeaveCriticalSection(&This->cs);
2344
2345     return hr;
2346 }
2347
2348 /*** IBasicAudio methods ***/
2349 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface,
2350                                             long lVolume) {
2351     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2352     IBasicAudio* pBasicAudio;
2353     HRESULT hr;
2354
2355     TRACE("(%p/%p)->(%ld)\n", This, iface, lVolume);
2356
2357     EnterCriticalSection(&This->cs);
2358
2359     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2360
2361     if (hr == S_OK)
2362         hr = IBasicAudio_put_Volume(pBasicAudio, lVolume);
2363
2364     LeaveCriticalSection(&This->cs);
2365
2366     return hr;
2367 }
2368
2369 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface,
2370                                             long *plVolume) {
2371     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2372     IBasicAudio* pBasicAudio;
2373     HRESULT hr;
2374
2375     TRACE("(%p/%p)->(%p)\n", This, iface, plVolume);
2376
2377     EnterCriticalSection(&This->cs);
2378
2379     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2380
2381     if (hr == S_OK)
2382         hr = IBasicAudio_get_Volume(pBasicAudio, plVolume);
2383
2384     LeaveCriticalSection(&This->cs);
2385
2386     return hr;
2387 }
2388
2389 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface,
2390                                              long lBalance) {
2391     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2392     IBasicAudio* pBasicAudio;
2393     HRESULT hr;
2394
2395     TRACE("(%p/%p)->(%ld)\n", This, iface, lBalance);
2396
2397     EnterCriticalSection(&This->cs);
2398
2399     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2400
2401     if (hr == S_OK)
2402         hr = IBasicAudio_put_Balance(pBasicAudio, lBalance);
2403
2404     LeaveCriticalSection(&This->cs);
2405
2406     return hr;
2407 }
2408
2409 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface,
2410                                              long *plBalance) {
2411     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
2412     IBasicAudio* pBasicAudio;
2413     HRESULT hr;
2414
2415     TRACE("(%p/%p)->(%p)\n", This, iface, plBalance);
2416
2417     EnterCriticalSection(&This->cs);
2418
2419     hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio);
2420
2421     if (hr == S_OK)
2422         hr = IBasicAudio_get_Balance(pBasicAudio, plBalance);
2423
2424     LeaveCriticalSection(&This->cs);
2425
2426     return hr;
2427 }
2428
2429 static const IBasicAudioVtbl IBasicAudio_VTable =
2430 {
2431     BasicAudio_QueryInterface,
2432     BasicAudio_AddRef,
2433     BasicAudio_Release,
2434     BasicAudio_GetTypeInfoCount,
2435     BasicAudio_GetTypeInfo,
2436     BasicAudio_GetIDsOfNames,
2437     BasicAudio_Invoke,
2438     BasicAudio_put_Volume,
2439     BasicAudio_get_Volume,
2440     BasicAudio_put_Balance,
2441     BasicAudio_get_Balance
2442 };
2443
2444 /*** IUnknown methods ***/
2445 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface,
2446                                                 REFIID riid,
2447                                                 LPVOID*ppvObj) {
2448     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2449
2450     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2451
2452     return Filtergraph_QueryInterface(This, riid, ppvObj);
2453 }
2454
2455 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface) {
2456     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2457
2458     TRACE("(%p/%p)->()\n", This, iface);
2459
2460     return Filtergraph_AddRef(This);
2461 }
2462
2463 static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface) {
2464     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2465
2466     TRACE("(%p/%p)->()\n", This, iface);
2467
2468     return Filtergraph_Release(This);
2469 }
2470
2471 /*** IDispatch methods ***/
2472 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo *iface,
2473                                                   UINT*pctinfo) {
2474     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2475     IBasicVideo* pBasicVideo;
2476     HRESULT hr;
2477
2478     TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
2479
2480     EnterCriticalSection(&This->cs);
2481
2482     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2483
2484     if (hr == S_OK)
2485         hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo);
2486
2487     LeaveCriticalSection(&This->cs);
2488
2489     return hr;
2490 }
2491
2492 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo *iface,
2493                                              UINT iTInfo,
2494                                              LCID lcid,
2495                                              ITypeInfo**ppTInfo) {
2496     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2497     IBasicVideo* pBasicVideo;
2498     HRESULT hr;
2499
2500     TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
2501
2502     EnterCriticalSection(&This->cs);
2503
2504     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2505
2506     if (hr == S_OK)
2507         hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo);
2508
2509     LeaveCriticalSection(&This->cs);
2510
2511     return hr;
2512 }
2513
2514 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo *iface,
2515                                                REFIID riid,
2516                                                LPOLESTR*rgszNames,
2517                                                UINT cNames,
2518                                                LCID lcid,
2519                                                DISPID*rgDispId) {
2520     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2521     IBasicVideo* pBasicVideo;
2522     HRESULT hr;
2523
2524     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2525
2526     EnterCriticalSection(&This->cs);
2527
2528     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2529
2530     if (hr == S_OK)
2531         hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId);
2532
2533     LeaveCriticalSection(&This->cs);
2534
2535     return hr;
2536 }
2537
2538 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo *iface,
2539                                         DISPID dispIdMember,
2540                                         REFIID riid,
2541                                         LCID lcid,
2542                                         WORD wFlags,
2543                                         DISPPARAMS*pDispParams,
2544                                         VARIANT*pVarResult,
2545                                         EXCEPINFO*pExepInfo,
2546                                         UINT*puArgErr) {
2547     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2548     IBasicVideo* pBasicVideo;
2549     HRESULT hr;
2550
2551     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);
2552
2553     EnterCriticalSection(&This->cs);
2554
2555     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2556
2557     if (hr == S_OK)
2558         hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2559
2560     LeaveCriticalSection(&This->cs);
2561
2562     return hr;
2563 }
2564
2565 /*** IBasicVideo methods ***/
2566 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo *iface,
2567                                                      REFTIME *pAvgTimePerFrame) {
2568     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2569     IBasicVideo* pBasicVideo;
2570     HRESULT hr;
2571
2572     TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
2573
2574     EnterCriticalSection(&This->cs);
2575
2576     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2577
2578     if (hr == S_OK)
2579         hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame);
2580
2581     LeaveCriticalSection(&This->cs);
2582
2583     return hr;
2584 }
2585
2586 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo *iface,
2587                                              long *pBitRate) {
2588     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2589     IBasicVideo* pBasicVideo;
2590     HRESULT hr;
2591
2592     TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate);
2593
2594     EnterCriticalSection(&This->cs);
2595
2596     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2597
2598     if (hr == S_OK)
2599         hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate);
2600
2601     LeaveCriticalSection(&This->cs);
2602
2603     return hr;
2604 }
2605
2606 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo *iface,
2607                                                   long *pBitErrorRate) {
2608     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2609     IBasicVideo* pBasicVideo;
2610     HRESULT hr;
2611
2612     TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate);
2613
2614     EnterCriticalSection(&This->cs);
2615
2616     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2617
2618     if (hr == S_OK)
2619         hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate);
2620
2621     LeaveCriticalSection(&This->cs);
2622
2623     return hr;
2624 }
2625
2626 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo *iface,
2627                                                 long *pVideoWidth) {
2628     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2629     IBasicVideo* pBasicVideo;
2630     HRESULT hr;
2631
2632     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth);
2633
2634     EnterCriticalSection(&This->cs);
2635
2636     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2637
2638     if (hr == S_OK)
2639         hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth);
2640
2641     LeaveCriticalSection(&This->cs);
2642
2643     return hr;
2644 }
2645
2646 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo *iface,
2647                                                  long *pVideoHeight) {
2648     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2649     IBasicVideo* pBasicVideo;
2650     HRESULT hr;
2651
2652     TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight);
2653
2654     EnterCriticalSection(&This->cs);
2655
2656     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2657
2658     if (hr == S_OK)
2659         hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight);
2660
2661     LeaveCriticalSection(&This->cs);
2662
2663     return hr;
2664 }
2665
2666 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo *iface,
2667                                                 long SourceLeft) {
2668     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2669     IBasicVideo* pBasicVideo;
2670     HRESULT hr;
2671
2672     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceLeft);
2673
2674     EnterCriticalSection(&This->cs);
2675
2676     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2677
2678     if (hr == S_OK)
2679         hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft);
2680
2681     LeaveCriticalSection(&This->cs);
2682
2683     return hr;
2684 }
2685
2686 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo *iface,
2687                                                 long *pSourceLeft) {
2688     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2689     IBasicVideo* pBasicVideo;
2690     HRESULT hr;
2691
2692     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft);
2693
2694     EnterCriticalSection(&This->cs);
2695
2696     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2697
2698     if (hr == S_OK)
2699         hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft);
2700
2701     LeaveCriticalSection(&This->cs);
2702
2703     return hr;
2704 }
2705
2706 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo *iface,
2707                                                  long SourceWidth) {
2708     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2709     IBasicVideo* pBasicVideo;
2710     HRESULT hr;
2711
2712     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceWidth);
2713
2714     EnterCriticalSection(&This->cs);
2715
2716     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2717
2718     if (hr == S_OK)
2719         hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth);
2720
2721     LeaveCriticalSection(&This->cs);
2722
2723     return hr;
2724 }
2725
2726 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo *iface,
2727                                                  long *pSourceWidth) {
2728     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2729     IBasicVideo* pBasicVideo;
2730     HRESULT hr;
2731
2732     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth);
2733
2734     EnterCriticalSection(&This->cs);
2735
2736     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2737
2738     if (hr == S_OK)
2739         hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth);
2740
2741     LeaveCriticalSection(&This->cs);
2742
2743     return hr;
2744 }
2745
2746 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo *iface,
2747                                                long SourceTop) {
2748     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2749     IBasicVideo* pBasicVideo;
2750     HRESULT hr;
2751
2752     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceTop);
2753
2754     EnterCriticalSection(&This->cs);
2755
2756     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2757
2758     if (hr == S_OK)
2759         hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop);
2760
2761     LeaveCriticalSection(&This->cs);
2762
2763     return hr;
2764 }
2765
2766 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo *iface,
2767                                                long *pSourceTop) {
2768     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2769     IBasicVideo* pBasicVideo;
2770     HRESULT hr;
2771
2772     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop);
2773
2774     EnterCriticalSection(&This->cs);
2775
2776     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2777
2778     if (hr == S_OK)
2779         hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop);
2780
2781     LeaveCriticalSection(&This->cs);
2782
2783     return hr;
2784 }
2785
2786 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo *iface,
2787                                                   long SourceHeight) {
2788     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2789     IBasicVideo* pBasicVideo;
2790     HRESULT hr;
2791
2792     TRACE("(%p/%p)->(%ld)\n", This, iface, SourceHeight);
2793
2794     EnterCriticalSection(&This->cs);
2795
2796     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2797
2798     if (hr == S_OK)
2799         hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight);
2800
2801     LeaveCriticalSection(&This->cs);
2802
2803     return hr;
2804 }
2805
2806 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo *iface,
2807                                                   long *pSourceHeight) {
2808     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2809     IBasicVideo* pBasicVideo;
2810     HRESULT hr;
2811
2812     TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight);
2813
2814     EnterCriticalSection(&This->cs);
2815
2816     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2817
2818     if (hr == S_OK)
2819         hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight);
2820
2821     LeaveCriticalSection(&This->cs);
2822
2823     return hr;
2824 }
2825
2826 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo *iface,
2827                                                      long DestinationLeft) {
2828     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2829     IBasicVideo* pBasicVideo;
2830     HRESULT hr;
2831
2832     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationLeft);
2833
2834     EnterCriticalSection(&This->cs);
2835
2836     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2837
2838     if (hr == S_OK)
2839         hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft);
2840
2841     LeaveCriticalSection(&This->cs);
2842
2843     return hr;
2844 }
2845
2846 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo *iface,
2847                                                      long *pDestinationLeft) {
2848     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2849     IBasicVideo* pBasicVideo;
2850     HRESULT hr;
2851
2852     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft);
2853
2854     EnterCriticalSection(&This->cs);
2855
2856     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2857
2858     if (hr == S_OK)
2859         hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft);
2860
2861     LeaveCriticalSection(&This->cs);
2862
2863     return hr;
2864 }
2865
2866 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo *iface,
2867                                                       long DestinationWidth) {
2868     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2869     IBasicVideo* pBasicVideo;
2870     HRESULT hr;
2871
2872     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationWidth);
2873
2874     EnterCriticalSection(&This->cs);
2875
2876     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2877
2878     if (hr == S_OK)
2879         hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth);
2880
2881     LeaveCriticalSection(&This->cs);
2882
2883     return hr;
2884 }
2885
2886 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo *iface,
2887                                                       long *pDestinationWidth) {
2888     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2889     IBasicVideo* pBasicVideo;
2890     HRESULT hr;
2891
2892     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
2893
2894     EnterCriticalSection(&This->cs);
2895
2896     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2897
2898     if (hr == S_OK)
2899         hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth);
2900
2901     LeaveCriticalSection(&This->cs);
2902
2903     return hr;
2904 }
2905
2906 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo *iface,
2907                                                     long DestinationTop) {
2908     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2909     IBasicVideo* pBasicVideo;
2910     HRESULT hr;
2911
2912     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationTop);
2913
2914     EnterCriticalSection(&This->cs);
2915
2916     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2917
2918     if (hr == S_OK)
2919         hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop);
2920
2921     LeaveCriticalSection(&This->cs);
2922
2923     return hr;
2924 }
2925
2926 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo *iface,
2927                                                     long *pDestinationTop) {
2928     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2929     IBasicVideo* pBasicVideo;
2930     HRESULT hr;
2931
2932     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop);
2933
2934     EnterCriticalSection(&This->cs);
2935
2936     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2937
2938     if (hr == S_OK)
2939         hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop);
2940
2941     LeaveCriticalSection(&This->cs);
2942
2943     return hr;
2944 }
2945
2946 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo *iface,
2947                                                        long DestinationHeight) {
2948     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2949     IBasicVideo* pBasicVideo;
2950     HRESULT hr;
2951
2952     TRACE("(%p/%p)->(%ld)\n", This, iface, DestinationHeight);
2953
2954     EnterCriticalSection(&This->cs);
2955
2956     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2957
2958     if (hr == S_OK)
2959         hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight);
2960
2961     LeaveCriticalSection(&This->cs);
2962
2963     return hr;
2964 }
2965
2966 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo *iface,
2967                                                        long *pDestinationHeight) {
2968     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2969     IBasicVideo* pBasicVideo;
2970     HRESULT hr;
2971
2972     TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight);
2973
2974     EnterCriticalSection(&This->cs);
2975
2976     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
2977
2978     if (hr == S_OK)
2979         hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight);
2980
2981     LeaveCriticalSection(&This->cs);
2982
2983     return hr;
2984 }
2985
2986 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo *iface,
2987                                                    long Left,
2988                                                    long Top,
2989                                                    long Width,
2990                                                    long Height) {
2991     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2992     IBasicVideo* pBasicVideo;
2993     HRESULT hr;
2994
2995     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
2996
2997     EnterCriticalSection(&This->cs);
2998
2999     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3000
3001     if (hr == S_OK)
3002         hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height);
3003
3004     LeaveCriticalSection(&This->cs);
3005
3006     return hr;
3007 }
3008
3009 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo *iface,
3010                                                    long *pLeft,
3011                                                    long *pTop,
3012                                                    long *pWidth,
3013                                                    long *pHeight) {
3014     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3015     IBasicVideo* pBasicVideo;
3016     HRESULT hr;
3017
3018     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3019
3020     EnterCriticalSection(&This->cs);
3021
3022     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3023
3024     if (hr == S_OK)
3025         hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3026
3027     LeaveCriticalSection(&This->cs);
3028
3029     return hr;
3030 }
3031
3032 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo *iface) {
3033     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3034     IBasicVideo* pBasicVideo;
3035     HRESULT hr;
3036
3037     TRACE("(%p/%p)->()\n", This, iface);
3038
3039     EnterCriticalSection(&This->cs);
3040
3041     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3042
3043     if (hr == S_OK)
3044         hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo);
3045
3046     LeaveCriticalSection(&This->cs);
3047
3048     return hr;
3049 }
3050
3051 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo *iface,
3052                                                         long Left,
3053                                                         long Top,
3054                                                         long Width,
3055                                                         long Height) {
3056     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3057     IBasicVideo* pBasicVideo;
3058     HRESULT hr;
3059
3060     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
3061
3062     EnterCriticalSection(&This->cs);
3063
3064     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3065
3066     if (hr == S_OK)
3067         hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height);
3068
3069     LeaveCriticalSection(&This->cs);
3070
3071     return hr;
3072 }
3073
3074 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo *iface,
3075                                                         long *pLeft,
3076                                                         long *pTop,
3077                                                         long *pWidth,
3078                                                         long *pHeight) {
3079     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3080     IBasicVideo* pBasicVideo;
3081     HRESULT hr;
3082
3083     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
3084
3085     EnterCriticalSection(&This->cs);
3086
3087     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3088
3089     if (hr == S_OK)
3090         hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight);
3091
3092     LeaveCriticalSection(&This->cs);
3093
3094     return hr;
3095 }
3096
3097 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
3098     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3099     IBasicVideo* pBasicVideo;
3100     HRESULT hr;
3101
3102     TRACE("(%p/%p)->()\n", This, iface);
3103
3104     EnterCriticalSection(&This->cs);
3105
3106     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3107
3108     if (hr == S_OK)
3109         hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo);
3110
3111     LeaveCriticalSection(&This->cs);
3112
3113     return hr;
3114 }
3115
3116 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo *iface,
3117                                               long *pWidth,
3118                                               long *pHeight) {
3119     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3120     IBasicVideo* pBasicVideo;
3121     HRESULT hr;
3122
3123     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
3124
3125     EnterCriticalSection(&This->cs);
3126
3127     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3128
3129     if (hr == S_OK)
3130         hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight);
3131
3132     LeaveCriticalSection(&This->cs);
3133
3134     return hr;
3135 }
3136
3137 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo *iface,
3138                                                         long StartIndex,
3139                                                         long Entries,
3140                                                         long *pRetrieved,
3141                                                         long *pPalette) {
3142     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3143     IBasicVideo* pBasicVideo;
3144     HRESULT hr;
3145
3146     TRACE("(%p/%p)->(%ld, %ld, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
3147
3148     EnterCriticalSection(&This->cs);
3149
3150     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3151
3152     if (hr == S_OK)
3153         hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette);
3154
3155     LeaveCriticalSection(&This->cs);
3156
3157     return hr;
3158 }
3159
3160 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo *iface,
3161                                                  long *pBufferSize,
3162                                                  long *pDIBImage) {
3163     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3164     IBasicVideo* pBasicVideo;
3165     HRESULT hr;
3166
3167     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage);
3168
3169     EnterCriticalSection(&This->cs);
3170
3171     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3172
3173     if (hr == S_OK)
3174         hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage);
3175
3176     LeaveCriticalSection(&This->cs);
3177
3178     return hr;
3179 }
3180
3181 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo *iface) {
3182     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3183     IBasicVideo* pBasicVideo;
3184     HRESULT hr;
3185
3186     TRACE("(%p/%p)->()\n", This, iface);
3187
3188     EnterCriticalSection(&This->cs);
3189
3190     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3191
3192     if (hr == S_OK)
3193         hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo);
3194
3195     LeaveCriticalSection(&This->cs);
3196
3197     return hr;
3198 }
3199
3200 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo *iface) {
3201     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
3202     IBasicVideo* pBasicVideo;
3203     HRESULT hr;
3204
3205     TRACE("(%p/%p)->()\n", This, iface);
3206
3207     EnterCriticalSection(&This->cs);
3208
3209     hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo);
3210
3211     if (hr == S_OK)
3212         hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo);
3213
3214     LeaveCriticalSection(&This->cs);
3215
3216     return hr;
3217 }
3218
3219
3220 static const IBasicVideoVtbl IBasicVideo_VTable =
3221 {
3222     BasicVideo_QueryInterface,
3223     BasicVideo_AddRef,
3224     BasicVideo_Release,
3225     BasicVideo_GetTypeInfoCount,
3226     BasicVideo_GetTypeInfo,
3227     BasicVideo_GetIDsOfNames,
3228     BasicVideo_Invoke,
3229     BasicVideo_get_AvgTimePerFrame,
3230     BasicVideo_get_BitRate,
3231     BasicVideo_get_BitErrorRate,
3232     BasicVideo_get_VideoWidth,
3233     BasicVideo_get_VideoHeight,
3234     BasicVideo_put_SourceLeft,
3235     BasicVideo_get_SourceLeft,
3236     BasicVideo_put_SourceWidth,
3237     BasicVideo_get_SourceWidth,
3238     BasicVideo_put_SourceTop,
3239     BasicVideo_get_SourceTop,
3240     BasicVideo_put_SourceHeight,
3241     BasicVideo_get_SourceHeight,
3242     BasicVideo_put_DestinationLeft,
3243     BasicVideo_get_DestinationLeft,
3244     BasicVideo_put_DestinationWidth,
3245     BasicVideo_get_DestinationWidth,
3246     BasicVideo_put_DestinationTop,
3247     BasicVideo_get_DestinationTop,
3248     BasicVideo_put_DestinationHeight,
3249     BasicVideo_get_DestinationHeight,
3250     BasicVideo_SetSourcePosition,
3251     BasicVideo_GetSourcePosition,
3252     BasicVideo_SetDefaultSourcePosition,
3253     BasicVideo_SetDestinationPosition,
3254     BasicVideo_GetDestinationPosition,
3255     BasicVideo_SetDefaultDestinationPosition,
3256     BasicVideo_GetVideoSize,
3257     BasicVideo_GetVideoPaletteEntries,
3258     BasicVideo_GetCurrentImage,
3259     BasicVideo_IsUsingDefaultSource,
3260     BasicVideo_IsUsingDefaultDestination
3261 };
3262
3263
3264 /*** IUnknown methods ***/
3265 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface,
3266                                                  REFIID riid,
3267                                                  LPVOID*ppvObj) {
3268     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3269
3270     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
3271
3272     return Filtergraph_QueryInterface(This, riid, ppvObj);
3273 }
3274
3275 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) {
3276     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3277
3278     TRACE("(%p/%p)->()\n", This, iface);
3279
3280     return Filtergraph_AddRef(This);
3281 }
3282
3283 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) {
3284     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3285
3286     TRACE("(%p/%p)->()\n", This, iface);
3287
3288     return Filtergraph_Release(This);
3289 }
3290
3291 /*** IDispatch methods ***/
3292 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface,
3293                                                    UINT*pctinfo) {
3294     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3295     IVideoWindow* pVideoWindow;
3296     HRESULT hr;
3297
3298     TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo);
3299
3300     EnterCriticalSection(&This->cs);
3301
3302     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3303
3304     if (hr == S_OK)
3305         hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo);
3306
3307     LeaveCriticalSection(&This->cs);
3308
3309     return hr;
3310 }
3311
3312 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface,
3313                                               UINT iTInfo,
3314                                               LCID lcid,
3315                                               ITypeInfo**ppTInfo) {
3316     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3317     IVideoWindow* pVideoWindow;
3318     HRESULT hr;
3319
3320     TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo);
3321
3322     EnterCriticalSection(&This->cs);
3323
3324     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3325
3326     if (hr == S_OK)
3327         hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo);
3328
3329     LeaveCriticalSection(&This->cs);
3330
3331     return hr;
3332 }
3333
3334 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface,
3335                                                 REFIID riid,
3336                                                 LPOLESTR*rgszNames,
3337                                                 UINT cNames,
3338                                                 LCID lcid,
3339                                                 DISPID*rgDispId) {
3340     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3341     IVideoWindow* pVideoWindow;
3342     HRESULT hr;
3343
3344     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
3345
3346     EnterCriticalSection(&This->cs);
3347
3348     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3349
3350     if (hr == S_OK)
3351         hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId);
3352
3353     LeaveCriticalSection(&This->cs);
3354
3355     return hr;
3356 }
3357
3358 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface,
3359                                          DISPID dispIdMember,
3360                                          REFIID riid,
3361                                          LCID lcid,
3362                                          WORD wFlags,
3363                                          DISPPARAMS*pDispParams,
3364                                          VARIANT*pVarResult,
3365                                          EXCEPINFO*pExepInfo,
3366                                          UINT*puArgErr) {
3367     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3368     IVideoWindow* pVideoWindow;
3369     HRESULT hr;
3370
3371     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);
3372
3373     EnterCriticalSection(&This->cs);
3374
3375     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3376
3377     if (hr == S_OK)
3378         hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
3379
3380     LeaveCriticalSection(&This->cs);
3381
3382     return hr;
3383 }
3384
3385
3386 /*** IVideoWindow methods ***/
3387 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface,
3388                                               BSTR strCaption) {
3389     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3390     IVideoWindow* pVideoWindow;
3391     HRESULT hr;
3392     
3393     TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption);
3394
3395     EnterCriticalSection(&This->cs);
3396
3397     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3398
3399     if (hr == S_OK)
3400         hr = IVideoWindow_put_Caption(pVideoWindow, strCaption);
3401
3402     LeaveCriticalSection(&This->cs);
3403
3404     return hr;
3405 }
3406
3407 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface,
3408                                               BSTR *strCaption) {
3409     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3410     IVideoWindow* pVideoWindow;
3411     HRESULT hr;
3412
3413     TRACE("(%p/%p)->(%p)\n", This, iface, strCaption);
3414
3415     EnterCriticalSection(&This->cs);
3416
3417     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3418
3419     if (hr == S_OK)
3420         hr = IVideoWindow_get_Caption(pVideoWindow, strCaption);
3421
3422     LeaveCriticalSection(&This->cs);
3423
3424     return hr;
3425 }
3426
3427 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface,
3428                                                   long WindowStyle) {
3429     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3430     IVideoWindow* pVideoWindow;
3431     HRESULT hr;
3432
3433     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyle);
3434
3435     EnterCriticalSection(&This->cs);
3436
3437     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3438
3439     if (hr == S_OK)
3440         hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle);
3441
3442     LeaveCriticalSection(&This->cs);
3443
3444     return hr;
3445 }
3446
3447 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface,
3448                                                   long *WindowStyle) {
3449     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3450     IVideoWindow* pVideoWindow;
3451     HRESULT hr;
3452
3453     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle);
3454
3455     EnterCriticalSection(&This->cs);
3456
3457     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3458
3459     if (hr == S_OK)
3460         hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle);
3461
3462     LeaveCriticalSection(&This->cs);
3463
3464     return hr;
3465 }
3466
3467 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface,
3468                                                     long WindowStyleEx) {
3469     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3470     IVideoWindow* pVideoWindow;
3471     HRESULT hr;
3472
3473     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowStyleEx);
3474
3475     EnterCriticalSection(&This->cs);
3476
3477     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3478
3479     if (hr == S_OK)
3480         hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx);
3481
3482     LeaveCriticalSection(&This->cs);
3483
3484     return hr;
3485 }
3486
3487 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface,
3488                                                     long *WindowStyleEx) {
3489     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3490     IVideoWindow* pVideoWindow;
3491     HRESULT hr;
3492
3493     TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx);
3494
3495     EnterCriticalSection(&This->cs);
3496
3497     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3498
3499     if (hr == S_OK)
3500         hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx);
3501
3502     LeaveCriticalSection(&This->cs);
3503
3504     return hr;
3505 }
3506
3507 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface,
3508                                                long AutoShow) {
3509     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3510     IVideoWindow* pVideoWindow;
3511     HRESULT hr;
3512
3513     TRACE("(%p/%p)->(%ld)\n", This, iface, AutoShow);
3514
3515     EnterCriticalSection(&This->cs);
3516
3517     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3518
3519     if (hr == S_OK)
3520         hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow);
3521
3522     LeaveCriticalSection(&This->cs);
3523
3524     return hr;
3525 }
3526
3527 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface,
3528                                                long *AutoShow) {
3529     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3530     IVideoWindow* pVideoWindow;
3531     HRESULT hr;
3532
3533     TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
3534
3535     EnterCriticalSection(&This->cs);
3536
3537     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3538
3539     if (hr == S_OK)
3540         hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow);
3541
3542     LeaveCriticalSection(&This->cs);
3543
3544     return hr;
3545 }
3546
3547 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface,
3548                                                   long WindowState) {
3549     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3550     IVideoWindow* pVideoWindow;
3551     HRESULT hr;
3552
3553     TRACE("(%p/%p)->(%ld)\n", This, iface, WindowState);
3554
3555     EnterCriticalSection(&This->cs);
3556
3557     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3558
3559     if (hr == S_OK)
3560         hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState);
3561
3562     LeaveCriticalSection(&This->cs);
3563
3564     return hr;
3565 }
3566
3567 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface,
3568                                                   long *WindowState) {
3569     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3570     IVideoWindow* pVideoWindow;
3571     HRESULT hr;
3572
3573     TRACE("(%p/%p)->(%p)\n", This, iface, WindowState);
3574
3575     EnterCriticalSection(&This->cs);
3576
3577     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3578
3579     if (hr == S_OK)
3580         hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState);
3581
3582     LeaveCriticalSection(&This->cs);
3583
3584     return hr;
3585 }
3586
3587 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface,
3588                                                         long BackgroundPalette) {
3589     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3590     IVideoWindow* pVideoWindow;
3591     HRESULT hr;
3592
3593     TRACE("(%p/%p)->(%ld)\n", This, iface, BackgroundPalette);
3594
3595     EnterCriticalSection(&This->cs);
3596
3597     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3598
3599     if (hr == S_OK)
3600         hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette);
3601
3602     LeaveCriticalSection(&This->cs);
3603
3604     return hr;
3605 }
3606
3607 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface,
3608                                                         long *pBackgroundPalette) {
3609     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3610     IVideoWindow* pVideoWindow;
3611     HRESULT hr;
3612
3613     TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette);
3614
3615     EnterCriticalSection(&This->cs);
3616
3617     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3618
3619     if (hr == S_OK)
3620         hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette);
3621
3622     LeaveCriticalSection(&This->cs);
3623
3624     return hr;
3625 }
3626
3627 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface,
3628                                               long Visible) {
3629     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3630     IVideoWindow* pVideoWindow;
3631     HRESULT hr;
3632
3633     TRACE("(%p/%p)->(%ld)\n", This, iface, Visible);
3634
3635     EnterCriticalSection(&This->cs);
3636
3637     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3638
3639     if (hr == S_OK)
3640         hr = IVideoWindow_put_Visible(pVideoWindow, Visible);
3641
3642     LeaveCriticalSection(&This->cs);
3643
3644     return hr;
3645 }
3646
3647 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface,
3648                                               long *pVisible) {
3649     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3650     IVideoWindow* pVideoWindow;
3651     HRESULT hr;
3652
3653     TRACE("(%p/%p)->(%p)\n", This, iface, pVisible);
3654
3655     EnterCriticalSection(&This->cs);
3656
3657     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3658
3659     if (hr == S_OK)
3660         hr = IVideoWindow_get_Visible(pVideoWindow, pVisible);
3661
3662     LeaveCriticalSection(&This->cs);
3663
3664     return hr;
3665 }
3666
3667 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface,
3668                                            long Left) {
3669     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3670     IVideoWindow* pVideoWindow;
3671     HRESULT hr;
3672
3673     TRACE("(%p/%p)->(%ld)\n", This, iface, Left);
3674
3675     EnterCriticalSection(&This->cs);
3676
3677     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3678
3679     if (hr == S_OK)
3680         hr = IVideoWindow_put_Left(pVideoWindow, Left);
3681
3682     LeaveCriticalSection(&This->cs);
3683
3684     return hr;
3685 }
3686
3687 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface,
3688                                            long *pLeft) {
3689     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3690     IVideoWindow* pVideoWindow;
3691     HRESULT hr;
3692
3693     TRACE("(%p/%p)->(%p)\n", This, iface, pLeft);
3694
3695     EnterCriticalSection(&This->cs);
3696
3697     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3698
3699     if (hr == S_OK)
3700         hr = IVideoWindow_get_Left(pVideoWindow, pLeft);
3701
3702     LeaveCriticalSection(&This->cs);
3703
3704     return hr;
3705 }
3706
3707 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface,
3708                                             long Width) {
3709     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3710     IVideoWindow* pVideoWindow;
3711     HRESULT hr;
3712
3713     TRACE("(%p/%p)->(%ld)\n", This, iface, Width);
3714
3715     EnterCriticalSection(&This->cs);
3716
3717     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3718
3719     if (hr == S_OK)
3720         hr = IVideoWindow_put_Width(pVideoWindow, Width);
3721
3722     LeaveCriticalSection(&This->cs);
3723
3724     return hr;
3725 }
3726
3727 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface,
3728                                             long *pWidth) {
3729     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3730     IVideoWindow* pVideoWindow;
3731     HRESULT hr;
3732
3733     TRACE("(%p/%p)->(%p)\n", This, iface, pWidth);
3734
3735     EnterCriticalSection(&This->cs);
3736
3737     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3738
3739     if (hr == S_OK)
3740         hr = IVideoWindow_get_Width(pVideoWindow, pWidth);
3741
3742     LeaveCriticalSection(&This->cs);
3743
3744     return hr;
3745 }
3746
3747 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface,
3748                                           long Top) {
3749     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3750     IVideoWindow* pVideoWindow;
3751     HRESULT hr;
3752
3753     TRACE("(%p/%p)->(%ld)\n", This, iface, Top);
3754
3755     EnterCriticalSection(&This->cs);
3756
3757     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3758
3759     if (hr == S_OK)
3760         hr = IVideoWindow_put_Top(pVideoWindow, Top);
3761
3762     LeaveCriticalSection(&This->cs);
3763
3764     return hr;
3765 }
3766
3767 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface,
3768                                           long *pTop) {
3769     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3770     IVideoWindow* pVideoWindow;
3771     HRESULT hr;
3772
3773     TRACE("(%p/%p)->(%p)\n", This, iface, pTop);
3774
3775     EnterCriticalSection(&This->cs);
3776
3777     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3778
3779     if (hr == S_OK)
3780         hr = IVideoWindow_get_Top(pVideoWindow, pTop);
3781
3782     LeaveCriticalSection(&This->cs);
3783
3784     return hr;
3785 }
3786
3787 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface,
3788                                              long Height) {
3789     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3790     IVideoWindow* pVideoWindow;
3791     HRESULT hr;
3792
3793     TRACE("(%p/%p)->(%ld)\n", This, iface, Height);
3794
3795     EnterCriticalSection(&This->cs);
3796
3797     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3798
3799     if (hr == S_OK)
3800         hr = IVideoWindow_put_Height(pVideoWindow, Height);
3801
3802     LeaveCriticalSection(&This->cs);
3803
3804     return hr;
3805 }
3806
3807 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface,
3808                                              long *pHeight) {
3809     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3810     IVideoWindow* pVideoWindow;
3811     HRESULT hr;
3812
3813     TRACE("(%p/%p)->(%p)\n", This, iface, pHeight);
3814
3815     EnterCriticalSection(&This->cs);
3816
3817     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3818
3819     if (hr == S_OK)
3820         hr = IVideoWindow_get_Height(pVideoWindow, pHeight);
3821
3822     LeaveCriticalSection(&This->cs);
3823
3824     return hr;
3825 }
3826
3827 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface,
3828                                             OAHWND Owner) {
3829     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3830     IVideoWindow* pVideoWindow;
3831     HRESULT hr;
3832
3833     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner);
3834
3835     EnterCriticalSection(&This->cs);
3836
3837     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3838
3839     if (hr == S_OK)
3840         hr = IVideoWindow_put_Owner(pVideoWindow, Owner);
3841
3842     LeaveCriticalSection(&This->cs);
3843
3844     return hr;
3845 }
3846
3847 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface,
3848                                             OAHWND *Owner) {
3849     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3850     IVideoWindow* pVideoWindow;
3851     HRESULT hr;
3852
3853     TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
3854
3855     EnterCriticalSection(&This->cs);
3856
3857     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3858
3859     if (hr == S_OK)
3860         hr = IVideoWindow_get_Owner(pVideoWindow, Owner);
3861
3862     LeaveCriticalSection(&This->cs);
3863
3864     return hr;
3865 }
3866
3867 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface,
3868                                                    OAHWND Drain) {
3869     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3870     IVideoWindow* pVideoWindow;
3871     HRESULT hr;
3872
3873     TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain);
3874
3875     EnterCriticalSection(&This->cs);
3876
3877     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3878
3879     if (hr == S_OK)
3880         hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain);
3881
3882     LeaveCriticalSection(&This->cs);
3883
3884     return hr;
3885 }
3886
3887 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface,
3888                                                    OAHWND *Drain) {
3889     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3890     IVideoWindow* pVideoWindow;
3891     HRESULT hr;
3892
3893     TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
3894
3895     EnterCriticalSection(&This->cs);
3896
3897     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3898
3899     if (hr == S_OK)
3900         hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain);
3901
3902     LeaveCriticalSection(&This->cs);
3903
3904     return hr;
3905 }
3906
3907 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface,
3908                                                   long *Color) {
3909     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3910     IVideoWindow* pVideoWindow;
3911     HRESULT hr;
3912
3913     TRACE("(%p/%p)->(%p)\n", This, iface, Color);
3914
3915     EnterCriticalSection(&This->cs);
3916
3917     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3918
3919     if (hr == S_OK)
3920         hr = IVideoWindow_get_BorderColor(pVideoWindow, Color);
3921
3922     LeaveCriticalSection(&This->cs);
3923
3924     return hr;
3925 }
3926
3927 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface,
3928                                                   long Color) {
3929     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3930     IVideoWindow* pVideoWindow;
3931     HRESULT hr;
3932
3933     TRACE("(%p/%p)->(%ld)\n", This, iface, Color);
3934
3935     EnterCriticalSection(&This->cs);
3936
3937     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3938
3939     if (hr == S_OK)
3940         hr = IVideoWindow_put_BorderColor(pVideoWindow, Color);
3941
3942     LeaveCriticalSection(&This->cs);
3943
3944     return hr;
3945 }
3946
3947 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
3948                                                      long *FullScreenMode) {
3949     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3950     IVideoWindow* pVideoWindow;
3951     HRESULT hr;
3952
3953     TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode);
3954
3955     EnterCriticalSection(&This->cs);
3956
3957     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3958
3959     if (hr == S_OK)
3960         hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode);
3961
3962     LeaveCriticalSection(&This->cs);
3963
3964     return hr;
3965 }
3966
3967 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface,
3968                                                      long FullScreenMode) {
3969     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3970     IVideoWindow* pVideoWindow;
3971     HRESULT hr;
3972
3973     TRACE("(%p/%p)->(%ld)\n", This, iface, FullScreenMode);
3974
3975     EnterCriticalSection(&This->cs);
3976
3977     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3978
3979     if (hr == S_OK)
3980         hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode);
3981
3982     LeaveCriticalSection(&This->cs);
3983
3984     return hr;
3985 }
3986
3987 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface,
3988                                                       long Focus) {
3989     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
3990     IVideoWindow* pVideoWindow;
3991     HRESULT hr;
3992
3993     TRACE("(%p/%p)->(%ld)\n", This, iface, Focus);
3994
3995     EnterCriticalSection(&This->cs);
3996
3997     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
3998
3999     if (hr == S_OK)
4000         hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus);
4001
4002     LeaveCriticalSection(&This->cs);
4003
4004     return hr;
4005 }
4006
4007 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface,
4008                                                      OAHWND hwnd,
4009                                                      long uMsg,
4010                                                      LONG_PTR wParam,
4011                                                      LONG_PTR lParam) {
4012     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4013     IVideoWindow* pVideoWindow;
4014     HRESULT hr;
4015
4016     TRACE("(%p/%p)->(%08x, %ld, %08lx, %08lx)\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
4017
4018     EnterCriticalSection(&This->cs);
4019
4020     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4021
4022     if (hr == S_OK)
4023         hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam);
4024
4025     LeaveCriticalSection(&This->cs);
4026
4027     return hr;
4028 }
4029
4030 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface,
4031                                                     long Left,
4032                                                     long Top,
4033                                                     long Width,
4034                                                     long Height) {
4035     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4036     IVideoWindow* pVideoWindow;
4037     HRESULT hr;
4038     
4039     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld)\n", This, iface, Left, Top, Width, Height);
4040
4041     EnterCriticalSection(&This->cs);
4042
4043     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4044
4045     if (hr == S_OK)
4046         hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height);
4047
4048     LeaveCriticalSection(&This->cs);
4049
4050     return hr;
4051 }
4052
4053 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface,
4054                                                     long *pLeft,
4055                                                     long *pTop,
4056                                                     long *pWidth,
4057                                                     long *pHeight) {
4058     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4059     IVideoWindow* pVideoWindow;
4060     HRESULT hr;
4061
4062     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4063
4064     EnterCriticalSection(&This->cs);
4065
4066     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4067
4068     if (hr == S_OK)
4069         hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4070
4071     LeaveCriticalSection(&This->cs);
4072
4073     return hr;
4074 }
4075
4076 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface,
4077                                                        long *pWidth,
4078                                                        long *pHeight) {
4079     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4080     IVideoWindow* pVideoWindow;
4081     HRESULT hr;
4082
4083     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4084
4085     EnterCriticalSection(&This->cs);
4086
4087     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4088
4089     if (hr == S_OK)
4090         hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight);
4091
4092     LeaveCriticalSection(&This->cs);
4093
4094     return hr;
4095 }
4096
4097 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface,
4098                                                        long *pWidth,
4099                                                        long *pHeight) {
4100     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4101     IVideoWindow* pVideoWindow;
4102     HRESULT hr;
4103
4104     TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight);
4105
4106     EnterCriticalSection(&This->cs);
4107
4108     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4109
4110     if (hr == S_OK)
4111         hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight);
4112
4113     LeaveCriticalSection(&This->cs);
4114
4115     return hr;
4116 }
4117
4118 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface,
4119                                                      long *pLeft,
4120                                                      long *pTop,
4121                                                      long *pWidth,
4122                                                      long *pHeight) {
4123     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4124     IVideoWindow* pVideoWindow;
4125     HRESULT hr;
4126
4127     TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight);
4128
4129     EnterCriticalSection(&This->cs);
4130
4131     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4132
4133     if (hr == S_OK)
4134         hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight);
4135
4136     LeaveCriticalSection(&This->cs);
4137
4138     return hr;
4139 }
4140
4141 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface,
4142                                              long HideCursor) {
4143     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4144     IVideoWindow* pVideoWindow;
4145     HRESULT hr;
4146
4147     TRACE("(%p/%p)->(%ld)\n", This, iface, HideCursor);
4148
4149     EnterCriticalSection(&This->cs);
4150
4151     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4152
4153     if (hr == S_OK)
4154         hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor);
4155
4156     LeaveCriticalSection(&This->cs);
4157
4158     return hr;
4159 }
4160
4161 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface,
4162                                                  long *CursorHidden) {
4163     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
4164     IVideoWindow* pVideoWindow;
4165     HRESULT hr;
4166
4167     TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden);
4168
4169     EnterCriticalSection(&This->cs);
4170
4171     hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow);
4172
4173     if (hr == S_OK)
4174         hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden);
4175
4176     LeaveCriticalSection(&This->cs);
4177
4178     return hr;
4179 }
4180
4181
4182 static const IVideoWindowVtbl IVideoWindow_VTable =
4183 {
4184     VideoWindow_QueryInterface,
4185     VideoWindow_AddRef,
4186     VideoWindow_Release,
4187     VideoWindow_GetTypeInfoCount,
4188     VideoWindow_GetTypeInfo,
4189     VideoWindow_GetIDsOfNames,
4190     VideoWindow_Invoke,
4191     VideoWindow_put_Caption,
4192     VideoWindow_get_Caption,
4193     VideoWindow_put_WindowStyle,
4194     VideoWindow_get_WindowStyle,
4195     VideoWindow_put_WindowStyleEx,
4196     VideoWindow_get_WindowStyleEx,
4197     VideoWindow_put_AutoShow,
4198     VideoWindow_get_AutoShow,
4199     VideoWindow_put_WindowState,
4200     VideoWindow_get_WindowState,
4201     VideoWindow_put_BackgroundPalette,
4202     VideoWindow_get_BackgroundPalette,
4203     VideoWindow_put_Visible,
4204     VideoWindow_get_Visible,
4205     VideoWindow_put_Left,
4206     VideoWindow_get_Left,
4207     VideoWindow_put_Width,
4208     VideoWindow_get_Width,
4209     VideoWindow_put_Top,
4210     VideoWindow_get_Top,
4211     VideoWindow_put_Height,
4212     VideoWindow_get_Height,
4213     VideoWindow_put_Owner,
4214     VideoWindow_get_Owner,
4215     VideoWindow_put_MessageDrain,
4216     VideoWindow_get_MessageDrain,
4217     VideoWindow_get_BorderColor,
4218     VideoWindow_put_BorderColor,
4219     VideoWindow_get_FullScreenMode,
4220     VideoWindow_put_FullScreenMode,
4221     VideoWindow_SetWindowForeground,
4222     VideoWindow_NotifyOwnerMessage,
4223     VideoWindow_SetWindowPosition,
4224     VideoWindow_GetWindowPosition,
4225     VideoWindow_GetMinIdealImageSize,
4226     VideoWindow_GetMaxIdealImageSize,
4227     VideoWindow_GetRestorePosition,
4228     VideoWindow_HideCursor,
4229     VideoWindow_IsCursorHidden
4230 };
4231
4232
4233 /*** IUnknown methods ***/
4234 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface,
4235                                                 REFIID riid,
4236                                                 LPVOID*ppvObj) {
4237     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4238
4239     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
4240
4241     return Filtergraph_QueryInterface(This, riid, ppvObj);
4242 }
4243
4244 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) {
4245     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4246
4247     TRACE("(%p/%p)->()\n", This, iface);
4248
4249     return Filtergraph_AddRef(This);
4250 }
4251
4252 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) {
4253     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4254
4255     TRACE("(%p/%p)->()\n", This, iface);
4256
4257     return Filtergraph_Release(This);
4258 }
4259
4260 /*** IDispatch methods ***/
4261 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface,
4262                                                   UINT*pctinfo) {
4263     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4264
4265     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
4266
4267     return S_OK;
4268 }
4269
4270 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface,
4271                                              UINT iTInfo,
4272                                              LCID lcid,
4273                                              ITypeInfo**ppTInfo) {
4274     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4275
4276     TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
4277
4278     return S_OK;
4279 }
4280
4281 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface,
4282                                                REFIID riid,
4283                                                LPOLESTR*rgszNames,
4284                                                UINT cNames,
4285                                                LCID lcid,
4286                                                DISPID*rgDispId) {
4287     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4288
4289     TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
4290
4291     return S_OK;
4292 }
4293
4294 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface,
4295                                         DISPID dispIdMember,
4296                                         REFIID riid,
4297                                         LCID lcid,
4298                                         WORD wFlags,
4299                                         DISPPARAMS*pDispParams,
4300                                         VARIANT*pVarResult,
4301                                         EXCEPINFO*pExepInfo,
4302                                         UINT*puArgErr) {
4303     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4304
4305     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);
4306
4307     return S_OK;
4308 }
4309
4310 /*** IMediaEvent methods ***/
4311 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface,
4312                                                 OAEVENT *hEvent) {
4313     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4314
4315     TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
4316
4317     *hEvent = (OAEVENT)This->evqueue.msg_event;
4318
4319     return S_OK;
4320 }
4321
4322 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface,
4323                                           long *lEventCode,
4324                                           LONG_PTR *lParam1,
4325                                           LONG_PTR *lParam2,
4326                                           long msTimeout) {
4327     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4328     Event evt;
4329
4330     TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
4331
4332     if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
4333     {
4334         *lEventCode = evt.lEventCode;
4335         *lParam1 = evt.lParam1;
4336         *lParam2 = evt.lParam2;
4337         return S_OK;
4338     }
4339
4340     *lEventCode = 0;
4341     return E_ABORT;
4342 }
4343
4344 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface,
4345                                                    long msTimeout,
4346                                                    long *pEvCode) {
4347     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4348
4349     TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
4350
4351     if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
4352     {
4353         *pEvCode = This->CompletionStatus;
4354         return S_OK;
4355     }
4356
4357     *pEvCode = 0;
4358     return E_ABORT;
4359 }
4360
4361 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface,
4362                                                        long lEvCode) {
4363     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4364
4365     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4366
4367     if (lEvCode == EC_COMPLETE)
4368         This->HandleEcComplete = FALSE;
4369     else if (lEvCode == EC_REPAINT)
4370         This->HandleEcRepaint = FALSE;
4371     else if (lEvCode == EC_CLOCK_CHANGED)
4372         This->HandleEcClockChanged = FALSE;
4373     else
4374         return S_FALSE;
4375
4376     return S_OK;
4377 }
4378
4379 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface,
4380                                                         long lEvCode) {
4381     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4382
4383     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
4384
4385     if (lEvCode == EC_COMPLETE)
4386         This->HandleEcComplete = TRUE;
4387     else if (lEvCode == EC_REPAINT)
4388         This->HandleEcRepaint = TRUE;
4389     else if (lEvCode == EC_CLOCK_CHANGED)
4390         This->HandleEcClockChanged = TRUE;
4391     else
4392         return S_FALSE;
4393
4394     return S_OK;
4395 }
4396
4397 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface,
4398                                                  long lEvCode,
4399                                                  LONG_PTR lParam1,
4400                                                  LONG_PTR lParam2) {
4401     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4402
4403     TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
4404
4405     return S_OK;
4406 }
4407
4408 /*** IMediaEventEx methods ***/
4409 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface,
4410                                                  OAHWND hwnd,
4411                                                  long lMsg,
4412                                                  LONG_PTR lInstanceData) {
4413     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4414
4415     TRACE("(%p/%p)->(%08x, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
4416
4417     This->notif.hWnd = (HWND)hwnd;
4418     This->notif.msg = lMsg;
4419     This->notif.instance = (long) lInstanceData;
4420
4421     return S_OK;
4422 }
4423
4424 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface,
4425                                                 long lNoNotifyFlags) {
4426     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4427
4428     TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
4429
4430     if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1))
4431         return E_INVALIDARG;
4432
4433     This->notif.disabled = lNoNotifyFlags;
4434
4435     return S_OK;
4436 }
4437
4438 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface,
4439                                                 long *lplNoNotifyFlags) {
4440     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
4441
4442     TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
4443
4444     if (!lplNoNotifyFlags)
4445         return E_POINTER;
4446
4447     *lplNoNotifyFlags = This->notif.disabled;
4448
4449     return S_OK;
4450 }
4451
4452
4453 static const IMediaEventExVtbl IMediaEventEx_VTable =
4454 {
4455     MediaEvent_QueryInterface,
4456     MediaEvent_AddRef,
4457     MediaEvent_Release,
4458     MediaEvent_GetTypeInfoCount,
4459     MediaEvent_GetTypeInfo,
4460     MediaEvent_GetIDsOfNames,
4461     MediaEvent_Invoke,
4462     MediaEvent_GetEventHandle,
4463     MediaEvent_GetEvent,
4464     MediaEvent_WaitForCompletion,
4465     MediaEvent_CancelDefaultHandling,
4466     MediaEvent_RestoreDefaultHandling,
4467     MediaEvent_FreeEventParams,
4468     MediaEvent_SetNotifyWindow,
4469     MediaEvent_SetNotifyFlags,
4470     MediaEvent_GetNotifyFlags
4471 };
4472
4473
4474 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
4475 {
4476     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4477
4478     return Filtergraph_QueryInterface(This, riid, ppv);
4479 }
4480
4481 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
4482 {
4483     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4484
4485     return Filtergraph_AddRef(This);
4486 }
4487
4488 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
4489 {
4490     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4491
4492     return Filtergraph_Release(This);
4493 }
4494
4495 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
4496 {
4497     FIXME("(%p): stub\n", pClassID);
4498
4499     return E_NOTIMPL;
4500 }
4501
4502 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
4503 {
4504     FIXME("(): stub\n");
4505
4506     return E_NOTIMPL;
4507 }
4508
4509 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
4510 {
4511     FIXME("(): stub\n");
4512
4513     return E_NOTIMPL;
4514 }
4515
4516 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
4517 {
4518     FIXME("(0x%s): stub\n", wine_dbgstr_longlong(tStart));
4519
4520     return E_NOTIMPL;
4521 }
4522
4523 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
4524 {
4525     FIXME("(%d, %p): stub\n", dwMsTimeout, pState);
4526
4527     return E_NOTIMPL;
4528 }
4529
4530 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
4531 {
4532     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4533     HRESULT hr = S_OK;
4534     int i;
4535
4536     TRACE("(%p/%p)->(%p)\n", iface, This, pClock);
4537
4538     EnterCriticalSection(&This->cs);
4539     {
4540         for (i = 0;i < This->nFilters;i++)
4541         {
4542             hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
4543             if (FAILED(hr))
4544                 break;
4545         }
4546
4547         if (FAILED(hr))
4548         {
4549             for(;i >= 0;i--)
4550                 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
4551         }
4552         else
4553         {
4554             if (This->refClock)
4555                 IReferenceClock_Release(This->refClock);
4556             This->refClock = pClock;
4557             if (This->refClock)
4558                 IReferenceClock_AddRef(This->refClock);
4559
4560             if (This->HandleEcClockChanged)
4561             {
4562                 IMediaEventSink *pEventSink;
4563                 HRESULT eshr;
4564
4565                 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink);
4566                 if (SUCCEEDED(eshr))
4567                 {
4568                     IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0);
4569                     IMediaEventSink_Release(pEventSink);
4570                 }
4571             }
4572         }
4573     }
4574     LeaveCriticalSection(&This->cs);
4575
4576     return hr;
4577 }
4578
4579 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
4580 {
4581     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface);
4582
4583     TRACE("(%p/%p)->(%p)\n", iface, This, ppClock);
4584
4585     if (!ppClock)
4586         return E_POINTER;
4587
4588     EnterCriticalSection(&This->cs);
4589     {
4590         *ppClock = This->refClock;
4591         if (*ppClock)
4592             IReferenceClock_AddRef(*ppClock);
4593     }
4594     LeaveCriticalSection(&This->cs);
4595
4596     return S_OK;
4597 }
4598
4599 static const IMediaFilterVtbl IMediaFilter_VTable =
4600 {
4601     MediaFilter_QueryInterface,
4602     MediaFilter_AddRef,
4603     MediaFilter_Release,
4604     MediaFilter_GetClassID,
4605     MediaFilter_Stop,
4606     MediaFilter_Pause,
4607     MediaFilter_Run,
4608     MediaFilter_GetState,
4609     MediaFilter_SetSyncSource,
4610     MediaFilter_GetSyncSource
4611 };
4612
4613 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
4614 {
4615     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4616
4617     return Filtergraph_QueryInterface(This, riid, ppv);
4618 }
4619
4620 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
4621 {
4622     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4623
4624     return Filtergraph_AddRef(This);
4625 }
4626
4627 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
4628 {
4629     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4630
4631     return Filtergraph_Release(This);
4632 }
4633
4634 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
4635 {
4636     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
4637     Event evt;
4638
4639     TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
4640
4641     /* We need thread safety here, let's use the events queue's one */
4642     EnterCriticalSection(&This->evqueue.msg_crst);
4643
4644     if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
4645     {
4646         TRACE("Process EC_COMPLETE notification\n");
4647         if (++This->EcCompleteCount == This->nRenderers)
4648         {
4649             evt.lEventCode = EC_COMPLETE;
4650             evt.lParam1 = S_OK;
4651             evt.lParam2 = 0;
4652             TRACE("Send EC_COMPLETE to app\n");
4653             EventsQueue_PutEvent(&This->evqueue, &evt);
4654             if (!This->notif.disabled && This->notif.hWnd)
4655             {
4656                 TRACE("Send Window message\n");
4657                 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4658             }
4659             This->CompletionStatus = EC_COMPLETE;
4660             SetEvent(This->hEventCompletion);
4661         }
4662     }
4663     else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
4664     {
4665         /* FIXME: Not handled yet */
4666     }
4667     else
4668     {
4669         evt.lEventCode = EventCode;
4670         evt.lParam1 = EventParam1;
4671         evt.lParam2 = EventParam2;
4672         EventsQueue_PutEvent(&This->evqueue, &evt);
4673         if (!This->notif.disabled && This->notif.hWnd)
4674             PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
4675     }
4676
4677     LeaveCriticalSection(&This->evqueue.msg_crst);
4678     return S_OK;
4679 }
4680
4681 static const IMediaEventSinkVtbl IMediaEventSink_VTable =
4682 {
4683     MediaEventSink_QueryInterface,
4684     MediaEventSink_AddRef,
4685     MediaEventSink_Release,
4686     MediaEventSink_Notify
4687 };
4688
4689 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
4690 {
4691     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4692
4693     return Filtergraph_QueryInterface(This, riid, ppv);
4694 }
4695
4696 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface)
4697 {
4698     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4699
4700     return Filtergraph_AddRef(This);
4701 }
4702
4703 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface)
4704 {
4705     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4706
4707     return Filtergraph_Release(This);
4708 }
4709
4710 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface,
4711                                             IPin* pOutputPin,
4712                                             IPin* pInputPin,
4713                                             const AM_MEDIA_TYPE* pmtFirstConnection,
4714                                             IBaseFilter* pUsingFilter,
4715                                             HANDLE hAbortEvent,
4716                                             DWORD dwFlags)
4717 {
4718     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4719
4720     FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags);
4721     
4722     return E_NOTIMPL;
4723 }
4724
4725 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface,
4726                                               IGraphConfigCallback* pCallback,
4727                                               PVOID pvContext,
4728                                               DWORD dwFlags,
4729                                               HANDLE hAbortEvent)
4730 {
4731     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4732
4733     FIXME("(%p)->(%p, %p, %x, %p): stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent);
4734     
4735     return E_NOTIMPL;
4736 }
4737
4738 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface,
4739                                                    IBaseFilter* pFilter)
4740 {
4741     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4742
4743     FIXME("(%p)->(%p): stub!\n", This, pFilter);
4744     
4745     return E_NOTIMPL;
4746 }
4747
4748 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface,
4749                                                   IEnumFilters** pEnum)
4750 {
4751     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4752
4753     FIXME("(%p)->(%p): stub!\n", This, pEnum);
4754     
4755     return E_NOTIMPL;
4756 }
4757
4758 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface,
4759                                                         IBaseFilter* pFilter)
4760 {
4761     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4762
4763     FIXME("(%p)->(%p): stub!\n", This, pFilter);
4764     
4765     return E_NOTIMPL;
4766 }
4767
4768 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface,
4769                                                REFERENCE_TIME* prtStart)
4770 {
4771     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4772
4773     FIXME("(%p)->(%p): stub!\n", This, prtStart);
4774     
4775     return E_NOTIMPL;
4776 }
4777
4778 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface,
4779                                                   IPin* pOutputPin,
4780                                                   IPinConnection* pConnection,
4781                                                   HANDLE hEventAbort)
4782 {
4783     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4784
4785     FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort);
4786     
4787     return E_NOTIMPL;
4788 }
4789
4790 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface,
4791                                                  IBaseFilter* pFilter,
4792                                                  DWORD dwFlags)
4793 {
4794     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4795
4796     FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4797     
4798     return E_NOTIMPL;
4799 }
4800
4801 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface,
4802                                                  IBaseFilter* pFilter,
4803                                                  DWORD* dwFlags)
4804 {
4805     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4806
4807     FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags);
4808     
4809     return E_NOTIMPL;
4810 }
4811
4812 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface,
4813                                                  IBaseFilter* pFilter,
4814                                                  DWORD dwFlags)
4815 {
4816     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
4817
4818     FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags);
4819     
4820     return E_NOTIMPL;
4821 }
4822
4823 static const IGraphConfigVtbl IGraphConfig_VTable =
4824 {
4825     GraphConfig_QueryInterface,
4826     GraphConfig_AddRef,
4827     GraphConfig_Release,
4828     GraphConfig_Reconnect,
4829     GraphConfig_Reconfigure,
4830     GraphConfig_AddFilterToCache,
4831     GraphConfig_EnumCacheFilter,
4832     GraphConfig_RemoveFilterFromCache,
4833     GraphConfig_GetStartTime,
4834     GraphConfig_PushThroughData,
4835     GraphConfig_SetFilterFlags,
4836     GraphConfig_GetFilterFlags,
4837     GraphConfig_RemoveFilterEx
4838 };
4839
4840 static const IUnknownVtbl IInner_VTable =
4841 {
4842     FilterGraphInner_QueryInterface,
4843     FilterGraphInner_AddRef,
4844     FilterGraphInner_Release
4845 };
4846
4847 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
4848                                                  REFIID riid,
4849                                                  LPVOID * ppv) {
4850     if (This->bAggregatable)
4851         This->bUnkOuterValid = TRUE;
4852
4853     if (This->pUnkOuter)
4854     {
4855         if (This->bAggregatable)
4856             return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
4857
4858         if (IsEqualIID(riid, &IID_IUnknown))
4859         {
4860             HRESULT hr;
4861
4862             IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
4863             hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
4864             IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
4865             This->bAggregatable = TRUE;
4866             return hr;
4867         }
4868
4869         *ppv = NULL;
4870         return E_NOINTERFACE;
4871     }
4872
4873     return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
4874 }
4875
4876 static ULONG WINAPI Filtergraph_AddRef(IFilterGraphImpl *This) {
4877     if (This->pUnkOuter && This->bUnkOuterValid)
4878         return IUnknown_AddRef(This->pUnkOuter);
4879     return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
4880 }
4881
4882 static ULONG WINAPI Filtergraph_Release(IFilterGraphImpl *This) {
4883     if (This->pUnkOuter && This->bUnkOuterValid)
4884         return IUnknown_Release(This->pUnkOuter);
4885     return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
4886 }
4887
4888 /* This is the only function that actually creates a FilterGraph class... */
4889 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
4890 {
4891     IFilterGraphImpl *fimpl;
4892     HRESULT hr;
4893
4894     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
4895
4896     *ppObj = NULL;
4897
4898     fimpl = CoTaskMemAlloc(sizeof(*fimpl));
4899     fimpl->pUnkOuter = pUnkOuter;
4900     fimpl->bUnkOuterValid = FALSE;
4901     fimpl->bAggregatable = FALSE;
4902     fimpl->IInner_vtbl = &IInner_VTable;
4903     fimpl->IFilterGraph2_vtbl = &IFilterGraph2_VTable;
4904     fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
4905     fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
4906     fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
4907     fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
4908     fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
4909     fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
4910     fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
4911     fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
4912     fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable;
4913     fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable;
4914     fimpl->ref = 1;
4915     fimpl->ppFiltersInGraph = NULL;
4916     fimpl->pFilterNames = NULL;
4917     fimpl->nFilters = 0;
4918     fimpl->filterCapacity = 0;
4919     fimpl->nameIndex = 1;
4920     fimpl->refClock = NULL;
4921     fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
4922     fimpl->HandleEcComplete = TRUE;
4923     fimpl->HandleEcRepaint = TRUE;
4924     fimpl->HandleEcClockChanged = TRUE;
4925     fimpl->notif.hWnd = 0;
4926     fimpl->notif.disabled = FALSE;
4927     fimpl->nRenderers = 0;
4928     fimpl->EcCompleteCount = 0;
4929     fimpl->state = State_Stopped;
4930     EventsQueue_Init(&fimpl->evqueue);
4931     InitializeCriticalSection(&fimpl->cs);
4932     fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs");
4933     fimpl->nItfCacheEntries = 0;
4934     memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
4935
4936     hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
4937     if (FAILED(hr)) {
4938         ERR("Unable to create filter mapper (%x)\n", hr);
4939         return hr;
4940     }
4941     IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl);
4942
4943     *ppObj = fimpl;
4944     return S_OK;
4945 }
4946
4947 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj)
4948 {
4949     FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n");
4950     return FilterGraph_create(pUnkOuter, ppObj);
4951 }