//------------------------------------------------------------------------------ // File: DllSetup.cpp // // Desc: DirectShow base classes. // // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ #include #include //--------------------------------------------------------------------------- // 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(&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(&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; }