/* * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include #include #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(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++) { if (pList->m_lpfnInit) pList->m_lpfnInit(bLoading, pList->m_ClsID); } }