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