/*
 * Regster/Unregister servers. (for internal use)
 *
 * hidenori@a2.ctktv.ne.jp
 */

#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 "debugtools.h"
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;
}


