[PATCH v2 2/5] qcap: Reimplement COM registration and vending locally.

Zebediah Figura z.figura12 at gmail.com
Sun Mar 8 14:05:08 CDT 2020


From: Zebediah Figura <z.figura12 at gmail.com>

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
v2: Fix copy-paste error, thanks Chip.

 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..05b07ecd873 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 = &reg_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 = &reg_video_mt,
+    },
+    {
+        .dwFlags = REG_PINFLAG_B_OUTPUT,
+        .cInstances = 1,
+        .nMediaTypes = 1,
+        .lpMediaType = &reg_video_mt,
+    },
+    {
+        .dwFlags = REG_PINFLAG_B_OUTPUT,
+        .cInstances = 1,
+        .nMediaTypes = 1,
+        .lpMediaType = &reg_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, &reg_avi_mux);
+    IFilterMapper2_RegisterFilter(mapper, &CLSID_SmartTee, smart_teeW,
+            NULL, NULL, NULL, &reg_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_AviDest);
+    IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_SmartTee);
+
+    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;
 }
-- 
2.25.1




More information about the wine-devel mailing list