blob: ede9c3fd442b905202a410b8949afed0d5ee90f5 [file] [log] [blame]
//------------------------------------------------------------------------------
// 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;
}