mirror of
https://github.com/reactos/wine.git
synced 2025-03-04 10:47:49 +00:00
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@
|
SRCDIR = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
MODULE = qcap.dll
|
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
|
RC_SRCS = version.rc
|
||||||
|
|
||||||
|
364
dlls/qcap/dllsetup.c
Normal file
364
dlls/qcap/dllsetup.c
Normal 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
85
dlls/qcap/dllsetup.h
Normal 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 */
|
@ -1,4 +1,4 @@
|
|||||||
@ stub DllCanUnloadNow
|
@ stdcall -private DllCanUnloadNow() QCAP_DllCanUnloadNow
|
||||||
@ stdcall -private DllGetClassObject(ptr ptr ptr) QCAP_DllGetClassObject
|
@ stdcall -private DllGetClassObject(ptr ptr ptr) QCAP_DllGetClassObject
|
||||||
@ stdcall -private DllRegisterServer() QCAP_DllRegisterServer
|
@ 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) 2003 Dominik Strasser
|
||||||
|
* Copyright (C) 2005 Rolf Kalbermatter
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* 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
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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 "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);
|
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");
|
switch (fdwReason)
|
||||||
return 0;
|
{
|
||||||
|
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));
|
TRACE("()\n");
|
||||||
return CLASS_E_CLASSNOTAVAILABLE;
|
|
||||||
|
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
38
dlls/qcap/qcap_main.h
Normal 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 */
|
Loading…
x
Reference in New Issue
Block a user