2001-08-28 19:25:39 +02:00
|
|
|
/*
|
|
|
|
* Regster/Unregister servers. (for internal use)
|
|
|
|
*
|
2002-03-10 00:29:33 +01:00
|
|
|
* 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
|
2001-08-28 19:25:39 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "wingdi.h"
|
2001-09-07 21:46:49 +02:00
|
|
|
#include "winuser.h"
|
2001-08-28 19:25:39 +02:00
|
|
|
#include "winerror.h"
|
|
|
|
#include "winreg.h"
|
2001-09-07 21:46:49 +02:00
|
|
|
#include "uuids.h"
|
2001-08-28 19:25:39 +02:00
|
|
|
|
2002-03-10 00:29:33 +01:00
|
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
2001-08-28 19:25:39 +02:00
|
|
|
|
|
|
|
#include "regsvr.h"
|
|
|
|
|
2001-09-07 21:46:49 +02:00
|
|
|
#ifndef NUMELEMS
|
|
|
|
#define NUMELEMS(elem) (sizeof(elem)/sizeof((elem)[0]))
|
|
|
|
#endif /* NUMELEMS */
|
2001-08-28 19:25:39 +02:00
|
|
|
|
2001-10-28 22:16:00 +01:00
|
|
|
const WCHAR QUARTZ_wszREG_SZ[7] =
|
2001-09-07 21:46:49 +02:00
|
|
|
{'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[] =
|
2001-10-28 22:16:00 +01:00
|
|
|
{'F','i','l','t','e','r','D','a','t','a',0};
|
2001-09-07 21:46:49 +02:00
|
|
|
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};
|
2001-10-28 22:16:00 +01:00
|
|
|
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};
|
2001-09-07 21:46:49 +02:00
|
|
|
|
|
|
|
void QUARTZ_CatPathSepW( WCHAR* pBuf )
|
|
|
|
{
|
2001-10-14 18:13:14 +02:00
|
|
|
int len = lstrlenW(pBuf);
|
2001-09-07 21:46:49 +02:00
|
|
|
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,
|
2001-10-14 18:13:14 +02:00
|
|
|
sizeof(lpValue[0]) * (lstrlenW(lpValue)+1) );
|
2001-09-07 21:46:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
LONG QUARTZ_RegSetValueDWord(
|
|
|
|
HKEY hKey, LPCWSTR lpszName, DWORD dwValue )
|
2001-08-28 19:25:39 +02:00
|
|
|
{
|
2001-09-07 21:46:49 +02:00
|
|
|
return RegSetValueExW(
|
|
|
|
hKey, lpszName, 0, REG_DWORD,
|
|
|
|
(const BYTE*)(&dwValue), sizeof(DWORD) );
|
2001-08-28 19:25:39 +02:00
|
|
|
}
|
|
|
|
|
2001-09-07 21:46:49 +02:00
|
|
|
static
|
|
|
|
LONG QUARTZ_RegSetValueBinary(
|
|
|
|
HKEY hKey, LPCWSTR lpszName,
|
|
|
|
const BYTE* pData, int iLenOfData )
|
2001-08-28 19:25:39 +02:00
|
|
|
{
|
2001-09-07 21:46:49 +02:00
|
|
|
return RegSetValueExW(
|
|
|
|
hKey, lpszName, 0, REG_BINARY, pData, iLenOfData );
|
2001-08-28 19:25:39 +02:00
|
|
|
}
|
|
|
|
|
2001-09-07 21:46:49 +02:00
|
|
|
HRESULT QUARTZ_CreateCLSIDPath(
|
|
|
|
WCHAR* pwszBuf, DWORD dwBufLen,
|
|
|
|
const CLSID* pclsid,
|
|
|
|
LPCWSTR lpszPathFromCLSID )
|
|
|
|
{
|
|
|
|
int avail;
|
|
|
|
|
2001-10-14 18:13:14 +02:00
|
|
|
lstrcpyW( pwszBuf, QUARTZ_wszCLSID );
|
2001-09-07 21:46:49 +02:00
|
|
|
QUARTZ_CatPathSepW( pwszBuf+5 );
|
|
|
|
QUARTZ_GUIDtoString( pwszBuf+6, pclsid );
|
|
|
|
if ( lpszPathFromCLSID != NULL )
|
|
|
|
{
|
2001-10-14 18:13:14 +02:00
|
|
|
avail = (int)dwBufLen - lstrlenW(pwszBuf) - 8;
|
|
|
|
if ( avail <= lstrlenW(lpszPathFromCLSID) )
|
2001-09-07 21:46:49 +02:00
|
|
|
return E_FAIL;
|
|
|
|
QUARTZ_CatPathSepW( pwszBuf );
|
2001-10-14 18:13:14 +02:00
|
|
|
lstrcatW( pwszBuf, lpszPathFromCLSID );
|
2001-09-07 21:46:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return NOERROR;
|
|
|
|
}
|
2001-08-28 19:25:39 +02:00
|
|
|
|
2001-09-07 21:46:49 +02:00
|
|
|
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 */
|
2001-08-28 19:25:39 +02:00
|
|
|
{
|
2001-09-07 21:46:49 +02:00
|
|
|
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;
|
2001-08-28 19:25:39 +02:00
|
|
|
}
|
|
|
|
|
2001-09-07 21:46:49 +02:00
|
|
|
|
|
|
|
|
|
|
|
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 */
|
2001-08-28 19:25:39 +02:00
|
|
|
{
|
2001-09-07 21:46:49 +02:00
|
|
|
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 );
|
2001-10-14 18:13:14 +02:00
|
|
|
lstrcpyW( szFilterPath, QUARTZ_wszInstance );
|
2001-09-07 21:46:49 +02:00
|
|
|
QUARTZ_CatPathSepW( szFilterPath );
|
2001-10-14 18:13:14 +02:00
|
|
|
lstrcatW( szFilterPath, szCLSID );
|
2001-09-07 21:46:49 +02:00
|
|
|
|
|
|
|
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 );
|
2001-10-14 18:13:14 +02:00
|
|
|
lstrcpyW( szFilterPath, QUARTZ_wszInstance );
|
2001-09-07 21:46:49 +02:00
|
|
|
QUARTZ_CatPathSepW( szFilterPath );
|
2001-10-14 18:13:14 +02:00
|
|
|
lstrcatW( szFilterPath, ( lpInstance != NULL ) ? lpInstance : szCLSID );
|
2001-09-07 21:46:49 +02:00
|
|
|
|
|
|
|
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;
|
2001-08-28 19:25:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|