From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/qcap/Makefile.in | 4 +- dlls/qcap/audiorecord.c | 24 ++- dlls/qcap/avico.c | 25 ++- dlls/qcap/avimux.c | 17 +- dlls/qcap/capturegraph.c | 40 ++--- dlls/qcap/qcap_classes.idl | 71 ++++++++ dlls/qcap/qcap_main.c | 321 +++++++++++++++++++++++-------------- dlls/qcap/qcap_main.h | 19 +-- dlls/qcap/smartteefilter.c | 16 +- dlls/qcap/vfwcapture.c | 11 +- 10 files changed, 341 insertions(+), 207 deletions(-) create mode 100644 dlls/qcap/qcap_classes.idl
diff --git a/dlls/qcap/Makefile.in b/dlls/qcap/Makefile.in index d10075aea08..981a0dc3f39 100644 --- a/dlls/qcap/Makefile.in +++ b/dlls/qcap/Makefile.in @@ -8,7 +8,6 @@ C_SRCS = \ avico.c \ avimux.c \ capturegraph.c \ - dllfunc.c \ filter.c \ mediatype.c \ pin.c \ @@ -18,3 +17,6 @@ C_SRCS = \ vfwcapture.c
RC_SRCS = version.rc + +IDL_SRCS = \ + qcap_classes.idl diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c index 3c15734e894..48be64b63f5 100644 --- a/dlls/qcap/audiorecord.c +++ b/dlls/qcap/audiorecord.c @@ -154,22 +154,18 @@ static const IPersistPropertyBagVtbl PersistPropertyBagVtbl = PPB_Save };
-IUnknown* WINAPI QCAP_createAudioCaptureFilter(IUnknown *outer, HRESULT *phr) +HRESULT audio_record_create(IUnknown *outer, IUnknown **out) { - AudioRecord *This = NULL; + AudioRecord *object;
- FIXME("(%p, %p): the entire CLSID_AudioRecord implementation is just stubs\n", outer, phr); + if (!(object = CoTaskMemAlloc(sizeof(*object)))) + return E_OUTOFMEMORY; + memset(object, 0, sizeof(*object));
- This = CoTaskMemAlloc(sizeof(*This)); - if (This == NULL) { - *phr = E_OUTOFMEMORY; - return NULL; - } - memset(This, 0, sizeof(*This)); - This->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl; - - strmbase_filter_init(&This->filter, outer, &CLSID_AudioRecord, &filter_ops); + object->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl; + strmbase_filter_init(&object->filter, outer, &CLSID_AudioRecord, &filter_ops);
- *phr = S_OK; - return &This->filter.IUnknown_inner; + TRACE("Created audio recorder %p.\n", object); + *out = &object->filter.IUnknown_inner; + return S_OK; } diff --git a/dlls/qcap/avico.c b/dlls/qcap/avico.c index 53b8526f449..fc5826b16fe 100644 --- a/dlls/qcap/avico.c +++ b/dlls/qcap/avico.c @@ -480,25 +480,22 @@ static const struct strmbase_source_ops source_ops = .pfnDecideAllocator = AVICompressorOut_DecideAllocator, };
-IUnknown* WINAPI QCAP_createAVICompressor(IUnknown *outer, HRESULT *phr) +HRESULT avi_compressor_create(IUnknown *outer, IUnknown **out) { static const WCHAR source_name[] = {'O','u','t',0}; static const WCHAR sink_name[] = {'I','n',0}; - AVICompressor *compressor; + AVICompressor *object;
- compressor = heap_alloc_zero(sizeof(*compressor)); - if(!compressor) { - *phr = E_NOINTERFACE; - return NULL; - } - - strmbase_filter_init(&compressor->filter, outer, &CLSID_AVICo, &filter_ops); + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY;
- compressor->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl; + strmbase_filter_init(&object->filter, outer, &CLSID_AVICo, &filter_ops); + object->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
- strmbase_sink_init(&compressor->sink, &compressor->filter, sink_name, &sink_ops, NULL); - strmbase_source_init(&compressor->source, &compressor->filter, source_name, &source_ops); + strmbase_sink_init(&object->sink, &object->filter, sink_name, &sink_ops, NULL); + strmbase_source_init(&object->source, &object->filter, source_name, &source_ops);
- *phr = S_OK; - return &compressor->filter.IUnknown_inner; + TRACE("Created AVI compressor %p.\n", object); + *out = &object->filter.IUnknown_inner; + return S_OK; } diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c index 91a0b17f8e1..f1e703bfb60 100644 --- a/dlls/qcap/avimux.c +++ b/dlls/qcap/avimux.c @@ -1835,7 +1835,7 @@ static HRESULT create_input_pin(AviMux *avimux) return S_OK; }
-IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr) +HRESULT avi_mux_create(IUnknown *outer, IUnknown **out) { static const WCHAR output_name[] = {'A','V','I',' ','O','u','t',0};
@@ -1843,11 +1843,8 @@ IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr) PIN_INFO info; HRESULT hr;
- avimux = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AviMux)); - if(!avimux) { - *phr = E_OUTOFMEMORY; - return NULL; - } + if (!(avimux = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AviMux)))) + return E_OUTOFMEMORY;
strmbase_filter_init(&avimux->filter, outer, &CLSID_AviDest, &filter_ops); avimux->IConfigAviMux_iface.lpVtbl = &ConfigAviMuxVtbl; @@ -1870,13 +1867,13 @@ IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr) strmbase_source_cleanup(&avimux->source); strmbase_filter_cleanup(&avimux->filter); HeapFree(GetProcessHeap(), 0, avimux); - *phr = hr; - return NULL; + return hr; }
avimux->interleave = 10000000;
+ TRACE("Created AVI mux %p.\n", avimux); ObjectRefCount(TRUE); - *phr = S_OK; - return &avimux->filter.IUnknown_inner; + *out = &avimux->filter.IUnknown_inner; + return S_OK; } diff --git a/dlls/qcap/capturegraph.c b/dlls/qcap/capturegraph.c index 894d4f61e9c..33b0ecfaa11 100644 --- a/dlls/qcap/capturegraph.c +++ b/dlls/qcap/capturegraph.c @@ -74,33 +74,27 @@ static inline CaptureGraphImpl *impl_from_ICaptureGraphBuilder2(ICaptureGraphBui }
-IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter, - HRESULT *phr) +HRESULT capture_graph_create(IUnknown *outer, IUnknown **out) { - CaptureGraphImpl * pCapture = NULL; + CaptureGraphImpl *object;
- TRACE("(%p, %p)\n", pUnkOuter, phr); + if (outer) + return CLASS_E_NOAGGREGATION;
- *phr = CLASS_E_NOAGGREGATION; - if (pUnkOuter) - { - return NULL; - } - *phr = E_OUTOFMEMORY; + if (!(object = CoTaskMemAlloc(sizeof(*object)))) + return E_OUTOFMEMORY;
- pCapture = CoTaskMemAlloc(sizeof(CaptureGraphImpl)); - if (pCapture) - { - pCapture->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl; - pCapture->ICaptureGraphBuilder_iface.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->ICaptureGraphBuilder_iface; + object->ICaptureGraphBuilder2_iface.lpVtbl = &builder2_Vtbl; + object->ICaptureGraphBuilder_iface.lpVtbl = &builder_Vtbl; + object->ref = 1; + object->mygraph = NULL; + InitializeCriticalSection(&object->csFilter); + object->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CaptureGraphImpl.csFilter"); + + TRACE("Created capture graph builder %p.\n", object); + ObjectRefCount(TRUE); + *out = (IUnknown *)&object->ICaptureGraphBuilder_iface; + return S_OK; }
static HRESULT WINAPI diff --git a/dlls/qcap/qcap_classes.idl b/dlls/qcap/qcap_classes.idl new file mode 100644 index 00000000000..ac1ec9a21b9 --- /dev/null +++ b/dlls/qcap/qcap_classes.idl @@ -0,0 +1,71 @@ +/* + * COM classes for qcap + * + * Copyright 2019 Zebediah Figura + * + * 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 + */ + +#pragma makedep register + +[ + helpstring("Audio Capture Filter"), + threading(both), + uuid(e30629d2-27e5-11ce-875d-00608cb78066) +] +coclass AudioRecord {} + +[ + helpstring("Audio Capture Filter"), + threading(both), + uuid(d76e2820-1563-11cf-ac98-00aa004c0fa9) +] +coclass AVICo {} + +[ + helpstring("AVI mux"), + threading(both), + uuid(e2510970-f137-11ce-8b67-00aa00a3f1a6) +] +coclass AviDest {} + +[ + helpstring("Capture Graph Builder"), + threading(both), + uuid(bf87b6e0-8c27-11d0-b3f0-00aa003761c5) +] +coclass CaptureGraphBuilder {} + +[ + helpstring("Capture Graph Builder 2"), + threading(both), + uuid(bf87b6e1-8c27-11d0-b3f0-00aa003761c5) +] +coclass CaptureGraphBuilder2 {} + +[ + helpstring("Smart Tee Filter"), + threading(both), + uuid(cc58e280-8aa1-11d1-b3f1-00aa003761c5) +] +coclass SmartTee {} + +[ + helpstring("VFW Capture Filter"), + threading(both), + uuid(1b544c22-fd0b-11ce-8c63-00aa0044b51e) +] +coclass VfwCapture {} + diff --git a/dlls/qcap/qcap_main.c b/dlls/qcap/qcap_main.c index c5b4931c907..2b9850cb329 100644 --- a/dlls/qcap/qcap_main.c +++ b/dlls/qcap/qcap_main.c @@ -1,8 +1,9 @@ /* - * Qcap implementation, dllentry points + * DirectShow capture * * Copyright (C) 2003 Dominik Strasser * Copyright (C) 2005 Rolf Kalbermatter + * Copyright (C) 2019 Zebediah Figura * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +26,8 @@ #include <stdarg.h>
#define COBJMACROS - +#define NONAMELESSSTRUCT +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" #include "wingdi.h" @@ -33,6 +35,7 @@ #include "objbase.h" #include "uuids.h" #include "strmif.h" +#include "rpcproxy.h"
#include "qcap_main.h"
@@ -41,132 +44,207 @@
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
+static HINSTANCE qcap_instance; + static LONG objects_ref = 0;
-static const WCHAR wAudioCaptureFilter[] = -{'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0}; -static const WCHAR wAVICompressor[] = -{'A','V','I',' ','C','o','m','p','r','e','s','s','o','r',0}; -static const WCHAR wVFWCaptFilter[] = -{'V','F','W',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',0}; -static const WCHAR wVFWCaptFilterProp[] = -{'V','F','W',' ','C','a','p','t','u','r','e',' ','F','i','l','t','e','r',' ', - 'P','r','o','p','e','r','t','y',' ','P','a','g','e',0}; -static const WCHAR wAVIMux[] = -{'A','V','I',' ','m','u','x',0}; -static const WCHAR wAVIMuxPropPage[] = -{'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y',' ','P','a','g','e',0}; -static const WCHAR wAVIMuxPropPage1[] = -{'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y',' ','P','a','g','e','1',0}; -static const WCHAR wFileWriter[] = -{'F','i','l','e',' ','W','r','i','t','e','r',0}; -static const WCHAR wCaptGraphBuilder[] = -{'C','a','p','t','u','r','e',' ','G','r','a','p','h',' ','B','u','i','l','d','e','r',0}; -static const WCHAR wCaptGraphBuilder2[] = -{'C','a','p','t','u','r','e',' ','G','r','a','p','h',' ','B','u','i','l','d','e','r','2',0}; -static const WCHAR wInfPinTeeFilter[] = -{'I','n','f','i','n','i','t','e',' ','P','i','n',' ','T','e','e',' ','F','i', - 'l','t','e','r',0}; -static const WCHAR wSmartTeeFilter[] = -{'S','m','a','r','t',' ','T','e','e',' ','F','i','l','t','e','r',0}; -static const WCHAR wAudioInMixerProp[] = -{'A','u','d','i','o','I','n','p','u','t','M','i','x','e','r',' ','P','r','o', - 'p','e','r','t','y',' ','P','a','g','e',0}; - -FactoryTemplate const g_Templates[] = { +struct class_factory +{ + IClassFactory IClassFactory_iface; + HRESULT (*create_instance)(IUnknown *outer, IUnknown **out); +}; + +static inline struct class_factory *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface); +} + +static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory)) + { + *out = iface; + IClassFactory_AddRef(iface); + return S_OK; + } + + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI class_factory_AddRef(IClassFactory *iface) +{ + return 2; +} + +static ULONG WINAPI class_factory_Release(IClassFactory *iface) +{ + return 1; +} + +static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out) +{ + struct class_factory *factory = impl_from_IClassFactory(iface); + IUnknown *unk; + HRESULT hr; + + TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out); + + if (outer && !IsEqualGUID(iid, &IID_IUnknown)) + return E_NOINTERFACE; + + *out = NULL; + if (SUCCEEDED(hr = factory->create_instance(outer, &unk))) { - wAudioCaptureFilter, - &CLSID_AudioRecord, - QCAP_createAudioCaptureFilter, - NULL - },{ - wAVICompressor, - &CLSID_AVICo, - QCAP_createAVICompressor, - NULL - },{ - wVFWCaptFilter, - &CLSID_VfwCapture, - QCAP_createVFWCaptureFilter, - NULL - },{ - wVFWCaptFilterProp, - &CLSID_CaptureProperties, - NULL, /* FIXME: Implement QCAP_createVFWCaptureFilterPropertyPage */ - NULL - },{ - wAVIMux, - &CLSID_AviDest, - QCAP_createAVIMux, - NULL - },{ - wAVIMuxPropPage, - &CLSID_AviMuxProptyPage, - NULL, /* FIXME: Implement QCAP_createAVIMuxPropertyPage */ - NULL - },{ - wAVIMuxPropPage1, - &CLSID_AviMuxProptyPage1, - NULL, /* FIXME: Implement QCAP_createAVIMuxPropertyPage1 */ - NULL - },{ - wFileWriter, - &CLSID_FileWriter, - NULL, /* FIXME: Implement QCAP_createFileWriter */ - NULL - },{ - wCaptGraphBuilder, - &CLSID_CaptureGraphBuilder, - QCAP_createCaptureGraphBuilder2, - NULL - },{ - wCaptGraphBuilder2, - &CLSID_CaptureGraphBuilder2, - QCAP_createCaptureGraphBuilder2, - NULL - },{ - wInfPinTeeFilter, - &CLSID_InfTee, - NULL, /* FIXME: Implement QCAP_createInfinitePinTeeFilter */ - NULL - },{ - wSmartTeeFilter, - &CLSID_SmartTee, - QCAP_createSmartTeeFilter, - NULL - },{ - wAudioInMixerProp, - &CLSID_AudioInputMixerProperties, - NULL, /* FIXME: Implement QCAP_createAudioInputMixerPropertyPage */ - NULL + hr = IUnknown_QueryInterface(unk, iid, out); + IUnknown_Release(unk); } + return hr; +} + +static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL lock) +{ + TRACE("iface %p, lock %d.\n", iface, lock); + + if (lock) + InterlockedIncrement(&objects_ref); + else + InterlockedDecrement(&objects_ref); + return S_OK; +} + +static const IClassFactoryVtbl class_factory_vtbl = +{ + class_factory_QueryInterface, + class_factory_AddRef, + class_factory_Release, + class_factory_CreateInstance, + class_factory_LockServer, };
-const int g_cTemplates = ARRAY_SIZE(g_Templates); +static struct class_factory audio_record_cf = {{&class_factory_vtbl}, audio_record_create}; +static struct class_factory avi_compressor_cf = {{&class_factory_vtbl}, avi_compressor_create}; +static struct class_factory avi_mux_cf = {{&class_factory_vtbl}, avi_mux_create}; +static struct class_factory capture_graph_cf = {{&class_factory_vtbl}, capture_graph_create}; +static struct class_factory smart_tee_cf = {{&class_factory_vtbl}, smart_tee_create}; +static struct class_factory vfw_capture_cf = {{&class_factory_vtbl}, vfw_capture_create};
-/*********************************************************************** - * Dll EntryPoint (QCAP.@) - */ -BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { - return STRMBASE_DllMain(hInstDLL,fdwReason,lpv); + if (reason == DLL_PROCESS_ATTACH) + { + qcap_instance = instance; + DisableThreadLibraryCalls(instance); + } + return TRUE; }
-/*********************************************************************** - * DllGetClassObject - */ -HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) { - return STRMBASE_DllGetClassObject( rclsid, riid, ppv ); + struct class_factory *factory; + + TRACE("clsid %s, iid %s, out %p.\n", debugstr_guid(clsid), debugstr_guid(iid), out); + + if (IsEqualGUID(clsid, &CLSID_AudioRecord)) + factory = &audio_record_cf; + else if (IsEqualGUID(clsid, &CLSID_AVICo)) + factory = &avi_compressor_cf; + else if (IsEqualGUID(clsid, &CLSID_AviDest)) + factory = &avi_mux_cf; + else if (IsEqualGUID(clsid, &CLSID_CaptureGraphBuilder)) + factory = &capture_graph_cf; + else if (IsEqualGUID(clsid, &CLSID_CaptureGraphBuilder2)) + factory = &capture_graph_cf; + else if (IsEqualGUID(clsid, &CLSID_SmartTee)) + factory = &smart_tee_cf; + else if (IsEqualGUID(clsid, &CLSID_VfwCapture)) + factory = &vfw_capture_cf; + else + { + FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } + + return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, out); }
+static const REGPINTYPES reg_avi_mux_sink_mt = {&MEDIATYPE_Stream, &MEDIASUBTYPE_Avi}; + +static const REGFILTERPINS2 reg_avi_mux_pins[1] = +{ + { + .cInstances = 1, + .nMediaTypes = 1, + .lpMediaType = ®_avi_mux_sink_mt, + }, +}; + +static const REGFILTER2 reg_avi_mux = +{ + .dwVersion = 2, + .dwMerit = MERIT_DO_NOT_USE, + .u.s2.cPins2 = 1, + .u.s2.rgPins2 = reg_avi_mux_pins, +}; + +static const REGPINTYPES reg_video_mt = {&MEDIATYPE_Video, &GUID_NULL}; + +static const REGFILTERPINS2 reg_smart_tee_pins[3] = +{ + { + .cInstances = 1, + .nMediaTypes = 1, + .lpMediaType = ®_video_mt, + }, + { + .dwFlags = REG_PINFLAG_B_OUTPUT, + .cInstances = 1, + .nMediaTypes = 1, + .lpMediaType = ®_video_mt, + }, + { + .dwFlags = REG_PINFLAG_B_OUTPUT, + .cInstances = 1, + .nMediaTypes = 1, + .lpMediaType = ®_video_mt, + }, +}; + +static const REGFILTER2 reg_smart_tee = +{ + .dwVersion = 2, + .dwMerit = MERIT_DO_NOT_USE, + .u.s2.cPins2 = 3, + .u.s2.rgPins2 = reg_smart_tee_pins, +}; + /*********************************************************************** * DllRegisterServer (QCAP.@) */ HRESULT WINAPI DllRegisterServer(void) { - TRACE("()\n"); - return AMovieDllRegisterServer2(TRUE); + static const WCHAR avi_muxW[] = {'A','V','I',' ','M','u','x',0}; + static const WCHAR smart_teeW[] = {'S','m','a','r','t',' ','T','e','e',0}; + IFilterMapper2 *mapper; + HRESULT hr; + + if (FAILED(hr = __wine_register_resources( qcap_instance ))) + return hr; + + if (FAILED(hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, + &IID_IFilterMapper2, (void **)&mapper))) + return hr; + + IFilterMapper2_RegisterFilter(mapper, &CLSID_AviDest, avi_muxW, + NULL, NULL, NULL, ®_avi_mux); + IFilterMapper2_RegisterFilter(mapper, &CLSID_SmartTee, smart_teeW, + NULL, NULL, NULL, ®_smart_tee); + + IFilterMapper2_Release(mapper); + return S_OK; }
/*********************************************************************** @@ -174,8 +252,21 @@ HRESULT WINAPI DllRegisterServer(void) */ HRESULT WINAPI DllUnregisterServer(void) { - TRACE("\n"); - return AMovieDllRegisterServer2(FALSE); + IFilterMapper2 *mapper; + HRESULT hr; + + if (FAILED(hr = __wine_unregister_resources( qcap_instance ))) + return hr; + + if (FAILED(hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, + &IID_IFilterMapper2, (void **)&mapper))) + return hr; + + IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_SampleGrabber); + IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_NullRenderer); + + IFilterMapper2_Release(mapper); + return S_OK; }
/*********************************************************************** @@ -183,11 +274,9 @@ HRESULT WINAPI DllUnregisterServer(void) */ HRESULT WINAPI DllCanUnloadNow(void) { - TRACE("\n"); + TRACE(".\n");
- if (STRMBASE_DllCanUnloadNow() == S_OK && objects_ref == 0) - return S_OK; - return S_FALSE; + return objects_ref ? S_FALSE : S_OK; }
DWORD ObjectRefCount(BOOL increment) diff --git a/dlls/qcap/qcap_main.h b/dlls/qcap/qcap_main.h index ab02dbb9ab5..58c7a26f9e1 100644 --- a/dlls/qcap/qcap_main.h +++ b/dlls/qcap/qcap_main.h @@ -25,18 +25,11 @@
extern DWORD ObjectRefCount(BOOL increment) DECLSPEC_HIDDEN;
-extern IUnknown * WINAPI QCAP_createAudioCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createAVICompressor(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createVFWCaptureFilterPropertyPage(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createAVICompressor(IUnknown*,HRESULT*) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createAVIMuxPropertyPage(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createAVIMuxPropertyPage1(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createFileWriter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createInfinitePinTeeFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createSmartTeeFilter(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; -extern IUnknown * WINAPI QCAP_createAudioInputMixerPropertyPage(IUnknown *pUnkOuter, HRESULT *phr) DECLSPEC_HIDDEN; +HRESULT audio_record_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; +HRESULT avi_compressor_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; +HRESULT avi_mux_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; +HRESULT capture_graph_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; +HRESULT smart_tee_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; +HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
#endif /* _QCAP_MAIN_H_DEFINED */ diff --git a/dlls/qcap/smartteefilter.c b/dlls/qcap/smartteefilter.c index 5339cb5134f..46ec09ca7e4 100644 --- a/dlls/qcap/smartteefilter.c +++ b/dlls/qcap/smartteefilter.c @@ -321,7 +321,7 @@ static const struct strmbase_source_ops preview_ops = .pfnDecideAllocator = SmartTeeFilterPreview_DecideAllocator, };
-IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr) +HRESULT smart_tee_create(IUnknown *outer, IUnknown **out) { static const WCHAR captureW[] = {'C','a','p','t','u','r','e',0}; static const WCHAR previewW[] = {'P','r','e','v','i','e','w',0}; @@ -330,10 +330,7 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr) HRESULT hr;
if (!(object = CoTaskMemAlloc(sizeof(*object)))) - { - *phr = E_OUTOFMEMORY; - return NULL; - } + return E_OUTOFMEMORY; memset(object, 0, sizeof(*object));
strmbase_filter_init(&object->filter, outer, &CLSID_SmartTee, &filter_ops); @@ -342,14 +339,15 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr) &IID_IMemAllocator, (void **)&object->sink.pAllocator); if (FAILED(hr)) { - *phr = hr; strmbase_filter_cleanup(&object->filter); - return NULL; + CoTaskMemFree(object); + return hr; }
strmbase_source_init(&object->capture, &object->filter, captureW, &capture_ops); strmbase_source_init(&object->preview, &object->filter, previewW, &preview_ops);
- *phr = S_OK; - return &object->filter.IUnknown_inner; + TRACE("Created smart tee %p.\n", object); + *out = &object->filter.IUnknown_inner; + return S_OK; } diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c index 6cd4a84d2e1..d2acf9eda43 100644 --- a/dlls/qcap/vfwcapture.c +++ b/dlls/qcap/vfwcapture.c @@ -559,16 +559,13 @@ static const struct strmbase_source_ops source_ops = .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, };
-IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *outer, HRESULT *phr) +HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out) { static const WCHAR source_name[] = {'O','u','t','p','u','t',0}; VfwCapture *object;
if (!(object = CoTaskMemAlloc(sizeof(*object)))) - { - *phr = E_OUTOFMEMORY; - return NULL; - } + return E_OUTOFMEMORY;
strmbase_filter_init(&object->filter, outer, &CLSID_VfwCapture, &filter_ops);
@@ -583,6 +580,6 @@ IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *outer, HRESULT *phr)
TRACE("Created VFW capture filter %p.\n", object); ObjectRefCount(TRUE); - *phr = S_OK; - return &object->filter.IUnknown_inner; + *out = &object->filter.IUnknown_inner; + return S_OK; }