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