Implement DLL registering and unregistering functions, class factory

and server locking based on how it is done with DirectX samples.
This commit is contained in:
Rolf Kalbermatter 2005-05-07 18:00:33 +00:00 committed by Alexandre Julliard
parent ce8c9426eb
commit 836b7df693
6 changed files with 817 additions and 13 deletions

View File

@ -3,8 +3,12 @@ TOPOBJDIR = ../..
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

364
dlls/qcap/dllsetup.c Normal file
View File

@ -0,0 +1,364 @@
/*
* 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>
#include <assert.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 "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);
}
}

85
dlls/qcap/dllsetup.h Normal file
View File

@ -0,0 +1,85 @@
/*
* 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"
/* 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
*
****************************************************************************/
extern 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.
*
****************************************************************************/
extern void SetupInitializeServers(const CFactoryTemplate * pList, int num,
BOOL bLoading);
#endif /* _QCAP_DLLSETUP_H_DEFINED */

View File

@ -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

View File

@ -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,339 @@
* 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 <assert.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 "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;
static const WCHAR wAudioCaptFilter[] =
{'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};
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.@)
*/
HRESULT WINAPI QCAP_DllRegisterServer()
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
FIXME("(): stub\n");
return 0;
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;
}
/***********************************************************************
* DllGetClassObject (QCAP.@)
* DllRegisterServer (QCAP.@)
*/
HRESULT WINAPI QCAP_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
HRESULT WINAPI QCAP_DllRegisterServer()
{
FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
return CLASS_E_CLASSNOTAVAILABLE;
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);
}
/***********************************************************************
* DllCanUnloadNow (QCAP.@)
*/
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)
{
if (increment)
return InterlockedIncrement(&objects_ref);
return InterlockedDecrement(&objects_ref);
}

38
dlls/qcap/qcap_main.h Normal file
View File

@ -0,0 +1,38 @@
/*
* 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
extern DWORD ObjectRefCount(BOOL increment);
extern IUnknown * WINAPI QCAP_createAudioCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createAVICompressor(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createVFWCaptureFilterPropertyPage(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createAVImux(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createAVImuxPropertyPage(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createAVImuxPropertyPage1(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createFileWriter(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createCaptureGraphBuilder2(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createInfinitePinTeeFilter(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createSmartTeeFilter(IUnknown *pUnkOuter, HRESULT *phr);
extern IUnknown * WINAPI QCAP_createAudioInputMixerPropertyPage(IUnknown *pUnkOuter, HRESULT *phr);
#endif /* _QCAP_MAIN_H_DEFINED */