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