//------------------------------------------------------------------------------ | |
// File: DllSetup.cpp | |
// | |
// Desc: DirectShow base classes. | |
// | |
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. | |
//------------------------------------------------------------------------------ | |
#include <streams.h> | |
#include <strsafe.h> | |
//--------------------------------------------------------------------------- | |
// defines | |
#define MAX_KEY_LEN 260 | |
//--------------------------------------------------------------------------- | |
// externally defined functions/variable | |
extern int g_cTemplates; | |
extern CFactoryTemplate g_Templates[]; | |
//--------------------------------------------------------------------------- | |
// | |
// EliminateSubKey | |
// | |
// Try to enumerate all keys under this one. | |
// if we find anything, delete it completely. | |
// Otherwise just delete it. | |
// | |
// note - this was pinched/duplicated from | |
// Filgraph\Mapper.cpp - so should it be in | |
// a lib somewhere? | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
EliminateSubKey( HKEY hkey, LPCTSTR strSubKey ) | |
{ | |
HKEY hk; | |
if (0 == lstrlen(strSubKey) ) { | |
// defensive approach | |
return E_FAIL; | |
} | |
LONG lreturn = RegOpenKeyEx( hkey | |
, strSubKey | |
, 0 | |
, MAXIMUM_ALLOWED | |
, &hk ); | |
ASSERT( lreturn == ERROR_SUCCESS | |
|| lreturn == ERROR_FILE_NOT_FOUND | |
|| lreturn == ERROR_INVALID_HANDLE ); | |
if( ERROR_SUCCESS == lreturn ) | |
{ | |
// Keep on enumerating the first (zero-th) | |
// key and deleting that | |
for( ; ; ) | |
{ | |
TCHAR Buffer[MAX_KEY_LEN]; | |
DWORD dw = MAX_KEY_LEN; | |
FILETIME ft; | |
lreturn = RegEnumKeyEx( hk | |
, 0 | |
, Buffer | |
, &dw | |
, NULL | |
, NULL | |
, NULL | |
, &ft); | |
ASSERT( lreturn == ERROR_SUCCESS | |
|| lreturn == ERROR_NO_MORE_ITEMS ); | |
if( ERROR_SUCCESS == lreturn ) | |
{ | |
EliminateSubKey(hk, Buffer); | |
} | |
else | |
{ | |
break; | |
} | |
} | |
RegCloseKey(hk); | |
RegDeleteKey(hkey, strSubKey); | |
} | |
return NOERROR; | |
} | |
//--------------------------------------------------------------------------- | |
// | |
// AMovieSetupRegisterServer() | |
// | |
// registers specfied file "szFileName" as server for | |
// CLSID "clsServer". A description is also required. | |
// The ThreadingModel and ServerType are optional, as | |
// they default to InprocServer32 (i.e. dll) and Both. | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
AMovieSetupRegisterServer( CLSID clsServer | |
, LPCWSTR szDescription | |
, LPCWSTR szFileName | |
, LPCWSTR szThreadingModel = L"Both" | |
, LPCWSTR szServerType = L"InprocServer32" ) | |
{ | |
// temp buffer | |
// | |
TCHAR achTemp[MAX_PATH]; | |
// convert CLSID uuid to string and write | |
// out subkey as string - CLSID\{} | |
// | |
OLECHAR szCLSID[CHARS_IN_GUID]; | |
HRESULT hr = StringFromGUID2( clsServer | |
, szCLSID | |
, CHARS_IN_GUID ); | |
ASSERT( SUCCEEDED(hr) ); | |
// create key | |
// | |
HKEY hkey; | |
(void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("CLSID\\%ls"), szCLSID ); | |
LONG lreturn = RegCreateKey( HKEY_CLASSES_ROOT | |
, (LPCTSTR)achTemp | |
, &hkey ); | |
if( ERROR_SUCCESS != lreturn ) | |
{ | |
return AmHresultFromWin32(lreturn); | |
} | |
// set description string | |
// | |
(void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szDescription ); | |
lreturn = RegSetValue( hkey | |
, (LPCTSTR)NULL | |
, REG_SZ | |
, achTemp | |
, sizeof(achTemp) ); | |
if( ERROR_SUCCESS != lreturn ) | |
{ | |
RegCloseKey( hkey ); | |
return AmHresultFromWin32(lreturn); | |
} | |
// create CLSID\\{"CLSID"}\\"ServerType" key, | |
// using key to CLSID\\{"CLSID"} passed back by | |
// last call to RegCreateKey(). | |
// | |
HKEY hsubkey; | |
(void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szServerType ); | |
lreturn = RegCreateKey( hkey | |
, achTemp | |
, &hsubkey ); | |
if( ERROR_SUCCESS != lreturn ) | |
{ | |
RegCloseKey( hkey ); | |
return AmHresultFromWin32(lreturn); | |
} | |
// set Server string | |
// | |
(void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szFileName ); | |
lreturn = RegSetValue( hsubkey | |
, (LPCTSTR)NULL | |
, REG_SZ | |
, (LPCTSTR)achTemp | |
, sizeof(TCHAR) * (lstrlen(achTemp)+1) ); | |
if( ERROR_SUCCESS != lreturn ) | |
{ | |
RegCloseKey( hkey ); | |
RegCloseKey( hsubkey ); | |
return AmHresultFromWin32(lreturn); | |
} | |
(void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szThreadingModel ); | |
lreturn = RegSetValueEx( hsubkey | |
, TEXT("ThreadingModel") | |
, 0L | |
, REG_SZ | |
, (CONST BYTE *)achTemp | |
, sizeof(TCHAR) * (lstrlen(achTemp)+1) ); | |
// close hkeys | |
// | |
RegCloseKey( hkey ); | |
RegCloseKey( hsubkey ); | |
// and return | |
// | |
return HRESULT_FROM_WIN32(lreturn); | |
} | |
//--------------------------------------------------------------------------- | |
// | |
// AMovieSetupUnregisterServer() | |
// | |
// default ActiveMovie dll setup function | |
// - to use must be called from an exported | |
// function named DllRegisterServer() | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
AMovieSetupUnregisterServer( CLSID clsServer ) | |
{ | |
// convert CLSID uuid to string and write | |
// out subkey CLSID\{} | |
// | |
OLECHAR szCLSID[CHARS_IN_GUID]; | |
HRESULT hr = StringFromGUID2( clsServer | |
, szCLSID | |
, CHARS_IN_GUID ); | |
ASSERT( SUCCEEDED(hr) ); | |
TCHAR achBuffer[MAX_KEY_LEN]; | |
(void)StringCchPrintf( achBuffer, NUMELMS(achBuffer), TEXT("CLSID\\%ls"), szCLSID ); | |
// delete subkey | |
// | |
hr = EliminateSubKey( HKEY_CLASSES_ROOT, achBuffer ); | |
ASSERT( SUCCEEDED(hr) ); | |
// return | |
// | |
return NOERROR; | |
} | |
//--------------------------------------------------------------------------- | |
// | |
// AMovieSetupRegisterFilter through IFilterMapper2 | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata | |
, IFilterMapper2 * pIFM2 | |
, BOOL bRegister ) | |
{ | |
DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter"))); | |
// check we've got data | |
// | |
if( NULL == psetupdata ) return S_FALSE; | |
// unregister filter | |
// (as pins are subkeys of filter's CLSID key | |
// they do not need to be removed separately). | |
// | |
DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter"))); | |
HRESULT hr = pIFM2->UnregisterFilter( | |
0, // default category | |
0, // default instance name | |
*psetupdata->clsID ); | |
if( bRegister ) | |
{ | |
REGFILTER2 rf2; | |
rf2.dwVersion = 1; | |
rf2.dwMerit = psetupdata->dwMerit; | |
rf2.cPins = psetupdata->nPins; | |
rf2.rgPins = psetupdata->lpPin; | |
// register filter | |
// | |
DbgLog((LOG_TRACE, 3, TEXT("= = register filter"))); | |
hr = pIFM2->RegisterFilter(*psetupdata->clsID | |
, psetupdata->strName | |
, 0 // moniker | |
, 0 // category | |
, NULL // instance | |
, &rf2); | |
} | |
// handle one acceptable "error" - that | |
// of filter not being registered! | |
// (couldn't find a suitable #define'd | |
// name for the error!) | |
// | |
if( 0x80070002 == hr) | |
return NOERROR; | |
else | |
return hr; | |
} | |
//--------------------------------------------------------------------------- | |
// | |
// RegisterAllServers() | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
RegisterAllServers( LPCWSTR szFileName, BOOL bRegister ) | |
{ | |
HRESULT hr = NOERROR; | |
for( int i = 0; i < g_cTemplates; i++ ) | |
{ | |
// get i'th template | |
// | |
const CFactoryTemplate *pT = &g_Templates[i]; | |
DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), | |
(LPCWSTR)pT->m_Name )); | |
// register CLSID and InprocServer32 | |
// | |
if( bRegister ) | |
{ | |
hr = AMovieSetupRegisterServer( *(pT->m_ClsID) | |
, (LPCWSTR)pT->m_Name | |
, szFileName ); | |
} | |
else | |
{ | |
hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) ); | |
} | |
// check final error for this pass | |
// and break loop if we failed | |
// | |
if( FAILED(hr) ) | |
break; | |
} | |
return hr; | |
} | |
//--------------------------------------------------------------------------- | |
// | |
// AMovieDllRegisterServer2() | |
// | |
// default ActiveMovie dll setup function | |
// - to use must be called from an exported | |
// function named DllRegisterServer() | |
// | |
// this function is table driven using the | |
// static members of the CFactoryTemplate | |
// class defined in the dll. | |
// | |
// it registers the Dll as the InprocServer32 | |
// and then calls the IAMovieSetup.Register | |
// method. | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
AMovieDllRegisterServer2( BOOL bRegister ) | |
{ | |
HRESULT hr = NOERROR; | |
DbgLog((LOG_TRACE, 2, TEXT("AMovieDllRegisterServer2()"))); | |
// get file name (where g_hInst is the | |
// instance handle of the filter dll) | |
// | |
WCHAR achFileName[MAX_PATH]; | |
// WIN95 doesn't support GetModuleFileNameW | |
// | |
{ | |
char achTemp[MAX_PATH]; | |
DbgLog((LOG_TRACE, 2, TEXT("- get module file name"))); | |
// g_hInst handle is set in our dll entry point. Make sure | |
// DllEntryPoint in dllentry.cpp is called | |
ASSERT(g_hInst != 0); | |
if( 0 == GetModuleFileNameA( g_hInst | |
, achTemp | |
, sizeof(achTemp) ) ) | |
{ | |
// we've failed! | |
DWORD dwerr = GetLastError(); | |
return AmHresultFromWin32(dwerr); | |
} | |
MultiByteToWideChar( CP_ACP | |
, 0L | |
, achTemp | |
, lstrlenA(achTemp) + 1 | |
, achFileName | |
, NUMELMS(achFileName) ); | |
} | |
// | |
// first registering, register all OLE servers | |
// | |
if( bRegister ) | |
{ | |
DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers"))); | |
hr = RegisterAllServers( achFileName, TRUE ); | |
} | |
// | |
// next, register/unregister all filters | |
// | |
if( SUCCEEDED(hr) ) | |
{ | |
// init is ref counted so call just in case | |
// we're being called cold. | |
// | |
DbgLog((LOG_TRACE, 2, TEXT("- CoInitialize"))); | |
hr = CoInitialize( (LPVOID)NULL ); | |
ASSERT( SUCCEEDED(hr) ); | |
// get hold of IFilterMapper2 | |
// | |
DbgLog((LOG_TRACE, 2, TEXT("- obtain IFilterMapper2"))); | |
IFilterMapper2 *pIFM2 = 0; | |
IFilterMapper *pIFM = 0; | |
hr = CoCreateInstance( CLSID_FilterMapper2 | |
, NULL | |
, CLSCTX_INPROC_SERVER | |
, IID_IFilterMapper2 | |
, (void **)&pIFM2 ); | |
if(FAILED(hr)) | |
{ | |
DbgLog((LOG_TRACE, 2, TEXT("- trying IFilterMapper instead"))); | |
hr = CoCreateInstance( | |
CLSID_FilterMapper, | |
NULL, | |
CLSCTX_INPROC_SERVER, | |
IID_IFilterMapper, | |
(void **)&pIFM); | |
} | |
if( SUCCEEDED(hr) ) | |
{ | |
// scan through array of CFactoryTemplates | |
// registering servers and filters. | |
// | |
DbgLog((LOG_TRACE, 2, TEXT("- register Filters"))); | |
for( int i = 0; i < g_cTemplates; i++ ) | |
{ | |
// get i'th template | |
// | |
const CFactoryTemplate *pT = &g_Templates[i]; | |
if( NULL != pT->m_pAMovieSetup_Filter ) | |
{ | |
DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), (LPCWSTR)pT->m_Name )); | |
if(pIFM2) | |
{ | |
hr = AMovieSetupRegisterFilter2( pT->m_pAMovieSetup_Filter, pIFM2, bRegister ); | |
} | |
else | |
{ | |
hr = AMovieSetupRegisterFilter( pT->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) | |
pIFM2->Release(); | |
else | |
pIFM->Release(); | |
} | |
// and clear up | |
// | |
CoFreeUnusedLibraries(); | |
CoUninitialize(); | |
} | |
// | |
// if unregistering, unregister all OLE servers | |
// | |
if( SUCCEEDED(hr) && !bRegister ) | |
{ | |
DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers"))); | |
hr = RegisterAllServers( achFileName, FALSE ); | |
} | |
DbgLog((LOG_TRACE, 2, TEXT("- return %0x"), hr)); | |
return hr; | |
} | |
//--------------------------------------------------------------------------- | |
// | |
// AMovieDllRegisterServer() | |
// | |
// default ActiveMovie dll setup function | |
// - to use must be called from an exported | |
// function named DllRegisterServer() | |
// | |
// this function is table driven using the | |
// static members of the CFactoryTemplate | |
// class defined in the dll. | |
// | |
// it registers the Dll as the InprocServer32 | |
// and then calls the IAMovieSetup.Register | |
// method. | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
AMovieDllRegisterServer( void ) | |
{ | |
HRESULT hr = NOERROR; | |
// get file name (where g_hInst is the | |
// instance handle of the filter dll) | |
// | |
WCHAR achFileName[MAX_PATH]; | |
{ | |
// WIN95 doesn't support GetModuleFileNameW | |
// | |
char achTemp[MAX_PATH]; | |
if( 0 == GetModuleFileNameA( g_hInst | |
, achTemp | |
, sizeof(achTemp) ) ) | |
{ | |
// we've failed! | |
DWORD dwerr = GetLastError(); | |
return AmHresultFromWin32(dwerr); | |
} | |
MultiByteToWideChar( CP_ACP | |
, 0L | |
, achTemp | |
, lstrlenA(achTemp) + 1 | |
, achFileName | |
, NUMELMS(achFileName) ); | |
} | |
// scan through array of CFactoryTemplates | |
// registering servers and filters. | |
// | |
for( int i = 0; i < g_cTemplates; i++ ) | |
{ | |
// get i'th template | |
// | |
const CFactoryTemplate *pT = &g_Templates[i]; | |
// register CLSID and InprocServer32 | |
// | |
hr = AMovieSetupRegisterServer( *(pT->m_ClsID) | |
, (LPCWSTR)pT->m_Name | |
, achFileName ); | |
// instantiate all servers and get hold of | |
// IAMovieSetup, if implemented, and call | |
// IAMovieSetup.Register() method | |
// | |
if( SUCCEEDED(hr) && (NULL != pT->m_lpfnNew) ) | |
{ | |
// instantiate object | |
// | |
PAMOVIESETUP psetup; | |
hr = CoCreateInstance( *(pT->m_ClsID) | |
, 0 | |
, CLSCTX_INPROC_SERVER | |
, IID_IAMovieSetup | |
, reinterpret_cast<void**>(&psetup) ); | |
if( SUCCEEDED(hr) ) | |
{ | |
hr = psetup->Unregister(); | |
if( SUCCEEDED(hr) ) | |
hr = psetup->Register(); | |
psetup->Release(); | |
} | |
else | |
{ | |
if( (E_NOINTERFACE == hr ) | |
|| (VFW_E_NEED_OWNER == hr ) ) | |
hr = NOERROR; | |
} | |
} | |
// check final error for this pass | |
// and break loop if we failed | |
// | |
if( FAILED(hr) ) | |
break; | |
} // end-for | |
return hr; | |
} | |
//--------------------------------------------------------------------------- | |
// | |
// AMovieDllUnregisterServer() | |
// | |
// default ActiveMovie dll uninstall function | |
// - to use must be called from an exported | |
// function named DllRegisterServer() | |
// | |
// this function is table driven using the | |
// static members of the CFactoryTemplate | |
// class defined in the dll. | |
// | |
// it calls the IAMovieSetup.Unregister | |
// method and then unregisters the Dll | |
// as the InprocServer32 | |
// | |
//--------------------------------------------------------------------------- | |
STDAPI | |
AMovieDllUnregisterServer() | |
{ | |
// initialize return code | |
// | |
HRESULT hr = NOERROR; | |
// scan through CFactory template and unregister | |
// all OLE servers and filters. | |
// | |
for( int i = g_cTemplates; i--; ) | |
{ | |
// get i'th template | |
// | |
const CFactoryTemplate *pT = &g_Templates[i]; | |
// check method exists | |
// | |
if( NULL != pT->m_lpfnNew ) | |
{ | |
// instantiate object | |
// | |
PAMOVIESETUP psetup; | |
hr = CoCreateInstance( *(pT->m_ClsID) | |
, 0 | |
, CLSCTX_INPROC_SERVER | |
, IID_IAMovieSetup | |
, reinterpret_cast<void**>(&psetup) ); | |
if( SUCCEEDED(hr) ) | |
{ | |
hr = psetup->Unregister(); | |
psetup->Release(); | |
} | |
else | |
{ | |
if( (E_NOINTERFACE == hr ) | |
|| (VFW_E_NEED_OWNER == hr ) ) | |
hr = NOERROR; | |
} | |
} | |
// unregister CLSID and InprocServer32 | |
// | |
if( SUCCEEDED(hr) ) | |
{ | |
hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) ); | |
} | |
// check final error for this pass | |
// and break loop if we failed | |
// | |
if( FAILED(hr) ) | |
break; | |
} | |
return hr; | |
} |