Windows2003-3790/windows/appcompat/appverifier/appverifier.cpp

1979 lines
52 KiB
C++
Raw Normal View History

2001-01-01 00:00:00 +01:00
#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;
}