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
691
Native/DenAgent/DenAgent.cpp
Normal file
691
Native/DenAgent/DenAgent.cpp
Normal file
|
|
@ -0,0 +1,691 @@
|
|||
// DenAgent.cpp : Defines the class behaviors for the application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DenAgent.h"
|
||||
#include "DenAgentDlg.h"
|
||||
|
||||
#include "TrayWnd.h"
|
||||
#include <initguid.h>
|
||||
#include "DenAgent_i.c"
|
||||
#include "..\Inject\Inject.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
//FILELIST g_FileList[] = { { "messages.xml", "messages.dlc" }, { "memlocs.xml", "messages.dlc" }, { "decalplugins.xml", "messages.dlc" } };
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDenAgentApp
|
||||
|
||||
BEGIN_MESSAGE_MAP(CDenAgentApp, CWinApp)
|
||||
//{{AFX_MSG_MAP(CDenAgentApp)
|
||||
// NOTE - the ClassWizard will add and remove mapping macros here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code!
|
||||
//}}AFX_MSG
|
||||
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDenAgentApp construction
|
||||
|
||||
CDenAgentApp::CDenAgentApp()
|
||||
{
|
||||
// TODO: add construction code here,
|
||||
// Place all significant initialization in InitInstance
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// The one and only CDenAgentApp object
|
||||
|
||||
CDenAgentApp theApp;
|
||||
LONG g_fAbortDownload;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CDenAgentApp initialization
|
||||
|
||||
bool CheckForHardwareMode ()
|
||||
{
|
||||
RegKey key;
|
||||
|
||||
if (key.Open (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Microsoft Games\\Asheron's Call\\1.00", KEY_READ) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwValue = 0;
|
||||
|
||||
if (key.QueryDWORDValue ("UseHardware", dwValue) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return dwValue ? true : false;
|
||||
}
|
||||
|
||||
bool CheckForIE5OrLater ()
|
||||
{
|
||||
RegKey key;
|
||||
|
||||
if (key.Open (HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Internet Explorer", KEY_READ) != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
DWORD dwValue = 0;
|
||||
|
||||
TCHAR szVersionBuffer[256];
|
||||
DWORD dwSize = sizeof (szVersionBuffer);
|
||||
|
||||
if (key.QueryStringValue("Version", szVersionBuffer, &dwSize) != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
DWORD dwMajor = 0, dwMinor = 0, dwBuild1 = 0, dwBuild2 = 0;
|
||||
|
||||
if (::_stscanf (szVersionBuffer, _T("%ld.%ld.%ld.%ld"), &dwMajor, &dwMinor, &dwBuild1, &dwBuild2) != 4)
|
||||
return false;
|
||||
|
||||
// IE 5.01 is build: 5.00.2919.6307
|
||||
return !( dwMajor < 5 || ( dwMajor == 5 && dwMinor == 0 ) && ( ( dwBuild1 < 2919 ) || ( dwBuild1 == 2919 && dwBuild2 < 6307 ) ) );
|
||||
}
|
||||
|
||||
bool CDenAgentApp::getVersionString ( LPCTSTR szFilename, CString &strVersion )
|
||||
{
|
||||
DWORD dwDummy,
|
||||
dwVerSize = ::GetFileVersionInfoSize( const_cast< LPTSTR > ( szFilename ), &dwDummy );
|
||||
if( dwVerSize == 0 )
|
||||
return false;
|
||||
|
||||
BYTE *pbVersionInfo = reinterpret_cast< BYTE * >( ::_alloca( dwVerSize ) );
|
||||
|
||||
::GetFileVersionInfo( const_cast< LPTSTR > ( szFilename ), 0, dwVerSize, pbVersionInfo );
|
||||
|
||||
VS_FIXEDFILEINFO *vffi;
|
||||
UINT nLength = sizeof( VS_FIXEDFILEINFO );
|
||||
if( !::VerQueryValue( pbVersionInfo, _T( "\\" ), reinterpret_cast< LPVOID * >( &vffi ), &nLength ) )
|
||||
return false;
|
||||
|
||||
// Got it, so format it
|
||||
strVersion.FormatMessage ( IDS_VERSIONTEMPLATE, static_cast< int > ( HIWORD ( vffi->dwFileVersionMS ) ),
|
||||
static_cast< int > ( LOWORD ( vffi->dwFileVersionMS ) ), static_cast< int > ( HIWORD ( vffi->dwFileVersionLS ) ),
|
||||
static_cast< int > ( LOWORD ( vffi->dwFileVersionLS ) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDenAgentApp::getVersionInfo ( LPCTSTR szFilename, int &iReleaseMajor, int &iReleaseMinor, int &iBuildMajor, int &iBuildMinor )
|
||||
{
|
||||
DWORD dwDummy,
|
||||
dwVerSize = ::GetFileVersionInfoSize( const_cast< LPTSTR > ( szFilename ), &dwDummy );
|
||||
if( dwVerSize == 0 )
|
||||
return false;
|
||||
|
||||
BYTE *pbVersionInfo = reinterpret_cast< BYTE * >( ::_alloca( dwVerSize ) );
|
||||
|
||||
::GetFileVersionInfo( const_cast< LPTSTR > ( szFilename ), 0, dwVerSize, pbVersionInfo );
|
||||
|
||||
VS_FIXEDFILEINFO *vffi;
|
||||
UINT nLength = sizeof( VS_FIXEDFILEINFO );
|
||||
if( !::VerQueryValue( pbVersionInfo, _T( "\\" ), reinterpret_cast< LPVOID * >( &vffi ), &nLength ) )
|
||||
return false;
|
||||
|
||||
// Got it, so format it
|
||||
iReleaseMajor = static_cast< int > ( HIWORD ( vffi->dwFileVersionMS ) );
|
||||
iReleaseMinor = static_cast< int > ( LOWORD ( vffi->dwFileVersionMS ) );
|
||||
iBuildMajor = static_cast< int > ( HIWORD ( vffi->dwFileVersionLS ) );
|
||||
iBuildMinor = static_cast< int > ( LOWORD ( vffi->dwFileVersionLS ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDenAgentApp::getACVersionString ( CString &strVersion )
|
||||
{
|
||||
RegKey rk;
|
||||
if ( rk.Open ( HKEY_LOCAL_MACHINE, _T( "Software\\Microsoft\\Microsoft Games\\Asheron's Call\\1.00" ) ) != ERROR_SUCCESS )
|
||||
{
|
||||
::AfxMessageBox ( IDE_NOCLIENTEXE, MB_ICONWARNING );
|
||||
return false;
|
||||
}
|
||||
|
||||
TCHAR szClientPath[ MAX_PATH ];
|
||||
DWORD dwPathLength = MAX_PATH;
|
||||
if ( rk.QueryStringValue ( _T( "path" ), szClientPath, &dwPathLength ) != ERROR_SUCCESS )
|
||||
{
|
||||
::AfxMessageBox ( IDE_NOCLIENTEXE, MB_ICONWARNING );
|
||||
return false;
|
||||
}
|
||||
|
||||
::_tcscpy ( szClientPath + ( dwPathLength - 1 ), _T( "\\client.exe" ) );
|
||||
|
||||
bool bHasVersion = getVersionString ( szClientPath, strVersion );
|
||||
|
||||
if ( !bHasVersion )
|
||||
::AfxMessageBox ( IDE_NOCLIENTVER, MB_ICONWARNING );
|
||||
|
||||
return bHasVersion;
|
||||
}
|
||||
|
||||
bool CDenAgentApp::getCOMObjectDLL ( REFCLSID rclsid, CString &strFilename )
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
LPOLESTR oclsid;
|
||||
HRESULT hRes = ::StringFromCLSID ( rclsid, &oclsid );
|
||||
_ASSERTE ( SUCCEEDED ( hRes ) );
|
||||
LPCTSTR clsidName = OLE2T ( oclsid );
|
||||
::CoTaskMemFree ( oclsid );
|
||||
|
||||
TCHAR keyName[ MAX_PATH ];
|
||||
::_stprintf ( keyName, _T( "CLSID\\%s\\InprocServer32" ), clsidName );
|
||||
|
||||
RegKey rk;
|
||||
if ( rk.Open ( HKEY_CLASSES_ROOT, keyName ) != ERROR_SUCCESS )
|
||||
return false;
|
||||
|
||||
DWORD dwPathSize = MAX_PATH;
|
||||
|
||||
long regResult = rk.QueryStringValue ( NULL, strFilename.GetBuffer ( MAX_PATH ), &dwPathSize );
|
||||
|
||||
strFilename.ReleaseBuffer();
|
||||
|
||||
if (regResult != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
// Check to see if the default KeyValue points to the MS.NET core DLL
|
||||
const char *dotNetProxy = "mscoree.dll";
|
||||
|
||||
CString dotNetMatchString = strFilename.Right(strlen(dotNetProxy));
|
||||
|
||||
if (dotNetMatchString.CompareNoCase(dotNetProxy) == 0)
|
||||
{
|
||||
// Get CodeBase KeyValue - Should point to the Plugin DLL
|
||||
dwPathSize = MAX_PATH;
|
||||
if (rk.QueryStringValue ( "CodeBase", strFilename.GetBuffer ( MAX_PATH ), &dwPathSize ) == ERROR_SUCCESS)
|
||||
{
|
||||
// Release extra buffer (Not doing this seem to cause the Left() and Delete() funcs to fail)
|
||||
strFilename.ReleaseBuffer();
|
||||
// Check for garbage in KeyValue and delete it
|
||||
if (strFilename.Left(8) == "file:///")
|
||||
strFilename.Delete(0,8);
|
||||
}
|
||||
else
|
||||
{
|
||||
// CodeBase isn't accessable - Possible that plugin is in GAC
|
||||
// Return Path to MS.NET core DLL
|
||||
dwPathSize = MAX_PATH;
|
||||
if (rk.QueryStringValue ( NULL, strFilename.GetBuffer ( MAX_PATH ), &dwPathSize ) != ERROR_SUCCESS)
|
||||
{
|
||||
rk.Close();
|
||||
strFilename.ReleaseBuffer();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
rk.Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDenAgentApp::getAgentPath ( LPCTSTR szFilename, CString &strPath )
|
||||
{
|
||||
TCHAR *szAgentPath = strPath.GetBuffer ( MAX_PATH );
|
||||
::GetModuleFileName ( NULL, szAgentPath, MAX_PATH );
|
||||
|
||||
TCHAR *filePath = ::_tcsrchr ( szAgentPath, _T( '\\' ) );
|
||||
::strcpy ( filePath + 1, szFilename );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDenAgentApp::checkXMLVersion ( CString &strClientVersion, CString &strXMLFile, CTrayWnd* pTrayWnd )
|
||||
{
|
||||
MSXML::IXMLDOMDocumentPtr pDoc;
|
||||
|
||||
try
|
||||
{
|
||||
pDoc.CreateInstance ( __uuidof ( MSXML::DOMDocument ), NULL, CLSCTX_INPROC_SERVER );
|
||||
pDoc->async = false;
|
||||
BOOL bSuccess = pDoc->load( static_cast< LPCTSTR > ( strXMLFile ) );
|
||||
|
||||
if( !bSuccess )
|
||||
{
|
||||
std::string szXML;
|
||||
DecryptXML( static_cast< LPCSTR >( strXMLFile ), szXML );
|
||||
|
||||
if( szXML != "" )
|
||||
bSuccess = pDoc->loadXML( _bstr_t( szXML.c_str() ) );
|
||||
}
|
||||
|
||||
if( ! bSuccess )
|
||||
{
|
||||
CString strMessage;
|
||||
strMessage.FormatMessage ( IDE_NOXMLDOC, static_cast< LPCTSTR > ( strXMLFile ) );
|
||||
|
||||
CString strUpdate;
|
||||
strUpdate.LoadString( IDE_UPDATETEXT );
|
||||
strMessage += strUpdate;
|
||||
|
||||
if ( ::AfxMessageBox ( strMessage, MB_YESNO | MB_ICONERROR ) == IDYES )
|
||||
pTrayWnd->UpdateXMLFiles( );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the client version string
|
||||
MSXML::IXMLDOMNodePtr pVersionNode = pDoc->selectSingleNode ( _T( "/*/@version" ) );
|
||||
if ( pVersionNode == NULL )
|
||||
{
|
||||
CString strError;
|
||||
|
||||
strError.FormatMessage ( IDE_NOXMLVER, static_cast< LPCTSTR > ( strXMLFile ) );
|
||||
::AfxMessageBox ( strError, MB_ICONWARNING );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_variant_t vXMLVer = pVersionNode->text;
|
||||
if ( vXMLVer.vt != VT_BSTR )
|
||||
{
|
||||
CString strError;
|
||||
|
||||
strError.FormatMessage ( IDE_NOXMLVER, static_cast< LPCTSTR > ( strXMLFile ) );
|
||||
::AfxMessageBox ( strError, MB_ICONWARNING );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CString strXMLVer ( vXMLVer.bstrVal );
|
||||
if ( strClientVersion.Compare ( strXMLVer ) != 0 )
|
||||
{
|
||||
CString str;
|
||||
str.FormatMessage ( IDE_XMLCLIENTVERSIONMISMATCH, static_cast< LPCTSTR > ( strXMLFile ),
|
||||
static_cast< LPCTSTR > ( strClientVersion ), static_cast< LPCTSTR > ( strXMLVer ) );
|
||||
|
||||
CString strUpdate;
|
||||
strUpdate.LoadString( IDE_UPDATETEXT );
|
||||
str += strUpdate;
|
||||
|
||||
if ( ::AfxMessageBox ( str, MB_YESNO | MB_ICONWARNING ) == IDYES )
|
||||
pTrayWnd->UpdateXMLFiles( );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch ( _com_error & )
|
||||
{
|
||||
CString strMessage;
|
||||
strMessage.FormatMessage ( IDE_NOXMLDOC, static_cast< LPCTSTR > ( strXMLFile ) );
|
||||
::AfxMessageBox ( strMessage, MB_ICONERROR );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDenAgentApp::DecryptXML( const char *szPath, std::string &szXML )
|
||||
{
|
||||
if( szPath == NULL )
|
||||
{
|
||||
szXML = "";
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *f = fopen( szPath, "rb" );
|
||||
if( f == NULL )
|
||||
{
|
||||
szXML = "";
|
||||
return;
|
||||
}
|
||||
|
||||
szXML.clear();
|
||||
unsigned char szBuffer[1025];
|
||||
|
||||
try
|
||||
{
|
||||
CCryptProv crypt;
|
||||
if( crypt.Initialize( PROV_RSA_FULL, "Decal_Memlocs", MS_DEF_PROV ) == NTE_BAD_KEYSET )
|
||||
crypt.Initialize( PROV_RSA_FULL, "Decal_Memlocs", MS_DEF_PROV, CRYPT_NEWKEYSET );
|
||||
|
||||
CCryptMD5Hash hash;
|
||||
hash.Initialize( crypt );
|
||||
hash.AddString( DECAL_KEY );
|
||||
|
||||
CCryptDerivedKey key;
|
||||
key.Initialize( crypt, hash );
|
||||
|
||||
DWORD dwDecLen = 0;
|
||||
|
||||
while( ! feof(f) )
|
||||
{
|
||||
memset( szBuffer, 0, sizeof( szBuffer ) );
|
||||
dwDecLen = fread( szBuffer, 1, 1024, f );
|
||||
key.Decrypt( feof(f), (BYTE *) szBuffer, &dwDecLen );
|
||||
szXML += (char *)szBuffer;
|
||||
}
|
||||
|
||||
key.Destroy();
|
||||
hash.Destroy();
|
||||
crypt.Release();
|
||||
}
|
||||
|
||||
catch( ... )
|
||||
{
|
||||
// crap...
|
||||
szXML = "";
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
bool CDenAgentApp::checkXMLVersions ( CTrayWnd* pTrayWnd )
|
||||
{
|
||||
bool bOK = true;
|
||||
// Check the versions of the XML files
|
||||
CString strClientVersion;
|
||||
if ( getACVersionString ( strClientVersion ) )
|
||||
{
|
||||
CString strXMLFile;
|
||||
if ( getAgentPath ( _T( "memlocs.xml" ), strXMLFile ) )
|
||||
bOK = bOK && checkXMLVersion ( strClientVersion, strXMLFile, pTrayWnd );
|
||||
//if ( getAgentPath ( _T( "messages.xml" ), strXMLFile ) )
|
||||
//bOK = bOK && checkXMLVersion ( strClientVersion, strXMLFile );
|
||||
}
|
||||
|
||||
return bOK;
|
||||
}
|
||||
|
||||
void CDenAgentApp::getXMLBuilds ( cXMLBuild *pFirst, cXMLBuild *pLast )
|
||||
{
|
||||
MSXML::IXMLDOMDocumentPtr pDoc;
|
||||
pDoc.CreateInstance ( __uuidof ( MSXML::DOMDocument ), NULL, CLSCTX_INPROC_SERVER );
|
||||
pDoc->async = false;
|
||||
|
||||
for ( ; pFirst != pLast; ++ pFirst )
|
||||
{
|
||||
CString strPath;
|
||||
getAgentPath ( pFirst->XMLFile, strPath );
|
||||
|
||||
try
|
||||
{
|
||||
BOOL bSuccess = pDoc->load( static_cast< LPCTSTR > ( pFirst->XMLFile ) );
|
||||
|
||||
if( ! bSuccess )
|
||||
{
|
||||
std::string szXML;
|
||||
DecryptXML( static_cast< LPCSTR >( pFirst->XMLFile ), szXML );
|
||||
|
||||
if( szXML != "" )
|
||||
bSuccess = pDoc->loadXML( _bstr_t( szXML.c_str() ) );
|
||||
}
|
||||
|
||||
if( ! bSuccess )
|
||||
{
|
||||
CString strMessage;
|
||||
strMessage.FormatMessage( IDE_NOXMLDOC, pFirst->XMLFile );
|
||||
::AfxMessageBox ( strMessage, MB_ICONERROR );
|
||||
|
||||
pFirst->build = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read the client version string
|
||||
MSXML::IXMLDOMNodePtr pBuildNode = pDoc->selectSingleNode ( _T( "/*/@build" ) );
|
||||
if ( pBuildNode == NULL )
|
||||
{
|
||||
pFirst->build = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
pFirst->build = pBuildNode->GetnodeValue ();
|
||||
}
|
||||
catch ( _com_error & )
|
||||
{
|
||||
pFirst->build = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CDenAgentApp::InitInstance()
|
||||
{
|
||||
HWND hDenAgent = FindWindow(NULL, "Decal Agent");
|
||||
|
||||
if(hDenAgent)
|
||||
{
|
||||
::MessageBox(hDenAgent, "Decal is already running!", "Decal", 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!CheckForHardwareMode ())
|
||||
{
|
||||
::MessageBox
|
||||
(
|
||||
NULL,
|
||||
_T("Decal requires Asheron's Call to be installed with hardware 3d acceleration enabled! Decal will run, but will be unable to display any UI in-game."),
|
||||
_T("Decal Agent Startup Warning"),
|
||||
MB_OK
|
||||
);
|
||||
}
|
||||
|
||||
if (!CheckForIE5OrLater ())
|
||||
{
|
||||
::MessageBox
|
||||
(
|
||||
NULL,
|
||||
"Decal requires Internet Explorer 5.01 or later!",
|
||||
"Decal Agent Startup Error",
|
||||
MB_OK
|
||||
);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!InitATL())
|
||||
return FALSE;
|
||||
|
||||
|
||||
CCommandLineInfo cmdInfo;
|
||||
ParseCommandLine(cmdInfo);
|
||||
|
||||
if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Set our current directory to the path of DenAgent.exe
|
||||
// TODO: Fix all the code so that it doesn't rely on the current directory
|
||||
TCHAR szAppPath[MAX_PATH];
|
||||
::memset (szAppPath, 0, sizeof (szAppPath));
|
||||
::GetModuleFileName (0, szAppPath, MAX_PATH);
|
||||
|
||||
TCHAR *szLastSlash = ::_tcsrchr (szAppPath, _T('\\'));
|
||||
if (szLastSlash)
|
||||
{
|
||||
*szLastSlash = 0;
|
||||
::SetCurrentDirectory (szAppPath);
|
||||
}
|
||||
|
||||
// Move V1 plugins into the V2 registry format
|
||||
importV1Plugins ();
|
||||
|
||||
// Standard initialization
|
||||
// If you are not using these features and wish to reduce the size
|
||||
// of your final executable, you should remove from the following
|
||||
// the specific initialization routines you do not need.
|
||||
m_pTrayWnd = new CTrayWnd;
|
||||
m_pMainWnd = m_pTrayWnd;
|
||||
|
||||
m_pTrayWnd->CreateEx( 0, ::AfxRegisterWndClass( 0, NULL, NULL, NULL ), _T( "Decal Agent" ), WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL );
|
||||
|
||||
checkXMLVersions ( m_pTrayWnd );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
CDenAgentModule _Module;
|
||||
|
||||
BEGIN_OBJECT_MAP(ObjectMap)
|
||||
END_OBJECT_MAP()
|
||||
|
||||
LONG CDenAgentModule::Unlock()
|
||||
{
|
||||
AfxOleUnlockApp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LONG CDenAgentModule::Lock()
|
||||
{
|
||||
AfxOleLockApp();
|
||||
return 1;
|
||||
}
|
||||
LPCTSTR CDenAgentModule::FindOneOf(LPCTSTR p1, LPCTSTR p2)
|
||||
{
|
||||
while (*p1 != NULL)
|
||||
{
|
||||
LPCTSTR p = p2;
|
||||
while (*p != NULL)
|
||||
{
|
||||
if (*p1 == *p)
|
||||
return CharNext(p1);
|
||||
p = CharNext(p);
|
||||
}
|
||||
p1++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CDenAgentApp::ExitInstance()
|
||||
{
|
||||
delete m_pTrayWnd;
|
||||
|
||||
if (m_bATLInited)
|
||||
{
|
||||
_Module.RevokeClassObjects();
|
||||
_Module.Term();
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
return CWinApp::ExitInstance();
|
||||
|
||||
}
|
||||
|
||||
void CDenAgentApp::importV1Plugins ()
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
RegKey hkGroup;
|
||||
if ( hkGroup.Open ( HKEY_LOCAL_MACHINE, _T ( "Software\\Decal\\Plugins" ) ) != ERROR_SUCCESS )
|
||||
// No plugins - no problem
|
||||
return;
|
||||
|
||||
DWORD dwValues = 0;
|
||||
::RegQueryInfoKey ( hkGroup, NULL, NULL, NULL, NULL, NULL, NULL, &dwValues, NULL, NULL, NULL, NULL );
|
||||
|
||||
// Now - iterate through the values backwards
|
||||
for ( int i = dwValues - 1; i >= 0; -- i )
|
||||
{
|
||||
TCHAR szCLSID[ 64 ];
|
||||
DWORD dwCLSID = sizeof ( szCLSID );
|
||||
DWORD dwEnabled;
|
||||
DWORD dwEnabledSize = sizeof ( dwEnabled );
|
||||
|
||||
if ( ::RegEnumValue ( hkGroup, i, szCLSID, &dwCLSID, NULL, NULL, reinterpret_cast< BYTE * > ( &dwEnabled ), &dwEnabledSize ) != ERROR_SUCCESS )
|
||||
continue;
|
||||
|
||||
// Try and convert the name to a CLSID
|
||||
CLSID clsidPlugin;
|
||||
HRESULT hRes = ::CLSIDFromString ( T2OLE ( szCLSID ), &clsidPlugin );
|
||||
if ( FAILED ( hRes ) )
|
||||
continue;
|
||||
|
||||
// Delete the value and ask questions later
|
||||
hkGroup.DeleteValue ( szCLSID );
|
||||
|
||||
// Try and create a key to extract the friendly name
|
||||
CComPtr< IPlugin > pPlugin;
|
||||
hRes = ::CoCreateInstance ( clsidPlugin, NULL, CLSCTX_INPROC_SERVER, __uuidof ( IPlugin ),
|
||||
reinterpret_cast< LPVOID * > ( &pPlugin ) );
|
||||
|
||||
if ( FAILED ( hRes ) )
|
||||
// Bad plugin - skip
|
||||
continue;
|
||||
|
||||
CComBSTR strName;
|
||||
pPlugin->get_FriendlyName ( &strName );
|
||||
|
||||
// Create the Real registry key
|
||||
// Key configuration copied from Decal/cActiveXSurrogate::Register
|
||||
RegKey hkeyItem;
|
||||
if ( hkeyItem.Create ( hkGroup, szCLSID ) != ERROR_SUCCESS )
|
||||
continue;
|
||||
|
||||
// Friendly name
|
||||
hkeyItem.SetStringValue( NULL, OLE2T( strName ) );
|
||||
// Enabled by default
|
||||
hkeyItem.SetDWORDValue( _T( "Enabled" ), dwEnabled );
|
||||
// The V1 surrogate
|
||||
hkeyItem.SetStringValue( _T( "Surrogate" ), _T( "{3D837F6E-B5CA-4604-885F-7AB45FCFA62A}" ) );
|
||||
hkeyItem.Close();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CDenAgentApp::InitATL()
|
||||
{
|
||||
m_bATLInited = TRUE;
|
||||
|
||||
HRESULT hRes = CoInitialize(NULL);
|
||||
|
||||
if (FAILED(hRes))
|
||||
{
|
||||
m_bATLInited = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_Module.Init(ObjectMap, AfxGetInstanceHandle());
|
||||
_Module.dwThreadID = GetCurrentThreadId();
|
||||
|
||||
LPTSTR lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
|
||||
TCHAR szTokens[] = _T("-/");
|
||||
|
||||
BOOL bRun = TRUE;
|
||||
LPCTSTR lpszToken = _Module.FindOneOf(lpCmdLine, szTokens);
|
||||
while (lpszToken != NULL)
|
||||
{
|
||||
if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
|
||||
{
|
||||
_Module.UpdateRegistryFromResource(IDR_DENAGENT, FALSE);
|
||||
_Module.UnregisterServer(TRUE); //TRUE means typelib is unreg'd
|
||||
bRun = FALSE;
|
||||
break;
|
||||
}
|
||||
if (lstrcmpi(lpszToken, _T("RegServer"))==0)
|
||||
{
|
||||
_Module.UpdateRegistryFromResource(IDR_DENAGENT, TRUE);
|
||||
_Module.RegisterServer(TRUE);
|
||||
bRun = FALSE;
|
||||
break;
|
||||
}
|
||||
lpszToken = _Module.FindOneOf(lpszToken, szTokens);
|
||||
}
|
||||
|
||||
if (!bRun)
|
||||
{
|
||||
m_bATLInited = FALSE;
|
||||
_Module.Term();
|
||||
CoUninitialize();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
|
||||
REGCLS_MULTIPLEUSE);
|
||||
if (FAILED(hRes))
|
||||
{
|
||||
m_bATLInited = FALSE;
|
||||
CoUninitialize();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue