1979 lines
52 KiB
C++
1979 lines
52 KiB
C++
|
|
#include "precomp.h"
|
|
|
|
#include "dbsupport.h"
|
|
#include "viewlog.h"
|
|
|
|
using namespace ShimLib;
|
|
|
|
//#define AV_OPTIONS_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\AppVerifier"
|
|
|
|
#define AV_OPTION_CLEAR_LOG L"ClearLogsBeforeRun"
|
|
#define AV_OPTION_BREAK_ON_LOG L"BreakOnLog"
|
|
#define AV_OPTION_FULL_PAGEHEAP L"FullPageHeap"
|
|
#define AV_OPTION_AV_DEBUGGER L"UseAVDebugger"
|
|
#define AV_OPTION_DEBUGGER L"Debugger"
|
|
#define AV_OPTION_PROPAGATE L"PropagateTests"
|
|
|
|
|
|
//
|
|
// Forward declarations
|
|
//
|
|
|
|
CWinApp theApp;
|
|
|
|
|
|
HINSTANCE g_hInstance = NULL;
|
|
|
|
BOOL g_bSettingsDirty = FALSE;
|
|
|
|
BOOL g_bRefreshingSettings = FALSE;
|
|
|
|
BOOL g_bConsoleMode = FALSE;
|
|
|
|
BOOL g_bWin2KMode = FALSE;
|
|
|
|
BOOL g_bInternalMode = FALSE;
|
|
|
|
//
|
|
// dialog handles
|
|
//
|
|
HWND g_hDlgMain = NULL;
|
|
HWND g_hDlgOptions = NULL;
|
|
|
|
// forward function declarations
|
|
INT_PTR CALLBACK
|
|
DlgMain(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
INT_PTR CALLBACK
|
|
DlgRunAlone(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
INT_PTR CALLBACK
|
|
DlgConflict(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
void
|
|
RefreshSettingsList(
|
|
HWND hDlg,
|
|
BOOL bForceRefresh = FALSE
|
|
);
|
|
|
|
void
|
|
ReadOptions(
|
|
void
|
|
);
|
|
|
|
BOOL
|
|
GetAppTitleString(
|
|
wstring &strTitle
|
|
)
|
|
{
|
|
wstring strVersion;
|
|
|
|
if (!AVLoadString(IDS_APP_NAME, strTitle)) {
|
|
return FALSE;
|
|
}
|
|
|
|
#if defined(_WIN64)
|
|
if (!AVLoadString(IDS_VERSION_STRING_64, strVersion)) {
|
|
return FALSE;
|
|
}
|
|
#else
|
|
if (!AVLoadString(IDS_VERSION_STRING, strVersion)) {
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
strTitle += L" ";
|
|
strTitle += strVersion;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
ShowHTMLHelp(
|
|
void
|
|
)
|
|
{
|
|
SHELLEXECUTEINFOW sei;
|
|
WCHAR szPath[MAX_PATH];
|
|
WCHAR* pszBackSlash;
|
|
|
|
|
|
DWORD dwLen = GetModuleFileName(NULL, szPath, ARRAY_LENGTH(szPath));
|
|
|
|
if (!dwLen) {
|
|
return;
|
|
}
|
|
|
|
pszBackSlash = wcsrchr(szPath, L'\\');
|
|
if (pszBackSlash) {
|
|
pszBackSlash++;
|
|
*pszBackSlash = 0;
|
|
} else {
|
|
//
|
|
// punt and just try to find it on the path
|
|
//
|
|
szPath[0] = 0;
|
|
}
|
|
|
|
StringCchCatW(szPath, ARRAY_LENGTH(szPath), L"appverif.chm");
|
|
|
|
ZeroMemory(&sei, sizeof(sei));
|
|
|
|
sei.cbSize = sizeof(sei);
|
|
sei.lpVerb = L"open";
|
|
sei.lpFile = szPath;
|
|
sei.nShow = SW_SHOWNORMAL;
|
|
|
|
ShellExecuteExW(&sei);
|
|
}
|
|
|
|
BOOL
|
|
SearchGroupForSID(
|
|
DWORD dwGroup,
|
|
BOOL* pfIsMember
|
|
)
|
|
{
|
|
PSID pSID = NULL;
|
|
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
|
|
BOOL fRes = TRUE;
|
|
|
|
if (!AllocateAndInitializeSid(&SIDAuth,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
dwGroup,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&pSID)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pSID) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CheckTokenMembership(NULL, pSID, pfIsMember)) {
|
|
fRes = FALSE;
|
|
}
|
|
|
|
FreeSid(pSID);
|
|
|
|
return fRes;
|
|
}
|
|
|
|
BOOL
|
|
CanRun(
|
|
void
|
|
)
|
|
{
|
|
BOOL fIsAdmin;
|
|
|
|
if (!SearchGroupForSID(DOMAIN_ALIAS_RID_ADMINS, &fIsAdmin))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return fIsAdmin;
|
|
}
|
|
|
|
void
|
|
DumpResourceStringsToConsole(ULONG ulBegin, ULONG ulEnd)
|
|
{
|
|
ULONG ulRes;
|
|
wstring strText;
|
|
|
|
for (ulRes = ulBegin; ulRes != ulEnd + 1; ++ulRes) {
|
|
if (AVLoadString(ulRes, strText)) {
|
|
printf("%ls\n", strText.c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
DumpCurrentSettingsToConsole(void)
|
|
{
|
|
CAVAppInfo *pApp;
|
|
|
|
DumpResourceStringsToConsole(IDS_CURRENT_SETTINGS, IDS_CURRENT_SETTINGS);
|
|
|
|
for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
|
|
printf("%ls:\n", pApp->wstrExeName.c_str());
|
|
|
|
CTestInfo *pTest;
|
|
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pApp->IsTestActive(*pTest)) {
|
|
printf(" %ls\n", pTest->strTestName.c_str());
|
|
}
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
DumpResourceStringsToConsole(IDS_DONE, IDS_DONE);
|
|
}
|
|
|
|
void
|
|
DumpHelpToConsole(void)
|
|
{
|
|
|
|
DumpResourceStringsToConsole(IDS_HELP_INTRO_00, IDS_HELP_INTRO_10);
|
|
|
|
CTestInfo *pTest;
|
|
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pTest->eTestType == TEST_KERNEL &&
|
|
((pTest->bInternal && g_bInternalMode) || (pTest->bExternal && !g_bInternalMode)) &&
|
|
(pTest->bWin2KCompatible || !g_bWin2KMode)) {
|
|
|
|
printf(" %ls\n", pTest->strTestName.c_str());
|
|
}
|
|
}
|
|
|
|
DumpResourceStringsToConsole(IDS_HELP_SHIM_TESTS, IDS_HELP_SHIM_TESTS);
|
|
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pTest->eTestType == TEST_SHIM &&
|
|
((pTest->bInternal && g_bInternalMode) || (pTest->bExternal && !g_bInternalMode)) &&
|
|
(pTest->bWin2KCompatible || !g_bWin2KMode)) {
|
|
|
|
printf(" %ls\n", pTest->strTestName.c_str());
|
|
}
|
|
}
|
|
|
|
DumpResourceStringsToConsole(IDS_HELP_EXAMPLE_00, IDS_HELP_EXAMPLE_11);
|
|
}
|
|
|
|
void
|
|
HandleCommandLine(int argc, LPWSTR *argv)
|
|
{
|
|
WCHAR szApp[MAX_PATH];
|
|
wstring strTemp;
|
|
CWStringArray astrApps;
|
|
|
|
szApp[0] = 0;
|
|
|
|
g_bConsoleMode = TRUE;
|
|
|
|
//
|
|
// print the title
|
|
//
|
|
if (GetAppTitleString(strTemp)) {
|
|
printf("\n%ls\n", strTemp.c_str());
|
|
}
|
|
if (AVLoadString(IDS_COPYRIGHT, strTemp)) {
|
|
printf("%ls\n\n", strTemp.c_str());
|
|
}
|
|
|
|
//
|
|
// check for global operations
|
|
//
|
|
if (_wcsnicmp(argv[0], L"/q", 2) == 0) { // querysettings
|
|
DumpCurrentSettingsToConsole();
|
|
return;
|
|
}
|
|
if (_wcsicmp(argv[0], L"/?") == 0) { // help
|
|
DumpHelpToConsole();
|
|
return;
|
|
}
|
|
if (_wcsnicmp(argv[0], L"/r", 2) == 0) { // reset
|
|
g_aAppInfo.clear();
|
|
goto out;
|
|
}
|
|
|
|
//
|
|
// first get a list of the app names
|
|
//
|
|
for (int nArg = 0 ; nArg != argc; nArg++) {
|
|
WCHAR wc = argv[nArg][0];
|
|
|
|
if (wc != L'/' && wc != L'-' && wc != L'+') {
|
|
astrApps.push_back(argv[nArg]);
|
|
}
|
|
}
|
|
|
|
if (astrApps.size() == 0) {
|
|
AVErrorResourceFormat(IDS_NO_APP);
|
|
DumpHelpToConsole();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// now for each app name, parse the list and adjust its settings
|
|
//
|
|
for (wstring *pStr = astrApps.begin(); pStr != astrApps.end(); pStr++) {
|
|
CAVAppInfo *pApp;
|
|
BOOL bFound = FALSE;
|
|
|
|
//
|
|
// check to see if they submitted a full path
|
|
//
|
|
const WCHAR * pExe = NULL;
|
|
const WCHAR * pPath = NULL;
|
|
|
|
pExe = wcsrchr(pStr->c_str(), L'\\');
|
|
if (!pExe) {
|
|
if ((*pStr)[1] == L':') {
|
|
pExe = pStr->c_str() + 2;
|
|
}
|
|
} else {
|
|
pExe++;
|
|
}
|
|
|
|
if (pExe) {
|
|
pPath = pStr->c_str();
|
|
} else {
|
|
pExe = pStr->c_str();
|
|
}
|
|
|
|
//
|
|
// first, find or add the app to the list, and get a pointer to it
|
|
//
|
|
for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
|
|
if (_wcsicmp(pApp->wstrExeName.c_str(), pExe) == 0) {
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!bFound) {
|
|
CAVAppInfo App;
|
|
|
|
App.wstrExeName = pExe;
|
|
g_aAppInfo.push_back(App);
|
|
pApp = g_aAppInfo.end() - 1;
|
|
}
|
|
|
|
//
|
|
// if they submitted a full path, update the records
|
|
//
|
|
if (pPath) {
|
|
pApp->wstrExePath = pPath;
|
|
}
|
|
|
|
//
|
|
// now walk the command line again and make the adjustments
|
|
//
|
|
for (int nArg = 0 ; nArg != argc; nArg++) {
|
|
if (argv[nArg][0] == L'/') {
|
|
if (_wcsnicmp(argv[nArg], L"/a", 2) == 0) { // all
|
|
|
|
for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
pApp->AddTest(*pTest);
|
|
}
|
|
} else if (_wcsnicmp(argv[nArg], L"/n", 2) == 0) { // none
|
|
|
|
for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
pApp->RemoveTest(*pTest);
|
|
}
|
|
} else if (_wcsnicmp(argv[nArg], L"/d", 2) == 0) { // default
|
|
|
|
for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pTest->bDefault) {
|
|
pApp->AddTest(*pTest);
|
|
} else {
|
|
pApp->RemoveTest(*pTest);
|
|
}
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// unknown parameter
|
|
//
|
|
AVErrorResourceFormat(IDS_INVALID_PARAMETER, argv[nArg]);
|
|
DumpHelpToConsole();
|
|
return;
|
|
}
|
|
|
|
} else if (argv[nArg][0] == L'+' || argv[nArg][0] == L'-') {
|
|
|
|
BOOL bAdd = (argv[nArg][0] == L'+');
|
|
LPWSTR szParam = argv[nArg] + 1;
|
|
|
|
//
|
|
// see if it's a shim name
|
|
//
|
|
CTestInfo *pTest;
|
|
bFound = FALSE;
|
|
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (_wcsicmp(szParam, pTest->strTestName.c_str()) == 0) {
|
|
if (bAdd) {
|
|
pApp->AddTest(*pTest);
|
|
} else {
|
|
pApp->RemoveTest(*pTest);
|
|
}
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!bFound) {
|
|
//
|
|
// unknown test
|
|
//
|
|
|
|
AVErrorResourceFormat(IDS_INVALID_TEST, szParam);
|
|
DumpHelpToConsole();
|
|
return;
|
|
}
|
|
}
|
|
//
|
|
// anything that doesn't begin with a slash, plus, or minus
|
|
// is an app name, so we'll ignore it
|
|
//
|
|
|
|
}
|
|
}
|
|
|
|
out:
|
|
//
|
|
// save them to disk/registry
|
|
//
|
|
SetCurrentAppSettings();
|
|
|
|
//
|
|
// show them the current settings, for verification
|
|
//
|
|
DumpCurrentSettingsToConsole();
|
|
}
|
|
|
|
BOOL
|
|
CheckWindowsVersion(void)
|
|
{
|
|
OSVERSIONINFOEXW VersionInfo;
|
|
|
|
ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFOEXW));
|
|
VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
|
|
|
|
GetVersionEx((LPOSVERSIONINFOW)&VersionInfo);
|
|
|
|
if (VersionInfo.dwMajorVersion < 5 ||
|
|
(VersionInfo.dwMajorVersion == 5 && VersionInfo.dwMinorVersion == 0 && VersionInfo.wServicePackMajor < 3)) {
|
|
//
|
|
// too early - can't run
|
|
//
|
|
|
|
AVErrorResourceFormat(IDS_INVALID_VERSION);
|
|
|
|
return FALSE;
|
|
|
|
} else if (VersionInfo.dwMajorVersion == 5 && VersionInfo.dwMinorVersion == 0) {
|
|
//
|
|
// Win2K
|
|
//
|
|
g_bWin2KMode = TRUE;
|
|
} else {
|
|
//
|
|
// WinXP or above -- all is well
|
|
//
|
|
g_bWin2KMode = FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
extern "C" int APIENTRY
|
|
wWinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPWSTR lpCmdLine,
|
|
int nCmdShow
|
|
)
|
|
{
|
|
LPWSTR* argv = NULL;
|
|
int argc = 0;
|
|
|
|
g_hInstance = hInstance;
|
|
|
|
//
|
|
// check for appropriate version
|
|
//
|
|
if (!CheckWindowsVersion()) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// check for administrator access
|
|
//
|
|
if (!CanRun()) {
|
|
AVErrorResourceFormat(IDS_ACCESS_IS_DENIED);
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// check for internal mode
|
|
//
|
|
g_bInternalMode = IsInternalModeEnabled();
|
|
|
|
InitTestInfo();
|
|
|
|
GetCurrentAppSettings();
|
|
|
|
ReadOptions();
|
|
|
|
if (lpCmdLine && lpCmdLine[0]) {
|
|
argv = CommandLineToArgvW(lpCmdLine, &argc);
|
|
}
|
|
|
|
if (argc > 0) {
|
|
//
|
|
// we're in console mode, so handle everything as a console
|
|
//
|
|
HandleCommandLine(argc, argv);
|
|
return 1;
|
|
}
|
|
|
|
FreeConsole();
|
|
|
|
InitCommonControls();
|
|
|
|
LinkWindow_RegisterClass();
|
|
|
|
HACCEL hAccelMain = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCEL_MAIN));
|
|
|
|
HWND hMainDlg = CreateDialog(g_hInstance, (LPCTSTR)IDD_DLG_MAIN, NULL, DlgMain);
|
|
|
|
MSG msg;
|
|
|
|
//
|
|
// Main message loop:
|
|
//
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
if (!hAccelMain || !TranslateAccelerator(hMainDlg, hAccelMain, &msg)) {
|
|
if (!IsDialogMessage(hMainDlg, &msg)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
RefreshAppList(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
CAVAppInfoArray::iterator it;
|
|
|
|
HWND hList = GetDlgItem(hDlg, IDC_LIST_APPS);
|
|
|
|
ListView_DeleteAllItems(hList);
|
|
|
|
for (it = g_aAppInfo.begin(); it != g_aAppInfo.end(); it++) {
|
|
LVITEM lvi;
|
|
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM;
|
|
lvi.pszText = (LPWSTR)it->wstrExeName.c_str();
|
|
lvi.lParam = (LPARAM)it;
|
|
lvi.iItem = 9999;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_InsertItem(hList, &lvi);
|
|
}
|
|
|
|
RefreshSettingsList(hDlg);
|
|
}
|
|
|
|
void
|
|
DirtySettings(
|
|
HWND hDlg,
|
|
BOOL bDirty
|
|
)
|
|
{
|
|
g_bSettingsDirty = bDirty;
|
|
}
|
|
|
|
void
|
|
SaveSettings(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
DirtySettings(hDlg, FALSE);
|
|
|
|
SetCurrentAppSettings();
|
|
}
|
|
|
|
void
|
|
SaveSettingsIfDirty(HWND hDlg)
|
|
{
|
|
if (g_bSettingsDirty) {
|
|
SaveSettings(hDlg);
|
|
}
|
|
}
|
|
|
|
void
|
|
DisplayLog(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
g_szSingleLogFile[0] = 0;
|
|
|
|
DialogBox(g_hInstance, (LPCTSTR)IDD_VIEWLOG_PAGE, hDlg, DlgViewLog);
|
|
}
|
|
|
|
void
|
|
DisplaySingleLog(HWND hDlg)
|
|
{
|
|
WCHAR wszFilter[] = L"Log files (*.log)\0*.log\0";
|
|
OPENFILENAME ofn;
|
|
WCHAR wszAppFullPath[MAX_PATH];
|
|
WCHAR wszAppShortName[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
wstring wstrLogTitle;
|
|
|
|
if (!AVLoadString(IDS_VIEW_EXPORTED_LOG_TITLE, wstrLogTitle)) {
|
|
wstrLogTitle = _T("View Exported Log");
|
|
}
|
|
|
|
wszAppFullPath[0] = 0;
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hDlg;
|
|
ofn.hInstance = NULL;
|
|
ofn.lpstrFilter = wszFilter;
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nMaxCustFilter = 0;
|
|
ofn.nFilterIndex = 0;
|
|
ofn.lpstrFile = wszAppFullPath;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrFileTitle = wszAppShortName;
|
|
ofn.nMaxFileTitle = MAX_PATH;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = wstrLogTitle.c_str();
|
|
ofn.Flags = OFN_PATHMUSTEXIST |
|
|
OFN_HIDEREADONLY | // hide the "open read-only" checkbox
|
|
OFN_NONETWORKBUTTON | // no network button
|
|
OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
|
|
OFN_SHAREAWARE; // don't check the existance of file with OpenFile
|
|
ofn.lpstrDefExt = _T("log");
|
|
|
|
if ( !GetOpenFileName(&ofn) )
|
|
{
|
|
goto out;
|
|
}
|
|
|
|
hr = StringCchCopyW(g_szSingleLogFile, ARRAY_LENGTH(g_szSingleLogFile), wszAppFullPath);
|
|
if (FAILED(hr)) {
|
|
AVErrorResourceFormat(IDS_PATH_TOO_LONG, wszAppFullPath);
|
|
goto out;
|
|
}
|
|
|
|
DialogBox(g_hInstance, (LPCTSTR)IDD_VIEWLOG_PAGE, hDlg, DlgViewLog);
|
|
|
|
out:
|
|
g_szSingleLogFile[0] = 0;
|
|
}
|
|
|
|
void
|
|
SelectApp(
|
|
HWND hDlg,
|
|
int nWhich
|
|
)
|
|
{
|
|
HWND hList = GetDlgItem(hDlg, IDC_LIST_APPS);
|
|
|
|
int nItems = ListView_GetItemCount(hList);
|
|
|
|
if (nItems == 0) {
|
|
return;
|
|
}
|
|
|
|
if (nWhich > nItems - 1) {
|
|
nWhich = nItems - 1;
|
|
}
|
|
|
|
ListView_SetItemState(hList, nWhich, LVIS_SELECTED, LVIS_SELECTED);
|
|
}
|
|
|
|
void
|
|
RunSelectedApp(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
WCHAR wszCommandLine[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
SaveSettings(hDlg);
|
|
|
|
HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
|
|
|
|
int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
|
|
|
|
if (nApp == -1) {
|
|
return;
|
|
}
|
|
|
|
LVITEM lvi;
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nApp;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_GetItem(hAppList, &lvi);
|
|
|
|
CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
|
|
|
|
if (pApp->wstrExePath.size()) {
|
|
|
|
//
|
|
// first set the current directory properly, if possible
|
|
//
|
|
LPWSTR pwsz;
|
|
|
|
hr = StringCchCopyW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), pApp->wstrExePath.c_str());
|
|
if (FAILED(hr)) {
|
|
AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
|
|
goto out;
|
|
}
|
|
|
|
pwsz = wcsrchr(wszCommandLine, L'\\');
|
|
|
|
if (pwsz) {
|
|
*pwsz = 0;
|
|
SetCurrentDirectory(wszCommandLine);
|
|
*pwsz = L'\\';
|
|
}
|
|
|
|
//
|
|
// then prepare the command line
|
|
//
|
|
|
|
hr = StringCchPrintfW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), L"\"%s\"", pApp->wstrExePath.c_str());
|
|
if (FAILED(hr)) {
|
|
AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
|
|
goto out;
|
|
}
|
|
|
|
} else {
|
|
hr = StringCchPrintfW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), L"\"%s\"", pApp->wstrExeName.c_str());
|
|
if (FAILED(hr)) {
|
|
AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExeName.c_str());
|
|
goto out;
|
|
}
|
|
|
|
}
|
|
|
|
PROCESS_INFORMATION ProcessInfo;
|
|
BOOL bRet;
|
|
STARTUPINFO StartupInfo;
|
|
|
|
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
|
|
StartupInfo.cb = sizeof(StartupInfo);
|
|
|
|
ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
|
|
|
|
bRet = CreateProcess(NULL,
|
|
wszCommandLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&StartupInfo,
|
|
&ProcessInfo);
|
|
|
|
if (!bRet) {
|
|
WCHAR wszFilter[] = L"Executable files (*.exe)\0*.exe\0";
|
|
OPENFILENAME ofn;
|
|
WCHAR wszAppFullPath[MAX_PATH];
|
|
WCHAR wszAppShortName[MAX_PATH];
|
|
|
|
wstring strCaption;
|
|
|
|
if (!AVLoadString(IDS_LOCATE_APP, strCaption)) {
|
|
strCaption = _T("Please locate application");
|
|
}
|
|
|
|
if (pApp->wstrExePath.size()) {
|
|
hr = StringCchCopyW(wszAppFullPath, ARRAY_LENGTH(wszAppFullPath), pApp->wstrExePath.c_str());
|
|
if (FAILED(hr)) {
|
|
AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
|
|
goto out;
|
|
}
|
|
} else {
|
|
hr = StringCchCopyW(wszAppFullPath, ARRAY_LENGTH(wszAppFullPath), pApp->wstrExeName.c_str());
|
|
if (FAILED(hr)) {
|
|
AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExeName.c_str());
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hDlg;
|
|
ofn.hInstance = NULL;
|
|
ofn.lpstrFilter = wszFilter;
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nMaxCustFilter = 0;
|
|
ofn.nFilterIndex = 0;
|
|
ofn.lpstrFile = wszAppFullPath;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrFileTitle = wszAppShortName;
|
|
ofn.nMaxFileTitle = MAX_PATH;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = strCaption.c_str();
|
|
ofn.Flags = OFN_PATHMUSTEXIST |
|
|
OFN_HIDEREADONLY | // hide the "open read-only" checkbox
|
|
OFN_NONETWORKBUTTON | // no network button
|
|
OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
|
|
OFN_SHAREAWARE; // don't check the existance of file with OpenFile
|
|
ofn.lpstrDefExt = NULL;
|
|
|
|
if (!GetOpenFileName(&ofn)) {
|
|
return;
|
|
}
|
|
|
|
pApp->wstrExePath = wszAppFullPath;
|
|
pApp->wstrExeName = wszAppShortName;
|
|
hr = StringCchPrintfW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), L"\"%s\"", pApp->wstrExePath.c_str());
|
|
if (FAILED(hr)) {
|
|
AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
|
|
goto out;
|
|
}
|
|
|
|
RefreshAppList(hDlg);
|
|
|
|
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
|
|
StartupInfo.cb = sizeof(StartupInfo);
|
|
|
|
ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
|
|
|
|
bRet = CreateProcess(NULL,
|
|
wszCommandLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&StartupInfo,
|
|
&ProcessInfo);
|
|
if (!bRet) {
|
|
AVErrorResourceFormat(IDS_CANT_LAUNCH_EXE);
|
|
}
|
|
|
|
}
|
|
out:
|
|
return;
|
|
}
|
|
|
|
void
|
|
AddAppToList(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
|
|
WCHAR wszFilter[] = L"Executable files (*.exe)\0*.exe\0";
|
|
OPENFILENAME ofn;
|
|
WCHAR wszAppFullPath[MAX_PATH];
|
|
WCHAR wszAppShortName[MAX_PATH];
|
|
|
|
wstring wstrTitle;
|
|
|
|
if (!AVLoadString(IDS_ADD_APPLICATION_TITLE, wstrTitle)) {
|
|
wstrTitle = _T("Add Application");
|
|
}
|
|
|
|
wszAppFullPath[0] = 0;
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hDlg;
|
|
ofn.hInstance = NULL;
|
|
ofn.lpstrFilter = wszFilter;
|
|
ofn.lpstrCustomFilter = NULL;
|
|
ofn.nMaxCustFilter = 0;
|
|
ofn.nFilterIndex = 0;
|
|
ofn.lpstrFile = wszAppFullPath;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrFileTitle = wszAppShortName;
|
|
ofn.nMaxFileTitle = MAX_PATH;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.lpstrTitle = wstrTitle.c_str();
|
|
ofn.Flags = OFN_HIDEREADONLY | // hide the "open read-only" checkbox
|
|
OFN_NONETWORKBUTTON | // no network button
|
|
OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
|
|
OFN_SHAREAWARE; // don't check the existance of file with OpenFile
|
|
ofn.lpstrDefExt = _T("EXE");
|
|
|
|
if (!GetOpenFileName(&ofn)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// check to see if the app is already in the list
|
|
//
|
|
CAVAppInfo *pApp;
|
|
BOOL bFound = FALSE;
|
|
|
|
for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
|
|
if (_wcsicmp(pApp->wstrExeName.c_str(), wszAppShortName) == 0) {
|
|
//
|
|
// the app is already in the list, so just update the full
|
|
// path, if it's good
|
|
//
|
|
if (GetFileAttributes(wszAppFullPath) != -1) {
|
|
pApp->wstrExePath = wszAppFullPath;
|
|
}
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// if the app wasn't already in the list, add it to the list
|
|
//
|
|
if (!bFound) {
|
|
CAVAppInfo AppInfo;
|
|
|
|
AppInfo.wstrExeName = wszAppShortName;
|
|
|
|
//
|
|
// check to see if the file actually exists
|
|
//
|
|
if (GetFileAttributes(wszAppFullPath) != -1) {
|
|
AppInfo.wstrExePath = wszAppFullPath;
|
|
}
|
|
|
|
//
|
|
// init the default tests
|
|
//
|
|
CAVAppInfo *pDefaultApp = &g_aAppInfo[0];
|
|
CTestInfo *pTest;
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pDefaultApp->IsTestActive(*pTest)) {
|
|
AppInfo.AddTest(*pTest);
|
|
}
|
|
}
|
|
|
|
g_aAppInfo.push_back(AppInfo);
|
|
|
|
RefreshAppList(hDlg);
|
|
|
|
SelectApp(hDlg, 9999);
|
|
|
|
DirtySettings(hDlg, TRUE);
|
|
}
|
|
}
|
|
|
|
void
|
|
RemoveSelectedApp(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
|
|
|
|
int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
|
|
|
|
if (nApp == -1) {
|
|
return;
|
|
}
|
|
|
|
LVITEM lvi;
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nApp;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_GetItem(hAppList, &lvi);
|
|
|
|
CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
|
|
|
|
//
|
|
// if there is a debugger set for this app, for various reasons we want to
|
|
// kill the debugger before removing the app, or the debugger may linger forever
|
|
//
|
|
if (pApp->bBreakOnLog || pApp->bUseAVDebugger) {
|
|
pApp->bBreakOnLog = FALSE;
|
|
pApp->bUseAVDebugger = FALSE;
|
|
|
|
SetCurrentAppSettings();
|
|
}
|
|
|
|
g_aAppInfo.erase(pApp);
|
|
|
|
RefreshAppList(hDlg);
|
|
|
|
SelectApp(hDlg, nApp);
|
|
|
|
DirtySettings(hDlg, TRUE);
|
|
}
|
|
|
|
typedef struct _CONFLICT_DLG_INFO {
|
|
CTestInfo *pTest1;
|
|
CTestInfo *pTest2;
|
|
} CONFLICT_DLG_INFO, *PCONFLICT_DLG_INFO;
|
|
|
|
void
|
|
CheckForRunAlone(
|
|
CAVAppInfo *pApp
|
|
)
|
|
{
|
|
if (!pApp) {
|
|
return;
|
|
}
|
|
|
|
DWORD dwTests = 0;
|
|
|
|
//
|
|
// count the number of tests active
|
|
//
|
|
for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pApp->IsTestActive(*pTest)) {
|
|
dwTests++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// look for conflicts
|
|
//
|
|
for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
//
|
|
// if there are less than two, no chance for conflict
|
|
//
|
|
if (dwTests < 2) {
|
|
return;
|
|
}
|
|
|
|
if (pTest->bRunAlone && pApp->IsTestActive(*pTest)) {
|
|
CONFLICT_DLG_INFO DlgInfo;
|
|
|
|
ZeroMemory(&DlgInfo, sizeof(DlgInfo));
|
|
|
|
DlgInfo.pTest1 = pTest; // pTest2 is unused in this case
|
|
|
|
INT_PTR nResult = DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_MUST_RUN_ALONE), g_hDlgMain, DlgRunAlone, (LPARAM)&DlgInfo);
|
|
|
|
switch (nResult) {
|
|
case IDC_BTN_DISABLE1:
|
|
pApp->RemoveTest(*pTest);
|
|
DirtySettings(g_hDlgMain, TRUE);
|
|
RefreshSettingsList(g_hDlgMain, TRUE);
|
|
dwTests--;
|
|
break;
|
|
|
|
case IDC_BTN_DISABLE2:
|
|
//
|
|
// disable all the tests except the one passed in
|
|
//
|
|
for (CTestInfo *pTestTemp = g_aTestInfo.begin(); pTestTemp != g_aTestInfo.end(); pTestTemp++) {
|
|
if (pTest != pTestTemp) {
|
|
pApp->RemoveTest(*pTestTemp);
|
|
}
|
|
}
|
|
DirtySettings(g_hDlgMain, TRUE);
|
|
RefreshSettingsList(g_hDlgMain, TRUE);
|
|
dwTests = 1;
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CheckForConflictingTests(
|
|
CAVAppInfo *pApp,
|
|
LPCWSTR wszTest1,
|
|
LPCWSTR wszTest2
|
|
)
|
|
{
|
|
CONFLICT_DLG_INFO DlgInfo;
|
|
|
|
ZeroMemory(&DlgInfo, sizeof(DlgInfo));
|
|
|
|
//
|
|
// get the test pointers from the names
|
|
//
|
|
for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pTest->strTestName == wszTest1) {
|
|
DlgInfo.pTest1 = pTest;
|
|
}
|
|
if (pTest->strTestName == wszTest2) {
|
|
DlgInfo.pTest2 = pTest;
|
|
}
|
|
}
|
|
|
|
//
|
|
// if we didn't find one or the other tests, get out
|
|
//
|
|
if (!DlgInfo.pTest1 || !DlgInfo.pTest2) {
|
|
return;
|
|
}
|
|
|
|
if (pApp->IsTestActive(*DlgInfo.pTest1) && pApp->IsTestActive(*DlgInfo.pTest2)) {
|
|
INT_PTR nResult = DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_CONFLICT), g_hDlgMain, DlgConflict, (LPARAM)&DlgInfo);
|
|
|
|
switch (nResult) {
|
|
case IDC_BTN_DISABLE1:
|
|
pApp->RemoveTest(*DlgInfo.pTest1);
|
|
DirtySettings(g_hDlgMain, TRUE);
|
|
RefreshSettingsList(g_hDlgMain, TRUE);
|
|
break;
|
|
|
|
case IDC_BTN_DISABLE2:
|
|
pApp->RemoveTest(*DlgInfo.pTest2);
|
|
DirtySettings(g_hDlgMain, TRUE);
|
|
RefreshSettingsList(g_hDlgMain, TRUE);
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
ScanSettingsList(
|
|
HWND hDlg,
|
|
int nItem
|
|
)
|
|
{
|
|
|
|
HWND hSettingList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
|
|
HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
|
|
int nBegin, nEnd;
|
|
|
|
int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
|
|
|
|
if (nApp == -1) {
|
|
return;
|
|
}
|
|
|
|
LVITEM lvi;
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nApp;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_GetItem(hAppList, &lvi);
|
|
|
|
CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
|
|
|
|
if (!pApp) {
|
|
return;
|
|
}
|
|
|
|
int nItems = ListView_GetItemCount(hSettingList);
|
|
|
|
if (!nItems) {
|
|
//
|
|
// nothing in list
|
|
//
|
|
return;
|
|
}
|
|
|
|
if (nItem == -1 || nItem >= nItems) {
|
|
nBegin = 0;
|
|
nEnd = nItems;
|
|
} else {
|
|
nBegin = nItem;
|
|
nEnd = nItem + 1;
|
|
}
|
|
|
|
for (int i = nBegin; i < nEnd; ++i) {
|
|
BOOL bTestEnabled = FALSE;
|
|
BOOL bChecked = FALSE;
|
|
|
|
lvi.iItem = i;
|
|
|
|
ListView_GetItem(hSettingList, &lvi);
|
|
|
|
CTestInfo *pTest = (CTestInfo*)lvi.lParam;
|
|
|
|
bChecked = ListView_GetCheckState(hSettingList, i);
|
|
|
|
bTestEnabled = pApp->IsTestActive(*pTest);
|
|
|
|
if (bTestEnabled != bChecked) {
|
|
DirtySettings(hDlg, TRUE);
|
|
|
|
if (bChecked) {
|
|
pApp->AddTest(*pTest);
|
|
} else {
|
|
pApp->RemoveTest(*pTest);
|
|
}
|
|
}
|
|
|
|
CheckForRunAlone(pApp);
|
|
}
|
|
|
|
CheckForConflictingTests(pApp, L"LogFileChanges", L"WindowsFileProtection");
|
|
}
|
|
|
|
void
|
|
DisplaySettingsDescription(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
HWND hList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
|
|
|
|
int nItem = ListView_GetNextItem(hList, -1, LVNI_SELECTED);
|
|
|
|
if (nItem == -1) {
|
|
WCHAR szTestDesc[256];
|
|
|
|
LoadString(g_hInstance, IDS_VIEW_TEST_DESC, szTestDesc, ARRAY_LENGTH(szTestDesc));
|
|
SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), szTestDesc);
|
|
} else {
|
|
LVITEM lvi;
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nItem;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_GetItem(hList, &lvi);
|
|
|
|
CTestInfo *pTest = (CTestInfo*)lvi.lParam;
|
|
|
|
SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), pTest->strTestDescription.c_str());
|
|
}
|
|
|
|
}
|
|
|
|
CAVAppInfo *
|
|
GetCurrentAppSelection(
|
|
void
|
|
)
|
|
{
|
|
if (!g_hDlgMain) {
|
|
return NULL;
|
|
}
|
|
|
|
HWND hAppList = GetDlgItem(g_hDlgMain, IDC_LIST_APPS);
|
|
|
|
int nItem = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
|
|
|
|
if (nItem == -1) {
|
|
return NULL;
|
|
}
|
|
|
|
LVITEM lvi;
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nItem;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_GetItem(hAppList, &lvi);
|
|
|
|
CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
|
|
|
|
return pApp;
|
|
|
|
}
|
|
|
|
void
|
|
RefreshSettingsList(
|
|
HWND hDlg,
|
|
BOOL bForceRefresh
|
|
)
|
|
{
|
|
g_bRefreshingSettings = TRUE;
|
|
|
|
HWND hSettingList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
|
|
HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
|
|
|
|
static nLastItem = -1;
|
|
|
|
int nItem = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
|
|
|
|
if (nItem == -1) {
|
|
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), FALSE);
|
|
|
|
} else if (nItem == 0) {
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), TRUE);
|
|
|
|
} else {
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), TRUE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), TRUE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), TRUE);
|
|
}
|
|
|
|
if (nItem == nLastItem && !bForceRefresh) {
|
|
goto out;
|
|
|
|
}
|
|
|
|
ListView_DeleteAllItems(hSettingList);
|
|
|
|
DisplaySettingsDescription(hDlg);
|
|
|
|
nLastItem = nItem;
|
|
|
|
if (nItem != -1) {
|
|
LVITEM lvi;
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nItem;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_GetItem(hAppList, &lvi);
|
|
|
|
CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
|
|
|
|
if (!pApp) {
|
|
return;
|
|
}
|
|
|
|
CTestInfo* pTest;
|
|
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
//
|
|
// continue if this test isn't win2K compatible, and we're running on win2k
|
|
//
|
|
if (g_bWin2KMode && !pTest->bWin2KCompatible) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// continue if this test is invalid for the current internal/external mode
|
|
//
|
|
if ((g_bInternalMode && !pTest->bInternal) || (!g_bInternalMode && !pTest->bExternal)) {
|
|
continue;
|
|
}
|
|
|
|
WCHAR szText[256];
|
|
|
|
//
|
|
// don't check the return, because if it's truncated, that's acceptable
|
|
//
|
|
StringCchPrintfW(szText, ARRAY_LENGTH(szText), L"%s - %s", pTest->strTestName.c_str(), pTest->strTestFriendlyName.c_str());
|
|
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM;
|
|
lvi.pszText = (LPWSTR)szText;
|
|
lvi.lParam = (LPARAM)pTest;
|
|
lvi.iItem = 9999;
|
|
lvi.iSubItem = 0;
|
|
|
|
nItem = ListView_InsertItem(hSettingList, &lvi);
|
|
|
|
BOOL bCheck = pApp->IsTestActive(*pTest);
|
|
|
|
ListView_SetCheckState(hSettingList, nItem, bCheck);
|
|
}
|
|
}
|
|
out:
|
|
|
|
g_bRefreshingSettings = FALSE;
|
|
|
|
return;
|
|
}
|
|
|
|
static const DWORD MAX_DEBUGGER_LEN = 1024;
|
|
|
|
void
|
|
ReadOptions(
|
|
void
|
|
)
|
|
{
|
|
for (CAVAppInfo *pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); ++pApp) {
|
|
LPCWSTR szExe = pApp->wstrExeName.c_str();
|
|
|
|
|
|
WCHAR szDebugger[MAX_DEBUGGER_LEN];
|
|
|
|
pApp->bBreakOnLog = GetShimSettingDWORD(L"General", szExe, AV_OPTION_BREAK_ON_LOG, FALSE);
|
|
pApp->bFullPageHeap = GetShimSettingDWORD(L"General", szExe, AV_OPTION_FULL_PAGEHEAP, FALSE);
|
|
pApp->bUseAVDebugger = GetShimSettingDWORD(L"General", szExe, AV_OPTION_AV_DEBUGGER, FALSE);
|
|
pApp->bPropagateTests = GetShimSettingDWORD(L"General", szExe, AV_OPTION_PROPAGATE, FALSE);
|
|
|
|
szDebugger[0] = 0;
|
|
GetShimSettingString(L"General", szExe, AV_OPTION_DEBUGGER, szDebugger, MAX_DEBUGGER_LEN);
|
|
pApp->wstrDebugger = szDebugger;
|
|
}
|
|
}
|
|
|
|
void
|
|
SaveOptions(
|
|
void
|
|
)
|
|
{
|
|
|
|
for (CAVAppInfo *pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); ++pApp) {
|
|
LPCWSTR szExe = pApp->wstrExeName.c_str();
|
|
|
|
SaveShimSettingDWORD(L"General", szExe, AV_OPTION_BREAK_ON_LOG, (DWORD)pApp->bBreakOnLog);
|
|
SaveShimSettingDWORD(L"General", szExe, AV_OPTION_FULL_PAGEHEAP, (DWORD)pApp->bFullPageHeap);
|
|
SaveShimSettingDWORD(L"General", szExe, AV_OPTION_AV_DEBUGGER, (DWORD)pApp->bUseAVDebugger);
|
|
SaveShimSettingDWORD(L"General", szExe, AV_OPTION_PROPAGATE, (DWORD)pApp->bPropagateTests);
|
|
SaveShimSettingString(L"General", szExe, AV_OPTION_DEBUGGER, pApp->wstrDebugger.c_str());
|
|
}
|
|
|
|
SetCurrentAppSettings();
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK
|
|
DlgRunAlone(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
{
|
|
WCHAR wszTemp[256];
|
|
WCHAR wszExpandedTemp[512];
|
|
PCONFLICT_DLG_INFO pDlgInfo;
|
|
|
|
pDlgInfo = (PCONFLICT_DLG_INFO)lParam;
|
|
|
|
wszTemp[0] = 0;
|
|
AVLoadString(IDS_RUN_ALONE_MESSAGE, wszTemp, ARRAY_LENGTH(wszTemp));
|
|
|
|
StringCchPrintfW(
|
|
wszExpandedTemp,
|
|
ARRAY_LENGTH(wszExpandedTemp),
|
|
wszTemp,
|
|
pDlgInfo->pTest1->strTestFriendlyName.c_str()
|
|
);
|
|
|
|
SetDlgItemTextW(hDlg, IDC_CONFLICT_STATIC, wszExpandedTemp);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_BTN_DISABLE1:
|
|
case IDC_BTN_DISABLE2:
|
|
case IDCANCEL:
|
|
//
|
|
// return the button that was pressed
|
|
//
|
|
EndDialog(hDlg, (INT_PTR)LOWORD(wParam));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK
|
|
DlgConflict(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
{
|
|
WCHAR wszTemp[256];
|
|
WCHAR wszExpandedTemp[512];
|
|
PCONFLICT_DLG_INFO pDlgInfo;
|
|
|
|
pDlgInfo = (PCONFLICT_DLG_INFO)lParam;
|
|
|
|
wszTemp[0] = 0;
|
|
AVLoadString(IDS_CONFLICT_MESSAGE, wszTemp, ARRAY_LENGTH(wszTemp));
|
|
|
|
StringCchPrintf(
|
|
wszExpandedTemp,
|
|
ARRAY_LENGTH(wszExpandedTemp),
|
|
wszTemp,
|
|
pDlgInfo->pTest1->strTestFriendlyName.c_str(),
|
|
pDlgInfo->pTest2->strTestFriendlyName.c_str()
|
|
);
|
|
|
|
SetDlgItemTextW(hDlg, IDC_CONFLICT_STATIC, wszExpandedTemp);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_BTN_DISABLE1:
|
|
case IDC_BTN_DISABLE2:
|
|
case IDCANCEL:
|
|
//
|
|
// return the button that was pressed
|
|
//
|
|
EndDialog(hDlg, (INT_PTR)LOWORD(wParam));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR CALLBACK
|
|
DlgViewOptions(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
static CAVAppInfo *pApp;
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
|
|
g_hDlgOptions = hDlg;
|
|
pApp = GetCurrentAppSelection();
|
|
|
|
if (!pApp) {
|
|
return FALSE;
|
|
}
|
|
|
|
ReadOptions();
|
|
|
|
//
|
|
// initialize the combo box options
|
|
//
|
|
SendDlgItemMessage(hDlg,
|
|
IDC_COMBO_DEBUGGER,
|
|
CB_ADDSTRING,
|
|
0,
|
|
(LPARAM)L"ntsd");
|
|
SendDlgItemMessage(hDlg,
|
|
IDC_COMBO_DEBUGGER,
|
|
CB_ADDSTRING,
|
|
0,
|
|
(LPARAM)L"windbg");
|
|
|
|
if (pApp->bBreakOnLog) {
|
|
pApp->bUseAVDebugger = FALSE;
|
|
EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), TRUE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), TRUE);
|
|
|
|
if (!pApp->wstrDebugger.size()) {
|
|
SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, L"ntsd");
|
|
} else {
|
|
SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, pApp->wstrDebugger.c_str());
|
|
}
|
|
} else {
|
|
EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), TRUE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), FALSE);
|
|
}
|
|
|
|
/*SendDlgItemMessage(hDlg,
|
|
IDC_CLEAR_LOG_ON_CHANGES,
|
|
BM_SETCHECK,
|
|
(pApp->bClearSessionLogBeforeRun ? BST_CHECKED : BST_UNCHECKED),
|
|
0);*/
|
|
|
|
SendDlgItemMessage(hDlg,
|
|
IDC_BREAK_ON_LOG,
|
|
BM_SETCHECK,
|
|
(pApp->bBreakOnLog ? BST_CHECKED : BST_UNCHECKED),
|
|
0);
|
|
|
|
SendDlgItemMessage(hDlg,
|
|
IDC_FULL_PAGEHEAP,
|
|
BM_SETCHECK,
|
|
(pApp->bFullPageHeap ? BST_CHECKED : BST_UNCHECKED),
|
|
0);
|
|
|
|
SendDlgItemMessage(hDlg,
|
|
IDC_USE_AV_DEBUGGER,
|
|
BM_SETCHECK,
|
|
(pApp->bUseAVDebugger ? BST_CHECKED : BST_UNCHECKED),
|
|
0);
|
|
|
|
SendDlgItemMessage(hDlg,
|
|
IDC_PROPAGATE_TESTS,
|
|
BM_SETCHECK,
|
|
(pApp->bPropagateTests ? BST_CHECKED : BST_UNCHECKED),
|
|
0);
|
|
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_BREAK_ON_LOG:
|
|
{
|
|
BOOL bChecked = IsDlgButtonChecked(hDlg, IDC_BREAK_ON_LOG);
|
|
if (bChecked) {
|
|
WCHAR szTemp[256];
|
|
|
|
CheckDlgButton(hDlg, IDC_USE_AV_DEBUGGER, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), TRUE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), TRUE);
|
|
|
|
GetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, szTemp, ARRAY_LENGTH(szTemp));
|
|
|
|
if (!szTemp[0]) {
|
|
if (!pApp->wstrDebugger.size()) {
|
|
SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, L"ntsd");
|
|
} else {
|
|
SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, pApp->wstrDebugger.c_str());
|
|
}
|
|
}
|
|
} else {
|
|
EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), TRUE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
switch (((NMHDR FAR *) lParam)->code) {
|
|
|
|
case PSN_APPLY:
|
|
/* pApp->bClearSessionLogBeforeRun = (SendDlgItemMessage(hDlg,
|
|
IDC_CLEAR_LOG_ON_CHANGES,
|
|
BM_GETCHECK,
|
|
0,
|
|
0) == BST_CHECKED);*/
|
|
|
|
pApp->bBreakOnLog = (SendDlgItemMessage(hDlg,
|
|
IDC_BREAK_ON_LOG,
|
|
BM_GETCHECK,
|
|
0,
|
|
0) == BST_CHECKED);
|
|
|
|
pApp->bFullPageHeap = (SendDlgItemMessage(hDlg,
|
|
IDC_FULL_PAGEHEAP,
|
|
BM_GETCHECK,
|
|
0,
|
|
0) == BST_CHECKED);
|
|
|
|
pApp->bUseAVDebugger = (SendDlgItemMessage(hDlg,
|
|
IDC_USE_AV_DEBUGGER,
|
|
BM_GETCHECK,
|
|
0,
|
|
0) == BST_CHECKED);
|
|
|
|
pApp->bPropagateTests = (SendDlgItemMessage(hDlg,
|
|
IDC_PROPAGATE_TESTS,
|
|
BM_GETCHECK,
|
|
0,
|
|
0) == BST_CHECKED);
|
|
|
|
WCHAR szDebugger[MAX_DEBUGGER_LEN];
|
|
|
|
szDebugger[0] = 0;
|
|
GetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, szDebugger, ARRAY_LENGTH(szDebugger));
|
|
|
|
pApp->wstrDebugger = szDebugger;
|
|
|
|
SaveOptions();
|
|
|
|
g_hDlgOptions = NULL;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
ViewOptions(
|
|
HWND hDlg
|
|
)
|
|
{
|
|
HPROPSHEETPAGE *phPages = NULL;
|
|
PROPSHEETPAGE PageGlobal;
|
|
PROPSHEETHEADER psh;
|
|
|
|
CTestInfo* pTest;
|
|
DWORD dwPages = 1;
|
|
DWORD dwPage = 0;
|
|
|
|
CAVAppInfo *pApp = GetCurrentAppSelection();
|
|
|
|
if (!pApp) {
|
|
return;
|
|
}
|
|
|
|
LPCWSTR szExe = pApp->wstrExeName.c_str();
|
|
|
|
//
|
|
// count the number of pages
|
|
//
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pTest->PropSheetPage.pfnDlgProc) {
|
|
dwPages++;
|
|
}
|
|
}
|
|
|
|
phPages = new HPROPSHEETPAGE[dwPages];
|
|
if (!phPages) {
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// init the global page
|
|
//
|
|
PageGlobal.dwSize = sizeof(PROPSHEETPAGE);
|
|
PageGlobal.dwFlags = PSP_USETITLE;
|
|
PageGlobal.hInstance = g_hInstance;
|
|
PageGlobal.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS);
|
|
PageGlobal.pfnDlgProc = DlgViewOptions;
|
|
PageGlobal.pszTitle = MAKEINTRESOURCE(IDS_GLOBAL_OPTIONS);
|
|
PageGlobal.lParam = 0;
|
|
PageGlobal.pfnCallback = NULL;
|
|
phPages[0] = CreatePropertySheetPage(&PageGlobal);
|
|
|
|
if (!phPages[0]) {
|
|
//
|
|
// we need the global page minimum
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// add the pages for the various tests
|
|
//
|
|
dwPage = 1;
|
|
for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
|
|
if (pTest->PropSheetPage.pfnDlgProc) {
|
|
|
|
//
|
|
// we use the lParam to identify the exe involved
|
|
//
|
|
pTest->PropSheetPage.lParam = (LPARAM)szExe;
|
|
|
|
phPages[dwPage] = CreatePropertySheetPage(&(pTest->PropSheetPage));
|
|
if (!phPages[dwPage]) {
|
|
dwPages--;
|
|
} else {
|
|
dwPage++;
|
|
}
|
|
}
|
|
}
|
|
|
|
wstring wstrOptions;
|
|
AVLoadString(IDS_OPTIONS_TITLE, wstrOptions);
|
|
|
|
wstrOptions += L" - ";
|
|
wstrOptions += szExe;
|
|
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP;
|
|
psh.hwndParent = hDlg;
|
|
psh.hInstance = g_hInstance;
|
|
psh.pszCaption = wstrOptions.c_str();
|
|
psh.nPages = dwPages;
|
|
psh.nStartPage = 0;
|
|
psh.phpage = phPages;
|
|
psh.pfnCallback = NULL;
|
|
|
|
PropertySheet(&psh);
|
|
}
|
|
|
|
// Message handler for main dialog.
|
|
INT_PTR CALLBACK
|
|
DlgMain(
|
|
HWND hDlg,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
{
|
|
wstring strTemp;
|
|
|
|
g_hDlgMain = hDlg;
|
|
|
|
//
|
|
// set the caption to the appropriate version, etc.
|
|
//
|
|
if (GetAppTitleString(strTemp)) {
|
|
SetWindowText(hDlg, strTemp.c_str());
|
|
}
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_SAVE_SETTINGS), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), FALSE);
|
|
|
|
HWND hList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
|
|
|
|
if (hList) {
|
|
LVCOLUMN lvc;
|
|
|
|
lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.cx = 700;
|
|
lvc.iSubItem = 0;
|
|
lvc.pszText = L"xxx";
|
|
|
|
ListView_InsertColumn(hList, 0, &lvc);
|
|
ListView_SetExtendedListViewStyleEx(hList, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
|
|
|
|
}
|
|
|
|
hList = GetDlgItem(hDlg, IDC_LIST_APPS);
|
|
if (hList) {
|
|
LVITEM lvi;
|
|
LVCOLUMN lvc;
|
|
|
|
lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.cx = 250;
|
|
lvc.iSubItem = 0;
|
|
lvc.pszText = L"xxx";
|
|
|
|
ListView_InsertColumn(hList, 0, &lvc);
|
|
|
|
RefreshAppList(hDlg);
|
|
|
|
SelectApp(hDlg, 0);
|
|
}
|
|
|
|
WCHAR szTestDesc[256];
|
|
|
|
LoadString(g_hInstance, IDS_VIEW_TEST_DESC, szTestDesc, ARRAY_LENGTH(szTestDesc));
|
|
SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), szTestDesc);
|
|
|
|
//
|
|
// Show the app icon.
|
|
//
|
|
HICON hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
|
|
|
|
SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)hIcon);
|
|
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_ACTIVATE:
|
|
if (LOWORD(wParam) == WA_INACTIVE) {
|
|
SaveSettingsIfDirty(hDlg);
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_BTN_ADD:
|
|
AddAppToList(hDlg);
|
|
break;
|
|
|
|
case IDC_BTN_REMOVE:
|
|
RemoveSelectedApp(hDlg);
|
|
break;
|
|
|
|
case IDC_BTN_VIEW_LOG:
|
|
DisplayLog(hDlg);
|
|
break;
|
|
|
|
case IDC_BTN_VIEW_EXTERNAL_LOG:
|
|
DisplaySingleLog(hDlg);
|
|
break;
|
|
|
|
case IDC_BTN_OPTIONS:
|
|
ViewOptions(hDlg);
|
|
break;
|
|
|
|
case IDC_BTN_RUN:
|
|
RunSelectedApp(hDlg);
|
|
break;
|
|
|
|
case IDC_BTN_HELP:
|
|
ShowHTMLHelp();
|
|
break;
|
|
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
SaveSettings(hDlg);
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
g_hDlgMain = NULL;
|
|
PostQuitMessage(0);
|
|
return TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
LPNMHDR pnmh = (LPNMHDR)lParam;
|
|
|
|
HWND hItem = pnmh->hwndFrom;
|
|
|
|
if (hItem == GetDlgItem(hDlg, IDC_LIST_APPS)) {
|
|
switch (pnmh->code) {
|
|
case LVN_KEYDOWN:
|
|
{
|
|
LPNMLVKEYDOWN pnmkd = (LPNMLVKEYDOWN)lParam;
|
|
|
|
if (pnmkd->wVKey == VK_DELETE) {
|
|
if (IsWindowEnabled(GetDlgItem(hDlg, IDC_BTN_RUN))) {
|
|
RemoveSelectedApp(hDlg);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
|
|
|
if (!g_bRefreshingSettings && (pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED)) {
|
|
RefreshSettingsList(hDlg);
|
|
}
|
|
|
|
}
|
|
} else if (hItem == GetDlgItem(hDlg, IDC_LIST_SETTINGS)) {
|
|
switch (pnmh->code) {
|
|
case LVN_ITEMCHANGED:
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
|
|
|
if (!g_bRefreshingSettings) {
|
|
//
|
|
// check for change in selection
|
|
//
|
|
if ((pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED)) {
|
|
DisplaySettingsDescription(hDlg);
|
|
}
|
|
|
|
//
|
|
// check for change in checkbox
|
|
//
|
|
if ((pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) >> 12) != 0) {
|
|
ScanSettingsList(hDlg, pnmv->iItem);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|