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:
parent
ce8c9426eb
commit
836b7df693
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
Loading…
Reference in New Issue