- Use Interlocked* functions in AddRef and Release.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25 #include <stdarg.h>
26
27 #define COBJMACROS
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "dshow.h"
33 #include "wine/debug.h"
34 #include "quartz_private.h"
35 #define COM_NO_WINDOWS_H
36 #include "ole2.h"
37 #include "olectl.h"
38 #include "strmif.h"
39 #include "vfwmsgs.h"
40 #include "evcode.h"
41 #include "wine/unicode.h"
42
43
44 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45
46 typedef struct {
47     HWND hWnd;      /* Target window */
48     long msg;       /* User window message */
49     long instance;  /* User data */
50     int  disabled;  /* Disabled messages posting */
51 } WndNotify;
52
53 typedef struct {
54     long lEventCode;   /* Event code */
55     LONG_PTR lParam1;  /* Param1 */
56     LONG_PTR lParam2;  /* Param2 */
57 } Event;
58
59 /* messages ring implementation for queuing events (taken from winmm) */
60 #define EVENTS_RING_BUFFER_INCREMENT      64
61 typedef struct {
62     Event* messages;
63     int ring_buffer_size;
64     int msg_tosave;
65     int msg_toget;
66     CRITICAL_SECTION msg_crst;
67     HANDLE msg_event; /* Signaled for no empty queue */
68 } EventsQueue;
69
70 static int EventsQueue_Init(EventsQueue* omr)
71 {
72     omr->msg_toget = 0;
73     omr->msg_tosave = 0;
74     omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL);
75     omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT;
76     omr->messages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,omr->ring_buffer_size * sizeof(Event));
77
78     InitializeCriticalSection(&omr->msg_crst);
79     return TRUE;
80 }
81
82 static int EventsQueue_Destroy(EventsQueue* omr)
83 {
84     CloseHandle(omr->msg_event);
85     HeapFree(GetProcessHeap(),0,omr->messages);
86     DeleteCriticalSection(&omr->msg_crst);
87     return TRUE;
88 }
89
90 static int EventsQueue_PutEvent(EventsQueue* omr, Event* evt)
91 {
92     EnterCriticalSection(&omr->msg_crst);
93     if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)))
94     {
95         int old_ring_buffer_size = omr->ring_buffer_size;
96         omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT;
97         TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size);
98         omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event));
99         /* Now we need to rearrange the ring buffer so that the new
100            buffers just allocated are in between omr->msg_tosave and
101            omr->msg_toget.
102         */
103         if (omr->msg_tosave < omr->msg_toget)
104         {
105             memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]),
106                     &(omr->messages[omr->msg_toget]),
107                     sizeof(Event)*(old_ring_buffer_size - omr->msg_toget)
108                     );
109             omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT;
110         }
111     }
112     omr->messages[omr->msg_tosave] = *evt;
113     SetEvent(omr->msg_event);
114     omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size;
115     LeaveCriticalSection(&omr->msg_crst);
116     return TRUE;
117 }
118
119 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, long msTimeOut)
120 {
121     if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0)
122         return FALSE;
123         
124     EnterCriticalSection(&omr->msg_crst);
125
126     if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
127     {
128         LeaveCriticalSection(&omr->msg_crst);
129         return FALSE;
130     }
131
132     *evt = omr->messages[omr->msg_toget];
133     omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size;
134
135     /* Mark the buffer as empty if needed */
136     if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */
137         ResetEvent(omr->msg_event);
138
139     LeaveCriticalSection(&omr->msg_crst);
140     return TRUE;
141 }
142
143 typedef struct _IFilterGraphImpl {
144     IGraphBuilderVtbl *IGraphBuilder_vtbl;
145     IMediaControlVtbl *IMediaControl_vtbl;
146     IMediaSeekingVtbl *IMediaSeeking_vtbl;
147     IBasicAudioVtbl *IBasicAudio_vtbl;
148     IBasicVideoVtbl *IBasicVideo_vtbl;
149     IVideoWindowVtbl *IVideoWindow_vtbl;
150     IMediaEventExVtbl *IMediaEventEx_vtbl;
151     IMediaFilterVtbl *IMediaFilter_vtbl;
152     IMediaEventSinkVtbl *IMediaEventSink_vtbl;
153     /* IAMGraphStreams */
154     /* IAMStats */
155     /* IBasicVideo2 */
156     /* IFilterChain */
157     /* IFilterGraph2 */
158     /* IFilterMapper2 */
159     /* IGraphConfig */
160     /* IGraphVersion */
161     /* IMediaPosition */
162     /* IQueueCommand */
163     /* IRegisterServiceProvider */
164     /* IResourceMananger */
165     /* IServiceProvider */
166     /* IVideoFrameStep */
167
168     ULONG ref;
169     IFilterMapper2 * pFilterMapper2;
170     IBaseFilter ** ppFiltersInGraph;
171     LPWSTR * pFilterNames;
172     int nFilters;
173     int filterCapacity;
174     long nameIndex;
175     EventsQueue evqueue;
176     HANDLE hEventCompletion;
177     int CompletionStatus;
178     WndNotify notif;
179     int nRenderers;
180     int EcCompleteCount;
181     int HandleEcComplete;
182     int HandleEcRepaint;
183     OAFilterState state;
184     CRITICAL_SECTION cs;
185 } IFilterGraphImpl;
186
187
188 static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This,
189                                           REFIID riid,
190                                           LPVOID *ppvObj) {
191     TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj);
192     
193     if (IsEqualGUID(&IID_IUnknown, riid) ||
194         IsEqualGUID(&IID_IFilterGraph, riid) ||
195         IsEqualGUID(&IID_IGraphBuilder, riid)) {
196         *ppvObj = &(This->IGraphBuilder_vtbl);
197         TRACE("   returning IGraphBuilder interface (%p)\n", *ppvObj);
198     } else if (IsEqualGUID(&IID_IMediaControl, riid)) {
199         *ppvObj = &(This->IMediaControl_vtbl);
200         TRACE("   returning IMediaControl interface (%p)\n", *ppvObj);
201     } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) {
202         *ppvObj = &(This->IMediaSeeking_vtbl);
203         TRACE("   returning IMediaSeeking interface (%p)\n", *ppvObj);
204     } else if (IsEqualGUID(&IID_IBasicAudio, riid)) {
205         *ppvObj = &(This->IBasicAudio_vtbl);
206         TRACE("   returning IBasicAudio interface (%p)\n", *ppvObj);
207     } else if (IsEqualGUID(&IID_IBasicVideo, riid)) {
208         *ppvObj = &(This->IBasicVideo_vtbl);
209         TRACE("   returning IBasicVideo interface (%p)\n", *ppvObj);
210     } else if (IsEqualGUID(&IID_IVideoWindow, riid)) {
211         *ppvObj = &(This->IVideoWindow_vtbl);
212         TRACE("   returning IVideoWindow interface (%p)\n", *ppvObj);
213     } else if (IsEqualGUID(&IID_IMediaEvent, riid) ||
214            IsEqualGUID(&IID_IMediaEventEx, riid)) {
215         *ppvObj = &(This->IMediaEventEx_vtbl);
216         TRACE("   returning IMediaEvent(Ex) interface (%p)\n", *ppvObj);
217     } else if (IsEqualGUID(&IID_IMediaFilter, riid) ||
218           IsEqualGUID(&IID_IPersist, riid)) {
219         *ppvObj = &(This->IMediaFilter_vtbl);
220         TRACE("   returning IMediaFilter interface (%p)\n", *ppvObj);
221     } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) {
222         *ppvObj = &(This->IMediaEventSink_vtbl);
223         TRACE("   returning IMediaEventSink interface (%p)\n", *ppvObj);
224     } else {
225         *ppvObj = NULL;
226         FIXME("unknown interface %s\n", debugstr_guid(riid));
227         return E_NOINTERFACE;
228     }
229
230     InterlockedIncrement(&This->ref);
231     return S_OK;
232 }
233
234 static ULONG Filtergraph_AddRef(IFilterGraphImpl *This) {
235     ULONG ref = InterlockedIncrement(&This->ref);
236
237     TRACE("(%p)->(): new ref = %ld\n", This, ref);
238     
239     return ref;
240 }
241
242 static ULONG Filtergraph_Release(IFilterGraphImpl *This) {
243     ULONG ref = InterlockedDecrement(&This->ref);
244     
245     TRACE("(%p)->(): new ref = %ld\n", This, ref);
246     
247     if (ref == 0) {
248         IFilterMapper2_Release(This->pFilterMapper2);
249         CloseHandle(This->hEventCompletion);
250         EventsQueue_Destroy(&This->evqueue);
251         DeleteCriticalSection(&This->cs);
252         HeapFree(GetProcessHeap(), 0, This->ppFiltersInGraph);
253         HeapFree(GetProcessHeap(), 0, This->pFilterNames);
254         HeapFree(GetProcessHeap(), 0, This);
255     }
256     return ref;
257 }
258
259
260 /*** IUnknown methods ***/
261 static HRESULT WINAPI Graphbuilder_QueryInterface(IGraphBuilder *iface,
262                                                   REFIID riid,
263                                                   LPVOID*ppvObj) {
264     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
265     
266     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
267     return Filtergraph_QueryInterface(This, riid, ppvObj);
268 }
269
270 static ULONG WINAPI Graphbuilder_AddRef(IGraphBuilder *iface) {
271     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
272     
273     TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface);
274     
275     return Filtergraph_AddRef(This);
276 }
277
278 static ULONG WINAPI Graphbuilder_Release(IGraphBuilder *iface) {
279     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
280     
281     TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface);
282
283     return Filtergraph_Release(This);
284 }
285
286 /*** IFilterGraph methods ***/
287 static HRESULT WINAPI Graphbuilder_AddFilter(IGraphBuilder *iface,
288                                              IBaseFilter *pFilter,
289                                              LPCWSTR pName) {
290     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
291     HRESULT hr;
292     int i,j;
293     WCHAR* wszFilterName = NULL;
294     int duplicate_name = FALSE;
295     
296     TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName);
297
298     wszFilterName = (WCHAR*) CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
299     
300     if (pName)
301     {
302         /* Check if name already exists */
303         for(i = 0; i < This->nFilters; i++)
304             if (!strcmpW(This->pFilterNames[i], pName))
305             {
306                 duplicate_name = TRUE;
307                 break;
308             }
309     }
310
311     /* If no name given or name already existing, generate one */
312     if (!pName || duplicate_name)
313     {
314         static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0};
315         static const WCHAR wszFmt2[] = {'%','0','4','d',0};
316
317         for (j = 0; j < 10000 ; j++)
318         {
319             /* Create name */
320             if (pName)
321                 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex);
322             else
323                 sprintfW(wszFilterName, wszFmt2, This->nameIndex);
324             TRACE("Generated name %s\n", debugstr_w(wszFilterName));
325
326             /* Check if the generated name already exists */
327             for(i = 0; i < This->nFilters; i++)
328                 if (!strcmpW(This->pFilterNames[i], wszFilterName))
329                     break;
330
331             /* Compute next index and exit if generated name is suitable */
332             if (This->nameIndex++ == 10000)
333                 This->nameIndex = 1;
334             if (i == This->nFilters)
335                 break;
336         }
337         /* Unable to find a suitable name */
338         if (j == 10000)
339         {
340             CoTaskMemFree(wszFilterName);
341             return VFW_E_DUPLICATE_NAME;
342         }
343     }
344     else
345         memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
346
347     if (This->nFilters + 1 > This->filterCapacity)
348     {
349         int newCapacity = 2*This->filterCapacity;
350         IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
351         LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
352         memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
353         memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
354         CoTaskMemFree(This->ppFiltersInGraph);
355         CoTaskMemFree(This->pFilterNames);
356         This->ppFiltersInGraph = ppNewFilters;
357         This->pFilterNames = pNewNames;
358         This->filterCapacity = newCapacity;
359     }
360
361     hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName);
362
363     if (SUCCEEDED(hr))
364     {
365         IBaseFilter_AddRef(pFilter);
366         This->ppFiltersInGraph[This->nFilters] = pFilter;
367         This->pFilterNames[This->nFilters] = wszFilterName;
368         This->nFilters++;
369     }
370     else
371         CoTaskMemFree(wszFilterName);
372
373     if (SUCCEEDED(hr) && duplicate_name)
374         return VFW_S_DUPLICATE_NAME;
375         
376     return hr;
377 }
378
379 static HRESULT WINAPI Graphbuilder_RemoveFilter(IGraphBuilder *iface,
380                                                 IBaseFilter *pFilter) {
381     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
382     int i;
383     HRESULT hr = E_FAIL;
384
385     TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
386
387     /* FIXME: check graph is stopped */
388
389     for (i = 0; i < This->nFilters; i++)
390     {
391         if (This->ppFiltersInGraph[i] == pFilter)
392         {
393             /* FIXME: disconnect pins */
394             hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
395             if (SUCCEEDED(hr))
396             {
397                 IPin_Release(pFilter);
398                 CoTaskMemFree(This->pFilterNames[i]);
399                 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
400                 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
401                 This->nFilters--;
402                 return S_OK;
403             }
404             break;
405         }
406     }
407
408     return hr; /* FIXME: check this error code */
409 }
410
411 static HRESULT WINAPI Graphbuilder_EnumFilters(IGraphBuilder *iface,
412                                               IEnumFilters **ppEnum) {
413     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
414
415     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
416
417     return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum);
418 }
419
420 static HRESULT WINAPI Graphbuilder_FindFilterByName(IGraphBuilder *iface,
421                                                     LPCWSTR pName,
422                                                     IBaseFilter **ppFilter) {
423     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
424     int i;
425
426     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
427
428     *ppFilter = NULL;
429
430     for (i = 0; i < This->nFilters; i++)
431     {
432         if (!strcmpW(pName, This->pFilterNames[i]))
433         {
434             *ppFilter = This->ppFiltersInGraph[i];
435             IBaseFilter_AddRef(*ppFilter);
436             return S_OK;
437         }
438     }
439
440     return E_FAIL; /* FIXME: check this error code */
441 }
442
443 /* NOTE: despite the implication, it doesn't matter which
444  * way round you put in the input and output pins */
445 static HRESULT WINAPI Graphbuilder_ConnectDirect(IGraphBuilder *iface,
446                                                  IPin *ppinIn,
447                                                  IPin *ppinOut,
448                                                  const AM_MEDIA_TYPE *pmt) {
449     PIN_DIRECTION dir;
450     HRESULT hr;
451
452     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
453
454     TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt);
455
456     /* FIXME: check pins are in graph */
457
458     hr = IPin_QueryDirection(ppinIn, &dir);
459     if (SUCCEEDED(hr))
460     {
461         if (dir == PINDIR_INPUT)
462             hr = IPin_Connect(ppinOut, ppinIn, pmt);
463         else
464             hr = IPin_Connect(ppinIn, ppinOut, pmt);
465     }
466
467     return hr;
468 }
469
470 static HRESULT WINAPI Graphbuilder_Reconnect(IGraphBuilder *iface,
471                                              IPin *ppin) {
472     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
473
474     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, ppin);
475
476     return S_OK;
477 }
478
479 static HRESULT WINAPI Graphbuilder_Disconnect(IGraphBuilder *iface,
480                                               IPin *ppin) {
481     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
482
483     TRACE("(%p/%p)->(%p)\n", This, iface, ppin);
484
485     return IPin_Disconnect(ppin);
486 }
487
488 static HRESULT WINAPI Graphbuilder_SetDefaultSyncSource(IGraphBuilder *iface) {
489     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
490
491     TRACE("(%p/%p)->(): stub !!!\n", iface, This);
492
493     return S_OK;
494 }
495
496 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar)
497 {
498     static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
499     static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
500     IPropertyBag * pPropBagCat = NULL;
501     HRESULT hr;
502
503     VariantInit(pvar);
504     V_VT(pvar) = VT_BSTR;
505
506     hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat);
507
508     if (SUCCEEDED(hr))
509         hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
510
511     if (SUCCEEDED(hr))
512         hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
513
514     if (SUCCEEDED(hr))
515         hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
516
517     if (SUCCEEDED(hr))
518         TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal)));
519
520     if (pPropBagCat)
521         IPropertyBag_Release(pPropBagCat);
522
523     return hr;
524 }
525
526 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb)
527 {
528     HRESULT hr;
529     ULONG nb = 0;
530
531     TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb);
532     hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb);
533     if (hr == S_OK) {
534         /* Rendered input */
535     } else if (hr == S_FALSE) {
536         *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb);
537         hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb);
538         if (hr != S_OK) {
539             ERR("Error (%lx)\n", hr);
540         }
541     } else if (hr == E_NOTIMPL) {
542         /* Input connected to all outputs */
543         IEnumPins* penumpins;
544         IPin* ppin;
545         int i = 0;
546         TRACE("E_NOTIMPL\n");
547         hr = IBaseFilter_EnumPins(pfilter, &penumpins);
548         if (FAILED(hr)) {
549             ERR("filter Enumpins failed (%lx)\n", hr);
550             return hr;
551         }
552         i = 0;
553         /* Count output pins */
554         while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
555             PIN_DIRECTION pindir;
556             IPin_QueryDirection(ppin, &pindir);
557             if (pindir == PINDIR_OUTPUT)
558                 i++;
559             else
560                 IPin_Release(ppin);
561         }
562         *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
563         /* Retrieve output pins */
564         IEnumPins_Reset(penumpins);
565         i = 0;
566         while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) {
567             PIN_DIRECTION pindir;
568             IPin_QueryDirection(ppin, &pindir);
569             if (pindir == PINDIR_OUTPUT)
570                 (*pppins)[i++] = ppin;
571             else
572                 IPin_Release(ppin);
573         }
574         nb = i;
575         if (FAILED(hr)) {
576             ERR("Next failed (%lx)\n", hr);
577             return hr;
578         }
579         IEnumPins_Release(penumpins);
580     } else if (FAILED(hr)) {
581         ERR("Cannot get internal connection (%lx)\n", hr);
582         return hr;
583     }
584
585     *pnb = nb;
586     return S_OK;
587 }
588
589 /*** IGraphBuilder methods ***/
590 static HRESULT WINAPI Graphbuilder_Connect(IGraphBuilder *iface,
591                                            IPin *ppinOut,
592                                            IPin *ppinIn) {
593     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
594     HRESULT hr;
595     AM_MEDIA_TYPE* mt;
596     IEnumMediaTypes* penummt;
597     ULONG nbmt;
598     IEnumPins* penumpins;
599     IEnumMoniker* pEnumMoniker;
600     GUID tab[2];
601     ULONG nb;
602     IMoniker* pMoniker;
603     ULONG pin;
604
605     TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
606
607     /* Try direct connection first */
608     TRACE("Try direct connection first\n");
609     hr = IPin_Connect(ppinOut, ppinIn, NULL);
610     if (SUCCEEDED(hr)) {
611         TRACE("Direct connection successful\n");
612         return S_OK;
613     }
614     TRACE("Direct connection failed, trying to insert other filters\n");
615
616     /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream 
617      * filter to the minor mediatype of input pin of the renderer */
618     hr = IPin_EnumMediaTypes(ppinOut, &penummt);
619     if (FAILED(hr)) {
620         ERR("EnumMediaTypes (%lx)\n", hr);
621         return hr;
622     }
623
624     hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
625     if (FAILED(hr)) {
626         ERR("IEnumMediaTypes_Next (%lx)\n", hr);
627         return hr;
628     }
629
630     if (!nbmt) {
631         ERR("No media type found!\n");
632         return S_OK;
633     }
634     TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
635     TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
636
637     /* Try to find a suitable filter that can connect to the pin to render */
638     tab[0] = mt->majortype;
639     tab[1] = mt->subtype;
640     hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
641     if (FAILED(hr)) {
642         ERR("Unable to enum filters (%lx)\n", hr);
643         return hr;
644     }
645     
646     while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
647     {
648         VARIANT var;
649         GUID clsid;
650         IPin** ppins;
651         IPin* ppinfilter;
652         IBaseFilter* pfilter = NULL;
653
654         hr = GetFilterInfo(pMoniker, &clsid, &var);
655         IMoniker_Release(pMoniker);
656         if (FAILED(hr)) {
657            ERR("Unable to retrieve filter info (%lx)\n", hr);
658            goto error;
659         }
660
661         hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
662         if (FAILED(hr)) {
663            ERR("Unable to create filter (%lx), trying next one\n", hr);
664            goto error;
665         }
666
667         hr = IGraphBuilder_AddFilter(iface, pfilter, NULL);
668         if (FAILED(hr)) {
669             ERR("Unable to add filter (%lx)\n", hr);
670             IBaseFilter_Release(pfilter);
671             pfilter = NULL;
672             goto error;
673         }
674
675         hr = IBaseFilter_EnumPins(pfilter, &penumpins);
676         if (FAILED(hr)) {
677             ERR("Enumpins (%lx)\n", hr);
678             goto error;
679         }
680         hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
681         if (FAILED(hr)) {
682             ERR("Next (%lx)\n", hr);
683             goto error;
684         }
685         if (pin == 0) {
686             ERR("No Pin\n");
687             goto error;
688         }
689         IEnumPins_Release(penumpins);
690
691         hr = IPin_Connect(ppinOut, ppinfilter, NULL);
692         if (FAILED(hr)) {
693             TRACE("Cannot connect to filter (%lx), trying next one\n", hr);
694             goto error;
695         }
696         TRACE("Successfully connected to filter, follow chain...\n");
697
698         /* Render all output pins of the filter by calling IGraphBuilder_Render on each of them */
699         hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
700
701         if (SUCCEEDED(hr)) {
702             int i;
703             TRACE("pins to consider: %ld\n", nb);
704             for(i = 0; i < nb; i++) {
705                 TRACE("Processing pin %d\n", i);
706                 hr = IGraphBuilder_Connect(iface, ppins[0], ppinIn);
707                 if (FAILED(hr)) {
708                     TRACE("Cannot render pin %p (%lx)\n", ppinfilter, hr);
709                     return hr;
710                 }
711             }
712             CoTaskMemFree(ppins);
713         }
714         break;
715
716 error:
717         if (pfilter) {
718             IGraphBuilder_RemoveFilter(iface, pfilter);
719             IBaseFilter_Release(pfilter);
720         }
721     }
722
723     IEnumMediaTypes_Release(penummt);
724     DeleteMediaType(mt);
725     
726     return S_OK;
727 }
728
729 static HRESULT WINAPI Graphbuilder_Render(IGraphBuilder *iface,
730                                           IPin *ppinOut) {
731     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
732     IEnumMediaTypes* penummt;
733     AM_MEDIA_TYPE* mt;
734     ULONG nbmt;
735     HRESULT hr;
736
737     IEnumMoniker* pEnumMoniker;
738     GUID tab[2];
739     ULONG nb;
740     IMoniker* pMoniker;
741
742     TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
743
744     hr = IPin_EnumMediaTypes(ppinOut, &penummt);
745     if (FAILED(hr)) {
746         ERR("EnumMediaTypes (%lx)\n", hr);
747         return hr;
748     }
749
750     while(1)
751     {
752         hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
753         if (FAILED(hr)) {
754             ERR("IEnumMediaTypes_Next (%lx)\n", hr);
755             return hr;
756         }
757         if (!nbmt)
758             break;
759         TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
760         TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
761
762         /* Try to find a suitable renderer with the same media type */
763         tab[0] = mt->majortype;
764         tab[1] = GUID_NULL;
765         hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL);
766         if (FAILED(hr)) {
767             ERR("Unable to enum filters (%lx)\n", hr);
768             return hr;
769         }
770
771         while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
772         {
773             VARIANT var;
774             GUID clsid;
775             IPin* ppinfilter;
776             IBaseFilter* pfilter = NULL;
777             IEnumPins* penumpins;
778             ULONG pin;
779
780             hr = GetFilterInfo(pMoniker, &clsid, &var);
781             IMoniker_Release(pMoniker);
782             if (FAILED(hr)) {
783                 ERR("Unable to retrieve filter info (%lx)\n", hr);
784                 goto error;
785             }
786
787             hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
788             if (FAILED(hr)) {
789                ERR("Unable to create filter (%lx), trying next one\n", hr);
790                goto error;
791             }
792
793             hr = IGraphBuilder_AddFilter(iface, pfilter, NULL);
794             if (FAILED(hr)) {
795                 ERR("Unable to add filter (%lx)\n", hr);
796                 IBaseFilter_Release(pfilter);
797                 pfilter = NULL;
798                 goto error;
799             }
800
801             hr = IBaseFilter_EnumPins(pfilter, &penumpins);
802             if (FAILED(hr)) {
803                 ERR("Splitter Enumpins (%lx)\n", hr);
804                 goto error;
805             }
806             hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
807             if (FAILED(hr)) {
808                ERR("Next (%lx)\n", hr);
809                goto error;
810             }
811             if (pin == 0) {
812                ERR("No Pin\n");
813                goto error;
814             }
815             IEnumPins_Release(penumpins);
816
817             /* Connect the pin to render to the renderer */
818             hr = IGraphBuilder_Connect(iface, ppinOut, ppinfilter);
819             if (FAILED(hr)) {
820                 TRACE("Unable to connect to renderer (%lx)\n", hr);
821                 goto error;
822             }
823             break;
824
825 error:
826             if (pfilter) {
827                 IGraphBuilder_RemoveFilter(iface, pfilter);
828                 IBaseFilter_Release(pfilter);
829             }
830         }
831        
832         DeleteMediaType(mt);
833         break;  
834     }
835
836     IEnumMediaTypes_Release(penummt);
837     
838     return S_OK;
839 }
840
841 static HRESULT WINAPI Graphbuilder_RenderFile(IGraphBuilder *iface,
842                                               LPCWSTR lpcwstrFile,
843                                               LPCWSTR lpcwstrPlayList) {
844     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
845     static const WCHAR string[] = {'R','e','a','d','e','r',0};
846     IBaseFilter* preader = NULL;
847     IBaseFilter* psplitter;
848     IPin* ppinreader;
849     IPin* ppinsplitter;
850     IEnumPins* penumpins;
851     ULONG pin;
852     HRESULT hr;
853     IEnumMoniker* pEnumMoniker;
854     GUID tab[2];
855     IPin** ppins;
856     ULONG nb;
857     IMoniker* pMoniker;
858     IFileSourceFilter* pfile = NULL;
859     AM_MEDIA_TYPE mt;
860     WCHAR* filename;
861
862     TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList));
863
864     hr = IGraphBuilder_AddSourceFilter(iface, lpcwstrFile, string, &preader);
865
866     /* Retrieve file media type */
867     if (SUCCEEDED(hr))
868         hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
869     if (SUCCEEDED(hr)) {
870         hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
871         IFileSourceFilter_Release(pfile);
872     }
873
874     if (SUCCEEDED(hr)) {
875         tab[0] = mt.majortype;
876         tab[1] = mt.subtype;
877         hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, 0, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
878     } else {
879         if (preader) {
880              IGraphBuilder_RemoveFilter(iface, preader);
881              IBaseFilter_Release(preader);
882         }
883         return hr;
884     }
885
886     while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK)
887     {
888         VARIANT var;
889         GUID clsid;
890
891         hr = GetFilterInfo(pMoniker, &clsid, &var);
892         IMoniker_Release(pMoniker);
893         if (FAILED(hr)) {
894             ERR("Unable to retrieve filter info (%lx)\n", hr);
895             continue;
896         }
897
898         hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&psplitter);
899         if (FAILED(hr)) {
900            ERR("Unable to create filter (%lx), trying next one\n", hr);
901            continue;
902         }
903
904         hr = IGraphBuilder_AddFilter(iface, psplitter, NULL);
905         if (FAILED(hr)) {
906             ERR("Unable add filter (%lx)\n", hr);
907             return hr;
908         }
909
910         /* Connect file source and splitter filters together */
911         /* Make the splitter analyze incoming data */
912         hr = IBaseFilter_EnumPins(preader, &penumpins);
913         if (FAILED(hr)) {
914             ERR("Enumpins (%lx)\n", hr);
915             return hr;
916         }
917         hr = IEnumPins_Next(penumpins, 1, &ppinreader, &pin);
918         if (FAILED(hr)) {
919             ERR("Next (%lx)\n", hr);
920             return hr;
921         }
922         if (pin == 0) {
923             ERR("No Pin\n");
924             return E_FAIL;
925         }
926         IEnumPins_Release(penumpins);
927
928         hr = IBaseFilter_EnumPins(psplitter, &penumpins);
929         if (FAILED(hr)) {
930             ERR("Splitter Enumpins (%lx)\n", hr);
931             return hr;
932         }
933         hr = IEnumPins_Next(penumpins, 1, &ppinsplitter, &pin);
934         if (FAILED(hr)) {
935             ERR("Next (%lx)\n", hr);
936             return hr;
937         }
938         if (pin == 0) {
939             ERR("No Pin\n");
940             return E_FAIL;
941         }
942         IEnumPins_Release(penumpins);
943
944         hr = IPin_Connect(ppinreader, ppinsplitter, NULL);
945         if (FAILED(hr)) {
946             IBaseFilter_Release(ppinsplitter);
947             ppinsplitter = NULL;
948             TRACE("Cannot connect to filter (%lx), trying next one\n", hr);
949             break;
950         }
951         TRACE("Successfully connected to filter\n");
952         break;
953     }
954
955     /* Render all output pin of the splitter by calling IGraphBuilder_Render on each of them */
956     if (SUCCEEDED(hr))
957         hr = GetInternalConnections(psplitter, ppinsplitter, &ppins, &nb);
958     
959     if (SUCCEEDED(hr)) {
960         int i;
961         TRACE("pins to consider: %ld\n", nb);
962         for(i = 0; i < nb; i++) {
963             TRACE("Processing pin %d\n", i);
964             hr = IGraphBuilder_Render(iface, ppins[i]);
965             if (FAILED(hr)) {
966                 ERR("Cannot render pin %p (%lx)\n", ppins[i], hr);
967                 /* FIXME: We should clean created things properly */
968                 break;
969             }
970         }
971         CoTaskMemFree(ppins);
972     }
973     
974     return hr;
975 }
976
977 static HRESULT WINAPI Graphbuilder_AddSourceFilter(IGraphBuilder *iface,
978                                                    LPCWSTR lpcwstrFileName,
979                                                    LPCWSTR lpcwstrFilterName,
980                                                    IBaseFilter **ppFilter) {
981     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
982     HRESULT hr;
983     IBaseFilter* preader;
984     IFileSourceFilter* pfile = NULL;
985     AM_MEDIA_TYPE mt;
986     WCHAR* filename;
987
988     TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter);
989
990     /* Instantiate a file source filter */ 
991     hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader);
992     if (FAILED(hr)) {
993         ERR("Unable to create file source filter (%lx)\n", hr);
994         return hr;
995     }
996
997     hr = IGraphBuilder_AddFilter(iface, preader, lpcwstrFilterName);
998     if (FAILED(hr)) {
999         ERR("Unable add filter (%lx)\n", hr);
1000         IBaseFilter_Release(preader);
1001         return hr;
1002     }
1003
1004     hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile);
1005     if (FAILED(hr)) {
1006         ERR("Unable to get IFileSourceInterface (%lx)\n", hr);
1007         goto error;
1008     }
1009
1010     /* Load the file in the file source filter */
1011     hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL);
1012     if (FAILED(hr)) {
1013         ERR("Load (%lx)\n", hr);
1014         goto error;
1015     }
1016     
1017     IFileSourceFilter_GetCurFile(pfile, &filename, &mt);
1018     if (FAILED(hr)) {
1019         ERR("GetCurFile (%lx)\n", hr);
1020         goto error;
1021     }
1022     TRACE("File %s\n", debugstr_w(filename));
1023     TRACE("MajorType %s\n", debugstr_guid(&mt.majortype));
1024     TRACE("SubType %s\n", debugstr_guid(&mt.subtype));
1025
1026     if (ppFilter)
1027         *ppFilter = preader;
1028
1029     return S_OK;
1030     
1031 error:
1032     if (pfile)
1033         IFileSourceFilter_Release(pfile);
1034     IGraphBuilder_RemoveFilter(iface, preader);
1035     IBaseFilter_Release(preader);
1036        
1037     return hr;
1038 }
1039
1040 static HRESULT WINAPI Graphbuilder_SetLogFile(IGraphBuilder *iface,
1041                                               DWORD_PTR hFile) {
1042     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1043
1044     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) hFile);
1045
1046     return S_OK;
1047 }
1048
1049 static HRESULT WINAPI Graphbuilder_Abort(IGraphBuilder *iface) {
1050     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1051
1052     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1053
1054     return S_OK;
1055 }
1056
1057 static HRESULT WINAPI Graphbuilder_ShouldOperationContinue(IGraphBuilder *iface) {
1058     ICOM_THIS_MULTI(IFilterGraphImpl, IGraphBuilder_vtbl, iface);
1059
1060     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1061
1062     return S_OK;
1063 }
1064
1065
1066 static IGraphBuilderVtbl IGraphBuilder_VTable =
1067 {
1068     Graphbuilder_QueryInterface,
1069     Graphbuilder_AddRef,
1070     Graphbuilder_Release,
1071     Graphbuilder_AddFilter,
1072     Graphbuilder_RemoveFilter,
1073     Graphbuilder_EnumFilters,
1074     Graphbuilder_FindFilterByName,
1075     Graphbuilder_ConnectDirect,
1076     Graphbuilder_Reconnect,
1077     Graphbuilder_Disconnect,
1078     Graphbuilder_SetDefaultSyncSource,
1079     Graphbuilder_Connect,
1080     Graphbuilder_Render,
1081     Graphbuilder_RenderFile,
1082     Graphbuilder_AddSourceFilter,
1083     Graphbuilder_SetLogFile,
1084     Graphbuilder_Abort,
1085     Graphbuilder_ShouldOperationContinue
1086 };
1087
1088 /*** IUnknown methods ***/
1089 static HRESULT WINAPI Mediacontrol_QueryInterface(IMediaControl *iface,
1090                                                   REFIID riid,
1091                                                   LPVOID*ppvObj) {
1092     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1093
1094     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1095
1096     return Filtergraph_QueryInterface(This, riid, ppvObj);
1097 }
1098
1099 static ULONG WINAPI Mediacontrol_AddRef(IMediaControl *iface) {
1100     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1101
1102     TRACE("(%p/%p)->()\n", This, iface);
1103
1104     return Filtergraph_AddRef(This);
1105 }
1106
1107 static ULONG WINAPI Mediacontrol_Release(IMediaControl *iface) {
1108     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1109
1110     TRACE("(%p/%p)->()\n", This, iface);
1111
1112     return Filtergraph_Release(This);
1113
1114 }
1115
1116 /*** IDispatch methods ***/
1117 static HRESULT WINAPI Mediacontrol_GetTypeInfoCount(IMediaControl *iface,
1118                                                     UINT*pctinfo) {
1119     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1120
1121     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1122
1123     return S_OK;
1124 }
1125
1126 static HRESULT WINAPI Mediacontrol_GetTypeInfo(IMediaControl *iface,
1127                                                UINT iTInfo,
1128                                                LCID lcid,
1129                                                ITypeInfo**ppTInfo) {
1130     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1131
1132     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1133
1134     return S_OK;
1135 }
1136
1137 static HRESULT WINAPI Mediacontrol_GetIDsOfNames(IMediaControl *iface,
1138                                                  REFIID riid,
1139                                                  LPOLESTR*rgszNames,
1140                                                  UINT cNames,
1141                                                  LCID lcid,
1142                                                  DISPID*rgDispId) {
1143     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1144
1145     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1146
1147     return S_OK;
1148 }
1149
1150 static HRESULT WINAPI Mediacontrol_Invoke(IMediaControl *iface,
1151                                           DISPID dispIdMember,
1152                                           REFIID riid,
1153                                           LCID lcid,
1154                                           WORD wFlags,
1155                                           DISPPARAMS*pDispParams,
1156                                           VARIANT*pVarResult,
1157                                           EXCEPINFO*pExepInfo,
1158                                           UINT*puArgErr) {
1159     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1160
1161     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1162
1163     return S_OK;
1164 }
1165
1166 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, REFERENCE_TIME tStart)
1167 {
1168     HRESULT hr;
1169     IPin* pInputPin;
1170     IPin** ppPins;
1171     ULONG nb;
1172     ULONG i;
1173     PIN_INFO PinInfo;
1174
1175     TRACE("%p %p %lld\n", pGraph, pOutputPin, tStart);
1176
1177     hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
1178
1179     if (SUCCEEDED(hr))
1180         hr = IPin_QueryPinInfo(pInputPin, &PinInfo);
1181
1182     if (SUCCEEDED(hr))
1183         hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb);
1184
1185     if (SUCCEEDED(hr))
1186     {
1187         if (nb == 0)
1188         {
1189             TRACE("Reached a renderer\n");
1190             /* Count renderers for end of stream notification */
1191             pGraph->nRenderers++;
1192         }
1193         else
1194         {
1195             for(i = 0; i < nb; i++)
1196             {
1197                 /* Explore the graph downstream from this pin
1198                  * FIXME: We should prevent exploring from a pin more than once. This can happens when
1199                  * several input pins are connected to the same output (a MUX for instance). */
1200                 ExploreGraph(pGraph, ppPins[i], tStart);
1201             }
1202
1203             CoTaskMemFree(ppPins);
1204         }
1205         TRACE("Run filter %p\n", PinInfo.pFilter);
1206         IBaseFilter_Run(PinInfo.pFilter, tStart);
1207     }
1208
1209     return hr;
1210 }
1211
1212 /*** IMediaControl methods ***/
1213 static HRESULT WINAPI Mediacontrol_Run(IMediaControl *iface) {
1214     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1215     int i;
1216     IBaseFilter* pfilter;
1217     IEnumPins* pEnum;
1218     HRESULT hr;
1219     IPin* pPin;
1220     LONG dummy;
1221     PIN_DIRECTION dir;
1222
1223     TRACE("(%p/%p)->()\n", This, iface);
1224
1225     EnterCriticalSection(&This->cs);
1226
1227     if (This->state == State_Running)
1228     {
1229         LeaveCriticalSection(&This->cs);
1230         return S_OK;
1231     }
1232
1233     /* Explorer the graph from source filters to renderers, determine renderers number and
1234      * run filters from renderers to source filters */
1235     This->nRenderers = 0;  
1236     ResetEvent(This->hEventCompletion);
1237
1238     for(i = 0; i < This->nFilters; i++)
1239     {
1240         BOOL source = TRUE;
1241         pfilter = This->ppFiltersInGraph[i];
1242         hr = IBaseFilter_EnumPins(pfilter, &pEnum);
1243         if (hr != S_OK)
1244         {
1245             ERR("Enum pins failed %lx\n", hr);
1246             continue;
1247         }
1248         /* Check if it is a source filter */
1249         while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1250         {
1251             IPin_QueryDirection(pPin, &dir);
1252             if (dir == PINDIR_INPUT)
1253             {
1254                 source = FALSE;
1255                 break;
1256             }
1257         }
1258         if (source == TRUE)
1259         {
1260             TRACE("Found a source filter\n");
1261             IEnumPins_Reset(pEnum);
1262             while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
1263             {
1264                 /* Explore the graph downstream from this pin */
1265                 ExploreGraph(This, pPin, 0);
1266             }
1267             IBaseFilter_Run(pfilter, 0);
1268         }
1269         IEnumPins_Release(pEnum);
1270     }
1271
1272     This->state = State_Running;
1273
1274     LeaveCriticalSection(&This->cs);
1275     
1276     return S_FALSE;
1277 }
1278
1279 static HRESULT WINAPI Mediacontrol_Pause(IMediaControl *iface) {
1280     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1281
1282     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1283
1284     return S_OK;
1285 }
1286
1287 static HRESULT WINAPI Mediacontrol_Stop(IMediaControl *iface) {
1288     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1289
1290     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1291
1292     return S_OK;
1293 }
1294
1295 static HRESULT WINAPI Mediacontrol_GetState(IMediaControl *iface,
1296                                             LONG msTimeout,
1297                                             OAFilterState *pfs) {
1298     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1299
1300     TRACE("(%p/%p)->(%ld, %p): semi-stub !!!\n", This, iface, msTimeout, pfs);
1301
1302     EnterCriticalSection(&This->cs);
1303
1304     *pfs = This->state;
1305
1306     LeaveCriticalSection(&This->cs);
1307     
1308     return S_OK;
1309 }
1310
1311 static HRESULT WINAPI Mediacontrol_RenderFile(IMediaControl *iface,
1312                                               BSTR strFilename) {
1313     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1314
1315     TRACE("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename);
1316
1317     return S_OK;
1318 }
1319
1320 static HRESULT WINAPI Mediacontrol_AddSourceFilter(IMediaControl *iface,
1321                                                    BSTR strFilename,
1322                                                    IDispatch **ppUnk) {
1323     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1324
1325     TRACE("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk);
1326
1327     return S_OK;
1328 }
1329
1330 static HRESULT WINAPI Mediacontrol_get_FilterCollection(IMediaControl *iface,
1331                                                         IDispatch **ppUnk) {
1332     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1333
1334     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1335
1336     return S_OK;
1337 }
1338
1339 static HRESULT WINAPI Mediacontrol_get_RegFilterCollection(IMediaControl *iface,
1340                                                            IDispatch **ppUnk) {
1341     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1342
1343     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk);
1344
1345     return S_OK;
1346 }
1347
1348 static HRESULT WINAPI Mediacontrol_StopWhenReady(IMediaControl *iface) {
1349     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
1350
1351     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
1352
1353     return S_OK;
1354 }
1355
1356
1357 static IMediaControlVtbl IMediaControl_VTable =
1358 {
1359     Mediacontrol_QueryInterface,
1360     Mediacontrol_AddRef,
1361     Mediacontrol_Release,
1362     Mediacontrol_GetTypeInfoCount,
1363     Mediacontrol_GetTypeInfo,
1364     Mediacontrol_GetIDsOfNames,
1365     Mediacontrol_Invoke,
1366     Mediacontrol_Run,
1367     Mediacontrol_Pause,
1368     Mediacontrol_Stop,
1369     Mediacontrol_GetState,
1370     Mediacontrol_RenderFile,
1371     Mediacontrol_AddSourceFilter,
1372     Mediacontrol_get_FilterCollection,
1373     Mediacontrol_get_RegFilterCollection,
1374     Mediacontrol_StopWhenReady
1375 };
1376
1377
1378 /*** IUnknown methods ***/
1379 static HRESULT WINAPI Mediaseeking_QueryInterface(IMediaSeeking *iface,
1380                                                   REFIID riid,
1381                                                   LPVOID*ppvObj) {
1382     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1383
1384     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1385
1386     return Filtergraph_QueryInterface(This, riid, ppvObj);
1387 }
1388
1389 static ULONG WINAPI Mediaseeking_AddRef(IMediaSeeking *iface) {
1390     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1391
1392     TRACE("(%p/%p)->()\n", This, iface);
1393
1394     return Filtergraph_AddRef(This);
1395 }
1396
1397 static ULONG WINAPI Mediaseeking_Release(IMediaSeeking *iface) {
1398     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1399
1400     TRACE("(%p/%p)->()\n", This, iface);
1401
1402     return Filtergraph_Release(This);
1403 }
1404
1405 /*** IMediaSeeking methods ***/
1406 static HRESULT WINAPI Mediaseeking_GetCapabilities(IMediaSeeking *iface,
1407                                                    DWORD *pCapabilities) {
1408     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1409
1410     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCapabilities);
1411
1412     return S_OK;
1413 }
1414
1415 static HRESULT WINAPI Mediaseeking_CheckCapabilities(IMediaSeeking *iface,
1416                                                      DWORD *pCapabilities) {
1417     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1418
1419     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCapabilities);
1420
1421     return S_OK;
1422 }
1423
1424 static HRESULT WINAPI Mediaseeking_IsFormatSupported(IMediaSeeking *iface,
1425                                                      const GUID *pFormat) {
1426     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1427
1428     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1429
1430     return S_OK;
1431 }
1432
1433 static HRESULT WINAPI Mediaseeking_QueryPreferredFormat(IMediaSeeking *iface,
1434                                                         GUID *pFormat) {
1435     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1436
1437     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1438
1439     return S_OK;
1440 }
1441
1442 static HRESULT WINAPI Mediaseeking_GetTimeFormat(IMediaSeeking *iface,
1443                                                  GUID *pFormat) {
1444     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1445
1446     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1447
1448     return S_OK;
1449 }
1450
1451 static HRESULT WINAPI Mediaseeking_IsUsingTimeFormat(IMediaSeeking *iface,
1452                                                      const GUID *pFormat) {
1453     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1454
1455     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1456
1457     return S_OK;
1458 }
1459
1460 static HRESULT WINAPI Mediaseeking_SetTimeFormat(IMediaSeeking *iface,
1461                                                  const GUID *pFormat) {
1462     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1463
1464     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pFormat);
1465
1466     return S_OK;
1467 }
1468
1469 static HRESULT WINAPI Mediaseeking_GetDuration(IMediaSeeking *iface,
1470                                                LONGLONG *pDuration) {
1471     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1472
1473     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDuration);
1474
1475     return S_OK;
1476 }
1477
1478 static HRESULT WINAPI Mediaseeking_GetStopPosition(IMediaSeeking *iface,
1479                                                    LONGLONG *pStop) {
1480     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1481
1482     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pStop);
1483
1484     return S_OK;
1485 }
1486
1487 static HRESULT WINAPI Mediaseeking_GetCurrentPosition(IMediaSeeking *iface,
1488                                                       LONGLONG *pCurrent) {
1489     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1490
1491     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pCurrent);
1492
1493     return S_OK;
1494 }
1495
1496 static HRESULT WINAPI Mediaseeking_ConvertTimeFormat(IMediaSeeking *iface,
1497                                                      LONGLONG *pTarget,
1498                                                      const GUID *pTargetFormat,
1499                                                      LONGLONG Source,
1500                                                      const GUID *pSourceFormat) {
1501     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1502
1503     TRACE("(%p/%p)->(%p, %p, %lld, %p): stub !!!\n", This, iface, pTarget, pTargetFormat, Source, pSourceFormat);
1504
1505     return S_OK;
1506 }
1507
1508 static HRESULT WINAPI Mediaseeking_SetPositions(IMediaSeeking *iface,
1509                                                 LONGLONG *pCurrent,
1510                                                 DWORD dwCurrentFlags,
1511                                                 LONGLONG *pStop,
1512                                                 DWORD dwStopFlags) {
1513     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1514
1515     TRACE("(%p/%p)->(%p, %08lx, %p, %08lx): stub !!!\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
1516
1517     return S_OK;
1518 }
1519
1520 static HRESULT WINAPI Mediaseeking_GetPositions(IMediaSeeking *iface,
1521                                                 LONGLONG *pCurrent,
1522                                                 LONGLONG *pStop) {
1523     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1524
1525     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pCurrent, pStop);
1526
1527     return S_OK;
1528 }
1529
1530 static HRESULT WINAPI Mediaseeking_GetAvailable(IMediaSeeking *iface,
1531                                                 LONGLONG *pEarliest,
1532                                                 LONGLONG *pLatest) {
1533     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1534
1535     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest);
1536
1537     return S_OK;
1538 }
1539
1540 static HRESULT WINAPI Mediaseeking_SetRate(IMediaSeeking *iface,
1541                                            double dRate) {
1542     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1543
1544     TRACE("(%p/%p)->(%f): stub !!!\n", This, iface, dRate);
1545
1546     return S_OK;
1547 }
1548
1549 static HRESULT WINAPI Mediaseeking_GetRate(IMediaSeeking *iface,
1550                                            double *pdRate) {
1551     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1552
1553     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate);
1554
1555     return S_OK;
1556 }
1557
1558 static HRESULT WINAPI Mediaseeking_GetPreroll(IMediaSeeking *iface,
1559                                               LONGLONG *pllPreroll) {
1560     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface);
1561
1562     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll);
1563
1564     return S_OK;
1565 }
1566
1567
1568 static IMediaSeekingVtbl IMediaSeeking_VTable =
1569 {
1570     Mediaseeking_QueryInterface,
1571     Mediaseeking_AddRef,
1572     Mediaseeking_Release,
1573     Mediaseeking_GetCapabilities,
1574     Mediaseeking_CheckCapabilities,
1575     Mediaseeking_IsFormatSupported,
1576     Mediaseeking_QueryPreferredFormat,
1577     Mediaseeking_GetTimeFormat,
1578     Mediaseeking_IsUsingTimeFormat,
1579     Mediaseeking_SetTimeFormat,
1580     Mediaseeking_GetDuration,
1581     Mediaseeking_GetStopPosition,
1582     Mediaseeking_GetCurrentPosition,
1583     Mediaseeking_ConvertTimeFormat,
1584     Mediaseeking_SetPositions,
1585     Mediaseeking_GetPositions,
1586     Mediaseeking_GetAvailable,
1587     Mediaseeking_SetRate,
1588     Mediaseeking_GetRate,
1589     Mediaseeking_GetPreroll
1590 };
1591
1592 /*** IUnknown methods ***/
1593 static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface,
1594                                                 REFIID riid,
1595                                                 LPVOID*ppvObj) {
1596     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1597
1598     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1599
1600     return Filtergraph_QueryInterface(This, riid, ppvObj);
1601 }
1602
1603 static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) {
1604     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1605
1606     TRACE("(%p/%p)->()\n", This, iface);
1607
1608     return Filtergraph_AddRef(This);
1609 }
1610
1611 static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) {
1612     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1613
1614     TRACE("(%p/%p)->()\n", This, iface);
1615
1616     return Filtergraph_Release(This);
1617 }
1618
1619 /*** IDispatch methods ***/
1620 static HRESULT WINAPI Basicaudio_GetTypeInfoCount(IBasicAudio *iface,
1621                                                   UINT*pctinfo) {
1622     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1623
1624     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1625
1626     return S_OK;
1627 }
1628
1629 static HRESULT WINAPI Basicaudio_GetTypeInfo(IBasicAudio *iface,
1630                                              UINT iTInfo,
1631                                              LCID lcid,
1632                                              ITypeInfo**ppTInfo) {
1633     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1634
1635     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1636
1637     return S_OK;
1638 }
1639
1640 static HRESULT WINAPI Basicaudio_GetIDsOfNames(IBasicAudio *iface,
1641                                                REFIID riid,
1642                                                LPOLESTR*rgszNames,
1643                                                UINT cNames,
1644                                                LCID lcid,
1645                                                DISPID*rgDispId) {
1646     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1647
1648     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1649
1650     return S_OK;
1651 }
1652
1653 static HRESULT WINAPI Basicaudio_Invoke(IBasicAudio *iface,
1654                                         DISPID dispIdMember,
1655                                         REFIID riid,
1656                                         LCID lcid,
1657                                         WORD wFlags,
1658                                         DISPPARAMS*pDispParams,
1659                                         VARIANT*pVarResult,
1660                                         EXCEPINFO*pExepInfo,
1661                                         UINT*puArgErr) {
1662     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1663
1664     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1665
1666     return S_OK;
1667 }
1668
1669 /*** IBasicAudio methods ***/
1670 static HRESULT WINAPI Basicaudio_put_Volume(IBasicAudio *iface,
1671                                             long lVolume) {
1672     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1673
1674     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, lVolume);
1675
1676     return S_OK;
1677 }
1678
1679 static HRESULT WINAPI Basicaudio_get_Volume(IBasicAudio *iface,
1680                                             long *plVolume) {
1681     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1682
1683     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, plVolume);
1684
1685     return S_OK;
1686 }
1687
1688 static HRESULT WINAPI Basicaudio_put_Balance(IBasicAudio *iface,
1689                                              long lBalance) {
1690     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1691
1692     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, lBalance);
1693
1694     return S_OK;
1695 }
1696
1697 static HRESULT WINAPI Basicaudio_get_Balance(IBasicAudio *iface,
1698                                              long *plBalance) {
1699     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface);
1700
1701     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, plBalance);
1702
1703     return S_OK;
1704 }
1705
1706 static IBasicAudioVtbl IBasicAudio_VTable =
1707 {
1708     Basicaudio_QueryInterface,
1709     Basicaudio_AddRef,
1710     Basicaudio_Release,
1711     Basicaudio_GetTypeInfoCount,
1712     Basicaudio_GetTypeInfo,
1713     Basicaudio_GetIDsOfNames,
1714     Basicaudio_Invoke,
1715     Basicaudio_put_Volume,
1716     Basicaudio_get_Volume,
1717     Basicaudio_put_Balance,
1718     Basicaudio_get_Balance
1719 };
1720
1721 /*** IUnknown methods ***/
1722 static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface,
1723                                                 REFIID riid,
1724                                                 LPVOID*ppvObj) {
1725     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1726
1727     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
1728
1729     return Filtergraph_QueryInterface(This, riid, ppvObj);
1730 }
1731
1732 static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) {
1733     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1734
1735     TRACE("(%p/%p)->()\n", This, iface);
1736
1737     return Filtergraph_AddRef(This);
1738 }
1739
1740 static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) {
1741     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1742
1743     TRACE("(%p/%p)->()\n", This, iface);
1744
1745     return Filtergraph_Release(This);
1746 }
1747
1748 /*** IDispatch methods ***/
1749 static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface,
1750                                                   UINT*pctinfo) {
1751     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1752
1753     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
1754
1755     return S_OK;
1756 }
1757
1758 static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface,
1759                                              UINT iTInfo,
1760                                              LCID lcid,
1761                                              ITypeInfo**ppTInfo) {
1762     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1763
1764     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
1765
1766     return S_OK;
1767 }
1768
1769 static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface,
1770                                                REFIID riid,
1771                                                LPOLESTR*rgszNames,
1772                                                UINT cNames,
1773                                                LCID lcid,
1774                                                DISPID*rgDispId) {
1775     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1776
1777     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
1778
1779     return S_OK;
1780 }
1781
1782 static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface,
1783                                         DISPID dispIdMember,
1784                                         REFIID riid,
1785                                         LCID lcid,
1786                                         WORD wFlags,
1787                                         DISPPARAMS*pDispParams,
1788                                         VARIANT*pVarResult,
1789                                         EXCEPINFO*pExepInfo,
1790                                         UINT*puArgErr) {
1791     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1792
1793     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
1794
1795     return S_OK;
1796 }
1797
1798 /*** IBasicVideo methods ***/
1799 static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface,
1800                                                      REFTIME *pAvgTimePerFrame) {
1801     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1802
1803     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pAvgTimePerFrame);
1804
1805     return S_OK;
1806 }
1807
1808 static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface,
1809                                              long *pBitRate) {
1810     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1811
1812     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate);
1813
1814     return S_OK;
1815 }
1816
1817 static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface,
1818                                                   long *pBitErrorRate) {
1819     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1820
1821     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate);
1822
1823     return S_OK;
1824 }
1825
1826 static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface,
1827                                                 long *pVideoWidth) {
1828     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1829
1830     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVideoWidth);
1831
1832     return S_OK;
1833 }
1834
1835 static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface,
1836                                                  long *pVideoHeight) {
1837     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1838
1839     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVideoHeight);
1840
1841     return S_OK;
1842 }
1843
1844 static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface,
1845                                                 long SourceLeft) {
1846     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1847
1848     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceLeft);
1849
1850     return S_OK;
1851 }
1852
1853 static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface,
1854                                                 long *pSourceLeft) {
1855     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1856
1857     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceLeft);
1858
1859     return S_OK;
1860 }
1861
1862 static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface,
1863                                                  long SourceWidth) {
1864     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1865
1866     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceWidth);
1867
1868     return S_OK;
1869 }
1870
1871 static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface,
1872                                                  long *pSourceWidth) {
1873     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1874
1875     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceWidth);
1876
1877     return S_OK;
1878 }
1879
1880 static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface,
1881                                                long SourceTop) {
1882     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1883
1884     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceTop);
1885
1886     return S_OK;
1887 }
1888
1889 static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface,
1890                                                long *pSourceTop) {
1891     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1892
1893     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceTop);
1894
1895     return S_OK;
1896 }
1897
1898 static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface,
1899                                                   long SourceHeight) {
1900     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1901
1902     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, SourceHeight);
1903
1904     return S_OK;
1905 }
1906
1907 static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface,
1908                                                   long *pSourceHeight) {
1909     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1910
1911     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pSourceHeight);
1912
1913     return S_OK;
1914 }
1915
1916 static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface,
1917                                                      long DestinationLeft) {
1918     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1919
1920     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationLeft);
1921
1922     return S_OK;
1923 }
1924
1925 static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface,
1926                                                      long *pDestinationLeft) {
1927     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1928
1929     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationLeft);
1930
1931     return S_OK;
1932 }
1933
1934 static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
1935                                                       long DestinationWidth) {
1936     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1937
1938     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationWidth);
1939
1940     return S_OK;
1941 }
1942
1943 static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
1944                                                       long *pDestinationWidth) {
1945     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1946
1947     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationWidth);
1948
1949     return S_OK;
1950 }
1951
1952 static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
1953                                                     long DestinationTop) {
1954     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1955
1956     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationTop);
1957
1958     return S_OK;
1959 }
1960
1961 static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface,
1962                                                     long *pDestinationTop) {
1963     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1964
1965     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationTop);
1966
1967     return S_OK;
1968 }
1969
1970 static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface,
1971                                                        long DestinationHeight) {
1972     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1973
1974     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, DestinationHeight);
1975
1976     return S_OK;
1977 }
1978
1979 static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface,
1980                                                        long *pDestinationHeight) {
1981     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1982
1983     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pDestinationHeight);
1984
1985     return S_OK;
1986 }
1987
1988 static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface,
1989                                                    long Left,
1990                                                    long Top,
1991                                                    long Width,
1992                                                    long Height) {
1993     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
1994
1995     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
1996
1997     return S_OK;
1998 }
1999
2000 static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface,
2001                                                    long *pLeft,
2002                                                    long *pTop,
2003                                                    long *pWidth,
2004                                                    long *pHeight) {
2005     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2006
2007     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2008
2009     return S_OK;
2010 }
2011
2012 static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) {
2013     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2014
2015     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2016
2017     return S_OK;
2018 }
2019
2020 static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface,
2021                                                         long Left,
2022                                                         long Top,
2023                                                         long Width,
2024                                                         long Height) {
2025     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2026
2027     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
2028
2029     return S_OK;
2030 }
2031
2032 static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface,
2033                                                         long *pLeft,
2034                                                         long *pTop,
2035                                                         long *pWidth,
2036                                                         long *pHeight) {
2037     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2038
2039     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2040
2041     return S_OK;
2042 }
2043
2044 static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) {
2045     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2046
2047     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2048
2049     return S_OK;
2050 }
2051
2052 static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface,
2053                                               long *pWidth,
2054                                               long *pHeight) {
2055     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2056
2057     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
2058
2059     return S_OK;
2060 }
2061
2062 static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface,
2063                                                         long StartIndex,
2064                                                         long Entries,
2065                                                         long *pRetrieved,
2066                                                         long *pPalette) {
2067     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2068
2069     TRACE("(%p/%p)->(%ld, %ld, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette);
2070
2071     return S_OK;
2072 }
2073
2074 static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface,
2075                                                  long *pBufferSize,
2076                                                  long *pDIBImage) {
2077     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2078
2079     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage);
2080
2081     return S_OK;
2082 }
2083
2084 static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) {
2085     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2086
2087     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2088
2089     return S_OK;
2090 }
2091
2092 static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) {
2093     ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface);
2094
2095     TRACE("(%p/%p)->(): stub !!!\n", This, iface);
2096
2097     return S_OK;
2098 }
2099
2100
2101 static IBasicVideoVtbl IBasicVideo_VTable =
2102 {
2103     Basicvideo_QueryInterface,
2104     Basicvideo_AddRef,
2105     Basicvideo_Release,
2106     Basicvideo_GetTypeInfoCount,
2107     Basicvideo_GetTypeInfo,
2108     Basicvideo_GetIDsOfNames,
2109     Basicvideo_Invoke,
2110     Basicvideo_get_AvgTimePerFrame,
2111     Basicvideo_get_BitRate,
2112     Basicvideo_get_BitErrorRate,
2113     Basicvideo_get_VideoWidth,
2114     Basicvideo_get_VideoHeight,
2115     Basicvideo_put_SourceLeft,
2116     Basicvideo_get_SourceLeft,
2117     Basicvideo_put_SourceWidth,
2118     Basicvideo_get_SourceWidth,
2119     Basicvideo_put_SourceTop,
2120     Basicvideo_get_SourceTop,
2121     Basicvideo_put_SourceHeight,
2122     Basicvideo_get_SourceHeight,
2123     Basicvideo_put_DestinationLeft,
2124     Basicvideo_get_DestinationLeft,
2125     Basicvideo_put_DestinationWidth,
2126     Basicvideo_get_DestinationWidth,
2127     Basicvideo_put_DestinationTop,
2128     Basicvideo_get_DestinationTop,
2129     Basicvideo_put_DestinationHeight,
2130     Basicvideo_get_DestinationHeight,
2131     Basicvideo_SetSourcePosition,
2132     Basicvideo_GetSourcePosition,
2133     Basicvideo_SetDefaultSourcePosition,
2134     Basicvideo_SetDestinationPosition,
2135     Basicvideo_GetDestinationPosition,
2136     Basicvideo_SetDefaultDestinationPosition,
2137     Basicvideo_GetVideoSize,
2138     Basicvideo_GetVideoPaletteEntries,
2139     Basicvideo_GetCurrentImage,
2140     Basicvideo_IsUsingDefaultSource,
2141     Basicvideo_IsUsingDefaultDestination
2142 };
2143
2144
2145 /*** IUnknown methods ***/
2146 static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
2147                                                  REFIID riid,
2148                                                  LPVOID*ppvObj) {
2149     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2150
2151     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2152
2153     return Filtergraph_QueryInterface(This, riid, ppvObj);
2154 }
2155
2156 static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
2157     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2158
2159     TRACE("(%p/%p)->()\n", This, iface);
2160
2161     return Filtergraph_AddRef(This);
2162 }
2163
2164 static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
2165     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2166
2167     TRACE("(%p/%p)->()\n", This, iface);
2168
2169     return Filtergraph_Release(This);
2170 }
2171
2172 /*** IDispatch methods ***/
2173 static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface,
2174                                                    UINT*pctinfo) {
2175     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2176
2177     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
2178
2179     return S_OK;
2180 }
2181
2182 static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface,
2183                                               UINT iTInfo,
2184                                               LCID lcid,
2185                                               ITypeInfo**ppTInfo) {
2186     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2187
2188     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
2189
2190     return S_OK;
2191 }
2192
2193 static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface,
2194                                                 REFIID riid,
2195                                                 LPOLESTR*rgszNames,
2196                                                 UINT cNames,
2197                                                 LCID lcid,
2198                                                 DISPID*rgDispId) {
2199     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2200
2201     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2202
2203     return S_OK;
2204 }
2205
2206 static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface,
2207                                          DISPID dispIdMember,
2208                                          REFIID riid,
2209                                          LCID lcid,
2210                                          WORD wFlags,
2211                                          DISPPARAMS*pDispParams,
2212                                          VARIANT*pVarResult,
2213                                          EXCEPINFO*pExepInfo,
2214                                          UINT*puArgErr) {
2215     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2216
2217     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2218
2219     return S_OK;
2220 }
2221
2222 /*** IVideoWindow methods ***/
2223 static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface,
2224                                               BSTR strCaption) {
2225     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2226
2227     TRACE("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strCaption), strCaption);
2228
2229     return S_OK;
2230 }
2231
2232 static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface,
2233                                               BSTR *strCaption) {
2234     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2235
2236     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, strCaption);
2237
2238     return S_OK;
2239 }
2240
2241 static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface,
2242                                                   long WindowStyle) {
2243     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2244
2245     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowStyle);
2246
2247     return S_OK;
2248 }
2249
2250 static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface,
2251                                                   long *WindowStyle) {
2252     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2253
2254     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowStyle);
2255
2256     return S_OK;
2257 }
2258
2259 static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface,
2260                                                     long WindowStyleEx) {
2261     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2262
2263     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowStyleEx);
2264
2265     return S_OK;
2266 }
2267
2268 static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface,
2269                                                     long *WindowStyleEx) {
2270     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2271
2272     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowStyleEx);
2273
2274     return S_OK;
2275 }
2276
2277 static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface,
2278                                                long AutoShow) {
2279     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2280
2281     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, AutoShow);
2282
2283     return S_OK;
2284 }
2285
2286 static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface,
2287                                                long *AutoShow) {
2288     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2289
2290     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, AutoShow);
2291
2292     return S_OK;
2293 }
2294
2295 static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface,
2296                                                   long WindowState) {
2297     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2298
2299     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, WindowState);
2300
2301     return S_OK;
2302 }
2303
2304 static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface,
2305                                                   long *WindowState) {
2306     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2307
2308     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, WindowState);
2309
2310     return S_OK;
2311 }
2312
2313 static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface,
2314                                                         long BackgroundPalette) {
2315     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2316
2317     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, BackgroundPalette);
2318
2319     return S_OK;
2320 }
2321
2322 static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface,
2323                                                         long *pBackgroundPalette) {
2324     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2325
2326     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
2327
2328     return S_OK;
2329 }
2330
2331 static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface,
2332                                               long Visible) {
2333     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2334
2335     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Visible);
2336
2337     return S_OK;
2338 }
2339
2340 static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface,
2341                                               long *pVisible) {
2342     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2343
2344     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pVisible);
2345
2346     return S_OK;
2347 }
2348
2349 static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface,
2350                                            long Left) {
2351     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2352
2353     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Left);
2354
2355     return S_OK;
2356 }
2357
2358 static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface,
2359                                            long *pLeft) {
2360     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2361
2362     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pLeft);
2363
2364     return S_OK;
2365 }
2366
2367 static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface,
2368                                             long Width) {
2369     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2370
2371     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Width);
2372
2373     return S_OK;
2374 }
2375
2376 static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface,
2377                                             long *pWidth) {
2378     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2379
2380     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pWidth);
2381
2382     return S_OK;
2383 }
2384
2385 static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface,
2386                                           long Top) {
2387     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2388
2389     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Top);
2390
2391     return S_OK;
2392 }
2393
2394 static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface,
2395                                           long *pTop) {
2396     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2397
2398     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pTop);
2399
2400     return S_OK;
2401 }
2402
2403 static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface,
2404                                              long Height) {
2405     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2406
2407     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Height);
2408
2409     return S_OK;
2410 }
2411
2412 static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface,
2413                                              long *pHeight) {
2414     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2415
2416     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pHeight);
2417
2418     return S_OK;
2419 }
2420
2421 static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface,
2422                                             OAHWND Owner) {
2423     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2424
2425     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Owner);
2426
2427     return S_OK;
2428 }
2429
2430 static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface,
2431                                             OAHWND *Owner) {
2432     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2433
2434     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Owner);
2435
2436     return S_OK;
2437 }
2438
2439 static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface,
2440                                                    OAHWND Drain) {
2441     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2442
2443     TRACE("(%p/%p)->(%08lx): stub !!!\n", This, iface, (DWORD) Drain);
2444
2445     return S_OK;
2446 }
2447
2448 static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface,
2449                                                    OAHWND *Drain) {
2450     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2451
2452     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, Drain);
2453
2454     return S_OK;
2455 }
2456
2457 static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface,
2458                                                   long *Color) {
2459     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2460
2461     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
2462
2463     return S_OK;
2464 }
2465
2466 static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface,
2467                                                   long Color) {
2468     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2469
2470     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Color);
2471
2472     return S_OK;
2473 }
2474
2475 static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface,
2476                                                      long *FullScreenMode) {
2477     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2478
2479     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
2480
2481     return S_OK;
2482 }
2483
2484 static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface,
2485                                                      long FullScreenMode) {
2486     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2487
2488     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, FullScreenMode);
2489
2490     return S_OK;
2491 }
2492
2493 static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface,
2494                                                       long Focus) {
2495     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2496
2497     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, Focus);
2498
2499     return S_OK;
2500 }
2501
2502 static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface,
2503                                                      OAHWND hwnd,
2504                                                      long uMsg,
2505                                                      LONG_PTR wParam,
2506                                                      LONG_PTR lParam) {
2507     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2508
2509     TRACE("(%p/%p)->(%08lx, %ld, %08lx, %08lx): stub !!!\n", This, iface, (DWORD) hwnd, uMsg, wParam, lParam);
2510
2511     return S_OK;
2512 }
2513
2514 static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface,
2515                                                     long Left,
2516                                                     long Top,
2517                                                     long Width,
2518                                                     long Height) {
2519     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2520     
2521     TRACE("(%p/%p)->(%ld, %ld, %ld, %ld): stub !!!\n", This, iface, Left, Top, Width, Height);
2522
2523     return S_OK;
2524 }
2525
2526 static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface,
2527                                                     long *pLeft,
2528                                                     long *pTop,
2529                                                     long *pWidth,
2530                                                     long *pHeight) {
2531     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2532
2533     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2534
2535     return S_OK;
2536 }
2537
2538 static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface,
2539                                                        long *pWidth,
2540                                                        long *pHeight) {
2541     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2542
2543     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
2544
2545     return S_OK;
2546 }
2547
2548 static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface,
2549                                                        long *pWidth,
2550                                                        long *pHeight) {
2551     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2552
2553     TRACE("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pWidth, pHeight);
2554
2555     return S_OK;
2556 }
2557
2558 static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface,
2559                                                      long *pLeft,
2560                                                      long *pTop,
2561                                                      long *pWidth,
2562                                                      long *pHeight) {
2563     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2564
2565     TRACE("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
2566
2567     return S_OK;
2568 }
2569
2570 static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface,
2571                                              long HideCursor) {
2572     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2573
2574     TRACE("(%p/%p)->(%ld): stub !!!\n", This, iface, HideCursor);
2575
2576     return S_OK;
2577 }
2578
2579 static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface,
2580                                                  long *CursorHidden) {
2581     ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface);
2582
2583     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
2584
2585     return S_OK;
2586 }
2587
2588
2589 static IVideoWindowVtbl IVideoWindow_VTable =
2590 {
2591     Videowindow_QueryInterface,
2592     Videowindow_AddRef,
2593     Videowindow_Release,
2594     Videowindow_GetTypeInfoCount,
2595     Videowindow_GetTypeInfo,
2596     Videowindow_GetIDsOfNames,
2597     Videowindow_Invoke,
2598     Videowindow_put_Caption,
2599     Videowindow_get_Caption,
2600     Videowindow_put_WindowStyle,
2601     Videowindow_get_WindowStyle,
2602     Videowindow_put_WindowStyleEx,
2603     Videowindow_get_WindowStyleEx,
2604     Videowindow_put_AutoShow,
2605     Videowindow_get_AutoShow,
2606     Videowindow_put_WindowState,
2607     Videowindow_get_WindowState,
2608     Videowindow_put_BackgroundPalette,
2609     Videowindow_get_BackgroundPalette,
2610     Videowindow_put_Visible,
2611     Videowindow_get_Visible,
2612     Videowindow_put_Left,
2613     Videowindow_get_Left,
2614     Videowindow_put_Width,
2615     Videowindow_get_Width,
2616     Videowindow_put_Top,
2617     Videowindow_get_Top,
2618     Videowindow_put_Height,
2619     Videowindow_get_Height,
2620     Videowindow_put_Owner,
2621     Videowindow_get_Owner,
2622     Videowindow_put_MessageDrain,
2623     Videowindow_get_MessageDrain,
2624     Videowindow_get_BorderColor,
2625     Videowindow_put_BorderColor,
2626     Videowindow_get_FullScreenMode,
2627     Videowindow_put_FullScreenMode,
2628     Videowindow_SetWindowForeground,
2629     Videowindow_NotifyOwnerMessage,
2630     Videowindow_SetWindowPosition,
2631     Videowindow_GetWindowPosition,
2632     Videowindow_GetMinIdealImageSize,
2633     Videowindow_GetMaxIdealImageSize,
2634     Videowindow_GetRestorePosition,
2635     Videowindow_HideCursor,
2636     Videowindow_IsCursorHidden
2637 };
2638
2639
2640 /*** IUnknown methods ***/
2641 static HRESULT WINAPI Mediaevent_QueryInterface(IMediaEventEx *iface,
2642                                                 REFIID riid,
2643                                                 LPVOID*ppvObj) {
2644     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2645
2646     TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
2647
2648     return Filtergraph_QueryInterface(This, riid, ppvObj);
2649 }
2650
2651 static ULONG WINAPI Mediaevent_AddRef(IMediaEventEx *iface) {
2652     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2653
2654     TRACE("(%p/%p)->()\n", This, iface);
2655
2656     return Filtergraph_AddRef(This);
2657 }
2658
2659 static ULONG WINAPI Mediaevent_Release(IMediaEventEx *iface) {
2660     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2661
2662     TRACE("(%p/%p)->()\n", This, iface);
2663
2664     return Filtergraph_Release(This);
2665 }
2666
2667 /*** IDispatch methods ***/
2668 static HRESULT WINAPI Mediaevent_GetTypeInfoCount(IMediaEventEx *iface,
2669                                                   UINT*pctinfo) {
2670     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2671
2672     TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo);
2673
2674     return S_OK;
2675 }
2676
2677 static HRESULT WINAPI Mediaevent_GetTypeInfo(IMediaEventEx *iface,
2678                                              UINT iTInfo,
2679                                              LCID lcid,
2680                                              ITypeInfo**ppTInfo) {
2681     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2682
2683     TRACE("(%p/%p)->(%d, %ld, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo);
2684
2685     return S_OK;
2686 }
2687
2688 static HRESULT WINAPI Mediaevent_GetIDsOfNames(IMediaEventEx *iface,
2689                                                REFIID riid,
2690                                                LPOLESTR*rgszNames,
2691                                                UINT cNames,
2692                                                LCID lcid,
2693                                                DISPID*rgDispId) {
2694     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2695
2696     TRACE("(%p/%p)->(%s (%p), %p, %d, %ld, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId);
2697
2698     return S_OK;
2699 }
2700
2701 static HRESULT WINAPI Mediaevent_Invoke(IMediaEventEx *iface,
2702                                         DISPID dispIdMember,
2703                                         REFIID riid,
2704                                         LCID lcid,
2705                                         WORD wFlags,
2706                                         DISPPARAMS*pDispParams,
2707                                         VARIANT*pVarResult,
2708                                         EXCEPINFO*pExepInfo,
2709                                         UINT*puArgErr) {
2710     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2711
2712     TRACE("(%p/%p)->(%ld, %s (%p), %ld, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr);
2713
2714     return S_OK;
2715 }
2716
2717 /*** IMediaEvent methods ***/
2718 static HRESULT WINAPI Mediaevent_GetEventHandle(IMediaEventEx *iface,
2719                                                 OAEVENT *hEvent) {
2720     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2721
2722     TRACE("(%p/%p)->(%p)\n", This, iface, hEvent);
2723
2724     *hEvent = (OAEVENT)This->evqueue.msg_event;
2725
2726     return S_OK;
2727 }
2728
2729 static HRESULT WINAPI Mediaevent_GetEvent(IMediaEventEx *iface,
2730                                           long *lEventCode,
2731                                           LONG_PTR *lParam1,
2732                                           LONG_PTR *lParam2,
2733                                           long msTimeout) {
2734     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2735     Event evt;
2736
2737     TRACE("(%p/%p)->(%p, %p, %p, %ld)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
2738
2739     if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout))
2740     {
2741         *lEventCode = evt.lEventCode;
2742         *lParam1 = evt.lParam1;
2743         *lParam2 = evt.lParam2;
2744         return S_OK;
2745     }
2746
2747     *lEventCode = 0;
2748     return E_ABORT;
2749 }
2750
2751 static HRESULT WINAPI Mediaevent_WaitForCompletion(IMediaEventEx *iface,
2752                                                    long msTimeout,
2753                                                    long *pEvCode) {
2754     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2755
2756     TRACE("(%p/%p)->(%ld, %p)\n", This, iface, msTimeout, pEvCode);
2757
2758     if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0)
2759     {
2760         *pEvCode = This->CompletionStatus;
2761         return S_OK;
2762     }
2763
2764     *pEvCode = 0;
2765     return E_ABORT;
2766 }
2767
2768 static HRESULT WINAPI Mediaevent_CancelDefaultHandling(IMediaEventEx *iface,
2769                                                        long lEvCode) {
2770     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2771
2772     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
2773
2774     if (lEvCode == EC_COMPLETE)
2775         This->HandleEcComplete = FALSE;
2776     else if (lEvCode == EC_REPAINT)
2777         This->HandleEcRepaint = FALSE;
2778     else
2779         return S_FALSE;
2780
2781     return S_OK;
2782 }
2783
2784 static HRESULT WINAPI Mediaevent_RestoreDefaultHandling(IMediaEventEx *iface,
2785                                                         long lEvCode) {
2786     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2787
2788     TRACE("(%p/%p)->(%ld)\n", This, iface, lEvCode);
2789
2790     if (lEvCode == EC_COMPLETE)
2791         This->HandleEcComplete = TRUE;
2792     else if (lEvCode == EC_REPAINT)
2793         This->HandleEcRepaint = TRUE;
2794     else
2795         return S_FALSE;
2796
2797     return S_OK;
2798 }
2799
2800 static HRESULT WINAPI Mediaevent_FreeEventParams(IMediaEventEx *iface,
2801                                                  long lEvCode,
2802                                                  LONG_PTR lParam1,
2803                                                  LONG_PTR lParam2) {
2804     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2805
2806     TRACE("(%p/%p)->(%ld, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2);
2807
2808     return S_OK;
2809 }
2810
2811 /*** IMediaEventEx methods ***/
2812 static HRESULT WINAPI Mediaevent_SetNotifyWindow(IMediaEventEx *iface,
2813                                                  OAHWND hwnd,
2814                                                  long lMsg,
2815                                                  LONG_PTR lInstanceData) {
2816     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2817
2818     TRACE("(%p/%p)->(%08lx, %ld, %08lx)\n", This, iface, (DWORD) hwnd, lMsg, lInstanceData);
2819
2820     This->notif.hWnd = (HWND)hwnd;
2821     This->notif.msg = lMsg;
2822     This->notif.instance = (long) lInstanceData;
2823
2824     return S_OK;
2825 }
2826
2827 static HRESULT WINAPI Mediaevent_SetNotifyFlags(IMediaEventEx *iface,
2828                                                 long lNoNotifyFlags) {
2829     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2830
2831     TRACE("(%p/%p)->(%ld)\n", This, iface, lNoNotifyFlags);
2832
2833     if ((lNoNotifyFlags != 0) || (lNoNotifyFlags != 1))
2834         return E_INVALIDARG;
2835
2836     This->notif.disabled = lNoNotifyFlags;
2837
2838     return S_OK;
2839 }
2840
2841 static HRESULT WINAPI Mediaevent_GetNotifyFlags(IMediaEventEx *iface,
2842                                                 long *lplNoNotifyFlags) {
2843     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2844
2845     TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags);
2846
2847     if (!lplNoNotifyFlags)
2848         return E_POINTER;
2849
2850     *lplNoNotifyFlags = This->notif.disabled;
2851
2852     return S_OK;
2853 }
2854
2855
2856 static IMediaEventExVtbl IMediaEventEx_VTable =
2857 {
2858     Mediaevent_QueryInterface,
2859     Mediaevent_AddRef,
2860     Mediaevent_Release,
2861     Mediaevent_GetTypeInfoCount,
2862     Mediaevent_GetTypeInfo,
2863     Mediaevent_GetIDsOfNames,
2864     Mediaevent_Invoke,
2865     Mediaevent_GetEventHandle,
2866     Mediaevent_GetEvent,
2867     Mediaevent_WaitForCompletion,
2868     Mediaevent_CancelDefaultHandling,
2869     Mediaevent_RestoreDefaultHandling,
2870     Mediaevent_FreeEventParams,
2871     Mediaevent_SetNotifyWindow,
2872     Mediaevent_SetNotifyFlags,
2873     Mediaevent_GetNotifyFlags
2874 };
2875
2876
2877 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv)
2878 {
2879     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2880
2881     return Filtergraph_QueryInterface(This, riid, ppv);
2882 }
2883
2884 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface)
2885 {
2886     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2887
2888     return Filtergraph_AddRef(This);
2889 }
2890
2891 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface)
2892 {
2893     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface);
2894
2895     return Filtergraph_Release(This);
2896 }
2897
2898 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID)
2899 {
2900     FIXME("(%p): stub\n", pClassID);
2901
2902     return E_NOTIMPL;
2903 }
2904
2905 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
2906 {
2907     FIXME("(): stub\n");
2908
2909     return E_NOTIMPL;
2910 }
2911
2912 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
2913 {
2914     FIXME("(): stub\n");
2915
2916     return E_NOTIMPL;
2917 }
2918
2919 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
2920 {
2921     FIXME("(%lld): stub\n", tStart);
2922
2923     return E_NOTIMPL;
2924 }
2925
2926 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState)
2927 {
2928     FIXME("(%ld, %p): stub\n", dwMsTimeout, pState);
2929
2930     return E_NOTIMPL;
2931 }
2932
2933 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
2934 {
2935     FIXME("(%p): stub\n", pClock);
2936
2937     return E_NOTIMPL;
2938 }
2939
2940 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock)
2941 {
2942     FIXME("(%p): stub\n", ppClock);
2943
2944     return E_NOTIMPL;
2945 }
2946
2947 static IMediaFilterVtbl IMediaFilter_VTable =
2948 {
2949     MediaFilter_QueryInterface,
2950     MediaFilter_AddRef,
2951     MediaFilter_Release,
2952     MediaFilter_GetClassID,
2953     MediaFilter_Stop,
2954     MediaFilter_Pause,
2955     MediaFilter_Run,
2956     MediaFilter_GetState,
2957     MediaFilter_SetSyncSource,
2958     MediaFilter_GetSyncSource
2959 };
2960
2961 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv)
2962 {
2963     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
2964
2965     return Filtergraph_QueryInterface(This, riid, ppv);
2966 }
2967
2968 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface)
2969 {
2970     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
2971
2972     return Filtergraph_AddRef(This);
2973 }
2974
2975 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface)
2976 {
2977     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
2978
2979     return Filtergraph_Release(This);
2980 }
2981
2982 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
2983 {
2984     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface);
2985     Event evt;
2986
2987     TRACE("(%p/%p)->(%ld, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
2988
2989     /* We need thread safety here, let's use the events queue's one */
2990     EnterCriticalSection(&This->evqueue.msg_crst);
2991
2992     if ((EventCode == EC_COMPLETE) && This->HandleEcComplete)
2993     {
2994         if (++This->EcCompleteCount == This->nRenderers)
2995         {
2996             evt.lEventCode = EC_COMPLETE;
2997             evt.lParam1 = S_OK;
2998             evt.lParam2 = 0;
2999             EventsQueue_PutEvent(&This->evqueue, &evt);
3000             if (!This->notif.disabled && This->notif.hWnd)
3001                 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
3002             This->CompletionStatus = EC_COMPLETE;
3003             SetEvent(This->hEventCompletion);
3004         }
3005     }
3006     else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint)
3007     {
3008         /* FIXME: Not handled yet */
3009     }
3010     else
3011     {
3012         evt.lEventCode = EventCode;
3013         evt.lParam1 = EventParam1;
3014         evt.lParam2 = EventParam2;
3015         EventsQueue_PutEvent(&This->evqueue, &evt);
3016         if (!This->notif.disabled && This->notif.hWnd)
3017             PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance);
3018     }
3019
3020     LeaveCriticalSection(&This->evqueue.msg_crst);
3021     return S_OK;
3022 }
3023
3024 static IMediaEventSinkVtbl IMediaEventSink_VTable =
3025 {
3026     MediaEventSink_QueryInterface,
3027     MediaEventSink_AddRef,
3028     MediaEventSink_Release,
3029     MediaEventSink_Notify
3030 };
3031
3032 /* This is the only function that actually creates a FilterGraph class... */
3033 HRESULT FILTERGRAPH_create(IUnknown *pUnkOuter, LPVOID *ppObj) {
3034     IFilterGraphImpl *fimpl;
3035     HRESULT hr;
3036
3037     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
3038
3039     if( pUnkOuter )
3040         return CLASS_E_NOAGGREGATION;
3041
3042     fimpl = (IFilterGraphImpl *) HeapAlloc(GetProcessHeap(), 0, sizeof(*fimpl));
3043     fimpl->IGraphBuilder_vtbl = &IGraphBuilder_VTable;
3044     fimpl->IMediaControl_vtbl = &IMediaControl_VTable;
3045     fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable;
3046     fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable;
3047     fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable;
3048     fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable;
3049     fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable;
3050     fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable;
3051     fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable;
3052     fimpl->ref = 1;
3053     fimpl->ppFiltersInGraph = NULL;
3054     fimpl->pFilterNames = NULL;
3055     fimpl->nFilters = 0;
3056     fimpl->filterCapacity = 0;
3057     fimpl->nameIndex = 1;
3058     fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE,0);
3059     fimpl->HandleEcComplete = TRUE;
3060     fimpl->HandleEcRepaint = TRUE;
3061     fimpl->notif.hWnd = 0;
3062     fimpl->notif.disabled = TRUE;
3063     fimpl->nRenderers = 0;
3064     fimpl->EcCompleteCount = 0;
3065     fimpl->state = State_Stopped;
3066     EventsQueue_Init(&fimpl->evqueue);
3067     InitializeCriticalSection(&fimpl->cs);
3068
3069     hr = CoCreateInstance(&CLSID_FilterMapper, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
3070     if (FAILED(hr)) {
3071         ERR("Unable to create filter mapper (%lx)\n", hr);
3072         return hr;
3073     }
3074
3075     *ppObj = fimpl;
3076     return S_OK;
3077 }