openDecal/Native/DenAgent/DenAgentDlg.cpp
erik d1442e3747 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>
2026-02-08 18:27:56 +01:00

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();
}