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