|  | /* Capture Graph Builder, Minimal edition | 
|  | * | 
|  | * Copyright 2005 Maarten Lankhorst | 
|  | * Copyright 2005 Rolf Kalbermatter | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <stdarg.h> | 
|  |  | 
|  | #define COBJMACROS | 
|  | #define NONAMELESSSTRUCT | 
|  | #define NONAMELESSUNION | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "wingdi.h" | 
|  | #include "winerror.h" | 
|  | #include "objbase.h" | 
|  |  | 
|  | #include "evcode.h" | 
|  | #include "strmif.h" | 
|  | #include "control.h" | 
|  | #include "vfwmsgs.h" | 
|  | /* | 
|  | *#include "amvideo.h" | 
|  | *#include "mmreg.h" | 
|  | *#include "dshow.h" | 
|  | *#include "ddraw.h" | 
|  | */ | 
|  | #include "qcap_main.h" | 
|  |  | 
|  | #include "wine/unicode.h" | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(qcap); | 
|  |  | 
|  | /*********************************************************************** | 
|  | *   ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation | 
|  | */ | 
|  | typedef struct CaptureGraphImpl | 
|  | { | 
|  | const ICaptureGraphBuilder2Vtbl * lpVtbl2; | 
|  | const ICaptureGraphBuilderVtbl * lpVtbl; | 
|  | LONG ref; | 
|  | IGraphBuilder *mygraph; | 
|  |  | 
|  | CRITICAL_SECTION csFilter; | 
|  | } CaptureGraphImpl; | 
|  |  | 
|  | static const ICaptureGraphBuilderVtbl builder_Vtbl; | 
|  | static const ICaptureGraphBuilder2Vtbl builder2_Vtbl; | 
|  |  | 
|  | static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder( ICaptureGraphBuilder *iface ) | 
|  | { | 
|  | return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl)); | 
|  | } | 
|  |  | 
|  | static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2( ICaptureGraphBuilder2 *iface ) | 
|  | { | 
|  | return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl2)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | converts This to an interface pointer | 
|  | */ | 
|  | #define _IUnknown_(This)                (IUnknown*)&(This->lpVtbl2) | 
|  | #define _ICaptureGraphBuilder_(This)    (ICaptureGraphBuilder*)&(This->lpVtbl) | 
|  | #define _ICaptureGraphBuilder2_(This)   (ICaptureGraphBuilder2*)&(This->lpVtbl2) | 
|  |  | 
|  |  | 
|  | IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter, | 
|  | HRESULT *phr) | 
|  | { | 
|  | CaptureGraphImpl * pCapture = NULL; | 
|  |  | 
|  | TRACE("(%p, %p)\n", pUnkOuter, phr); | 
|  |  | 
|  | *phr = CLASS_E_NOAGGREGATION; | 
|  | if (pUnkOuter) | 
|  | { | 
|  | return NULL; | 
|  | } | 
|  | *phr = E_OUTOFMEMORY; | 
|  |  | 
|  | pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl)); | 
|  | if (pCapture) | 
|  | { | 
|  | pCapture->lpVtbl2 = &builder2_Vtbl; | 
|  | pCapture->lpVtbl = &builder_Vtbl; | 
|  | pCapture->ref = 1; | 
|  | pCapture->mygraph = NULL; | 
|  | InitializeCriticalSection(&pCapture->csFilter); | 
|  | pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter"); | 
|  | *phr = S_OK; | 
|  | ObjectRefCount(TRUE); | 
|  | } | 
|  | return (IUnknown *)pCapture; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface, | 
|  | REFIID riid, | 
|  | LPVOID * ppv) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv); | 
|  |  | 
|  | *ppv = NULL; | 
|  | if (IsEqualIID(riid, &IID_IUnknown)) | 
|  | *ppv = _IUnknown_(This); | 
|  | else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder)) | 
|  | *ppv = _ICaptureGraphBuilder_(This); | 
|  | else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2)) | 
|  | *ppv = _ICaptureGraphBuilder2_(This); | 
|  |  | 
|  | if (*ppv) | 
|  | { | 
|  | IUnknown_AddRef((IUnknown *)(*ppv)); | 
|  | TRACE ("-- Interface = %p\n", *ppv); | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | TRACE ("-- Interface: E_NOINTERFACE\n"); | 
|  | return E_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI | 
|  | fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  | DWORD ref = InterlockedIncrement(&This->ref); | 
|  |  | 
|  | TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1); | 
|  | return ref; | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI | 
|  | fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  | DWORD ref = InterlockedDecrement(&This->ref); | 
|  |  | 
|  | TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1); | 
|  |  | 
|  | if (!ref) | 
|  | { | 
|  | FIXME("Release IGraphFilter or w/e\n"); | 
|  | This->csFilter.DebugInfo->Spare[0] = 0; | 
|  | DeleteCriticalSection(&This->csFilter); | 
|  | This->lpVtbl = NULL; | 
|  | This->lpVtbl2 = NULL; | 
|  | if (This->mygraph != NULL) | 
|  | IGraphBuilder_Release(This->mygraph); | 
|  | CoTaskMemFree(This); | 
|  | ObjectRefCount(FALSE); | 
|  | } | 
|  | return ref; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface, | 
|  | IGraphBuilder *pfg) | 
|  | { | 
|  | /* The graph builder will automatically create a filter graph if you don't call | 
|  | this method. If you call this method after the graph builder has created its | 
|  | own filter graph, the call will fail. */ | 
|  | IMediaEvent *pmev; | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | TRACE("(%p/%p)->(%p)\n", This, iface, pfg); | 
|  |  | 
|  | if (This->mygraph) | 
|  | return E_UNEXPECTED; | 
|  |  | 
|  | if (!pfg) | 
|  | return E_POINTER; | 
|  |  | 
|  | This->mygraph = pfg; | 
|  | IGraphBuilder_AddRef(This->mygraph); | 
|  | if (SUCCEEDED(IUnknown_QueryInterface(This->mygraph, | 
|  | &IID_IMediaEvent, (LPVOID *)&pmev))) | 
|  | { | 
|  | IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT); | 
|  | IMediaEvent_Release(pmev); | 
|  | } | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface, | 
|  | IGraphBuilder **pfg) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | TRACE("(%p/%p)->(%p)\n", This, iface, pfg); | 
|  |  | 
|  | if (!pfg) | 
|  | return E_POINTER; | 
|  |  | 
|  | *pfg = This->mygraph; | 
|  | if (!This->mygraph) | 
|  | { | 
|  | TRACE("(%p) Getting NULL filtergraph\n", iface); | 
|  | return E_UNEXPECTED; | 
|  | } | 
|  |  | 
|  | IGraphBuilder_AddRef(This->mygraph); | 
|  |  | 
|  | TRACE("(%p) return filtergraph %p\n", iface, *pfg); | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface, | 
|  | const GUID *pType, | 
|  | LPCOLESTR lpstrFile, | 
|  | IBaseFilter **ppf, | 
|  | IFileSinkFilter **ppSink) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface, | 
|  | debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink); | 
|  |  | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface, | 
|  | const GUID *pCategory, | 
|  | const GUID *pType, | 
|  | IBaseFilter *pf, | 
|  | REFIID riid, | 
|  | void **ppint) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface, | 
|  | debugstr_guid(pCategory), debugstr_guid(pType), | 
|  | pf, debugstr_guid(riid), ppint); | 
|  |  | 
|  | return IBaseFilter_QueryInterface(pf, riid, ppint); | 
|  | /* Looks for the specified interface on the filter, upstream and | 
|  | * downstream from the filter, and, optionally, only on the output | 
|  | * pin of the given category. | 
|  | */ | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface, | 
|  | const GUID *pCategory, | 
|  | const GUID *pType, | 
|  | IUnknown *pSource, | 
|  | IBaseFilter *pfCompressor, | 
|  | IBaseFilter *pfRenderer) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  | IPin *pin_in = NULL; | 
|  | IPin *pin_out = NULL; | 
|  | HRESULT hr; | 
|  |  | 
|  | FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface, | 
|  | debugstr_guid(pCategory), debugstr_guid(pType), | 
|  | pSource, pfCompressor, pfRenderer); | 
|  |  | 
|  | if (pfCompressor) | 
|  | FIXME("Intermediate streams not supported yet\n"); | 
|  |  | 
|  | if (!This->mygraph) | 
|  | { | 
|  | FIXME("Need a capture graph\n"); | 
|  | return E_UNEXPECTED; | 
|  | } | 
|  |  | 
|  | ICaptureGraphBuilder2_FindPin(iface, pSource, PINDIR_OUTPUT, pCategory, pType, TRUE, 0, &pin_in); | 
|  | if (!pin_in) | 
|  | return E_FAIL; | 
|  | ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, pCategory, pType, TRUE, 0, &pin_out); | 
|  | if (!pin_out) | 
|  | { | 
|  | IPin_Release(pin_in); | 
|  | return E_FAIL; | 
|  | } | 
|  |  | 
|  | /* Uses 'Intelligent Connect', so Connect, not ConnectDirect here */ | 
|  | hr = IFilterGraph2_Connect(This->mygraph, pin_in, pin_out); | 
|  | IPin_Release(pin_in); | 
|  | IPin_Release(pin_out); | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface, | 
|  | const GUID *pCategory, | 
|  | const GUID *pType, | 
|  | IBaseFilter *pFilter, | 
|  | REFERENCE_TIME *pstart, | 
|  | REFERENCE_TIME *pstop, | 
|  | WORD wStartCookie, | 
|  | WORD wStopCookie) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface, | 
|  | debugstr_guid(pCategory), debugstr_guid(pType), | 
|  | pFilter, pstart, pstop, wStartCookie, wStopCookie); | 
|  |  | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface, | 
|  | LPCOLESTR lpwstr, | 
|  | DWORDLONG dwlSize) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface, | 
|  | debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize)); | 
|  |  | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface, | 
|  | LPOLESTR lpwstrOld, | 
|  | LPOLESTR lpwstrNew, | 
|  | int fAllowEscAbort, | 
|  | IAMCopyCaptureFileProgress *pCallback) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface, | 
|  | debugstr_w(lpwstrOld), debugstr_w(lpwstrNew), | 
|  | fAllowEscAbort, pCallback); | 
|  |  | 
|  | return E_NOTIMPL; | 
|  | } | 
|  |  | 
|  | static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected) | 
|  | { | 
|  | IPin *partner; | 
|  | PIN_DIRECTION pindir; | 
|  |  | 
|  | IPin_QueryDirection(pin, &pindir); | 
|  | if (pindir != direction) | 
|  | { | 
|  | TRACE("No match, wrong direction\n"); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK) | 
|  | { | 
|  | IPin_Release(partner); | 
|  | TRACE("No match, %p already connected to %p\n", pin, partner); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | if (cat || type) | 
|  | FIXME("Ignoring category/type\n"); | 
|  |  | 
|  | TRACE("Match made in heaven\n"); | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface, | 
|  | IUnknown *pSource, | 
|  | PIN_DIRECTION pindir, | 
|  | const GUID *pCategory, | 
|  | const GUID *pType, | 
|  | BOOL fUnconnected, | 
|  | INT num, | 
|  | IPin **ppPin) | 
|  | { | 
|  | HRESULT hr; | 
|  | IEnumPins *enumpins = NULL; | 
|  | IPin *pin; | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); | 
|  |  | 
|  | TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This, iface, | 
|  | pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType), | 
|  | fUnconnected, num, ppPin); | 
|  |  | 
|  | pin = NULL; | 
|  |  | 
|  | hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin); | 
|  | if (hr == E_NOINTERFACE) | 
|  | { | 
|  | IBaseFilter *filter = NULL; | 
|  | int numcurrent = 0; | 
|  |  | 
|  | hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter); | 
|  | if (hr == E_NOINTERFACE) | 
|  | { | 
|  | WARN("Input not filter or pin?!\n"); | 
|  | return E_FAIL; | 
|  | } | 
|  |  | 
|  | hr = IBaseFilter_EnumPins(filter, &enumpins); | 
|  | if (FAILED(hr)) | 
|  | { | 
|  | WARN("Could not enumerate\n"); | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | IEnumPins_Reset(enumpins); | 
|  |  | 
|  | while (1) | 
|  | { | 
|  | hr = IEnumPins_Next(enumpins, 1, &pin, NULL); | 
|  | if (hr == VFW_E_ENUM_OUT_OF_SYNC) | 
|  | { | 
|  | numcurrent = 0; | 
|  | IEnumPins_Reset(enumpins); | 
|  | pin = NULL; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (hr != S_OK) | 
|  | break; | 
|  | TRACE("Testing match\n"); | 
|  | if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num) | 
|  | break; | 
|  | IPin_Release(pin); | 
|  | pin = NULL; | 
|  | } | 
|  | IEnumPins_Release(enumpins); | 
|  |  | 
|  | if (hr != S_OK) | 
|  | { | 
|  | WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent); | 
|  | return E_FAIL; | 
|  | } | 
|  | } | 
|  | else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected)) | 
|  | { | 
|  | IPin_Release(pin); | 
|  | return E_FAIL; | 
|  | } | 
|  |  | 
|  | *ppPin = pin; | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static const ICaptureGraphBuilder2Vtbl builder2_Vtbl = | 
|  | { | 
|  | fnCaptureGraphBuilder2_QueryInterface, | 
|  | fnCaptureGraphBuilder2_AddRef, | 
|  | fnCaptureGraphBuilder2_Release, | 
|  | fnCaptureGraphBuilder2_SetFilterGraph, | 
|  | fnCaptureGraphBuilder2_GetFilterGraph, | 
|  | fnCaptureGraphBuilder2_SetOutputFileName, | 
|  | fnCaptureGraphBuilder2_FindInterface, | 
|  | fnCaptureGraphBuilder2_RenderStream, | 
|  | fnCaptureGraphBuilder2_ControlStream, | 
|  | fnCaptureGraphBuilder2_AllocCapFile, | 
|  | fnCaptureGraphBuilder2_CopyCaptureFile, | 
|  | fnCaptureGraphBuilder2_FindPin | 
|  | }; | 
|  |  | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface, | 
|  | REFIID riid, LPVOID * ppv) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return IUnknown_QueryInterface(_ICaptureGraphBuilder2_(This), riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI | 
|  | fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return IUnknown_AddRef(_ICaptureGraphBuilder2_(This)); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI | 
|  | fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return IUnknown_Release(_ICaptureGraphBuilder2_(This)); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface, | 
|  | IGraphBuilder *pfg) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_SetFiltergraph(_ICaptureGraphBuilder2_(This), pfg); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface, | 
|  | IGraphBuilder **pfg) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_GetFiltergraph(_ICaptureGraphBuilder2_(This), pfg); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface, | 
|  | const GUID *pType, LPCOLESTR lpstrFile, | 
|  | IBaseFilter **ppf, IFileSinkFilter **ppSink) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_SetOutputFileName(_ICaptureGraphBuilder2_(This), | 
|  | pType, lpstrFile, ppf, ppSink); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface, | 
|  | const GUID *pCategory, IBaseFilter *pf, | 
|  | REFIID riid, void **ppint) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_FindInterface(_ICaptureGraphBuilder2_(This), | 
|  | pCategory, NULL, pf, riid, ppint); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface, | 
|  | const GUID *pCategory, IUnknown *pSource, | 
|  | IBaseFilter *pfCompressor, IBaseFilter *pfRenderer) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_RenderStream(_ICaptureGraphBuilder2_(This), | 
|  | pCategory, NULL, pSource, | 
|  | pfCompressor, pfRenderer); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder * iface, | 
|  | const GUID *pCategory, IBaseFilter *pFilter, | 
|  | REFERENCE_TIME *pstart, REFERENCE_TIME *pstop, | 
|  | WORD wStartCookie, WORD wStopCookie) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_ControlStream(_ICaptureGraphBuilder2_(This), | 
|  | pCategory, NULL, pFilter, pstart, | 
|  | pstop, wStartCookie, wStopCookie); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface, | 
|  | LPCOLESTR lpstr, DWORDLONG dwlSize) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_AllocCapFile(_ICaptureGraphBuilder2_(This), | 
|  | lpstr, dwlSize); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI | 
|  | fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface, | 
|  | LPOLESTR lpwstrOld, LPOLESTR lpwstrNew, | 
|  | int fAllowEscAbort, | 
|  | IAMCopyCaptureFileProgress *pCallback) | 
|  | { | 
|  | CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface); | 
|  | TRACE("%p --> Forwarding to v2 (%p)\n", iface, This); | 
|  | return ICaptureGraphBuilder2_CopyCaptureFile(_ICaptureGraphBuilder2_(This), | 
|  | lpwstrOld, lpwstrNew, | 
|  | fAllowEscAbort, pCallback); | 
|  | } | 
|  |  | 
|  | static const ICaptureGraphBuilderVtbl builder_Vtbl = | 
|  | { | 
|  | fnCaptureGraphBuilder_QueryInterface, | 
|  | fnCaptureGraphBuilder_AddRef, | 
|  | fnCaptureGraphBuilder_Release, | 
|  | fnCaptureGraphBuilder_SetFiltergraph, | 
|  | fnCaptureGraphBuilder_GetFiltergraph, | 
|  | fnCaptureGraphBuilder_SetOutputFileName, | 
|  | fnCaptureGraphBuilder_FindInterface, | 
|  | fnCaptureGraphBuilder_RenderStream, | 
|  | fnCaptureGraphBuilder_ControlStream, | 
|  | fnCaptureGraphBuilder_AllocCapFile, | 
|  | fnCaptureGraphBuilder_CopyCaptureFile | 
|  | }; |