| /* |
| * Regster/Unregister servers. (for internal use) |
| * |
| * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp> |
| * |
| * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include "config.h" |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "wingdi.h" |
| #include "winuser.h" |
| #include "winerror.h" |
| #include "winreg.h" |
| #include "uuids.h" |
| |
| #include "wine/debug.h" |
| WINE_DEFAULT_DEBUG_CHANNEL(quartz); |
| |
| #include "regsvr.h" |
| |
| #ifndef NUMELEMS |
| #define NUMELEMS(elem) (sizeof(elem)/sizeof((elem)[0])) |
| #endif /* NUMELEMS */ |
| |
| const WCHAR QUARTZ_wszREG_SZ[7] = |
| {'R','E','G','_','S','Z',0}; |
| const WCHAR QUARTZ_wszInprocServer32[] = |
| {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0}; |
| const WCHAR QUARTZ_wszThreadingModel[] = |
| {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; |
| const WCHAR QUARTZ_wszBoth[] = |
| {'B','o','t','h',0}; |
| const WCHAR QUARTZ_wszCLSID[] = |
| {'C','L','S','I','D',0}; |
| const WCHAR QUARTZ_wszFilterData[] = |
| {'F','i','l','t','e','r','D','a','t','a',0}; |
| const WCHAR QUARTZ_wszFriendlyName[] = |
| {'F','r','i','e','n','d','l','y','N','a','m','e',0}; |
| const WCHAR QUARTZ_wszInstance[] = |
| {'I','n','s','t','a','n','c','e',0}; |
| const WCHAR QUARTZ_wszMerit[] = |
| {'M','e','r','i','t',0}; |
| const WCHAR QUARTZ_wszMediaType[] = |
| {'M','e','d','i','a',' ','T','y','p','e',0}; |
| const WCHAR QUARTZ_wszSubType[] = |
| {'S','u','b','T','y','p','e',0}; |
| const WCHAR QUARTZ_wszExtensions[] = |
| {'E','x','t','e','n','s','i','o','n','s',0}; |
| const WCHAR QUARTZ_wszSourceFilter[] = |
| {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0}; |
| |
| void QUARTZ_CatPathSepW( WCHAR* pBuf ) |
| { |
| int len = lstrlenW(pBuf); |
| pBuf[len] = '\\'; |
| pBuf[len+1] = 0; |
| } |
| |
| void QUARTZ_GUIDtoString( WCHAR* pBuf, const GUID* pguid ) |
| { |
| /* W"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}" */ |
| static const WCHAR wszFmt[] = |
| {'{','%','0','8','X','-','%','0','4','X','-','%','0','4','X', |
| '-','%','0','2','X','%','0','2','X','-','%','0','2','X','%', |
| '0','2','X','%','0','2','X','%','0','2','X','%','0','2','X', |
| '%','0','2','X','}',0}; |
| |
| wsprintfW( pBuf, wszFmt, |
| pguid->Data1, pguid->Data2, pguid->Data3, |
| pguid->Data4[0], pguid->Data4[1], |
| pguid->Data4[2], pguid->Data4[3], |
| pguid->Data4[4], pguid->Data4[5], |
| pguid->Data4[6], pguid->Data4[7] ); |
| } |
| |
| static |
| LONG QUARTZ_RegOpenKeyW( |
| HKEY hkRoot, LPCWSTR lpszPath, |
| REGSAM rsAccess, HKEY* phKey, |
| BOOL fCreateKey ) |
| { |
| DWORD dwDisp; |
| WCHAR wszREG_SZ[ NUMELEMS(QUARTZ_wszREG_SZ) ]; |
| |
| memcpy(wszREG_SZ,QUARTZ_wszREG_SZ,sizeof(QUARTZ_wszREG_SZ) ); |
| |
| if ( fCreateKey ) |
| return RegCreateKeyExW( |
| hkRoot, lpszPath, 0, wszREG_SZ, |
| REG_OPTION_NON_VOLATILE, rsAccess, NULL, phKey, &dwDisp ); |
| else |
| return RegOpenKeyExW( |
| hkRoot, lpszPath, 0, rsAccess, phKey ); |
| } |
| |
| static |
| LONG QUARTZ_RegSetValueString( |
| HKEY hKey, LPCWSTR lpszName, LPCWSTR lpValue ) |
| { |
| return RegSetValueExW( |
| hKey, lpszName, 0, REG_SZ, |
| (const BYTE*)lpValue, |
| sizeof(lpValue[0]) * (lstrlenW(lpValue)+1) ); |
| } |
| |
| static |
| LONG QUARTZ_RegSetValueDWord( |
| HKEY hKey, LPCWSTR lpszName, DWORD dwValue ) |
| { |
| return RegSetValueExW( |
| hKey, lpszName, 0, REG_DWORD, |
| (const BYTE*)(&dwValue), sizeof(DWORD) ); |
| } |
| |
| static |
| LONG QUARTZ_RegSetValueBinary( |
| HKEY hKey, LPCWSTR lpszName, |
| const BYTE* pData, int iLenOfData ) |
| { |
| return RegSetValueExW( |
| hKey, lpszName, 0, REG_BINARY, pData, iLenOfData ); |
| } |
| |
| HRESULT QUARTZ_CreateCLSIDPath( |
| WCHAR* pwszBuf, DWORD dwBufLen, |
| const CLSID* pclsid, |
| LPCWSTR lpszPathFromCLSID ) |
| { |
| int avail; |
| |
| lstrcpyW( pwszBuf, QUARTZ_wszCLSID ); |
| QUARTZ_CatPathSepW( pwszBuf+5 ); |
| QUARTZ_GUIDtoString( pwszBuf+6, pclsid ); |
| if ( lpszPathFromCLSID != NULL ) |
| { |
| avail = (int)dwBufLen - lstrlenW(pwszBuf) - 8; |
| if ( avail <= lstrlenW(lpszPathFromCLSID) ) |
| return E_FAIL; |
| QUARTZ_CatPathSepW( pwszBuf ); |
| lstrcatW( pwszBuf, lpszPathFromCLSID ); |
| } |
| |
| return NOERROR; |
| } |
| |
| HRESULT QUARTZ_OpenCLSIDKey( |
| HKEY* phKey, /* [OUT] hKey */ |
| REGSAM rsAccess, /* [IN] access */ |
| BOOL fCreate, /* TRUE = RegCreateKey, FALSE = RegOpenKey */ |
| const CLSID* pclsid, /* CLSID */ |
| LPCWSTR lpszPathFromCLSID ) /* related path from CLSID */ |
| { |
| WCHAR szKey[ 1024 ]; |
| HRESULT hr; |
| LONG lr; |
| |
| hr = QUARTZ_CreateCLSIDPath( |
| szKey, NUMELEMS(szKey), |
| pclsid, lpszPathFromCLSID ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| lr = QUARTZ_RegOpenKeyW( |
| HKEY_CLASSES_ROOT, szKey, rsAccess, phKey, fCreate ); |
| if ( lr != ERROR_SUCCESS ) |
| return E_FAIL; |
| |
| return S_OK; |
| } |
| |
| |
| |
| HRESULT QUARTZ_RegisterAMovieDLLServer( |
| const CLSID* pclsid, /* [IN] CLSID */ |
| LPCWSTR lpFriendlyName, /* [IN] Friendly name */ |
| LPCWSTR lpNameOfDLL, /* [IN] name of the registered DLL */ |
| BOOL fRegister ) /* [IN] TRUE = register, FALSE = unregister */ |
| { |
| HRESULT hr; |
| HKEY hKey; |
| |
| if ( fRegister ) |
| { |
| hr = QUARTZ_OpenCLSIDKey( |
| &hKey, KEY_ALL_ACCESS, TRUE, |
| pclsid, NULL ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| if ( lpFriendlyName != NULL && QUARTZ_RegSetValueString( |
| hKey, NULL, lpFriendlyName ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| |
| RegCloseKey( hKey ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| hr = QUARTZ_OpenCLSIDKey( |
| &hKey, KEY_ALL_ACCESS, TRUE, |
| pclsid, QUARTZ_wszInprocServer32 ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| if ( QUARTZ_RegSetValueString( |
| hKey, NULL, lpNameOfDLL ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| if ( QUARTZ_RegSetValueString( |
| hKey, QUARTZ_wszThreadingModel, |
| QUARTZ_wszBoth ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| |
| RegCloseKey( hKey ); |
| if ( FAILED(hr) ) |
| return hr; |
| } |
| else |
| { |
| hr = QUARTZ_OpenCLSIDKey( |
| &hKey, KEY_ALL_ACCESS, FALSE, |
| pclsid, NULL ); |
| if ( FAILED(hr) ) |
| return NOERROR; |
| |
| RegDeleteValueW( hKey, NULL ); |
| RegDeleteValueW( hKey, QUARTZ_wszThreadingModel ); |
| |
| RegCloseKey( hKey ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| /* I think key should be deleted only if no subkey exists. */ |
| FIXME( "unregister %s - key should be removed!\n", |
| debugstr_guid(pclsid) ); |
| } |
| |
| return NOERROR; |
| } |
| |
| |
| HRESULT QUARTZ_RegisterCategory( |
| const CLSID* pguidFilterCategory, /* [IN] Category */ |
| LPCWSTR lpFriendlyName, /* [IN] friendly name */ |
| DWORD dwMerit, /* [IN] merit */ |
| BOOL fRegister ) /* [IN] TRUE = register, FALSE = unregister */ |
| { |
| HRESULT hr; |
| HKEY hKey; |
| WCHAR szFilterPath[ 256 ]; |
| WCHAR szCLSID[ 256 ]; |
| |
| QUARTZ_GUIDtoString( szCLSID, pguidFilterCategory ); |
| lstrcpyW( szFilterPath, QUARTZ_wszInstance ); |
| QUARTZ_CatPathSepW( szFilterPath ); |
| lstrcatW( szFilterPath, szCLSID ); |
| |
| if ( fRegister ) |
| { |
| hr = QUARTZ_OpenCLSIDKey( |
| &hKey, KEY_ALL_ACCESS, TRUE, |
| &CLSID_ActiveMovieCategories, szFilterPath ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| if ( QUARTZ_RegSetValueString( |
| hKey, QUARTZ_wszCLSID, szCLSID ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| if ( lpFriendlyName != NULL && QUARTZ_RegSetValueString( |
| hKey, QUARTZ_wszFriendlyName, |
| lpFriendlyName ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| if ( dwMerit != 0 && |
| QUARTZ_RegSetValueDWord( |
| hKey, QUARTZ_wszMerit, dwMerit ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| |
| RegCloseKey( hKey ); |
| if ( FAILED(hr) ) |
| return hr; |
| } |
| else |
| { |
| hr = QUARTZ_OpenCLSIDKey( |
| &hKey, KEY_ALL_ACCESS, FALSE, |
| &CLSID_ActiveMovieCategories, szFilterPath ); |
| if ( FAILED(hr) ) |
| return NOERROR; |
| |
| RegDeleteValueW( hKey, QUARTZ_wszCLSID ); |
| RegDeleteValueW( hKey, QUARTZ_wszFriendlyName ); |
| RegDeleteValueW( hKey, QUARTZ_wszMerit ); |
| |
| RegCloseKey( hKey ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| /* I think key should be deleted only if no subkey exists. */ |
| FIXME( "unregister category %s - key should be removed!\n", |
| debugstr_guid(pguidFilterCategory) ); |
| } |
| |
| return NOERROR; |
| } |
| |
| |
| HRESULT QUARTZ_RegisterAMovieFilter( |
| const CLSID* pguidFilterCategory, /* [IN] Category */ |
| const CLSID* pclsid, /* [IN] CLSID of this filter */ |
| const BYTE* pbFilterData, /* [IN] filter data(no spec) */ |
| DWORD cbFilterData, /* [IN] size of the filter data */ |
| LPCWSTR lpFriendlyName, /* [IN] friendly name */ |
| LPCWSTR lpInstance, /* [IN] instance */ |
| BOOL fRegister ) /* [IN] TRUE = register, FALSE = unregister */ |
| { |
| HRESULT hr; |
| HKEY hKey; |
| WCHAR szFilterPath[ 256 ]; |
| WCHAR szCLSID[ 256 ]; |
| |
| QUARTZ_GUIDtoString( szCLSID, pclsid ); |
| lstrcpyW( szFilterPath, QUARTZ_wszInstance ); |
| QUARTZ_CatPathSepW( szFilterPath ); |
| lstrcatW( szFilterPath, ( lpInstance != NULL ) ? lpInstance : szCLSID ); |
| |
| if ( fRegister ) |
| { |
| hr = QUARTZ_OpenCLSIDKey( |
| &hKey, KEY_ALL_ACCESS, TRUE, |
| pguidFilterCategory, szFilterPath ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| if ( QUARTZ_RegSetValueString( |
| hKey, QUARTZ_wszCLSID, szCLSID ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| if ( pbFilterData != NULL && cbFilterData > 0 && |
| QUARTZ_RegSetValueBinary( |
| hKey, QUARTZ_wszFilterData, |
| pbFilterData, cbFilterData ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| if ( lpFriendlyName != NULL && QUARTZ_RegSetValueString( |
| hKey, QUARTZ_wszFriendlyName, |
| lpFriendlyName ) != ERROR_SUCCESS ) |
| hr = E_FAIL; |
| |
| RegCloseKey( hKey ); |
| if ( FAILED(hr) ) |
| return hr; |
| } |
| else |
| { |
| hr = QUARTZ_OpenCLSIDKey( |
| &hKey, KEY_ALL_ACCESS, FALSE, |
| pguidFilterCategory, szFilterPath ); |
| if ( FAILED(hr) ) |
| return NOERROR; |
| |
| RegDeleteValueW( hKey, QUARTZ_wszCLSID ); |
| RegDeleteValueW( hKey, QUARTZ_wszFilterData ); |
| RegDeleteValueW( hKey, QUARTZ_wszFriendlyName ); |
| |
| RegCloseKey( hKey ); |
| if ( FAILED(hr) ) |
| return hr; |
| |
| /* I think key should be deleted only if no subkey exists. */ |
| FIXME( "unregister category %s filter %s - key should be removed!\n", |
| debugstr_guid(pguidFilterCategory), |
| debugstr_guid(pclsid) ); |
| } |
| |
| return NOERROR; |
| } |
| |
| |