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