//------------------------------------------------------------------------------ // 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; const CLSID *filterCategory = &psetupdata->filterCategory; // register filter // DbgLog((LOG_TRACE, 3, TEXT("= = register filter"))); hr = pIFM2->RegisterFilter(*psetupdata->clsID , psetupdata->strName , 0 // moniker , filterCategory // 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; }