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>
844 lines
24 KiB
C++
844 lines
24 KiB
C++
// DenAgentDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "DenAgent.h"
|
|
#include "DenAgentDlg.h"
|
|
#include "DownloaderDlg.h"
|
|
#include "OptionsDlg.h"
|
|
#include "ExportDlg.h"
|
|
#include "TrayWnd.h"
|
|
#include "AutoUpdate.h"
|
|
|
|
#include "..\Inject\InjectApi.h"
|
|
|
|
#include "AddRemoveDlg.h"
|
|
#include ".\denagentdlg.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDenAgentDlg dialog
|
|
|
|
CDenAgentDlg::CDenAgentDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CDenAgentDlg::IDD, pParent),
|
|
m_pCurrentDrag ( NULL ), m_bDoingUpdate( false ), m_bDoUpdate( false )
|
|
{
|
|
//{{AFX_DATA_INIT(CDenAgentDlg)
|
|
//}}AFX_DATA_INIT
|
|
|
|
// Load the icon, unload will be done automagically
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_TRAYICON);
|
|
}
|
|
|
|
void CDenAgentDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CDenAgentDlg)
|
|
DDX_Control(pDX, IDC_PLUGINS, m_wndPlugins);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CDenAgentDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CDenAgentDlg)
|
|
ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
|
|
ON_BN_CLICKED(IDC_ADDREMOVE, OnAddremove)
|
|
ON_BN_CLICKED(IDC_UPDATE, OnUpdate)
|
|
ON_BN_CLICKED(IDC_OPTIONS, OnOptions)
|
|
ON_NOTIFY(LVN_DELETEITEM, IDC_PLUGINS, OnDeleteitemPlugins)
|
|
ON_NOTIFY(NM_CLICK, IDC_PLUGINS, OnClickPlugins)
|
|
ON_NOTIFY(LVN_BEGINDRAG, IDC_PLUGINS, OnBegindragPlugins)
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_LBUTTONUP()
|
|
//}}AFX_MSG_MAP
|
|
ON_BN_CLICKED(IDC_DELETE, OnBnClickedDelete)
|
|
ON_BN_CLICKED(IDC_EXPORT, OnBnClickedExport)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDenAgentDlg message handlers
|
|
|
|
BOOL CDenAgentDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
SetForegroundWindow();
|
|
BringWindowToTop();
|
|
|
|
// Create the decal object
|
|
HRESULT hRes = ::CoCreateInstance ( __uuidof ( Decal ), NULL, CLSCTX_INPROC_SERVER, __uuidof ( IDecal ),
|
|
reinterpret_cast< LPVOID * > ( &m_pDecal ) );
|
|
|
|
// Set up the list control and image list
|
|
m_groups.Create ( IDB_GROUPS, 16, 0, RGB(255,0,255));
|
|
m_wndPlugins.SetImageList ( &m_groups, LVSIL_SMALL );
|
|
|
|
// Prepare the column list
|
|
CRect rcListClient;
|
|
m_wndPlugins.GetClientRect ( rcListClient );
|
|
|
|
CClientDC dcList ( &m_wndPlugins );
|
|
dcList.SelectObject ( m_wndPlugins.GetFont () );
|
|
|
|
int nVersionWidth = dcList.GetTextExtent ( CString ( _T( "100.00.00.00001" ) ) ).cx;
|
|
|
|
m_wndPlugins.InsertColumn ( 0, _T( "Component" ), LVCFMT_LEFT, rcListClient.Width () - nVersionWidth - 16, 0 );
|
|
m_wndPlugins.InsertColumn ( 1, _T( "Version" ), LVCFMT_RIGHT, nVersionWidth, 1 );
|
|
|
|
m_wndPlugins.SetExtendedStyle ( LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP );
|
|
|
|
if ( FAILED ( hRes ) )
|
|
{
|
|
AfxMessageBox ( _T( "Failed to create Decal Object." ) );
|
|
EndDialog ( IDCANCEL );
|
|
return FALSE;
|
|
}
|
|
|
|
loadPluginList ();
|
|
|
|
// Set the icon into the window for runtime
|
|
SetIcon(m_hIcon, TRUE); // Set big icon
|
|
SetIcon(m_hIcon, FALSE); // Set small icon
|
|
|
|
TCHAR szModule[ MAX_PATH ];
|
|
::GetModuleFileName ( NULL, szModule, MAX_PATH );
|
|
|
|
CString strVersion;
|
|
CDenAgentApp::getVersionString ( szModule, strVersion );
|
|
CDenAgentApp::getVersionInfo ( szModule, iReleaseMajor, iReleaseMinor, iBuildMajor, iBuildMinor );
|
|
|
|
SetWindowText( CString("Decal Agent ") + strVersion );
|
|
|
|
updateFileInfo();
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
}
|
|
|
|
void CDenAgentDlg::OnRefresh()
|
|
{
|
|
loadPluginList ();
|
|
}
|
|
|
|
void CDenAgentDlg::OnAddremove()
|
|
{
|
|
CFile cf;
|
|
CFileStatus cfs;
|
|
|
|
RegKey key;
|
|
CString strDecalPlugins("decalplugins.xml");
|
|
|
|
if( key.Create( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Decal\\Agent" )) == ERROR_SUCCESS )
|
|
{
|
|
TCHAR szDecalDirectory[ MAX_PATH + 1];
|
|
DWORD dwSize = MAX_PATH;
|
|
|
|
if(key.QueryStringValue( _T( "AgentPath" ), szDecalDirectory, &dwSize )==ERROR_SUCCESS)
|
|
{
|
|
strDecalPlugins = CString(szDecalDirectory) + "\\decalplugins.xml";
|
|
}
|
|
}
|
|
|
|
if(!cf.GetStatus(strDecalPlugins, cfs))
|
|
{
|
|
if(MessageBox("Your list of Decal Components is missing.\n\nWould like to Download them?", NULL, MB_YESNO)==IDYES)
|
|
OnUpdate();
|
|
}
|
|
else
|
|
{
|
|
|
|
CTime modification_time = cfs.m_mtime;
|
|
CTime now = CTime::GetCurrentTime ();
|
|
|
|
if((modification_time.GetDay() < now.GetDay()) && (modification_time.GetMonth() <= now.GetMonth()) && (modification_time.GetYear() <= now.GetYear()))
|
|
if(MessageBox("Your list of Decal Components are outdated.\n\nWould you like to Update?", NULL, MB_YESNO)==IDYES)
|
|
{
|
|
m_bDoingUpdate = true;
|
|
OnUpdate();
|
|
}
|
|
}
|
|
|
|
cAddRemoveDlg dlg( this );
|
|
dlg.m_pDecal = m_pDecal;
|
|
dlg.DoModal ();
|
|
|
|
loadPluginList ();
|
|
}
|
|
|
|
int CDenAgentDlg::getDragInsertBefore ( CPoint &ptClient )
|
|
{
|
|
_ASSERTE ( m_pCurrentDrag != NULL );
|
|
|
|
CRect rc;
|
|
m_wndPlugins.GetWindowRect ( rc );
|
|
ScreenToClient ( rc );
|
|
|
|
ptClient.x = ptClient.x - rc.left;
|
|
ptClient.y = ptClient.y - rc.top;
|
|
|
|
int nItemHit = m_wndPlugins.HitTest ( ptClient );
|
|
|
|
if ( nItemHit != -1 )
|
|
{
|
|
cPlugin *pPlugin = reinterpret_cast< cPlugin * > ( m_wndPlugins.GetItemData ( nItemHit ) );
|
|
if ( pPlugin != NULL && pPlugin->m_dragimage == m_pCurrentDrag->m_dragimage )
|
|
return nItemHit;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Tries to update the local copy of decal
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CDenAgentDlg::updateDecal(_variant_t vCodeBase) {
|
|
USES_CONVERSION;
|
|
|
|
if (MessageBox("A New Version of Decal exists.\n\nWould you like to Update?",NULL, MB_ICONQUESTION | MB_YESNO) == IDYES) {
|
|
ShellExecute(m_hWnd,"open",OLE2A(vCodeBase.bstrVal),0,0,0);
|
|
EndDialog(0);
|
|
GetParent()->DestroyWindow();
|
|
PostQuitMessage(0);
|
|
}
|
|
}
|
|
|
|
struct cPluginGroup
|
|
{
|
|
LPCTSTR m_groupName,
|
|
m_groupKey;
|
|
int m_iconIndex;
|
|
};
|
|
|
|
void CDenAgentDlg::loadPluginList ()
|
|
{
|
|
m_wndPlugins.SetRedraw ( FALSE );
|
|
|
|
int nTop = m_wndPlugins.GetTopIndex ();
|
|
|
|
// Save the original selection
|
|
GUID idSelected = GUID_NULL;
|
|
{
|
|
POSITION pos = m_wndPlugins.GetFirstSelectedItemPosition ();
|
|
if ( pos != NULL )
|
|
{
|
|
int nSelected = m_wndPlugins.GetNextSelectedItem ( pos );
|
|
cPlugin *pPlugin = reinterpret_cast< cPlugin * > ( m_wndPlugins.GetItemData ( nSelected ) );
|
|
if ( pPlugin != NULL )
|
|
idSelected = pPlugin->m_id;
|
|
}
|
|
}
|
|
|
|
// Erase the contents of the list and collection
|
|
m_wndPlugins.DeleteAllItems ();
|
|
CDenAgentApp::importV1Plugins ();
|
|
|
|
USES_CONVERSION;
|
|
|
|
static cPluginGroup _groups[] = {
|
|
{ _T( "Plugins" ), _T( "Plugins" ), 4 },
|
|
{ _T( "Network Filters" ), _T( "NetworkFilters" ), 1 },
|
|
{ _T( "File Filters" ), _T( "FileFilters" ), 1 },
|
|
{ _T( "Services" ), _T( "Services" ), 0 },
|
|
{ _T( "Surrogates" ), _T( "Surrogates" ), 3 },
|
|
{ _T( "Input Actions" ), _T( "InputActions" ), 2 } },
|
|
*_end_groups = _groups + sizeof ( _groups ) / sizeof ( cPluginGroup );
|
|
|
|
int nCount = 0;
|
|
for ( cPluginGroup *i = _groups; i != _end_groups; ++ i )
|
|
{
|
|
int nGroup = m_wndPlugins.InsertItem ( LVIF_IMAGE | LVIF_TEXT, nCount ++, i->m_groupName, 0,
|
|
0, i->m_iconIndex, 0 );
|
|
|
|
CComPtr<IDecalEnum> pEnum;
|
|
HRESULT hRes = m_pDecal->get_Configuration ( _bstr_t ( i->m_groupKey ), GUID_NULL, &pEnum );
|
|
_ASSERTE( SUCCEEDED ( hRes ) );
|
|
|
|
while ( pEnum->Next () == S_OK )
|
|
{
|
|
CLSID clsid;
|
|
hRes = pEnum->get_ComClass ( &clsid );
|
|
_ASSERTE ( SUCCEEDED ( hRes ) );
|
|
|
|
VARIANT_BOOL bEnabled;
|
|
hRes = pEnum->get_Enabled ( &bEnabled );
|
|
_ASSERTE ( SUCCEEDED ( hRes ) );
|
|
|
|
int nState = ( clsid == idSelected ) ? LVIS_SELECTED | LVIS_FOCUSED : 0;
|
|
|
|
LVITEM lvi = { LVIF_STATE | LVIF_IMAGE | LVIF_INDENT | LVIF_PARAM | LVIF_TEXT, nCount ++, 0,
|
|
nState, nState, NULL, -1, ( bEnabled ) ? 6 : 5, reinterpret_cast< LPARAM > ( new cPlugin ( clsid, i->m_groupKey, !!bEnabled, i->m_iconIndex ) ), 1 };
|
|
|
|
CComBSTR strName;
|
|
if ( SUCCEEDED ( pEnum->get_FriendlyName( &strName ) ) )
|
|
lvi.pszText = OLE2T ( strName );
|
|
else
|
|
{
|
|
LPOLESTR szProgID;
|
|
if ( FAILED ( ::ProgIDFromCLSID ( clsid, &szProgID ) ) )
|
|
{
|
|
hRes = ::StringFromCLSID ( clsid, &szProgID );
|
|
_ASSERTE ( SUCCEEDED ( hRes ) );
|
|
}
|
|
|
|
// This *must* succeed
|
|
lvi.pszText = OLE2T ( szProgID );
|
|
::CoTaskMemFree ( szProgID );
|
|
}
|
|
|
|
lvi.cchTextMax = ::_tcslen ( lvi.pszText );
|
|
int nItem = m_wndPlugins.InsertItem ( &lvi );
|
|
|
|
// Load the version info
|
|
CString strDLL;
|
|
if ( !CDenAgentApp::getCOMObjectDLL ( clsid, strDLL ) )
|
|
{
|
|
m_wndPlugins.SetItemText ( nItem, 1, _T( "<No DLL>" ) );
|
|
continue;
|
|
}
|
|
|
|
CString strDLLVersion;
|
|
if ( !CDenAgentApp::getVersionString ( strDLL, strDLLVersion ) )
|
|
m_wndPlugins.SetItemText ( nItem, 1, _T( "<No Version>" ) );
|
|
else
|
|
m_wndPlugins.SetItemText ( nItem, 1, strDLLVersion );
|
|
}
|
|
}
|
|
|
|
m_wndPlugins.SetRedraw ( TRUE );
|
|
m_wndPlugins.Invalidate ();
|
|
|
|
// Scroll back to the top index of before
|
|
RECT rc;
|
|
m_wndPlugins.GetItemRect ( 0, &rc, LVIR_BOUNDS );
|
|
m_wndPlugins.Scroll ( CSize ( 0, ( rc.bottom - rc.top ) * nTop ) );
|
|
}
|
|
|
|
void CDenAgentDlg::OnUpdate()
|
|
{
|
|
USES_CONVERSION;
|
|
// Release Decal object so it can be updated.
|
|
m_pDecal.Release();
|
|
m_pDecal = NULL;
|
|
CoFreeUnusedLibraries();
|
|
RegKey key;
|
|
|
|
cDownloaderDlg dlg;
|
|
bool bUpdates = false;
|
|
|
|
if (key.Create( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Decal\\Agent" )) != ERROR_SUCCESS)
|
|
return;
|
|
|
|
TCHAR szURLDirectory[1024];
|
|
TCHAR szDecalDirectory[MAX_PATH + 1];
|
|
DWORD dwSize = 1024;
|
|
|
|
if (key.QueryStringValue( _T( "DecalDirectory" ), szURLDirectory, &dwSize ) != ERROR_SUCCESS)
|
|
{
|
|
::_tcscpy(szURLDirectory, "http://decal.acdev.org");
|
|
key.SetStringValue("DecalDirectory", "http://decal.acdev.org");
|
|
}
|
|
|
|
dwSize = MAX_PATH;
|
|
|
|
if (key.QueryStringValue( _T( "AgentPath" ), szDecalDirectory, &dwSize ) == ERROR_SUCCESS) {
|
|
// Gouru: szDecalDirectory may have trailing slash in registry, all following
|
|
// code assumes it does not, and adds another one. Since this could potentially
|
|
// cause path problems, the extra slash (if extant) is removed here
|
|
if ( szDecalDirectory[strlen(szDecalDirectory)-1] == '/'
|
|
|| szDecalDirectory[strlen(szDecalDirectory)-1] == '\\'
|
|
){
|
|
szDecalDirectory[strlen(szDecalDirectory)-1] = 0 ;
|
|
}
|
|
|
|
AutoUpdate aUpdate(szDecalDirectory);
|
|
|
|
aUpdate.initialiseFromXML(std::string(szURLDirectory));
|
|
|
|
if (!aUpdate.performUpdate())
|
|
MessageBox("Decal component update failed!");
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
MSXML::IXMLDOMDocumentPtr pDPDoc;
|
|
|
|
pDPDoc.CreateInstance( __uuidof( MSXML::DOMDocument ) );
|
|
pDPDoc->async = false;
|
|
|
|
VARIANT_BOOL bSuccess = pDPDoc->load( "decalplugins.xml" );
|
|
|
|
if(bSuccess)
|
|
{
|
|
MSXML::IXMLDOMElementPtr pNode = pDPDoc->selectSingleNode( _T("decal") );
|
|
_variant_t vVersion = pNode->getAttribute( _T( "version" ) ), vCodeBase = pNode->getAttribute( _T( "codebase" ) );
|
|
|
|
char *sVersion = OLE2A(vVersion.bstrVal);
|
|
|
|
int iRemoteReleaseMajor, iRemoteReleaseMinor;
|
|
int iRemoteBuildMajor, iRemoteBuildMinor;
|
|
|
|
sscanf(sVersion, "%d.%d.%d.%d", &iRemoteReleaseMajor, &iRemoteReleaseMinor, &iRemoteBuildMajor, &iRemoteBuildMinor);
|
|
|
|
if (iReleaseMajor == iRemoteReleaseMajor)
|
|
{
|
|
if (iReleaseMinor == iRemoteReleaseMinor)
|
|
{
|
|
if (iBuildMajor == iRemoteBuildMajor)
|
|
{
|
|
if (iBuildMinor < iRemoteBuildMinor)
|
|
updateDecal(vCodeBase);
|
|
}
|
|
else if (iBuildMajor < iRemoteBuildMajor)
|
|
updateDecal(vCodeBase);
|
|
}
|
|
else if (iReleaseMinor < iRemoteReleaseMinor)
|
|
updateDecal(vCodeBase);
|
|
}
|
|
else if (iReleaseMajor < iRemoteReleaseMajor)
|
|
updateDecal(vCodeBase);
|
|
|
|
|
|
MSXML::IXMLDOMNodeListPtr pPlugins = pDPDoc->selectNodes( _T( "/decal/plugin" ) );
|
|
for( MSXML::IXMLDOMElementPtr pPlugin = pPlugins->nextNode(); pPlugin.GetInterfacePtr() != NULL; pPlugin = pPlugins->nextNode() )
|
|
{
|
|
_variant_t vClsid = pPlugin->getAttribute( _T( "clsid" ) ),
|
|
vCodebase = pPlugin->getAttribute( _T( "codebase" ) ),
|
|
vVersion = pPlugin->getAttribute( _T( "version" ) ),
|
|
vName = pPlugin->getAttribute( _T( "name" ) );
|
|
|
|
DWORD dwMajor;
|
|
DWORD dwMinor;
|
|
|
|
convertVersion( OLE2T( vVersion.bstrVal ), dwMajor, dwMinor );
|
|
|
|
RegKey keyPlugin;
|
|
|
|
if( keyPlugin.Open( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Decal\\Plugins\\" ), KEY_READ ) == ERROR_SUCCESS )
|
|
{
|
|
keyPlugin.Close();
|
|
|
|
if( keyPlugin.Open( HKEY_CLASSES_ROOT, CString(_T("\\CLSID\\")) + OLE2T(vClsid.bstrVal) + _T("\\InprocServer32"), KEY_READ ) != ERROR_SUCCESS ) continue;
|
|
|
|
DWORD dwSize = MAX_PATH;
|
|
TCHAR szDllName[MAX_PATH];
|
|
|
|
if(keyPlugin.QueryStringValue("", szDllName, &dwSize) != ERROR_SUCCESS) continue;
|
|
|
|
keyPlugin.Close();
|
|
|
|
DWORD dwHandle;
|
|
DWORD dwVerInfoSize = GetFileVersionInfoSize(szDllName,&dwHandle);
|
|
if(!dwVerInfoSize) continue;
|
|
|
|
LPBYTE pVersionData = NULL;
|
|
|
|
pVersionData = new BYTE[dwVerInfoSize];
|
|
|
|
if(!GetFileVersionInfo(szDllName, dwHandle, dwVerInfoSize, pVersionData))
|
|
{
|
|
delete [] pVersionData;
|
|
continue;
|
|
}
|
|
|
|
VS_FIXEDFILEINFO* pFixedFileInfo;
|
|
|
|
UINT uFixedInfoSize;
|
|
if(!VerQueryValue(pVersionData, "\\", (void**) &pFixedFileInfo, &uFixedInfoSize))
|
|
{
|
|
delete [] pVersionData;
|
|
continue;
|
|
}
|
|
|
|
|
|
if (HIWORD(pFixedFileInfo->dwFileVersionMS) == HIWORD(dwMajor))
|
|
{
|
|
if (LOWORD(pFixedFileInfo->dwFileVersionMS) == LOWORD(dwMajor))
|
|
{
|
|
if (HIWORD(pFixedFileInfo->dwFileVersionLS) == HIWORD(dwMinor))
|
|
{
|
|
if (LOWORD(pFixedFileInfo->dwFileVersionLS) < LOWORD(dwMinor))
|
|
bUpdates = true;
|
|
}
|
|
else if (HIWORD(pFixedFileInfo->dwFileVersionLS) < HIWORD(dwMinor))
|
|
bUpdates = true;
|
|
}
|
|
else if (LOWORD(pFixedFileInfo->dwFileVersionMS) < LOWORD(dwMajor))
|
|
bUpdates = true;
|
|
}
|
|
else if (HIWORD(pFixedFileInfo->dwFileVersionMS) < HIWORD(dwMajor))
|
|
bUpdates = true;
|
|
|
|
delete [] pVersionData;
|
|
}
|
|
}
|
|
|
|
if((bUpdates) && (!m_bDoingUpdate))
|
|
{
|
|
if (MessageBox("Decal has detected that one or more of your plugins are out of date.\n\nWould you like to view the plugin list?",NULL, MB_ICONQUESTION | MB_YESNO) == IDYES)
|
|
{
|
|
HRESULT hRes = ::CoCreateInstance ( __uuidof ( Decal ), NULL, CLSCTX_INPROC_SERVER, __uuidof ( IDecal ),
|
|
reinterpret_cast< LPVOID * > ( &m_pDecal ) );
|
|
|
|
cAddRemoveDlg ardlg( this );
|
|
ardlg.m_pDecal = m_pDecal;
|
|
ardlg.DoModal();
|
|
loadPluginList();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_bDoingUpdate = false;
|
|
|
|
updateFileInfo ();
|
|
|
|
HRESULT hRes = ::CoCreateInstance ( __uuidof ( Decal ), NULL, CLSCTX_INPROC_SERVER, __uuidof ( IDecal ),
|
|
reinterpret_cast< LPVOID * > ( &m_pDecal ) );
|
|
}
|
|
|
|
void CDenAgentDlg::OnOptions()
|
|
{
|
|
cOptionsDlg dlg;
|
|
dlg.DoModal();
|
|
}
|
|
|
|
void CDenAgentDlg::convertVersion( LPTSTR szVersion, DWORD &dwVersionMajor, DWORD &dwVersionMinor )
|
|
{
|
|
int wVersionParts[ 4 ],
|
|
*i_ver = wVersionParts;
|
|
|
|
for( TCHAR *szVersionPart = ::_tcstok( szVersion, _T( "." ) ); szVersionPart != NULL; szVersionPart = ::_tcstok( NULL, _T( "." ) ), ++ i_ver )
|
|
::_stscanf( szVersionPart, _T( "%i" ), i_ver );
|
|
|
|
dwVersionMajor = MAKELONG( wVersionParts[ 1 ], wVersionParts[ 0 ] );
|
|
dwVersionMinor = MAKELONG( wVersionParts[ 3 ], wVersionParts[ 2 ] );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CDenAgentDlg::updateFileInfo(void)
|
|
{
|
|
struct cFiles
|
|
{
|
|
LPCTSTR szFilename;
|
|
LPCTSTR szRootElement;
|
|
LPCTSTR szVElement;
|
|
UINT nDlgID;
|
|
};
|
|
|
|
static cFiles files[] = {
|
|
{ _T( "messages.xml" ), _T("schema"), _T("revision"), IDC_MESSAGES_TEXT },
|
|
{ _T( "memlocs.xml" ), _T(""), _T("locations"), IDC_MEMLOCS_TEXT },
|
|
{ _T( "decalplugins.xml" ), _T(""), _T(""), IDC_DECALPLUGINS_TEXT } },
|
|
*end_files = files + sizeof ( files ) / sizeof ( cFiles );
|
|
|
|
for ( cFiles *i = files; i != end_files; ++ i )
|
|
{
|
|
CString strFileInfo;
|
|
GetFileInfoBase ( i->szFilename, i->szRootElement, i->szVElement, strFileInfo );
|
|
SetDlgItemText ( i->nDlgID, strFileInfo );
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CDenAgentDlg::GetFileInfoBase(LPCTSTR pszFilename, LPCTSTR pszRootElement, LPCTSTR pszVElement, CString &szFileInfo)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
RegKey key;
|
|
TCHAR szVal[MAX_PATH+1];
|
|
DWORD dwSize = MAX_PATH;
|
|
static BOOL bAlreadyBuggedUser = false;
|
|
|
|
szFileInfo = _T("file not found");
|
|
|
|
// Open the registry key
|
|
if(key.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Decal\\Agent")) == ERROR_SUCCESS)
|
|
{
|
|
// Determine the agent path
|
|
if (key.QueryStringValue(_T("AgentPath"), szVal, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
CString szFilename, szAgentPath(szVal);
|
|
|
|
// Create the filename
|
|
szFilename.Format(_T("%s%s%s"),
|
|
szAgentPath,
|
|
(szAgentPath.Right(1) != _T("\\")) ? _T("\\") : _T(""),
|
|
pszFilename);
|
|
|
|
// Look for the data file
|
|
CFileStatus FileStatus;
|
|
if (CFile::GetStatus((LPCTSTR)szFilename, FileStatus))
|
|
{
|
|
if (strlen(pszVElement)) {
|
|
MSXML::IXMLDOMDocumentPtr m_pDoc;
|
|
MSXML::IXMLDOMElementPtr pVersionElement;
|
|
|
|
m_pDoc.CreateInstance( __uuidof( MSXML::DOMDocument ) );
|
|
m_pDoc->async = false;
|
|
|
|
BOOL bSuccess = m_pDoc->load( _bstr_t(szFilename) );
|
|
if( !bSuccess )
|
|
{
|
|
std::string szXML;
|
|
CDenAgentApp::DecryptXML( static_cast< LPCSTR >( szFilename ), szXML );
|
|
|
|
if( szXML != "" )
|
|
bSuccess = m_pDoc->loadXML( _bstr_t( szXML.c_str() ) );
|
|
|
|
szXML = " ";
|
|
for( int i = 0; i < 2500; ++i )
|
|
szXML += "DIRL";
|
|
}
|
|
|
|
if( !bSuccess )
|
|
return;
|
|
|
|
if (strlen(pszRootElement)) {
|
|
MSXML::IXMLDOMElementPtr pRootElement = m_pDoc->selectSingleNode(_T(pszRootElement));
|
|
pVersionElement = pRootElement->selectSingleNode(_T(pszVElement));
|
|
} else {
|
|
pVersionElement = m_pDoc->selectSingleNode(_T(pszVElement));
|
|
}
|
|
|
|
if (pVersionElement) {
|
|
_variant_t vVersion = pVersionElement->getAttribute(_T("version"));
|
|
|
|
szFileInfo.Format(_T("%d bytes, Version %s"), (DWORD) FileStatus.m_size, OLE2T(vVersion.bstrVal));
|
|
} else {
|
|
CString szDateTime = FileStatus.m_mtime.Format(_T("%#m/%#d/%Y %#I:%M %p"));
|
|
szFileInfo.Format(_T("%d bytes, %s"), (DWORD) FileStatus.m_size, szDateTime);
|
|
}
|
|
} else {
|
|
CString szDateTime = FileStatus.m_mtime.Format(_T("%#m/%#d/%Y %#I:%M %p"));
|
|
szFileInfo.Format(_T("%d bytes, %s"), (DWORD) FileStatus.m_size, szDateTime);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is mainly to protect me from myself :) Yes, I did almost post a bug report
|
|
// because I didn't have XML files in and AC was crashing. --elph
|
|
if( m_bDoUpdate )
|
|
{
|
|
m_bDoUpdate = false;
|
|
OnUpdate( );
|
|
}
|
|
else if (szFileInfo == _T("file not found") && !bAlreadyBuggedUser) {
|
|
::MessageBox(NULL, "One or more of your XML files were not found!\nPlease click the Update button to ensure that Decal works correctly!", "Decal", MB_OK|MB_ICONERROR);
|
|
bAlreadyBuggedUser = true;
|
|
}
|
|
}
|
|
|
|
void CDenAgentDlg::OnDeleteitemPlugins(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
|
|
|
// Clear the plugin
|
|
delete reinterpret_cast< cPlugin * > ( pNMListView->lParam );
|
|
|
|
*pResult = 0;
|
|
}
|
|
|
|
void CDenAgentDlg::OnClickPlugins(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
*pResult = 0;
|
|
LPNMITEMACTIVATE pItemActivate = reinterpret_cast< LPNMITEMACTIVATE > ( pNMHDR );
|
|
|
|
if ( pItemActivate->iItem == -1 || pItemActivate->lParam == 0 )
|
|
// A plugin item was not hit
|
|
return;
|
|
|
|
// Hit test to see if the icon was hit (checkbox)
|
|
if ( pItemActivate->ptAction.x < 16 || pItemActivate->ptAction.x > 32 )
|
|
return;
|
|
|
|
// Invert the check
|
|
cPlugin *pPlugin = reinterpret_cast< cPlugin * > ( m_wndPlugins.GetItemData ( pItemActivate->iItem ) );
|
|
CComPtr< IDecalEnum > pEnum;
|
|
|
|
if (pPlugin && SUCCEEDED ( m_pDecal->get_Configuration ( _bstr_t ( pPlugin->m_group ), pPlugin->m_id, &pEnum ) ) )
|
|
{
|
|
pPlugin->m_bEnabled = !pPlugin->m_bEnabled;
|
|
|
|
// Write the registry and the icons
|
|
pEnum->put_Enabled ( ( pPlugin->m_bEnabled ) ? VARIANT_TRUE : VARIANT_FALSE );
|
|
|
|
LVITEM lvi = { LVIF_IMAGE, pItemActivate->iItem, 0, 0, 0, NULL, 0,
|
|
( pPlugin->m_bEnabled ) ? 6 : 5, };
|
|
m_wndPlugins.SetItem ( &lvi );
|
|
}
|
|
else
|
|
// Bad data in the list - refresh
|
|
loadPluginList ();
|
|
}
|
|
|
|
void CDenAgentDlg::OnBegindragPlugins(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
*pResult = 0;
|
|
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
|
|
|
|
// Check if this item is valid for dragging
|
|
if ( pNMListView->iItem == -1 )
|
|
return;
|
|
|
|
cPlugin *pPlugin = reinterpret_cast< cPlugin * > ( m_wndPlugins.GetItemData ( pNMListView->iItem ) );
|
|
if ( pPlugin == NULL )
|
|
return;
|
|
|
|
m_wndPlugins.SetItemState ( pNMListView->iItem, LVIS_SELECTED, LVIS_SELECTED );
|
|
m_hDragImage = ListView_CreateDragImage ( m_wndPlugins.m_hWnd, pNMListView->iItem, &CPoint ( 0, 0 ) );
|
|
|
|
CRect rcItem;
|
|
m_wndPlugins.GetItemRect ( pNMListView->iItem, rcItem, LVIR_BOUNDS );
|
|
|
|
ImageList_BeginDrag ( m_hDragImage, 0, pNMListView->ptAction.x - rcItem.left, pNMListView->ptAction.y - rcItem.top );
|
|
ImageList_DragEnter ( m_wndPlugins.m_hWnd, pNMListView->ptAction.x, pNMListView->ptAction.y );
|
|
|
|
m_pCurrentDrag = pPlugin;
|
|
|
|
SetCapture ();
|
|
}
|
|
|
|
void CDenAgentDlg::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if ( m_pCurrentDrag != NULL )
|
|
{
|
|
SetCursor ( ::LoadCursor ( NULL, ( getDragInsertBefore ( point ) == -1 ) ? IDC_NO : IDC_ARROW ) );
|
|
ImageList_DragMove ( point.x, point.y );
|
|
}
|
|
|
|
CDialog::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
void CDenAgentDlg::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if ( m_pCurrentDrag != NULL )
|
|
{
|
|
ImageList_DragLeave ( m_wndPlugins.m_hWnd );
|
|
ImageList_EndDrag ();
|
|
ImageList_Destroy ( m_hDragImage );
|
|
|
|
ReleaseCapture ();
|
|
|
|
int nInsertBefore = getDragInsertBefore ( point );
|
|
if ( nInsertBefore != -1 )
|
|
{
|
|
{
|
|
CComPtr< IDecalEnum > pEnum;
|
|
if ( SUCCEEDED ( m_pDecal->get_Configuration ( _bstr_t ( m_pCurrentDrag->m_group ), GUID_NULL, &pEnum ) ) )
|
|
{
|
|
if ( SUCCEEDED ( pEnum->Skip ( m_pCurrentDrag->m_id ) ) )
|
|
pEnum->MoveBefore ( reinterpret_cast< cPlugin * > ( m_wndPlugins.GetItemData ( nInsertBefore ) )->m_id );
|
|
}
|
|
}
|
|
|
|
loadPluginList ();
|
|
}
|
|
|
|
m_pCurrentDrag = NULL;
|
|
}
|
|
|
|
CDialog::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CDenAgentDlg::OnBnClickedDelete()
|
|
{
|
|
/*
|
|
HOW TO USE THIS FEATURE
|
|
create a string value under your plugin key called "Uninstaller"
|
|
the value of this key should be the name of your uninstaller program,
|
|
as listed under HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\
|
|
for MSI installers the name will be a GUID, for others it may be a GUID or plain text
|
|
|
|
that's it
|
|
-para
|
|
*/
|
|
|
|
USES_CONVERSION;
|
|
|
|
int nSelMark = m_wndPlugins.GetSelectionMark();
|
|
if ( nSelMark == -1 )
|
|
return;
|
|
|
|
cPlugin *pPlugin = reinterpret_cast< cPlugin * >(m_wndPlugins.GetItemData( nSelMark ));
|
|
if ( pPlugin == NULL )
|
|
return;
|
|
|
|
//ask permission MB_OKCANCEL | MB_ICONEXCLAMATION = IDOK
|
|
//_snprintf(szMsg, 512, "You are about to remove %s\nPress OK to continue", stuff)
|
|
if ( ::MessageBox(NULL, _T("You are about to remove this plugin.\nPress OK to continue"), _T("Remove Plugin"), MB_OKCANCEL | MB_ICONEXCLAMATION) != IDOK )
|
|
return;
|
|
|
|
//load up the decal registry and remove this entry
|
|
RegKey keyPlugin;
|
|
CString decalPluginKey;
|
|
BSTR sClsid;
|
|
|
|
StringFromCLSID(pPlugin->m_id, &sClsid);
|
|
if ((stricmp(pPlugin->m_group, "plugins") == 0) || (stricmp(pPlugin->m_group, "networkfilters") == 0))
|
|
{
|
|
decalPluginKey.Format("SOFTWARE\\Decal\\%s", pPlugin->m_group);
|
|
|
|
if (keyPlugin.Open(HKEY_LOCAL_MACHINE, _T(decalPluginKey), KEY_ALL_ACCESS) == ERROR_SUCCESS)
|
|
{
|
|
RegKey keySub;
|
|
if (keySub.Open(keyPlugin.m_hKey, OLE2T(sClsid), KEY_READ) == ERROR_SUCCESS)
|
|
{
|
|
//read the uninstaller string and fire it off
|
|
TCHAR sUninstall[512];
|
|
DWORD dwSize = 512;
|
|
|
|
if (keySub.QueryStringValue(_T("Uninstaller"), sUninstall, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
RegKey keyUninstall;
|
|
CString sUninstallKey;
|
|
|
|
sUninstallKey.Format("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s", sUninstall);
|
|
if (keyUninstall.Open(HKEY_LOCAL_MACHINE, _T(sUninstallKey), KEY_READ) == ERROR_SUCCESS)
|
|
{
|
|
TCHAR sUninstallPath[512];
|
|
dwSize = 512;
|
|
|
|
keyUninstall.QueryStringValue(_T("UninstallString"), sUninstallPath, &dwSize);
|
|
keyUninstall.Close();
|
|
|
|
//execute!
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
memset(&pi, 0, sizeof(pi));
|
|
si.cb = sizeof(si);
|
|
|
|
CreateProcess(NULL, sUninstallPath, NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi);
|
|
}
|
|
} else {
|
|
::MessageBox(NULL, _T("There was no uninstaller key defined for this object\nYou will have to uninstall it manually"), _T("Decal Error"), MB_ICONEXCLAMATION);
|
|
}
|
|
keySub.Close();
|
|
}
|
|
|
|
keyPlugin.DeleteSubKey(OLE2T(sClsid));
|
|
keyPlugin.Close();
|
|
}
|
|
else
|
|
::MessageBox(NULL, _T("Unable to open registry"), _T("Decal Error"), MB_ICONEXCLAMATION);
|
|
|
|
//refresh
|
|
loadPluginList();
|
|
}
|
|
}
|
|
void CDenAgentDlg::OnBnClickedExport()
|
|
{
|
|
cExportDlg dlg;
|
|
dlg.SetDecal(m_pDecal);
|
|
dlg.DoModal();
|
|
}
|