openDecal/Native/DenAgent/AddRemoveDlg.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

687 lines
18 KiB
C++

// AddRemoveDlg.cpp : implementation file
//
#include "stdafx.h"
#include "DenAgent.h"
#include "AddRemoveDlg.h"
#include "DownloadDlg.h"
#include "..\Inject\Inject.h"
#include "..\Inject\Inject_i.c"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// cAddRemoveDlg dialog
cAddRemoveDlg::cAddRemoveDlg(CWnd* pParent /*=NULL*/)
: CDialog(cAddRemoveDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(cAddRemoveDlg)
//}}AFX_DATA_INIT
}
void cAddRemoveDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(cAddRemoveDlg)
DDX_Control(pDX, IDC_PLUGINS, m_wndPlugins);
//}}AFX_DATA_MAP
}
void cAddRemoveDlg::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 cAddRemoveDlg::loadListing()
{
USES_CONVERSION;
// Clear old data
m_wndPlugins.SetRedraw( FALSE );
m_wndPlugins.DeleteAllItems();
m_plugins.clear();
if (m_pDoc->load("decalplugins.xml") == VARIANT_FALSE)
return;
MSXML::IXMLDOMNodeListPtr pPlugins = m_pDoc->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" ) );
cPlugin p;
::CLSIDFromString( vClsid.bstrVal, &p.m_clsid );
convertVersion( OLE2T( vVersion.bstrVal ), p.m_dwMajor, p.m_dwMinor );
::wcscpy( p.m_szURL, OLE2W( vCodebase.bstrVal ) );
CString csurl(p.m_szURL);
if((-1!=csurl.Find(".exe", 0)) || (-1!=csurl.Find(".msi", 0)) || (-1!=csurl.Find(".dll", 0)) || (-1!=csurl.Find(".zip", 0)) || (-1!=csurl.Find(".js", 0)) || (-1!=csurl.Find(".vbs", 0)))
p.m_bBinary = TRUE;
else
p.m_bBinary = FALSE;
// Now get matching info from the registry - if available
RegKey keyPlugin;
CString csVersion;
CString decalPluginKey;
// See if this plugin is installed in the Decal plugin list
decalPluginKey.Format("SOFTWARE\\Decal\\Plugins\\%s", OLE2T(vClsid.bstrVal));
if (keyPlugin.Open(HKEY_LOCAL_MACHINE, _T(decalPluginKey), KEY_READ) == ERROR_SUCCESS)
{
CString szDllName;
keyPlugin.Close();
// It is! Get the DLL for the CLSID
if (!CDenAgentApp::getCOMObjectDLL(p.m_clsid, szDllName))
goto NotInstalled;
int iMajor, iMinor, iBuildMajor, iBuildMinor;
// Now get the version from the DLL
if (!CDenAgentApp::getVersionInfo(szDllName, iMajor, iMinor, iBuildMajor, iBuildMinor))
goto NotInstalled;
// Setup the installed data by shifting the majors into the HIWORDs, minors into the LOWORDs
p.m_dwInstalledMajor = (iMajor << 16) | iMinor;
p.m_dwInstalledMinor = (iBuildMajor << 16) | iBuildMinor;
// Format a version string
csVersion.Format("%d.%d.%d.%d", iMajor, iMinor, iBuildMajor, iBuildMinor);
p.m_bInstalled = true;
}
else
{
NotInstalled:
p.m_bInstalled = false;
p.m_dwInstalledMajor = 0;
p.m_dwInstalledMinor = 0;
}
m_plugins.push_back( p );
// Next, load this data into the listbox
int nIndex = m_wndPlugins.InsertItem( m_wndPlugins.GetItemCount(), OLE2T( vName.bstrVal ) );
m_wndPlugins.SetItemData( nIndex, reinterpret_cast< DWORD >( &m_plugins.back() ) );
m_wndPlugins.SetItemText( nIndex, 1, OLE2T( vVersion.bstrVal ) );
if( p.m_bInstalled )
m_wndPlugins.SetItemText( nIndex, 2, csVersion );
else
m_wndPlugins.SetItemText( nIndex, 2, _T( "Not Installed" ) );
// Set the proper image indicator
int nImage = 0;
if (p.m_bInstalled)
{
CString szInstalled, szKnown;
// Write them out, padded with lots of zeroes
szInstalled.Format(_T("%.10d.%.10d.%.10d.%.10d"),
HIWORD(p.m_dwInstalledMajor), LOWORD(p.m_dwInstalledMajor),
HIWORD(p.m_dwInstalledMinor), LOWORD(p.m_dwInstalledMinor));
szKnown.Format(_T("%.10d.%.10d.%.10d.%.10d"),
HIWORD(p.m_dwMajor), LOWORD(p.m_dwMajor),
HIWORD(p.m_dwMinor), LOWORD(p.m_dwMinor));
// Determine the image
if (szInstalled == szKnown)
{
nImage = 2;
}
else if (szInstalled > szKnown)
{
nImage = 3;
}
else if (szInstalled < szKnown)
{
nImage = 1;
}
}
m_wndPlugins.SetItem(nIndex, 0, LVIF_IMAGE, 0, nImage, 0, 0, 0);
}
if(!m_SortInfo.pListControl)
{
m_SortInfo.nAscendingSortOrder = TRUE;
m_SortInfo.nColumnNo = 2;
m_SortInfo.pListControl = &m_wndPlugins;
}
m_wndPlugins.SortItems(ComparePlugins, (DWORD)&m_SortInfo);
m_wndPlugins.SetRedraw( TRUE );
}
BEGIN_MESSAGE_MAP(cAddRemoveDlg, CDialog)
//{{AFX_MSG_MAP(cAddRemoveDlg)
ON_BN_CLICKED(IDC_CHANGE_DIR, OnChangeDir)
ON_BN_CLICKED(IDC_INSTALL, OnInstall)
ON_NOTIFY(NM_DBLCLK, IDC_PLUGINS, OnDblclkPlugins)
ON_BN_CLICKED(IDC_UPGRADE, OnUpgrade)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_PLUGINS, OnColumnclickPlugins)
ON_NOTIFY(LVN_GETINFOTIP, IDC_PLUGINS, OnInfoTip)
ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_PLUGINS, OnSelChanged)
ON_NOTIFY(NM_CLICK, IDC_PLUGINS, OnSelChanged)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// cAddRemoveDlg message handlers
void cAddRemoveDlg::OnChangeDir()
{
// TODO: Add your control notification handler code here
}
void cAddRemoveDlg::OnInstall()
{
// cDownloadDlg dlg( this );
// TODO: Get the currently selected item
cPlugin *pPlugin = reinterpret_cast< cPlugin * >( m_wndPlugins.GetItemData( m_wndPlugins.GetSelectionMark() ) );
if(pPlugin==NULL)
return;
/* dlg.m_clsid = pPlugin->m_clsid;
dlg.m_dwMajor = pPlugin->m_dwMajor;
dlg.m_dwMinor = pPlugin->m_dwMinor;
dlg.m_strURL = pPlugin->m_szURL;
dlg.m_bDownloadPlugin = true;
if( dlg.DoModal() != IDOK )
return;
// The download was successful - try and create an instance
CComPtr< IPlugin > pPluginObj;
HRESULT hRes = dlg.m_pFactory->CreateInstance( NULL, __uuidof( IPlugin ), reinterpret_cast< void ** >( &pPluginObj ) );
if( FAILED( hRes ) )
// Something isn't right
AfxMessageBox( _T( "The newly downloaded plugin dosen't appear to work." ), MB_ICONERROR | MB_OK, 0 );
dlg.m_pFactory->LockServer( FALSE );
// Refresh the view
loadListing();
*/
CString url(pPlugin->m_szURL);
ShellExecute(m_hWnd,"open",url,0,0,0);
}
void cAddRemoveDlg::OnDblclkPlugins(NMHDR* pNMHDR, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
*pResult = 0;
}
void cAddRemoveDlg::OnUpgrade()
{
OnInstall();
}
BOOL cAddRemoveDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Load the string
RegKey keyAgent;
if( keyAgent.Open( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Decal\\Agent" )) != ERROR_SUCCESS )
{
::AfxMessageBox( _T( "Critical registry keys are missing, this installation is broken.\r\nRepair the installation." ), MB_ICONERROR | MB_OK, 0 );
EndDialog( IDCANCEL );
return FALSE;
}
// Make it look nicer
m_wndPlugins.SetExtendedStyle( m_wndPlugins.GetExtendedStyle() | LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_INFOTIP);
// Create and assign the image list
//m_ImageList.Create(IDR_VERSION_STATES, 21, 0, RGB(255, 255, 255));
m_ImageList.Create(IDB_IMAGES, 16, 0, RGB(255,0,255));
m_wndPlugins.SetImageList(&m_ImageList, LVSIL_SMALL);
// Setup the columns in the list control
m_wndPlugins.InsertColumn( 0, _T( "Plugin Name" ), LVCFMT_LEFT, 175 );
m_wndPlugins.InsertColumn( 1, _T( "Version" ), LVCFMT_LEFT, 75, 1 );
m_wndPlugins.InsertColumn( 2, _T( "Installed" ), LVCFMT_LEFT, 75, 2 );
m_wndPlugins.m_pAddRemoveDlg = this;
m_pDoc.CreateInstance( __uuidof( MSXML::DOMDocument ) );
m_pDoc->async = false;
m_SortInfo.pListControl = NULL;
loadListing();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void cAddRemoveDlg::OnColumnclickPlugins(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView->iSubItem == m_SortInfo.nColumnNo)
m_SortInfo.nAscendingSortOrder = !m_SortInfo.nAscendingSortOrder;
else
m_SortInfo.nAscendingSortOrder = TRUE;
m_SortInfo.nColumnNo = pNMListView->iSubItem;
m_SortInfo.pListControl = &m_wndPlugins;
m_wndPlugins.SortItems( ComparePlugins, (DWORD)&m_SortInfo );
*pResult = 0;
}
int CALLBACK cAddRemoveDlg::ComparePlugins(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
SortInfo *pSortInfo = (SortInfo *) lParamSort;
CListCtrl *pListControl = pSortInfo->pListControl;
int lFirstData = -1, lSecondData = -1;
LV_FINDINFO FindInfo;
FindInfo.flags = LVFI_PARAM | LVFI_WRAP;
FindInfo.lParam = lParam1;
lFirstData = pListControl->FindItem(&FindInfo);
FindInfo.lParam = lParam2;
lSecondData = pListControl->FindItem(&FindInfo,lFirstData);
ASSERT(lFirstData != -1); ASSERT(lSecondData != -1);
CString FirstText = pListControl->GetItemText(lFirstData,pSortInfo->nColumnNo);
CString SecondText = pListControl->GetItemText(lSecondData,pSortInfo->nColumnNo);
return FirstText.CompareNoCase(SecondText) * ((pSortInfo->nAscendingSortOrder)?1:-1);
}
void cAddRemoveDlg::OnInfoTip( NMHDR *pNMHDR, LRESULT *pResult )
{
NMLVGETINFOTIP *pInfoTip = reinterpret_cast<NMLVGETINFOTIP*>(pNMHDR);
cPlugin *pPlugin = reinterpret_cast< cPlugin * >( m_wndPlugins.GetItemData( pInfoTip->iItem ) );
if(pPlugin==NULL)
return;
CString strTipText(pPlugin->m_szURL);
lstrcpy(pInfoTip->pszText, strTipText);
*pResult = 0;
}
void cAddRemoveDlg::DisplayError(HRESULT hr)
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,hr, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&lpMsgBuf, 0, NULL );
char szTemp[100];
wsprintf(szTemp, "%s\n", lpMsgBuf);
MessageBox(szTemp, "Decal Plugin Registration" , MB_ICONEXCLAMATION);
}
bool cAddRemoveDlg::ReadTypeLib(CString cstrDll, bool bMultipleFiles)
{
USES_CONVERSION;
bool bRegedDLL = false;
HINSTANCE hDLL = LoadLibrary(cstrDll);
if(hDLL)
{
DLLREG DllReg = (DLLREG)GetProcAddress(hDLL, "DllRegisterServer");
if(DllReg!=NULL)
{
DllReg();
bRegedDLL = true;
}
FreeLibrary(hDLL);
}
ITypeLib *pTypeLib = NULL;
ITypeInfo *pTypeInfo = NULL;
TYPEATTR *pTypeAttr = NULL;
bool bSuccess = false;
HRESULT hr;
WCHAR* pwszClassID = NULL;
int i;
UINT iCount;
hr = LoadTypeLib(A2OLE(cstrDll),&pTypeLib);
if ( FAILED(hr))
{
goto _cleanup;
DisplayError(hr);
}
iCount = pTypeLib->GetTypeInfoCount();
for (i=0; i < iCount ; i++)
{
if (FAILED(hr = (pTypeLib->GetTypeInfo(i, &pTypeInfo))))
{
DisplayError(hr);
goto _cleanup;
}
if (FAILED(hr = (pTypeInfo->GetTypeAttr(&pTypeAttr))))
{
DisplayError(hr);
goto _cleanup;
}
if (TKIND_COCLASS == pTypeAttr->typekind)
{
HREFTYPE hRefType;
ITypeInfo *pTInfoImpl;
TYPEATTR *pTAttr = NULL;
CComBSTR bstrName;
for( int j = 0 ; j < pTypeAttr->cImplTypes ; ++j )
{
hr = pTypeInfo->GetRefTypeOfImplType( j, &hRefType );
if( SUCCEEDED( hr ) )
{
hr = pTypeInfo->GetRefTypeInfo( hRefType, &pTInfoImpl );
if( SUCCEEDED( hr ) )
{
hr = pTInfoImpl->GetDocumentation( -1, &bstrName, NULL, NULL, NULL );
hr = pTInfoImpl->GetTypeAttr(&pTAttr);
if( SUCCEEDED( hr ) )
{
if((pTAttr->guid==IID_IPlugin) && (bstrName == CComBSTR("IPlugin")))
{
StringFromCLSID(pTypeAttr->guid, &pwszClassID);
RegKey key;
if( key.Create( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Decal\\Plugins" )) == ERROR_SUCCESS )
if(key.SetDWORDValue(OLE2A(pwszClassID), (DWORD)0x1) == ERROR_SUCCESS)
bSuccess = true;
CoTaskMemFree(pwszClassID);
}
pTInfoImpl->ReleaseTypeAttr(pTAttr);
}
bstrName.Empty();
pTInfoImpl->Release();
}
}
}
}
pTypeInfo->ReleaseTypeAttr(pTypeAttr);
pTypeInfo->Release();
}
_cleanup:
if (pTypeAttr)
pTypeInfo->ReleaseTypeAttr(pTypeAttr);
if (pTypeInfo)
pTypeInfo->Release();
if(pTypeLib)
pTypeLib->Release();
if(bSuccess)
{
MessageBox(CString("Decal Plugin: ") + cstrDll + " was sucessfully registered.", "Decal Plugin Registration", MB_ICONINFORMATION );
return true;
}
else if(bRegedDLL)
{
MessageBox(CString("File: ") + cstrDll + " was sucessfully registered.\n\nHowever, Decal was unable to determine if the DLL was a Decal Plugin.\n\nIf it was, it should appear in the Plugin List, otherwise it wasn't.", "Decal Plugin Registration", MB_ICONINFORMATION );
return true;
}
else if(!bMultipleFiles)
MessageBox("Registration failed. Dll might not be a Decal Plugin.", "Decal Plugin Registration", MB_ICONEXCLAMATION);
return false;
}
struct cFileType
{
CString m_strExt;
CComPtr< IDecalFileSurrogate > m_pFile;
};
typedef std::list< cFileType > cFileTypeList;
void cAddRemoveDlg::OnBrowse()
{
USES_CONVERSION;
// Walk through the list of surrogates and build up a string
CComPtr< IDecalEnum > pEnum;
m_pDecal->get_Configuration( CComBSTR( _T( "Surrogates" ) ), GUID_NULL, &pEnum );
CString strOpen = _T( "Decal Components (" );
cFileTypeList filetypes;
std::string ssTemp;
std::list<std::string> vExtensions;
while( pEnum->Next() == S_OK )
{
CComPtr< IDecalFileSurrogate > pFileSurrogate;
if( FAILED( pEnum->CreateInstance( __uuidof( IDecalFileSurrogate ), reinterpret_cast< void ** >( &pFileSurrogate ) ) ) )
// This surrogate did not support files, move on
continue;
CComBSTR strExt, strDescription;
pFileSurrogate->get_Extension( &strExt );
pFileSurrogate->get_Description( &strDescription );
TCHAR szItem[ 255 ];
LPTSTR szExt = OLE2T( strExt ),
szDesc = OLE2T( strDescription );
::_stprintf( szItem, _T( "*.%s," ), szExt );
//::_stprintf( szItem, _T( "%s (*.%s)|*.%s|" ), szDesc, szExt, szExt );
strOpen += szItem;
ssTemp = szExt;
vExtensions.push_back( ssTemp );
cFileType ft;
ft.m_strExt = szExt;
ft.m_pFile = pFileSurrogate;
filetypes.push_back( ft );
}
strOpen.Delete( strOpen.GetLength() - 1, 1 ); // Remove that last ","
strOpen += _T( ") |" );
for( std::list<std::string>::iterator z = vExtensions.begin(); z != vExtensions.end(); z++ )
{
TCHAR szExtension[ 15 ];
::_stprintf( szExtension, _T( "*.%s;" ), z->data() );
strOpen += szExtension;
}
strOpen += _T( "|" );
// Changed fd( TRUE, NULL, NULL, (etc) to NULL, NULL, NULL - removes open as readonly checkbox
CFileDialog fd( NULL, NULL, NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST, strOpen, this );
if( fd.DoModal() != IDOK )
return;
CString strExt = fd.GetFileExt();
// Find the matching file type
for( cFileTypeList::iterator i = filetypes.begin(); i != filetypes.end(); ++ i )
{
if( i->m_strExt.CompareNoCase( strExt ) == 0 )
{
// Found our match
HRESULT hRes = i->m_pFile->Register( CComBSTR( fd.GetPathName() ) );
if( FAILED( hRes ) )
AfxMessageBox( _T( "Failed to register plugin." ) );
break;
}
}
// Dump the proxy libraries
::CoFreeUnusedLibraries();
}
BEGIN_MESSAGE_MAP(CListViewSC, CListCtrl)
//{{AFX_MSG_MAP(CListViewSC)
ON_WM_DROPFILES()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CListViewSC::OnDropFiles( HDROP dropInfo )
{
char szTemp[MAX_PATH+1];
m_bGotAFile = false;
int iTotal = DragQueryFile(dropInfo, 0xFFFFFFFF, NULL, NULL);
for(int i = 0; i<iTotal; i++)
{
DragQueryFile(dropInfo, i, szTemp, sizeof(szTemp));
if(~FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(szTemp))
{
LPTSTR pszFileExt = PathFindExtension(szTemp);
if(CString(pszFileExt).CompareNoCase(".dll") == 0)
{
m_pAddRemoveDlg->ReadTypeLib(szTemp, false);
m_bGotAFile = true;
}
else if( iTotal == 1 )
{
m_pAddRemoveDlg->MessageBox("Invalid Decal Plugin.", "Decal Plugin Registration", MB_ICONEXCLAMATION);
m_bGotAFile = true;
}
}
else if(FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(szTemp))
SearchDirectory(szTemp);
}
if(!m_bGotAFile)
MessageBox("Could not locate any Decal Plugins.", "Decal Plugin Registration", MB_ICONEXCLAMATION);
m_pAddRemoveDlg->loadListing();
return;
}
bool CListViewSC::SearchDirectory(char *szDirectory)
{
WIN32_FIND_DATA finder;
HANDLE session;
char buffer[MAX_PATH+1];
SetCurrentDirectory(szDirectory);
GetCurrentDirectory(_MAX_PATH, buffer);
session = FindFirstFile("*", &finder);
if(session==INVALID_HANDLE_VALUE)
return false;
do
{
if((~finder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
if(CString(PathFindExtension(finder.cFileName)).CompareNoCase(".dll") == 0 )
{
GetCurrentDirectory(_MAX_PATH, buffer);
if(buffer[strlen(buffer)-1]=='\\')
wsprintf(buffer, "%s%s", buffer, finder.cFileName);
else
wsprintf(buffer, "%s\\%s", buffer, finder.cFileName);
if(m_pAddRemoveDlg->ReadTypeLib(buffer, true))
m_bGotAFile = true;
}
}
else if(finder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(*finder.cFileName!='.')
{
SearchDirectory(finder.cFileName);
SetCurrentDirectory("..");
GetCurrentDirectory(_MAX_PATH, buffer);
}
}
}
while(FindNextFile(session, &finder));
FindClose(session);
return true;
}
void cAddRemoveDlg::OnRefresh()
{
loadListing();
}
void cAddRemoveDlg::OnSelChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
int nSelectionMark = m_wndPlugins.GetSelectionMark();
if ( nSelectionMark == -1 )
return;
cPlugin *pPlugin = reinterpret_cast<cPlugin *>(m_wndPlugins.GetItemData( nSelectionMark ));
if (pPlugin == NULL)
return;
if (pPlugin->m_bBinary)
SetDlgItemText(IDC_INSTALL, "Download");
else
SetDlgItemText(IDC_INSTALL, "Visit Website");
*pResult = 0;
}