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