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