richedit: Add more tests for URL autodetection on WM_CHAR, make them pass under Wine.
[wine] / dlls / qcap / capturegraph.c
1 /* Capture Graph Builder, Minimal edition
2  *
3  * Copyright 2005 Maarten Lankhorst
4  * Copyright 2005 Rolf Kalbermatter
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include "config.h"
21
22 #include <stdio.h>
23 #include <stdarg.h>
24
25 #define COBJMACROS
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "objbase.h"
33
34 #include "evcode.h"
35 #include "strmif.h"
36 #include "control.h"
37 #include "vfwmsgs.h"
38 /*
39  *#include "amvideo.h"
40  *#include "mmreg.h"
41  *#include "dshow.h"
42  *#include "ddraw.h"
43  */
44 #include "qcap_main.h"
45
46 #include "wine/unicode.h"
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
50
51 /***********************************************************************
52 *   ICaptureGraphBuilder & ICaptureGraphBuilder2 implementation
53 */
54 typedef struct CaptureGraphImpl
55 {
56     const ICaptureGraphBuilder2Vtbl * lpVtbl2;
57     const ICaptureGraphBuilderVtbl * lpVtbl;
58     LONG ref;
59     IGraphBuilder *mygraph;
60
61     CRITICAL_SECTION csFilter;
62 } CaptureGraphImpl;
63
64 static const ICaptureGraphBuilderVtbl builder_Vtbl;
65 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl;
66
67 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder( ICaptureGraphBuilder *iface )
68 {
69     return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl));
70 }
71
72 static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2( ICaptureGraphBuilder2 *iface )
73 {
74     return (CaptureGraphImpl *)((char*)iface - FIELD_OFFSET(CaptureGraphImpl, lpVtbl2));
75 }
76
77 /*
78   converts This to an interface pointer
79 */
80 #define _IUnknown_(This)                (IUnknown*)&(This->lpVtbl2)
81 #define _ICaptureGraphBuilder_(This)    (ICaptureGraphBuilder*)&(This->lpVtbl)
82 #define _ICaptureGraphBuilder2_(This)   (ICaptureGraphBuilder2*)&(This->lpVtbl2)
83
84
85 IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter,
86                                                     HRESULT *phr)
87 {
88     CaptureGraphImpl * pCapture = NULL;
89
90     TRACE("(%p, %p)\n", pUnkOuter, phr);
91
92     *phr = CLASS_E_NOAGGREGATION;
93     if (pUnkOuter)
94     {
95         return NULL;
96     }
97     *phr = E_OUTOFMEMORY;
98
99     pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl));
100     if (pCapture)
101     {
102         pCapture->lpVtbl2 = &builder2_Vtbl;
103         pCapture->lpVtbl = &builder_Vtbl;
104         pCapture->ref = 1;
105         pCapture->mygraph = NULL;
106         InitializeCriticalSection(&pCapture->csFilter);
107         pCapture->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter");
108         *phr = S_OK;
109         ObjectRefCount(TRUE);
110     }
111     return (IUnknown *)pCapture;
112 }
113
114 static HRESULT WINAPI
115 fnCaptureGraphBuilder2_QueryInterface(ICaptureGraphBuilder2 * iface,
116                                       REFIID riid,
117                                       LPVOID * ppv)
118 {
119     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
120
121     TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
122
123     *ppv = NULL;
124     if (IsEqualIID(riid, &IID_IUnknown))
125         *ppv = _IUnknown_(This);
126     else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder))
127         *ppv = _ICaptureGraphBuilder_(This);
128     else if (IsEqualIID(riid, &IID_ICaptureGraphBuilder2))
129         *ppv = _ICaptureGraphBuilder2_(This);
130
131     if (*ppv)
132     {
133         IUnknown_AddRef((IUnknown *)(*ppv));
134         TRACE ("-- Interface = %p\n", *ppv);
135         return S_OK;
136     }
137
138     TRACE ("-- Interface: E_NOINTERFACE\n");
139     return E_NOINTERFACE;
140 }
141
142 static ULONG WINAPI
143 fnCaptureGraphBuilder2_AddRef(ICaptureGraphBuilder2 * iface)
144 {
145     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
146     DWORD ref = InterlockedIncrement(&This->ref);
147
148     TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
149     return ref;
150 }
151
152 static ULONG WINAPI
153 fnCaptureGraphBuilder2_Release(ICaptureGraphBuilder2 * iface)
154 {
155     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
156     DWORD ref = InterlockedDecrement(&This->ref);
157
158     TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
159
160     if (!ref)
161     {
162         FIXME("Release IGraphFilter or w/e\n");
163         This->csFilter.DebugInfo->Spare[0] = 0;
164         DeleteCriticalSection(&This->csFilter);
165         This->lpVtbl = NULL;
166         This->lpVtbl2 = NULL;
167         if (This->mygraph != NULL)
168             IGraphBuilder_Release(This->mygraph);
169         CoTaskMemFree(This);
170         ObjectRefCount(FALSE);
171     }
172     return ref;
173 }
174
175 static HRESULT WINAPI
176 fnCaptureGraphBuilder2_SetFilterGraph(ICaptureGraphBuilder2 * iface,
177                                       IGraphBuilder *pfg)
178 {
179 /* The graph builder will automatically create a filter graph if you don't call
180    this method. If you call this method after the graph builder has created its
181    own filter graph, the call will fail. */
182     IMediaEvent *pmev;
183     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
184
185     TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
186
187     if (This->mygraph)
188         return E_UNEXPECTED;
189
190     if (!pfg)
191         return E_POINTER;
192
193     This->mygraph = pfg;
194     IGraphBuilder_AddRef(This->mygraph);
195     if (SUCCEEDED(IUnknown_QueryInterface(This->mygraph,
196                                           &IID_IMediaEvent, (LPVOID *)&pmev)))
197     {
198         IMediaEvent_CancelDefaultHandling(pmev, EC_REPAINT);
199         IMediaEvent_Release(pmev);
200     }
201     return S_OK;
202 }
203
204 static HRESULT WINAPI
205 fnCaptureGraphBuilder2_GetFilterGraph(ICaptureGraphBuilder2 * iface,
206                                       IGraphBuilder **pfg)
207 {
208     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
209
210     TRACE("(%p/%p)->(%p)\n", This, iface, pfg);
211
212     if (!pfg)
213         return E_POINTER;
214
215     *pfg = This->mygraph;
216     if (!This->mygraph)
217     {
218         TRACE("(%p) Getting NULL filtergraph\n", iface);
219         return E_UNEXPECTED;
220     }
221
222     IGraphBuilder_AddRef(This->mygraph);
223    
224     TRACE("(%p) return filtergraph %p\n", iface, *pfg);
225     return S_OK;
226 }
227
228 static HRESULT WINAPI
229 fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface,
230                                          const GUID *pType,
231                                          LPCOLESTR lpstrFile,
232                                          IBaseFilter **ppf,
233                                          IFileSinkFilter **ppSink)
234 {
235     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
236
237     FIXME("(%p/%p)->(%s, %s, %p, %p) Stub!\n", This, iface,
238           debugstr_guid(pType), debugstr_w(lpstrFile), ppf, ppSink);
239
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI
244 fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface,
245                                      const GUID *pCategory,
246                                      const GUID *pType,
247                                      IBaseFilter *pf,
248                                      REFIID riid,
249                                      void **ppint)
250 {
251     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
252
253     FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface,
254           debugstr_guid(pCategory), debugstr_guid(pType),
255           pf, debugstr_guid(riid), ppint);
256
257     return IBaseFilter_QueryInterface(pf, riid, ppint);
258     /* Looks for the specified interface on the filter, upstream and
259      * downstream from the filter, and, optionally, only on the output
260      * pin of the given category.
261      */
262 }
263
264 static HRESULT WINAPI
265 fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
266                                     const GUID *pCategory,
267                                     const GUID *pType,
268                                     IUnknown *pSource,
269                                     IBaseFilter *pfCompressor,
270                                     IBaseFilter *pfRenderer)
271 {
272     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
273     IPin *pin_in = NULL;
274     IPin *pin_out = NULL;
275     HRESULT hr;
276
277     FIXME("(%p/%p)->(%s, %s, %p, %p, %p) Stub!\n", This, iface,
278           debugstr_guid(pCategory), debugstr_guid(pType),
279           pSource, pfCompressor, pfRenderer);
280
281     if (pfCompressor)
282         FIXME("Intermediate streams not supported yet\n");
283
284     if (!This->mygraph)
285     {
286         FIXME("Need a capture graph\n");
287         return E_UNEXPECTED;
288     }
289
290     ICaptureGraphBuilder2_FindPin(iface, pSource, PINDIR_OUTPUT, pCategory, pType, TRUE, 0, &pin_in);
291     if (!pin_in)
292         return E_FAIL;
293     ICaptureGraphBuilder2_FindPin(iface, (IUnknown*)pfRenderer, PINDIR_INPUT, pCategory, pType, TRUE, 0, &pin_out);
294     if (!pin_out)
295     {
296         IPin_Release(pin_in);
297         return E_FAIL;
298     }
299
300     /* Uses 'Intelligent Connect', so Connect, not ConnectDirect here */
301     hr = IFilterGraph2_Connect(This->mygraph, pin_in, pin_out);
302     IPin_Release(pin_in);
303     IPin_Release(pin_out);
304     return hr;
305 }
306
307 static HRESULT WINAPI
308 fnCaptureGraphBuilder2_ControlStream(ICaptureGraphBuilder2 * iface,
309                                      const GUID *pCategory,
310                                      const GUID *pType,
311                                      IBaseFilter *pFilter,
312                                      REFERENCE_TIME *pstart,
313                                      REFERENCE_TIME *pstop,
314                                      WORD wStartCookie,
315                                      WORD wStopCookie)
316 {
317     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
318
319     FIXME("(%p/%p)->(%s, %s, %p, %p, %p, %i, %i) Stub!\n", This, iface,
320           debugstr_guid(pCategory), debugstr_guid(pType),
321           pFilter, pstart, pstop, wStartCookie, wStopCookie);
322
323     return E_NOTIMPL;
324 }
325
326 static HRESULT WINAPI
327 fnCaptureGraphBuilder2_AllocCapFile(ICaptureGraphBuilder2 * iface,
328                                     LPCOLESTR lpwstr,
329                                     DWORDLONG dwlSize)
330 {
331     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
332
333     FIXME("(%p/%p)->(%s, 0x%s) Stub!\n", This, iface,
334           debugstr_w(lpwstr), wine_dbgstr_longlong(dwlSize));
335
336     return E_NOTIMPL;
337 }
338
339 static HRESULT WINAPI
340 fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface,
341                                        LPOLESTR lpwstrOld,
342                                        LPOLESTR lpwstrNew,
343                                        int fAllowEscAbort,
344                                        IAMCopyCaptureFileProgress *pCallback)
345 {
346     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
347
348     FIXME("(%p/%p)->(%s, %s, %i, %p) Stub!\n", This, iface,
349           debugstr_w(lpwstrOld), debugstr_w(lpwstrNew),
350           fAllowEscAbort, pCallback);
351
352     return E_NOTIMPL;
353 }
354
355 static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected)
356 {
357     IPin *partner;
358     PIN_DIRECTION pindir;
359
360     IPin_QueryDirection(pin, &pindir);
361     if (pindir != direction)
362     {
363         TRACE("No match, wrong direction\n");
364         return FALSE;
365     }
366
367     if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK)
368     {
369         IPin_Release(partner);
370         TRACE("No match, %p already connected to %p\n", pin, partner);
371         return FALSE;
372     }
373
374     if (cat || type)
375         FIXME("Ignoring category/type\n");
376
377     TRACE("Match made in heaven\n");
378
379     return TRUE;
380 }
381
382 static HRESULT WINAPI
383 fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface,
384                                IUnknown *pSource,
385                                PIN_DIRECTION pindir,
386                                const GUID *pCategory,
387                                const GUID *pType,
388                                BOOL fUnconnected,
389                                INT num,
390                                IPin **ppPin)
391 {
392     HRESULT hr;
393     IEnumPins *enumpins = NULL;
394     IPin *pin;
395     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
396
397     TRACE("(%p/%p)->(%p, %x, %s, %s, %d, %i, %p)\n", This, iface,
398           pSource, pindir, debugstr_guid(pCategory), debugstr_guid(pType),
399           fUnconnected, num, ppPin);
400
401     pin = NULL;
402
403     hr = IUnknown_QueryInterface(pSource, &IID_IPin, (void**)&pin);
404     if (hr == E_NOINTERFACE)
405     {
406         IBaseFilter *filter = NULL;
407         int numcurrent = 0;
408
409         hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&filter);
410         if (hr == E_NOINTERFACE)
411         {
412             WARN("Input not filter or pin?!\n");
413             return E_FAIL;
414         }
415
416         hr = IBaseFilter_EnumPins(filter, &enumpins);
417         if (FAILED(hr))
418         {
419             WARN("Could not enumerate\n");
420             return hr;
421         }
422
423         IEnumPins_Reset(enumpins);
424
425         while (1)
426         {
427             hr = IEnumPins_Next(enumpins, 1, &pin, NULL);
428             if (hr == VFW_E_ENUM_OUT_OF_SYNC)
429             {
430                 numcurrent = 0;
431                 IEnumPins_Reset(enumpins);
432                 pin = NULL;
433                 continue;
434             }
435
436             if (hr != S_OK)
437                 break;
438             TRACE("Testing match\n");
439             if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num)
440                 break;
441             IPin_Release(pin);
442             pin = NULL;
443         }
444         IEnumPins_Release(enumpins);
445
446         if (hr != S_OK)
447         {
448             WARN("Could not find %s pin # %d\n", (pindir == PINDIR_OUTPUT ? "output" : "input"), numcurrent);
449             return E_FAIL;
450         }
451     }
452     else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected))
453     {
454         IPin_Release(pin);
455         return E_FAIL;
456     }
457
458     *ppPin = pin;
459     return S_OK;
460 }
461
462 static const ICaptureGraphBuilder2Vtbl builder2_Vtbl =
463 {   
464     fnCaptureGraphBuilder2_QueryInterface,
465     fnCaptureGraphBuilder2_AddRef,
466     fnCaptureGraphBuilder2_Release,
467     fnCaptureGraphBuilder2_SetFilterGraph,
468     fnCaptureGraphBuilder2_GetFilterGraph,
469     fnCaptureGraphBuilder2_SetOutputFileName,
470     fnCaptureGraphBuilder2_FindInterface,
471     fnCaptureGraphBuilder2_RenderStream,
472     fnCaptureGraphBuilder2_ControlStream,
473     fnCaptureGraphBuilder2_AllocCapFile,
474     fnCaptureGraphBuilder2_CopyCaptureFile,
475     fnCaptureGraphBuilder2_FindPin
476 };
477
478
479 static HRESULT WINAPI
480 fnCaptureGraphBuilder_QueryInterface(ICaptureGraphBuilder * iface,
481                                      REFIID riid, LPVOID * ppv)
482 {
483     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
484     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
485     return IUnknown_QueryInterface(_ICaptureGraphBuilder2_(This), riid, ppv);
486 }
487
488 static ULONG WINAPI
489 fnCaptureGraphBuilder_AddRef(ICaptureGraphBuilder * iface)
490 {
491     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
492     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
493     return IUnknown_AddRef(_ICaptureGraphBuilder2_(This));
494 }
495
496 static ULONG WINAPI
497 fnCaptureGraphBuilder_Release(ICaptureGraphBuilder * iface)
498 {
499     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
500     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
501     return IUnknown_Release(_ICaptureGraphBuilder2_(This));
502 }
503
504 static HRESULT WINAPI
505 fnCaptureGraphBuilder_SetFiltergraph(ICaptureGraphBuilder * iface,
506                                      IGraphBuilder *pfg)
507 {
508     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
509     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
510     return ICaptureGraphBuilder2_SetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
511 }
512
513 static HRESULT WINAPI
514 fnCaptureGraphBuilder_GetFiltergraph(ICaptureGraphBuilder * iface,
515                                      IGraphBuilder **pfg)
516 {
517     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
518     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
519     return ICaptureGraphBuilder2_GetFiltergraph(_ICaptureGraphBuilder2_(This), pfg);
520 }
521
522 static HRESULT WINAPI
523 fnCaptureGraphBuilder_SetOutputFileName(ICaptureGraphBuilder * iface,
524                                         const GUID *pType, LPCOLESTR lpstrFile,
525                                         IBaseFilter **ppf, IFileSinkFilter **ppSink)
526 {
527     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
528     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
529     return ICaptureGraphBuilder2_SetOutputFileName(_ICaptureGraphBuilder2_(This),
530                                                    pType, lpstrFile, ppf, ppSink);
531 }
532
533 static HRESULT WINAPI
534 fnCaptureGraphBuilder_FindInterface(ICaptureGraphBuilder * iface,
535                                     const GUID *pCategory, IBaseFilter *pf,
536                                     REFIID riid, void **ppint)
537 {
538     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
539     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
540     return ICaptureGraphBuilder2_FindInterface(_ICaptureGraphBuilder2_(This),
541                                                pCategory, NULL, pf, riid, ppint);
542 }
543
544 static HRESULT WINAPI
545 fnCaptureGraphBuilder_RenderStream(ICaptureGraphBuilder * iface,
546                                    const GUID *pCategory, IUnknown *pSource,
547                                    IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
548 {
549     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
550     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
551     return ICaptureGraphBuilder2_RenderStream(_ICaptureGraphBuilder2_(This),
552                                               pCategory, NULL, pSource,
553                                               pfCompressor, pfRenderer);
554 }
555
556 static HRESULT WINAPI
557 fnCaptureGraphBuilder_ControlStream(ICaptureGraphBuilder * iface,
558                                     const GUID *pCategory, IBaseFilter *pFilter,
559                                     REFERENCE_TIME *pstart, REFERENCE_TIME *pstop,
560                                     WORD wStartCookie, WORD wStopCookie)
561 {
562     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
563     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
564     return ICaptureGraphBuilder2_ControlStream(_ICaptureGraphBuilder2_(This),
565                                                pCategory, NULL, pFilter, pstart, 
566                                                pstop, wStartCookie, wStopCookie);
567 }
568
569 static HRESULT WINAPI
570 fnCaptureGraphBuilder_AllocCapFile(ICaptureGraphBuilder * iface,
571                                    LPCOLESTR lpstr, DWORDLONG dwlSize)
572 {
573     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
574     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
575     return ICaptureGraphBuilder2_AllocCapFile(_ICaptureGraphBuilder2_(This),
576                                               lpstr, dwlSize);
577 }
578
579 static HRESULT WINAPI
580 fnCaptureGraphBuilder_CopyCaptureFile(ICaptureGraphBuilder * iface,
581                                       LPOLESTR lpwstrOld, LPOLESTR lpwstrNew,
582                                       int fAllowEscAbort,
583                                       IAMCopyCaptureFileProgress *pCallback)
584 {
585     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder(iface);
586     TRACE("%p --> Forwarding to v2 (%p)\n", iface, This);
587     return ICaptureGraphBuilder2_CopyCaptureFile(_ICaptureGraphBuilder2_(This),
588                                                  lpwstrOld, lpwstrNew,
589                                                  fAllowEscAbort, pCallback);
590 }
591
592 static const ICaptureGraphBuilderVtbl builder_Vtbl =
593 {   
594    fnCaptureGraphBuilder_QueryInterface,
595    fnCaptureGraphBuilder_AddRef,
596    fnCaptureGraphBuilder_Release,
597    fnCaptureGraphBuilder_SetFiltergraph,
598    fnCaptureGraphBuilder_GetFiltergraph,
599    fnCaptureGraphBuilder_SetOutputFileName,
600    fnCaptureGraphBuilder_FindInterface,
601    fnCaptureGraphBuilder_RenderStream,
602    fnCaptureGraphBuilder_ControlStream,
603    fnCaptureGraphBuilder_AllocCapFile,
604    fnCaptureGraphBuilder_CopyCaptureFile
605 };