Initial commit: Complete open-source Decal rebuild
All 5 phases of the open-source Decal rebuild: Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil) Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters - Decal.Core, DecalControls, DecalRender, D3DService Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL Phase 4: DenAgent WinForms tray application Phase 5: WiX installer and build script 25 C# projects building with 0 errors. Native C++ projects require VS 2022 + Windows SDK (x86). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
d1442e3747
1382 changed files with 170725 additions and 0 deletions
194
Native/Decal/ActiveXSurrogate.cpp
Normal file
194
Native/Decal/ActiveXSurrogate.cpp
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// ActiveXSurrogate.cpp : Implementation of cActiveXSurrogate
|
||||
#include "stdafx.h"
|
||||
#include "Decal.h"
|
||||
#include "ActiveXSurrogate.h"
|
||||
|
||||
// Duplicated from Inject.h to prevent circular dependency
|
||||
class IPluginSite;
|
||||
|
||||
class __declspec(uuid("{BA3E677F-8E44-4829-982E-58BBBC5C5F9B}")) IPlugin
|
||||
: public IUnknown
|
||||
{
|
||||
public:
|
||||
STDMETHOD(Initialize)(IPluginSite *pSite, long) = 0;
|
||||
STDMETHOD(Terminate)() = 0;
|
||||
STDMETHOD(get_FriendlyName)(BSTR *pstrName) = 0;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// cActiveXSurrogate
|
||||
|
||||
typedef HRESULT (__stdcall *pfnDllRegisterServer)();
|
||||
typedef HRESULT (__stdcall *pfnDllUnregisterServer)();
|
||||
|
||||
STDMETHODIMP cActiveXSurrogate::Register(BSTR strFilename)
|
||||
{
|
||||
USES_CONVERSION;
|
||||
LPCTSTR szFilename = OLE2T( strFilename );
|
||||
|
||||
// First, register the library
|
||||
HMODULE hLib = ::LoadLibrary( szFilename );
|
||||
if( hLib == NULL )
|
||||
return E_FAIL;
|
||||
|
||||
pfnDllRegisterServer pfnReg = reinterpret_cast< pfnDllRegisterServer >( ::GetProcAddress( hLib, _T( "DllRegisterServer" ) ) );
|
||||
HRESULT hRes = E_FAIL;
|
||||
if( pfnReg != NULL )
|
||||
hRes = pfnReg();
|
||||
|
||||
::FreeLibrary( hLib );
|
||||
|
||||
if( FAILED( hRes ) )
|
||||
return hRes;
|
||||
|
||||
// Next open up the type library and look for suitable classes, they have
|
||||
// to be creatable - then we make one and see if it implements IPlugin2
|
||||
CComPtr< ITypeLib > pTypeLib;
|
||||
hRes = ::LoadTypeLib( strFilename, &pTypeLib );
|
||||
|
||||
if( FAILED( hRes ) )
|
||||
return hRes;
|
||||
|
||||
UINT nTypeInfoCount = pTypeLib->GetTypeInfoCount();
|
||||
int nFound = 0;
|
||||
|
||||
for( UINT i = 0; i < nTypeInfoCount; ++ i )
|
||||
{
|
||||
TYPEKIND tk;
|
||||
pTypeLib->GetTypeInfoType( i, &tk );
|
||||
|
||||
if( tk != TKIND_COCLASS )
|
||||
// Only coclasses
|
||||
continue;
|
||||
|
||||
CComPtr< ITypeInfo > pClass1;
|
||||
pTypeLib->GetTypeInfo( i, &pClass1 );
|
||||
|
||||
TYPEATTR *pta;
|
||||
pClass1->GetTypeAttr( &pta );
|
||||
|
||||
if( pta->wTypeFlags & TYPEFLAG_FCANCREATE )
|
||||
{
|
||||
// Create an instance of the plugin and see if it implements IPlugin
|
||||
CComPtr< IUnknown > pUnkPlugin;
|
||||
HRESULT hRes = pClass1->CreateInstance ( NULL, IID_IUnknown, reinterpret_cast< LPVOID * > ( &pUnkPlugin ) );
|
||||
if ( SUCCEEDED ( hRes ) )
|
||||
{
|
||||
// Check for the IPlugin2 interface
|
||||
CComPtr< IPlugin2 > pPlugin2;
|
||||
if ( SUCCEEDED ( pUnkPlugin->QueryInterface ( &pPlugin2 ) ) )
|
||||
{
|
||||
// This is a plugin (anything that implements IPlugin2 is a plugin afterall, make the registry key
|
||||
LPCSTR szCLSID;
|
||||
LPOLESTR strCLSID;
|
||||
::StringFromCLSID( pta->guid, &strCLSID );
|
||||
szCLSID = OLE2T( strCLSID );
|
||||
::CoTaskMemFree( strCLSID );
|
||||
|
||||
TCHAR szRegKey[ 255 ];
|
||||
::_tcscat ( ::_tcscpy ( szRegKey, _T( "Software\\Decal\\Plugins\\" ) ), szCLSID );
|
||||
|
||||
RegKey key;
|
||||
key.Create( HKEY_LOCAL_MACHINE, szRegKey );
|
||||
|
||||
CComBSTR strDescription;
|
||||
pClass1->GetDocumentation( MEMBERID_NIL, NULL, &strDescription, NULL, NULL );
|
||||
|
||||
key.SetStringValue( NULL, OLE2T( strDescription ) );
|
||||
key.SetStringValue( _T("File"), szFilename );
|
||||
key.SetDWORDValue( _T( "Enabled" ), 1 );
|
||||
key.SetStringValue( _T("Uninstall"), _T( "{7559F22F-C56F-4621-AE08-9C354D799D4B}" ) );
|
||||
|
||||
++ nFound;
|
||||
}
|
||||
else
|
||||
{
|
||||
CComPtr< IPlugin > pPlugin;
|
||||
if ( SUCCEEDED( pUnkPlugin->QueryInterface ( &pPlugin ) ) )
|
||||
{
|
||||
// This is a V1 plugin - same registration, but use a surrogate
|
||||
LPCSTR szCLSID;
|
||||
LPOLESTR strCLSID;
|
||||
::StringFromCLSID( pta->guid, &strCLSID );
|
||||
szCLSID = OLE2T( strCLSID );
|
||||
::CoTaskMemFree( strCLSID );
|
||||
|
||||
TCHAR szRegKey[ 255 ];
|
||||
::_tcscat ( ::_tcscpy ( szRegKey, _T( "Software\\Decal\\Plugins\\" ) ), szCLSID );
|
||||
|
||||
RegKey key;
|
||||
key.Create( HKEY_LOCAL_MACHINE, szRegKey );
|
||||
|
||||
CComBSTR strDescription;
|
||||
pPlugin->get_FriendlyName( &strDescription );
|
||||
|
||||
// Friendly name
|
||||
key.SetStringValue( NULL, OLE2T( strDescription ) );
|
||||
// File for uninstalling
|
||||
key.SetStringValue( _T( "File" ), szFilename );
|
||||
// Enabled by default
|
||||
key.SetDWORDValue( _T( "Enabled" ), 1 );
|
||||
// This object uninstalls
|
||||
key.SetStringValue( _T("Uninstall"), _T( "{7559F22F-C56F-4621-AE08-9C354D799D4B}" ));
|
||||
// The V1 surrogate
|
||||
key.SetStringValue( _T( "Surrogate" ), _T( "{3D837F6E-B5CA-4604-885F-7AB45FCFA62A}" ) );
|
||||
|
||||
++ nFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pClass1->ReleaseTypeAttr( pta );
|
||||
}
|
||||
|
||||
return ( nFound > 0 ) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP cActiveXSurrogate::Uninstall()
|
||||
{
|
||||
USES_CONVERSION;
|
||||
TCHAR szParent[ 255 ];
|
||||
::_tcscat ( ::_tcscpy ( szParent, _T( "Software\\Decal\\Plugins\\" ) ), OLE2T( m_strGroup ) );
|
||||
|
||||
RegKey rk;
|
||||
if( rk.Open( HKEY_LOCAL_MACHINE, szParent ) != ERROR_SUCCESS )
|
||||
{
|
||||
_ASSERT( FALSE );
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
LPOLESTR strCLSID;
|
||||
::StringFromCLSID( m_clsid, &strCLSID );
|
||||
|
||||
LPTSTR szCLSID = OLE2T( strCLSID );
|
||||
|
||||
::CoTaskMemFree( strCLSID );
|
||||
|
||||
if( rk.RecurseDeleteKey( szCLSID ) != ERROR_SUCCESS )
|
||||
{
|
||||
_ASSERT( FALSE );
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Load the library and call DLL unreg server
|
||||
LPCTSTR szFilename = OLE2T( m_strFile );
|
||||
|
||||
// First, register the library
|
||||
HMODULE hLib = ::LoadLibrary( szFilename );
|
||||
if( hLib == NULL )
|
||||
return E_FAIL;
|
||||
|
||||
pfnDllUnregisterServer pfnReg = reinterpret_cast< pfnDllUnregisterServer >( ::GetProcAddress( hLib, _T( "DllUnregisterServer" ) ) );
|
||||
HRESULT hRes = E_FAIL;
|
||||
if( pfnReg != NULL )
|
||||
hRes = pfnReg();
|
||||
|
||||
::FreeLibrary( hLib );
|
||||
|
||||
// Just call this to make sure the library isn't locked so the user
|
||||
// can delete it after this point.
|
||||
::CoFreeUnusedLibraries();
|
||||
|
||||
return hRes;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue