[QCAP] DLL setup function implementation, patch 1, trying as inline

Rolf Kalbermatter rolf.kalbermatter at citeng.com
Fri May 6 15:30:56 CDT 2005


Changelog
  - dlls/qcap/qcap_main.c
    dlls/qcap/qcap_main.h
    dlls/qcap/dllsetup.c
    dlls/qcap/dllsetup.c
      Implement DLL registering and unregistering functions, class
factory
      and server locking based on how it is done with DirectX samples.

      No classes are implemented by this patch but the implementations
      from Maarten Lankhorst will follow shortly.

Rolf Kalbermatter

Index: Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/qcap/Makefile.in,v
retrieving revision 1.7
diff -u -r1.7 Makefile.in
--- dlls/qcap/Makefile.in	14 May 2004 21:37:32 -0000	1.7
+++ dlls/qcap/Makefile.in	6 May 2005 18:29:49 -0000
@@ -3,8 +3,11 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = qcap.dll
+IMPORTS   = ole32 oleaut32 user32 advapi32 kernel32
+EXTRALIBS = -lstrmiids -luuid $(LIBUNICODE)
 
-C_SRCS = qcap_main.c
+C_SRCS = dllsetup.c \
+         qcap_main.c
 
 RC_SRCS = version.rc
 
Index: qcap.spec
===================================================================
RCS file: /home/wine/wine/dlls/qcap/qcap.spec,v
retrieving revision 1.6
diff -u -r1.6 qcap.spec
--- dlls/qcap/qcap.spec	30 Jul 2003 03:48:55 -0000	1.6
+++ dlls/qcap/qcap.spec	6 May 2005 18:29:49 -0000
@@ -1,4 +1,4 @@
-@ stub DllCanUnloadNow
+@ stdcall -private DllCanUnloadNow() QCAP_DllCanUnloadNow
 @ stdcall -private DllGetClassObject(ptr ptr ptr)
QCAP_DllGetClassObject
 @ stdcall -private DllRegisterServer() QCAP_DllRegisterServer
-@ stub DllUnregisterServer
+@ stdcall -private DllUnregisterServer() QCAP_DllUnregisterServer
Index: qcap_main.c
===================================================================
RCS file: /home/wine/wine/dlls/qcap/qcap_main.h,v
--- /dev/null	2003-03-14 14:07:09.000000000 +0100
+++ dlls/qcap/qcap_main.h	2005-05-06 19:12:16.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ * Qcap main header file
+ *
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
USA
+ */
+#ifndef _QCAP_MAIN_H_DEFINED
+#define _QCAP_MAIN_H_DEFINED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DWORD ObjectRefCount(BOOL increment);
+
+IUnknown * CALLBACK QCAP_createAudioCaptureFilter(IUnknown *pUnkOuter,
HRESULT *phr);
+IUnknown * CALLBACK QCAP_createAVICompressor(IUnknown *pUnkOuter,
HRESULT *phr);
+IUnknown * CALLBACK QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter,
HRESULT *phr);
+IUnknown * CALLBACK QCAP_createVFWCaptureFilterPropertyPage(IUnknown
*pUnkOuter, HRESULT *phr);
+IUnknown * CALLBACK QCAP_createAVImux(IUnknown *pUnkOuter, HRESULT
*phr);
+IUnknown * CALLBACK QCAP_createAVImuxPropertyPage(IUnknown *pUnkOuter,
HRESULT *phr);
+IUnknown * CALLBACK QCAP_createAVImuxPropertyPage1(IUnknown *pUnkOuter,
HRESULT *phr);
+IUnknown * CALLBACK QCAP_createFileWriter(IUnknown *pUnkOuter, HRESULT
*phr);
+IUnknown * CALLBACK QCAP_createCaptureGraphBuilder2(IUnknown
*pUnkOuter, HRESULT *phr);
+IUnknown * CALLBACK QCAP_createInfinitePinTeeFilter(IUnknown
*pUnkOuter, HRESULT *phr);
+IUnknown * CALLBACK QCAP_createSmartTeeFilter(IUnknown *pUnkOuter,
HRESULT *phr);
+IUnknown * CALLBACK QCAP_createAudioInputMixerPropertyPage(IUnknown
*pUnkOuter, HRESULT *phr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: qcap_main.c
===================================================================
RCS file: /home/wine/wine/dlls/qcap/qcap_main.c,v
retrieving revision 1.3
diff -u -r1.3 qcap_main.c
--- dlls/qcap/qcap_main.c	21 May 2004 20:54:48 -0000	1.3
+++ dlls/qcap/qcap_main.c	6 May 2005 18:29:49 -0000
@@ -1,7 +1,8 @@
 /*
- * Qcap implementation
+ * Qcap implementation, dllentry points
  *
  * Copyright (C) 2003 Dominik Strasser
+ * Copyright (C) 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
@@ -17,27 +18,340 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
USA
  */
+#include "config.h"
 
-#include "wine/debug.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+#define COBJMACROS
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
 #include "winerror.h"
+#include "objbase.h"
+#include "uuids.h"
+#include "strmif.h"
 
+#include "dllsetup.h"
+#include "qcap_main.h"
+
+#include <assert.h>
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
 
+static DWORD objects_ref = 0;
+static DWORD server_locks = 0;
+static HINSTANCE ghInst = NULL;
+
+const WCHAR wAudioCaptFilter[] =
+{'A','u','d','i','o',' ','C','a','p','t','u','r','e','
','F','i','l','t','e','r',0};
+const WCHAR wAVICompressor[] =
+{'A','V','I',' ','C','o','m','p','r','e','s','s','o','r',0};
+const WCHAR wVFWCaptFilter[] =
+{'V','F','W',' ','C','a','p','t','u','r','e','
','F','i','l','t','e','r',0};
+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};
+const WCHAR wAVIMux[] =
+{'A','V','I',' ','m','u','x',0};
+const WCHAR wAVIMuxPropPage[] =
+{'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y','
','P','a','g','e',0};
+const WCHAR wAVIMuxPropPage1[] =
+{'A','V','I',' ','m','u','x',' ','P','r','o','p','e','r','t','y','
','P','a','g','e','1',0};
+const WCHAR wFileWriter[] =
+{'F','i','l','e',' ','W','r','i','t','e','r',0};
+const WCHAR wCaptGraphBuilder[] =
+{'C','a','p','t','u','r','e',' ','G','r','a','p','h','
','B','u','i','l','d','e','r',0};
+const WCHAR wCaptGraphBuilder2[] =
+{'C','a','p','t','u','r','e',' ','G','r','a','p','h','
','B','u','i','l','d','e','r','2',0};
+const WCHAR wInfPinTeeFilter[] =
+{'I','n','f','i','n','i','t','e',' ','P','i','n',' ','T','e','e','
','F','i',
+ 'l','t','e','r',0};
+const WCHAR wSmartTeeFilter[] =
+{'S','m','a','r','t',' ','T','e','e',' ','F','i','l','t','e','r',0};
+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};
+ 
+static CFactoryTemplate const g_cTemplates[] = {
+/*
+    {
+        wAudioCaptureFilter, 
+        &CLSID_AudioCaptureFilter,
+        QCAP_createAudioCaptureFilter,
+        NULL
+    },{
+        wAVICompressor, 
+        &CLSID_AVICompressor, 
+        QCAP_createAVICompressor,
+        NULL
+    },{
+        wVFWCaptFilter,
+        &CLSID_VFWCaptureFilter,
+        QCAP_createVFWCaptureFilter,
+        NULL
+    },{
+        wVFWCaptFilterProp,
+        &CLSID_VFWCaptureFilterPropertyPage,
+        QCAP_createVFWCaptureFilterPropertyPage,
+        NULL
+    },{
+        wAVIMux,
+        &CLSID_AVImux,
+        QCAP_createAVImux,
+        NULL
+    },{
+        wAVIMuxPropPage,
+        &CLSID_AVImuxPropertyPage,
+        QCAP_createAVImuxPropertyPage,
+        NULL
+    },{
+        wAVIMuxPropPage1,
+        &CLSID_AVImuxPropertyPage1,
+        QCAP_createAVImuxPropertyPage1,
+        NULL
+    },{
+        wFileWriter,
+        &CLSID_FileWriter,
+        QCAP_createFileWriter,
+        NULL
+    },{
+        wCaptGraphBuilder,
+        &CLSID_CaptureGraphBuilder,
+        QCAP_createCaptureGraphBuilder2,
+        NULL
+    },{
+        wCaptGraphBuilder2,
+        &CLSID_CaptureGraphBuilder2,
+        QCAP_createCaptureGraphBuilder2,
+        NULL
+    },{
+        wInfPinTeeFilter, 
+        &CLSID_InfinitePinTeeFilter, 
+        QCAP_createInfinitePinTeeFilter,
+        NULL
+    },{
+        wSmartTeeFilter,
+        &CLSID_SmartTeeFilter,
+        QCAP_createSmartTeeFilter,
+        NULL
+    },{
+        wAudioInMixerProp,
+        &CLSID_AudioInputMixerPropertyPage,
+        QCAP_createAudioInputMixerPropertyPage,
+        NULL
+    }*/
+};
+
+static int g_numTemplates = sizeof(g_cTemplates) /
sizeof(g_cTemplates[0]);
+
 
/***********************************************************************
- *      DllRegisterServer (QCAP.@)
+ *    Dll EntryPoint (QCAP.@)
+ */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(hInstDLL);
+            ghInst = hInstDLL;
+            SetupInitializeServers(g_cTemplates, g_numTemplates, TRUE);
+            break;
+        case DLL_PROCESS_DETACH:
+            SetupInitializeServers(g_cTemplates, g_numTemplates,
FALSE);
+            break;
+    }
+    return TRUE;
+}
+
+/**********************************************************************
*
+ *    DllRegisterServer (QCAP.@)
  */
 HRESULT WINAPI QCAP_DllRegisterServer()
 {
-	FIXME("(): stub\n");
-	return 0;
+    TRACE("()\n");
+
+    return SetupRegisterServers(g_cTemplates, g_numTemplates, ghInst,
TRUE);	
+}
+
+/**********************************************************************
*
+ *    DllUnregisterServer (QCAP.@)
+ */
+HRESULT WINAPI QCAP_DllUnregisterServer(void)
+{
+    TRACE("\n");
+
+    return SetupRegisterServers(g_cTemplates, g_numTemplates, ghInst,
FALSE);	
 }
 
 
/***********************************************************************
- *		DllGetClassObject (QCAP.@)
+ *    DllCanUnloadNow (QCAP.@)
  */
-HRESULT WINAPI QCAP_DllGetClassObject(REFCLSID rclsid, REFIID iid,
LPVOID *ppv)
+HRESULT WINAPI QCAP_DllCanUnloadNow(void)
+{
+    TRACE("\n");
+
+    if (objects_ref == 0 || server_locks == 0)
+        return S_OK;
+    return S_FALSE;	
+}
+
+/**********************************************************************
********
+ * DLL ClassFactory
+ */
+typedef struct {
+    IClassFactory ITF_IClassFactory;
+
+    DWORD ref;
+    LPFNNewCOMObject pfnCreateInstance;
+} IClassFactoryImpl;
+
+static HRESULT WINAPI
+DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
+{
+    IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+        IsEqualGUID(riid, &IID_IClassFactory))
+    {
+        IClassFactory_AddRef(iface);
+        *ppobj = This;
+        return S_OK;
+    }
+
+    WARN("(%p)->(%s,%p), not found\n", This, debugstr_guid(riid),
ppobj);
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
+{
+    IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
+{
+    IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    if (ref == 0)
+        HeapFree(GetProcessHeap(), 0, This);
+
+    return ref;
+}
+
+static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface,
LPUNKNOWN pOuter,
+                                          REFIID riid, LPVOID *ppobj)
+{
+    IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+    HRESULT hres = ERROR_SUCCESS;
+    LPUNKNOWN punk;
+
+    TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid),
ppobj);
+
+    if (!ppobj)
+        return E_POINTER;
+
+    /* Enforce the normal OLE rules regarding interfaces and delegation
*/
+    if (pOuter && !IsEqualGUID(riid, &IID_IUnknown))
+        return E_NOINTERFACE;
+
+    *ppobj = NULL;
+    punk = This->pfnCreateInstance(pOuter, &hres);
+    if (!punk)
+    {
+        /* No object created, update error if it isn't done already and
return */
+        if (!FAILED(hres))
+            hres = E_OUTOFMEMORY;
+    return hres;
+    }
+
+    if (SUCCEEDED(hres))
+    {
+        hres = IUnknown_QueryInterface(punk, riid, ppobj);
+    }
+    /* Releasing the object. If everything was successful,
QueryInterface
+       should have incremented the refcount once more, otherwise this
will
+       purge the object. */
+    IUnknown_Release(punk);
+    return hres;
+}
+
+static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface, BOOL
dolock)
+{
+    IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+    TRACE("(%p)->(%d)\n",This, dolock);
+
+    if (dolock)
+        InterlockedIncrement(&server_locks);
+    else
+        InterlockedDecrement(&server_locks);
+    return S_OK;
+}
+
+static IClassFactoryVtbl DSCF_Vtbl =
+{
+    DSCF_QueryInterface,
+    DSCF_AddRef,
+    DSCF_Release,
+    DSCF_CreateInstance,
+    DSCF_LockServer
+};
+
+/**********************************************************************
*
+ *    DllGetClassObject (QCAP.@)
+ */
+HRESULT WINAPI QCAP_DllGetClassObject(REFCLSID rclsid, REFIID riid,
LPVOID *ppv)
+{
+    const CFactoryTemplate *pList = g_cTemplates;
+    IClassFactoryImpl *factory;
+    int i;
+
+    TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid),
ppv);
+
+    if (!ppv)
+        return E_POINTER;
+
+    *ppv = NULL;
+
+    if (!IsEqualGUID(&IID_IClassFactory, riid) &&
+        !IsEqualGUID(&IID_IUnknown, riid))
+        return E_NOINTERFACE;
+
+    for (i = 0; i < g_numTemplates; i++, pList++)
+    {
+        if (IsEqualGUID(pList->m_ClsID, rclsid))
+            break;
+    }
+
+    if (i == g_numTemplates)
+    {
+        FIXME("%s: no class found.\n", debugstr_guid(rclsid));
+        return CLASS_E_CLASSNOTAVAILABLE;
+    }
+
+    factory = HeapAlloc(GetProcessHeap(), 0,
sizeof(IClassFactoryImpl));
+    if (!factory)
+        return E_OUTOFMEMORY;
+
+    factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
+    factory->ref = 1;
+
+    factory->pfnCreateInstance = pList->m_lpfnNew;
+
+    *ppv = &(factory->ITF_IClassFactory);
+    return S_OK;
+}
+
+DWORD ObjectRefCount(BOOL increment)
 {
-
FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_gui
d(iid));
-    return CLASS_E_CLASSNOTAVAILABLE;
+    if (increment)
+        return InterlockedIncrement(&objects_ref);
+    return InterlockedDecrement(&objects_ref);
 }
Index: dllsetup.h
===================================================================
RCS file: /home/wine/wine/dlls/qcap/dllsetup.h,v
--- /dev/null	2003-03-14 14:07:09.000000000 +0100
+++ dlls/qcap/dllsetup.h	2005-05-06 20:06:17.000000000 +0200
@@ -0,0 +1,93 @@
+/*
+ * DirectX DLL registration and unregistration
+ *
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
USA
+ */
+
+#ifndef _QCAP_DLLSETUP_H_DEFINED
+#define _QCAP_DLLSETUP_H_DEFINED
+
+#define COBJMACROS
+#include "strmif.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Filter Setup data structures not defined in axextend.idl
+    They are not part of the standard SDK headers but come from the
combase.h header
+    file in the DirectX Samples/Multimedia/BaseClasses */
+typedef REGPINTYPES AMOVIESETUP_MEDIATYPE, 
+    * PAMOVIESETUP_MEDIATYPE, 
+    * LPAMOVIESETUP_MEDIATYPE;
+
+typedef REGFILTERPINS AMOVIESETUP_PIN, 
+    * PAMOVIESETUP_PIN, 
+    * LPAMOVIESETUP_PIN;
+
+typedef struct _AMOVIESETUP_FILTER
+{
+    const CLSID           *clsID;
+    const WCHAR           *strName;
+    DWORD                 dwMerit;
+    UINT                  nPins;
+    const AMOVIESETUP_PIN *lpPin;
+} AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * LPAMOVIESETUP_FILTER;
+
+/* This needs to go into Combase.h */
+typedef IUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter,
HRESULT *phr);
+typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID
*rclsid);
+
+typedef struct tagCFactoryTemplate {
+    const WCHAR *m_Name;
+    const CLSID *m_ClsID;
+    LPFNNewCOMObject m_lpfnNew;
+    LPFNInitRoutine m_lpfnInit;
+    const AMOVIESETUP_FILTER *m_pAMovieSetup_Filter;
+} CFactoryTemplate;
+
+/**********************************************************************
******
+ * SetupRegisterServers
+ *
+ * This function is table driven using the static members of the
+ * CFactoryTemplate class defined in the Dll.
+ *
+ * It registers the Dll as the InprocServer32 for all the classes in
+ * CFactoryTemplate
+ *
+
************************************************************************
****/
+HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num,
+                             HINSTANCE hinst, BOOL bRegister);
+
+/**********************************************************************
******
+ * SetupInitializeServers
+ *
+ * This function is table driven using the static members of the
+ * CFactoryTemplate class defined in the Dll.
+ *
+ * It calls the intialize function for any class in CFactoryTemplate
with
+ * one defined.
+ *
+
************************************************************************
****/
+void SetupInitializeServers(const CFactoryTemplate * pList, int num,
+                            BOOL bLoading);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: dllsetup.c
===================================================================
RCS file: /home/wine/wine/dlls/qcap/dllsetup.c,v
--- /dev/null	2003-03-14 14:07:09.000000000 +0100
+++ dlls/qcap/dllsetup.c	2005-05-06 20:56:35.000000000 +0200
@@ -0,0 +1,365 @@
+/*
+ * DirectX DLL registration and unregistration
+ *
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
USA
+ */
+#include "config.h"
+
+#include <stdarg.h>
+
+#define COBJMACROS
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "uuids.h"
+
+#include "dllsetup.h"
+
+#include <assert.h>
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(qcap);
+
+/*
+ * defines and constants
+ */
+#define MAX_KEY_LEN  260
+
+static WCHAR const clsid_keyname[6] =
+{'C','L','S','I','D',0 };
+static WCHAR const ips32_keyname[15] =
+{'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0};
+static WCHAR const tmodel_keyname[15] =
+{'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
+static WCHAR const tmodel_both[] =
+{'B','o','t','h',0};
+
+/*
+ * Delete a key and all its subkeys
+ */
+HRESULT DeleteEntireSubKey(HKEY hkey, LPWSTR strSubKey)
+{
+    WCHAR buffer[MAX_KEY_LEN];
+    DWORD dw = MAX_KEY_LEN;
+    FILETIME ft;
+    HKEY hk;
+    LONG ret = RegOpenKeyExW(hkey, strSubKey, 0, MAXIMUM_ALLOWED, &hk);
+
+    if (ERROR_SUCCESS == ret)
+    {
+        /* Keep on enumerating the first key and deleting that */
+        for( ; ; )
+        {
+            dw = MAX_KEY_LEN;
+
+            ret = RegEnumKeyExW(hk, 0, buffer, &dw, NULL, NULL, NULL,
&ft);
+
+            if (ERROR_SUCCESS == ret)
+                DeleteEntireSubKey(hk, buffer);
+            else
+                break;
+        }
+        RegCloseKey(hk);
+        RegDeleteKeyW(hkey, strSubKey);
+    }
+    return NOERROR;
+}
+
+/*
+ * SetupRegisterClass()
+ */
+static HRESULT SetupRegisterClass(HKEY clsid, LPCWSTR szCLSID,
+                                  LPCWSTR szDescription,
+                                  LPCWSTR szFileName,
+                                  LPCWSTR szServerType,
+                                  LPCWSTR szThreadingModel)
+{
+    HKEY hkey, hsubkey;
+    LONG ret = RegCreateKeyW(clsid, szCLSID, &hkey);
+    if (ERROR_SUCCESS != ret)
+        return HRESULT_FROM_WIN32(ret);
+
+    /* set description string */
+    ret = RegSetValueW(hkey, NULL, REG_SZ, szDescription,
+                       sizeof(WCHAR) * (lstrlenW(szDescription) + 1));
+    if (ERROR_SUCCESS != ret)
+        goto err_out;
+
+    /* create CLSID\\{"CLSID"}\\"ServerType" key, using key to
CLSID\\{"CLSID"}
+       passed back by last call to RegCreateKeyW(). */
+    ret = RegCreateKeyW(hkey,  szServerType, &hsubkey);
+    if (ERROR_SUCCESS != ret)
+        goto err_out;
+
+    /* set server path */
+    ret = RegSetValueW(hsubkey, NULL, REG_SZ, szFileName,
+                       sizeof(WCHAR) * (lstrlenW(szFileName) + 1));
+    if (ERROR_SUCCESS != ret)
+        goto err_out;
+
+    /* set threading model */
+    ret = RegSetValueExW(hsubkey, tmodel_keyname, 0L, REG_SZ,
+                         (const BYTE*)szThreadingModel, 
+                         sizeof(WCHAR) * (lstrlenW(szThreadingModel) +
1));
+err_out:
+    if (hsubkey)
+        RegCloseKey(hsubkey);
+    RegCloseKey(hkey);
+    return HRESULT_FROM_WIN32(ret);
+}
+
+/*
+ * SetupRegisterFilter through IFilterMapper2
+ */
+static HRESULT SetupRegisterFilter2(const AMOVIESETUP_FILTER * const
pSetup,
+                                    IFilterMapper2 * pIFM2, BOOL
bRegister)
+{
+    HRESULT hr;
+
+    if (NULL == pSetup)
+        return S_FALSE;
+
+    /* unregister filter */
+    hr = IFilterMapper2_UnregisterFilter(pIFM2, 0, 0, pSetup->clsID);
+
+    if (bRegister)
+    {
+        REGFILTER2 rf2;
+        rf2.dwVersion = 1;
+        rf2.dwMerit = pSetup->dwMerit;
+        rf2.u.s.cPins = pSetup->nPins;
+        rf2.u.s.rgPins = pSetup->lpPin;
+    
+        /* register filter */
+        hr = IFilterMapper2_RegisterFilter(pIFM2, pSetup->clsID,
+                                           pSetup->strName, 0, 0, NULL,
&rf2);
+    }
+    else
+    {
+        /* filter not found is ignored here,
+           but there is no #define for 0x80070002  */
+        if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
+            hr = NOERROR;
+    }
+    return hr;
+}
+
+/*
+ * SetupRegisterFilter through IFilterMapper
+ */
+static HRESULT SetupRegisterFilter(const AMOVIESETUP_FILTER * const
pSetup,
+                                   IFilterMapper * pIFM, BOOL
bRegister)
+{
+    HRESULT hr;
+
+    if (NULL == pSetup)
+        return S_FALSE;
+
+    /* unregister filter */
+    hr = IFilterMapper_UnregisterFilter(pIFM, *pSetup->clsID);
+
+    if (bRegister)
+    {
+        /* register filter */
+        hr = IFilterMapper_RegisterFilter(pIFM, *pSetup->clsID,
+                                          pSetup->strName,
pSetup->dwMerit);
+        if (SUCCEEDED(hr))
+        {
+            const AMOVIESETUP_PIN *lpPin = pSetup->lpPin;
+            const AMOVIESETUP_MEDIATYPE *lpType;
+            UINT i, j;
+
+            for (i = 0; i < pSetup->nPins; i++, lpPin++)
+            {
+                hr = IFilterMapper_RegisterPin(pIFM, *(pSetup->clsID),
+                                               lpPin->strName,
+                                               lpPin->bRendered,
+                                               lpPin->bOutput,
+                                               lpPin->bZero,
+                                               lpPin->bMany,
+
*(lpPin->clsConnectsToFilter),
+
lpPin->strConnectsToPin);
+
+                if (SUCCEEDED(hr))
+                {
+                    lpType = lpPin->lpMediaType;
+
+                    /* and each pin's media types */
+                    for (j = 0; j < lpPin->nMediaTypes; j++, lpType++)
+                    {
+                        hr = IFilterMapper_RegisterPinType(pIFM,
*(pSetup->clsID),
+
lpPin->strName,
+
*(lpType->clsMajorType),
+
*(lpType->clsMinorType));
+                        if (FAILED(hr)) break;
+                    }
+                    if (FAILED(hr)) break;
+                }
+                if (FAILED(hr)) break;
+            }
+        }
+    }
+    else
+    {
+        /* filter not registered is ignored here, there is no
definition for 0x80070002  */
+        if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
+           hr = NOERROR;
+    }
+    return hr;
+}
+
+/*
+ * RegisterAllClasses()
+ */
+static HRESULT SetupRegisterAllClasses(const CFactoryTemplate * pList,
int num,
+                                       LPCWSTR szFileName, BOOL
bRegister)
+{
+    HRESULT hr = NOERROR;
+    HKEY hkey;
+    OLECHAR szCLSID[CHARS_IN_GUID];
+    LONG i, ret = RegCreateKeyW(HKEY_CLASSES_ROOT, clsid_keyname,
&hkey);
+    if (ERROR_SUCCESS != ret)
+        return HRESULT_FROM_WIN32(ret);
+
+    for (i = 0; i < num; i++, pList++)
+    {
+        /* (un)register CLSID and InprocServer32 */
+        hr = StringFromGUID2(pList->m_ClsID, szCLSID, CHARS_IN_GUID);
+        if (SUCCEEDED(hr))
+        {
+            if (bRegister )
+                hr = SetupRegisterClass(hkey, szCLSID,
+                                        pList->m_Name, szFileName,
+                                        ips32_keyname, tmodel_both);
+            else
+                hr = DeleteEntireSubKey(hkey, szCLSID);
+        }
+    }
+    RegCloseKey(hkey);
+    return hr;
+}
+
+
+/**********************************************************************
******
+ * SetupRegisterServers
+ *
+ * This function is table driven using the static members of the
+ * CFactoryTemplate class defined in the Dll.
+ *
+ * It registers the Dll as the InprocServer32 for all the classes in
+ * CFactoryTemplate
+ *
+
************************************************************************
****/
+HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num,
+                             HINSTANCE hinst, BOOL bRegister)
+{
+    HRESULT hr = NOERROR;
+    WCHAR szFileName[MAX_PATH];
+    IFilterMapper2 *pIFM2 = NULL;
+    IFilterMapper *pIFM = NULL;
+
+    /* Win95 wouldn't support the Unicode version of this API!! */
+    if (!GetModuleFileNameW(hinst, szFileName, MAX_PATH))
+        return HRESULT_FROM_WIN32(GetLastError());
+
+    /* first register all server classes, just to make sure */
+    if (bRegister)
+        hr = SetupRegisterAllClasses(pList, num, szFileName, TRUE );
+
+    /* next, register/unregister all filters */
+    if (SUCCEEDED(hr))
+    {
+        hr = CoInitialize((LPVOID)NULL);
+
+        TRACE("Getting IFilterMapper2\r\n");
+        hr = CoCreateInstance(&CLSID_FilterMapper2, NULL,
CLSCTX_INPROC_SERVER,
+                              &IID_IFilterMapper2, (void **)&pIFM2);
+        if (FAILED(hr))
+        {
+            TRACE("- trying IFilterMapper instead\r\n");
+
+            hr = CoCreateInstance(&CLSID_FilterMapper, NULL,
CLSCTX_INPROC_SERVER,
+                                  &IID_IFilterMapper, (void **)&pIFM);
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            int i;
+            
+            /* scan through array of CFactoryTemplates registering all
filters */
+            for (i = 0; i < num; i++, pList++)
+            {
+                if (NULL != pList->m_pAMovieSetup_Filter)
+                {
+                    if (pIFM2)
+                        hr =
SetupRegisterFilter2(pList->m_pAMovieSetup_Filter,
+                                                  pIFM2, bRegister);
+                    else
+                        hr =
SetupRegisterFilter(pList->m_pAMovieSetup_Filter,
+                                                 pIFM, bRegister);
+                }
+
+                /* check final error for this pass and break loop if we
failed */
+                if (FAILED(hr))
+                    break;
+            }
+
+            /* release interface */
+            if (pIFM2)
+                IFilterMapper2_Release(pIFM2);
+            else
+                IFilterMapper_Release(pIFM);
+        }
+
+        /* and clear up */
+        CoFreeUnusedLibraries();
+        CoUninitialize();
+    }
+
+    /* if unregistering, unregister all OLE servers */
+    if (SUCCEEDED(hr) && !bRegister)
+        hr = SetupRegisterAllClasses(pList, num, szFileName, FALSE);
+    return hr;
+}
+
+/**********************************************************************
******
+ * SetupInitializeServers
+ *
+ * This function is table driven using the static members of the
+ * CFactoryTemplate class defined in the Dll.
+ *
+ * It calls the intialize function for any class in CFactoryTemplate
with
+ * one defined.
+ *
+
************************************************************************
****/
+void SetupInitializeServers(const CFactoryTemplate * pList, int num,
+                            BOOL bLoading)
+{
+    int i;
+
+    for (i = 0; i < num; i++, pList++)
+    {
+        pList->m_lpfnInit(bLoading, pList->m_ClsID);
+    }
+}




More information about the wine-patches mailing list