Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1382 lines
35 KiB

  1. #include "precomp.h"
  2. #include "dbsupport.h"
  3. #include "viewlog.h"
  4. #define AV_OPTIONS_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\AppVerifier"
  5. #define AV_OPTION_CLEAR_LOG L"ClearLogsBeforeRun"
  6. #define AV_OPTION_BREAK_ON_LOG L"BreakOnLog"
  7. #define AV_OPTION_FULL_PAGEHEAP L"FullPageHeap"
  8. #define AV_OPTION_AV_DEBUGGER L"UseAVDebugger"
  9. //
  10. // Forward declarations
  11. //
  12. void RefreshSettingsList(HWND hDlg);
  13. CWinApp theApp;
  14. HINSTANCE g_hInstance = NULL;
  15. BOOL g_bSettingsDirty = FALSE;
  16. BOOL g_bRefreshingSettings = FALSE;
  17. BOOL g_bConsoleMode = FALSE;
  18. //
  19. // AppVerifier options
  20. //
  21. BOOL g_bClearSessionLogBeforeRun;
  22. BOOL g_bBreakOnLog;
  23. BOOL g_bFullPageHeap;
  24. BOOL g_bUseAVDebugger;
  25. // forward function declarations
  26. LRESULT CALLBACK DlgMain(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  27. BOOL
  28. GetAppTitleString(
  29. wstring &strTitle
  30. )
  31. {
  32. wstring strVersion;
  33. if (!AVLoadString(IDS_APP_NAME, strTitle)) {
  34. return FALSE;
  35. }
  36. if (!AVLoadString(IDS_VERSION_STRING, strVersion)) {
  37. return FALSE;
  38. }
  39. strTitle += L" ";
  40. strTitle += strVersion;
  41. return TRUE;
  42. }
  43. BOOL
  44. SearchGroupForSID(
  45. DWORD dwGroup,
  46. BOOL* pfIsMember
  47. )
  48. {
  49. PSID pSID;
  50. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  51. BOOL fRes = TRUE;
  52. if (!AllocateAndInitializeSid(&SIDAuth,
  53. 2,
  54. SECURITY_BUILTIN_DOMAIN_RID,
  55. dwGroup,
  56. 0,
  57. 0,
  58. 0,
  59. 0,
  60. 0,
  61. 0,
  62. &pSID)) {
  63. fRes = FALSE;
  64. }
  65. if (!CheckTokenMembership(NULL, pSID, pfIsMember)) {
  66. fRes = FALSE;
  67. }
  68. FreeSid(pSID);
  69. return fRes;
  70. }
  71. BOOL
  72. CanRun(
  73. void
  74. )
  75. {
  76. BOOL fIsAdmin;
  77. if (!SearchGroupForSID(DOMAIN_ALIAS_RID_ADMINS, &fIsAdmin))
  78. {
  79. return FALSE;
  80. }
  81. return fIsAdmin;
  82. }
  83. void
  84. DumpCurrentSettingsToConsole(void)
  85. {
  86. CAVAppInfo *pApp;
  87. printf("\n");
  88. printf("Current Verifier Settings:\n\n");
  89. for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
  90. printf("%ls:\n", pApp->wstrExeName.c_str());
  91. CTestInfo *pTest;
  92. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  93. if (pApp->IsTestActive(*pTest)) {
  94. printf(" %ls\n", pTest->strTestCommandLine.c_str());
  95. }
  96. }
  97. printf("\n");
  98. }
  99. printf("Done.\n");
  100. printf("\n");
  101. }
  102. void
  103. DumpHelpToConsole(void)
  104. {
  105. printf("\n");
  106. printf("Usage: appverif.exe [flags] [tests] [APP [APP...]]\n");
  107. printf("\n");
  108. printf("No command-line: run appverif.exe in GUI mode.\n");
  109. printf("\n");
  110. printf("Flags:\n");
  111. printf(" /? - print this help text.\n");
  112. printf(" /querysettings (/q) - dump current settings to console.\n");
  113. printf(" /reset (/r) - reset (clear) all settings for all apps.\n");
  114. printf(" /all (/a) - enable all tests for specified apps.\n");
  115. printf(" /default (/d) - enable default tests for specified apps.\n");
  116. printf(" /none (/n) - disable all tests for specified apps.\n");
  117. printf("\n");
  118. printf("Tests (prefix with '+' to add and '-' to remove):\n");
  119. printf("\n");
  120. printf(" Kernel Tests:\n");
  121. CTestInfo *pTest;
  122. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  123. if (pTest->eTestType == TEST_KERNEL) {
  124. printf(" %ls\n", pTest->strTestCommandLine.c_str());
  125. }
  126. }
  127. printf("\n");
  128. printf(" Shim Tests:\n");
  129. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  130. if (pTest->eTestType == TEST_SHIM) {
  131. printf(" %ls\n", pTest->strTestCommandLine.c_str());
  132. }
  133. }
  134. printf("\n");
  135. printf("(For descriptions of tests, run appverif.exe in GUI mode.)\n");
  136. printf("\n");
  137. printf("Examples:\n");
  138. printf("\n");
  139. printf(" appverif /d -pageheap foo.exe\n");
  140. printf(" (turn on default tests except pageheap for foo.exe)\n");
  141. printf("\n");
  142. printf(" appverif /a -locks foo.exe\n");
  143. printf(" (turn on all tests except locks for foo.exe)\n");
  144. printf("\n");
  145. printf(" appverif +pageheap foo.exe bar.exe\n");
  146. printf(" (turn on just pageheap for foo.exe & bar.exe)\n");
  147. printf("\n");
  148. printf(" appverif /n foo.exe\n");
  149. printf(" (clear all tests for foo.exe)\n");
  150. printf("\n");
  151. printf(" appverif /r\n");
  152. printf(" (clear all tests for all apps)\n");
  153. printf("\n");
  154. }
  155. void
  156. HandleCommandLine(int argc, LPWSTR *argv)
  157. {
  158. WCHAR szApp[MAX_PATH];
  159. wstring strTemp;
  160. CWStringArray astrApps;
  161. szApp[0] = 0;
  162. g_bConsoleMode = TRUE;
  163. //
  164. // print the title
  165. //
  166. if (GetAppTitleString(strTemp)) {
  167. printf("\n%ls\n", strTemp.c_str());
  168. }
  169. if (AVLoadString(IDS_COPYRIGHT, strTemp)) {
  170. printf("%ls\n\n", strTemp.c_str());
  171. }
  172. //
  173. // check for global operations
  174. //
  175. if (_wcsnicmp(argv[0], L"/q", 2) == 0) { // querysettings
  176. DumpCurrentSettingsToConsole();
  177. return;
  178. }
  179. if (_wcsicmp(argv[0], L"/?") == 0) { // help
  180. DumpHelpToConsole();
  181. return;
  182. }
  183. if (_wcsnicmp(argv[0], L"/r", 2) == 0) { // reset
  184. g_aAppInfo.clear();
  185. goto out;
  186. }
  187. //
  188. // first get a list of the app names
  189. //
  190. for (int nArg = 0 ; nArg != argc; nArg++) {
  191. WCHAR wc = argv[nArg][0];
  192. if (wc != L'/' && wc != L'-' && wc != L'+') {
  193. astrApps.push_back(argv[nArg]);
  194. }
  195. }
  196. if (astrApps.size() == 0) {
  197. AVErrorResourceFormat(IDS_NO_APP);
  198. DumpHelpToConsole();
  199. return;
  200. }
  201. //
  202. // now for each app name, parse the list and adjust its settings
  203. //
  204. for (wstring *pStr = astrApps.begin(); pStr != astrApps.end(); pStr++) {
  205. CAVAppInfo *pApp;
  206. BOOL bFound = FALSE;
  207. //
  208. // check to see if they submitted a full path
  209. //
  210. const WCHAR * pExe = NULL;
  211. const WCHAR * pPath = NULL;
  212. pExe = wcsrchr(pStr->c_str(), L'\\');
  213. if (!pExe) {
  214. if ((*pStr)[1] == L':') {
  215. pExe = pStr->c_str() + 2;
  216. }
  217. } else {
  218. pExe++;
  219. }
  220. if (pExe) {
  221. pPath = pStr->c_str();
  222. } else {
  223. pExe = pStr->c_str();
  224. }
  225. //
  226. // first, find or add the app to the list, and get a pointer to it
  227. //
  228. for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
  229. if (_wcsicmp(pApp->wstrExeName.c_str(), pExe) == 0) {
  230. bFound = TRUE;
  231. break;
  232. }
  233. }
  234. if (!bFound) {
  235. CAVAppInfo App;
  236. App.wstrExeName = pExe;
  237. g_aAppInfo.push_back(App);
  238. pApp = g_aAppInfo.end() - 1;
  239. }
  240. //
  241. // if they submitted a full path, update the records
  242. //
  243. if (pPath) {
  244. pApp->wstrExePath = pPath;
  245. }
  246. //
  247. // now walk the command line again and make the adjustments
  248. //
  249. for (int nArg = 0 ; nArg != argc; nArg++) {
  250. if (argv[nArg][0] == L'/') {
  251. if (_wcsnicmp(argv[nArg], L"/a", 2) == 0) { // all
  252. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  253. pApp->AddTest(*pTest);
  254. }
  255. } else if (_wcsnicmp(argv[nArg], L"/n", 2) == 0) { // none
  256. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  257. pApp->RemoveTest(*pTest);
  258. }
  259. } else if (_wcsnicmp(argv[nArg], L"/d", 2) == 0) { // default
  260. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  261. if (pTest->bDefault) {
  262. pApp->AddTest(*pTest);
  263. } else {
  264. pApp->RemoveTest(*pTest);
  265. }
  266. }
  267. } else {
  268. //
  269. // unknown parameter
  270. //
  271. AVErrorResourceFormat(IDS_INVALID_PARAMETER, argv[nArg]);
  272. DumpHelpToConsole();
  273. return;
  274. }
  275. } else if (argv[nArg][0] == L'+' || argv[nArg][0] == L'-') {
  276. BOOL bAdd = (argv[nArg][0] == L'+');
  277. LPWSTR szParam = argv[nArg] + 1;
  278. //
  279. // see if it's a shim name
  280. //
  281. CTestInfo *pTest;
  282. BOOL bFound = FALSE;
  283. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  284. if (_wcsicmp(szParam, pTest->strTestCommandLine.c_str()) == 0) {
  285. if (bAdd) {
  286. pApp->AddTest(*pTest);
  287. } else {
  288. pApp->RemoveTest(*pTest);
  289. }
  290. bFound = TRUE;
  291. break;
  292. }
  293. }
  294. if (!bFound) {
  295. //
  296. // unknown test
  297. //
  298. AVErrorResourceFormat(IDS_INVALID_TEST, szParam);
  299. DumpHelpToConsole();
  300. return;
  301. }
  302. }
  303. //
  304. // anything that doesn't begin with a slash, plus, or minus
  305. // is an app name, so we'll ignore it
  306. //
  307. }
  308. }
  309. out:
  310. //
  311. // save them to disk/registry
  312. //
  313. SetCurrentAppSettings();
  314. //
  315. // show them the current settings, for verification
  316. //
  317. DumpCurrentSettingsToConsole();
  318. }
  319. extern "C" int APIENTRY
  320. wWinMain(
  321. HINSTANCE hInstance,
  322. HINSTANCE hPrevInstance,
  323. LPWSTR lpCmdLine,
  324. int nCmdShow
  325. )
  326. {
  327. LPWSTR* argv = NULL;
  328. int argc = 0;
  329. g_hInstance = hInstance;
  330. InitTestInfo();
  331. GetCurrentAppSettings();
  332. if (lpCmdLine && lpCmdLine[0]) {
  333. argv = CommandLineToArgvW(lpCmdLine, &argc);
  334. }
  335. //
  336. // See if it's used as a debugger.
  337. //
  338. if (argc == 2 && _wcsicmp(argv[0], L"/debug") == 0) {
  339. FreeConsole();
  340. DebugApp(argv[1]);
  341. return 1;
  342. }
  343. if (!CanRun()) {
  344. AVErrorResourceFormat(IDS_ACCESS_IS_DENIED);
  345. return 0;
  346. }
  347. if (argc > 0) {
  348. //
  349. // we're in console mode, so handle everything as a console
  350. //
  351. HandleCommandLine(argc, argv);
  352. return 1;
  353. }
  354. FreeConsole();
  355. InitCommonControls();
  356. HWND hMainDlg = CreateDialog(g_hInstance, (LPCTSTR)IDD_DLG_MAIN, NULL, (DLGPROC)DlgMain);
  357. MSG msg;
  358. //
  359. // Main message loop:
  360. //
  361. while (GetMessage(&msg, NULL, 0, 0)) {
  362. if (!IsDialogMessage(hMainDlg, &msg)) {
  363. TranslateMessage(&msg);
  364. DispatchMessage(&msg);
  365. }
  366. }
  367. return 0;
  368. }
  369. void
  370. RefreshAppList(
  371. HWND hDlg
  372. )
  373. {
  374. CAVAppInfoArray::iterator it;
  375. HWND hList = GetDlgItem(hDlg, IDC_LIST_APPS);
  376. ListView_DeleteAllItems(hList);
  377. for (it = g_aAppInfo.begin(); it != g_aAppInfo.end(); it++) {
  378. LVITEM lvi;
  379. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  380. lvi.pszText = (LPWSTR)it->wstrExeName.c_str();
  381. lvi.lParam = (LPARAM)it;
  382. lvi.iItem = 9999;
  383. lvi.iSubItem = 0;
  384. ListView_InsertItem(hList, &lvi);
  385. }
  386. RefreshSettingsList(hDlg);
  387. }
  388. void
  389. DirtySettings(
  390. HWND hDlg,
  391. BOOL bDirty
  392. )
  393. {
  394. g_bSettingsDirty = bDirty;
  395. if (hDlg) {
  396. EnableWindow(GetDlgItem(hDlg, IDC_BTN_SAVE_SETTINGS), bDirty);
  397. }
  398. }
  399. void
  400. SaveSettings(
  401. HWND hDlg
  402. )
  403. {
  404. DirtySettings(hDlg, FALSE);
  405. SetCurrentAppSettings();
  406. }
  407. void
  408. SaveSettingsIfDirty(HWND hDlg)
  409. {
  410. if (g_bSettingsDirty) {
  411. SaveSettings(hDlg);
  412. }
  413. }
  414. void
  415. DisplayLog(
  416. HWND hDlg
  417. )
  418. {
  419. g_szSingleLogFile[0] = 0;
  420. DialogBox(g_hInstance, (LPCTSTR)IDD_VIEWLOG_PAGE, hDlg, (DLGPROC)DlgViewLog);
  421. }
  422. void
  423. DisplaySingleLog(HWND hDlg)
  424. {
  425. WCHAR wszFilter[] = L"Log files (*.log)\0*.log\0";
  426. OPENFILENAME ofn;
  427. WCHAR wszAppFullPath[MAX_PATH];
  428. WCHAR wszAppShortName[MAX_PATH];
  429. wstring wstrLogTitle;
  430. if (!AVLoadString(IDS_VIEW_EXPORTED_LOG_TITLE, wstrLogTitle)) {
  431. wstrLogTitle = _T("View Exported Log");
  432. }
  433. wszAppFullPath[0] = 0;
  434. ofn.lStructSize = sizeof(OPENFILENAME);
  435. ofn.hwndOwner = hDlg;
  436. ofn.hInstance = NULL;
  437. ofn.lpstrFilter = wszFilter;
  438. ofn.lpstrCustomFilter = NULL;
  439. ofn.nMaxCustFilter = 0;
  440. ofn.nFilterIndex = 0;
  441. ofn.lpstrFile = wszAppFullPath;
  442. ofn.nMaxFile = MAX_PATH;
  443. ofn.lpstrFileTitle = wszAppShortName;
  444. ofn.nMaxFileTitle = MAX_PATH;
  445. ofn.lpstrInitialDir = NULL;
  446. ofn.lpstrTitle = wstrLogTitle.c_str();
  447. ofn.Flags = OFN_PATHMUSTEXIST |
  448. OFN_HIDEREADONLY | // hide the "open read-only" checkbox
  449. OFN_NONETWORKBUTTON | // no network button
  450. OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
  451. OFN_SHAREAWARE; // don't check the existance of file with OpenFile
  452. ofn.lpstrDefExt = _T("log");
  453. if ( !GetOpenFileName(&ofn) )
  454. {
  455. return;
  456. }
  457. wcscpy(g_szSingleLogFile, wszAppFullPath);
  458. DialogBox(g_hInstance, (LPCTSTR)IDD_VIEWLOG_PAGE, hDlg, (DLGPROC)DlgViewLog);
  459. g_szSingleLogFile[0] = 0;
  460. }
  461. void
  462. SelectApp(
  463. HWND hDlg,
  464. int nWhich
  465. )
  466. {
  467. HWND hList = GetDlgItem(hDlg, IDC_LIST_APPS);
  468. int nItems = ListView_GetItemCount(hList);
  469. if (nItems == 0) {
  470. return;
  471. }
  472. if (nWhich > nItems - 1) {
  473. nWhich = nItems - 1;
  474. }
  475. ListView_SetItemState(hList, nWhich, LVIS_SELECTED, LVIS_SELECTED);
  476. }
  477. void
  478. RunSelectedApp(
  479. HWND hDlg
  480. )
  481. {
  482. WCHAR wszCommandLine[256];
  483. SaveSettings(hDlg);
  484. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  485. int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  486. if (nApp == -1) {
  487. return;
  488. }
  489. LVITEM lvi;
  490. lvi.mask = LVIF_PARAM;
  491. lvi.iItem = nApp;
  492. lvi.iSubItem = 0;
  493. ListView_GetItem(hAppList, &lvi);
  494. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  495. if (pApp->wstrExePath.size()) {
  496. LPWSTR pwsz;
  497. wcscpy(wszCommandLine, pApp->wstrExePath.c_str());
  498. pwsz = wcsrchr(wszCommandLine, L'\\');
  499. if (pwsz) {
  500. *pwsz = 0;
  501. SetCurrentDirectory(wszCommandLine);
  502. *pwsz = L'\\';
  503. }
  504. } else {
  505. wcscpy(wszCommandLine, pApp->wstrExeName.c_str());
  506. }
  507. PROCESS_INFORMATION ProcessInfo;
  508. BOOL bRet;
  509. STARTUPINFO StartupInfo;
  510. ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  511. StartupInfo.cb = sizeof(StartupInfo);
  512. ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
  513. bRet = CreateProcess(NULL,
  514. wszCommandLine,
  515. NULL,
  516. NULL,
  517. FALSE,
  518. 0,
  519. NULL,
  520. NULL,
  521. &StartupInfo,
  522. &ProcessInfo);
  523. if (!bRet) {
  524. WCHAR wszFilter[] = L"Executable files (*.exe)\0*.exe\0";
  525. OPENFILENAME ofn;
  526. WCHAR wszAppFullPath[MAX_PATH];
  527. WCHAR wszAppShortName[MAX_PATH];
  528. wcscpy(wszAppFullPath, wszCommandLine);
  529. ofn.lStructSize = sizeof(OPENFILENAME);
  530. ofn.hwndOwner = hDlg;
  531. ofn.hInstance = NULL;
  532. ofn.lpstrFilter = wszFilter;
  533. ofn.lpstrCustomFilter = NULL;
  534. ofn.nMaxCustFilter = 0;
  535. ofn.nFilterIndex = 0;
  536. ofn.lpstrFile = wszAppFullPath;
  537. ofn.nMaxFile = MAX_PATH;
  538. ofn.lpstrFileTitle = wszAppShortName;
  539. ofn.nMaxFileTitle = MAX_PATH;
  540. ofn.lpstrInitialDir = NULL;
  541. ofn.lpstrTitle = _T("Please locate application");
  542. ofn.Flags = OFN_PATHMUSTEXIST |
  543. OFN_HIDEREADONLY | // hide the "open read-only" checkbox
  544. OFN_NONETWORKBUTTON | // no network button
  545. OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
  546. OFN_SHAREAWARE; // don't check the existance of file with OpenFile
  547. ofn.lpstrDefExt = NULL;
  548. if (!GetOpenFileName(&ofn)) {
  549. return;
  550. }
  551. pApp->wstrExePath = wszAppFullPath;
  552. pApp->wstrExeName = wszAppShortName;
  553. wcscpy(wszCommandLine, pApp->wstrExePath.c_str());
  554. RefreshAppList(hDlg);
  555. ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  556. StartupInfo.cb = sizeof(StartupInfo);
  557. ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
  558. bRet = CreateProcess(NULL,
  559. wszCommandLine,
  560. NULL,
  561. NULL,
  562. FALSE,
  563. 0,
  564. NULL,
  565. NULL,
  566. &StartupInfo,
  567. &ProcessInfo);
  568. if (!bRet) {
  569. AVErrorResourceFormat(IDS_CANT_LAUNCH_EXE);
  570. }
  571. }
  572. }
  573. void
  574. AddAppToList(
  575. HWND hDlg
  576. )
  577. {
  578. WCHAR wszFilter[] = L"Executable files (*.exe)\0*.exe\0";
  579. OPENFILENAME ofn;
  580. WCHAR wszAppFullPath[MAX_PATH];
  581. WCHAR wszAppShortName[MAX_PATH];
  582. wstring wstrTitle;
  583. if (!AVLoadString(IDS_ADD_APPLICATION_TITLE, wstrTitle)) {
  584. wstrTitle = _T("Add Application");
  585. }
  586. wszAppFullPath[0] = 0;
  587. ofn.lStructSize = sizeof(OPENFILENAME);
  588. ofn.hwndOwner = hDlg;
  589. ofn.hInstance = NULL;
  590. ofn.lpstrFilter = wszFilter;
  591. ofn.lpstrCustomFilter = NULL;
  592. ofn.nMaxCustFilter = 0;
  593. ofn.nFilterIndex = 0;
  594. ofn.lpstrFile = wszAppFullPath;
  595. ofn.nMaxFile = MAX_PATH;
  596. ofn.lpstrFileTitle = wszAppShortName;
  597. ofn.nMaxFileTitle = MAX_PATH;
  598. ofn.lpstrInitialDir = NULL;
  599. ofn.lpstrTitle = wstrTitle.c_str();
  600. ofn.Flags = OFN_HIDEREADONLY | // hide the "open read-only" checkbox
  601. OFN_NONETWORKBUTTON | // no network button
  602. OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
  603. OFN_SHAREAWARE; // don't check the existance of file with OpenFile
  604. ofn.lpstrDefExt = _T("EXE");
  605. if (!GetOpenFileName(&ofn)) {
  606. return;
  607. }
  608. //
  609. // check to see if the app is already in the list
  610. //
  611. CAVAppInfo *pApp;
  612. BOOL bFound = FALSE;
  613. for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
  614. if (_wcsicmp(pApp->wstrExeName.c_str(), wszAppShortName) == 0) {
  615. //
  616. // the app is already in the list, so just update the full
  617. // path, if it's good
  618. //
  619. if (GetFileAttributes(wszAppFullPath) != -1) {
  620. pApp->wstrExePath = wszAppFullPath;
  621. }
  622. bFound = TRUE;
  623. }
  624. }
  625. //
  626. // if the app wasn't already in the list, add it to the list
  627. //
  628. if (!bFound) {
  629. CAVAppInfo AppInfo;
  630. AppInfo.wstrExeName = wszAppShortName;
  631. //
  632. // check to see if the file actually exists
  633. //
  634. if (GetFileAttributes(wszAppFullPath) != -1) {
  635. AppInfo.wstrExePath = wszAppFullPath;
  636. }
  637. //
  638. // init the default tests
  639. //
  640. CTestInfo *pTest;
  641. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  642. if (pTest->bDefault) {
  643. AppInfo.AddTest(*pTest);
  644. }
  645. }
  646. g_aAppInfo.push_back(AppInfo);
  647. RefreshAppList(hDlg);
  648. SelectApp(hDlg, 9999);
  649. DirtySettings(hDlg, TRUE);
  650. }
  651. }
  652. void
  653. RemoveSelectedApp(
  654. HWND hDlg
  655. )
  656. {
  657. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  658. int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  659. if (nApp == -1) {
  660. return;
  661. }
  662. LVITEM lvi;
  663. lvi.mask = LVIF_PARAM;
  664. lvi.iItem = nApp;
  665. lvi.iSubItem = 0;
  666. ListView_GetItem(hAppList, &lvi);
  667. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  668. g_aAppInfo.erase(pApp);
  669. RefreshAppList(hDlg);
  670. SelectApp(hDlg, nApp);
  671. DirtySettings(hDlg, TRUE);
  672. }
  673. void
  674. ScanSettingsList(
  675. HWND hDlg,
  676. int nItem
  677. )
  678. {
  679. HWND hSettingList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  680. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  681. int nBegin, nEnd;
  682. int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  683. if (nApp == -1) {
  684. return;
  685. }
  686. LVITEM lvi;
  687. lvi.mask = LVIF_PARAM;
  688. lvi.iItem = nApp;
  689. lvi.iSubItem = 0;
  690. ListView_GetItem(hAppList, &lvi);
  691. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  692. if (!pApp) {
  693. return;
  694. }
  695. int nItems = ListView_GetItemCount(hSettingList);
  696. if (!nItems) {
  697. //
  698. // nothing in list
  699. //
  700. return;
  701. }
  702. if (nItem == -1 || nItem >= nItems) {
  703. nBegin = 0;
  704. nEnd = nItems;
  705. } else {
  706. nBegin = nItem;
  707. nEnd = nItem + 1;
  708. }
  709. for (int i = nBegin; i < nEnd; ++i) {
  710. BOOL bTestEnabled = FALSE;
  711. BOOL bChecked = FALSE;
  712. lvi.iItem = i;
  713. ListView_GetItem(hSettingList, &lvi);
  714. CTestInfo *pTest = (CTestInfo*)lvi.lParam;
  715. bChecked = ListView_GetCheckState(hSettingList, i);
  716. bTestEnabled = pApp->IsTestActive(*pTest);
  717. if (bTestEnabled != bChecked) {
  718. DirtySettings(hDlg, TRUE);
  719. if (bChecked) {
  720. pApp->AddTest(*pTest);
  721. } else {
  722. pApp->RemoveTest(*pTest);
  723. }
  724. }
  725. }
  726. }
  727. void
  728. DisplaySettingsDescription(
  729. HWND hDlg
  730. )
  731. {
  732. HWND hList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  733. int nItem = ListView_GetNextItem(hList, -1, LVNI_SELECTED);
  734. if (nItem == -1) {
  735. WCHAR szTestDesc[256];
  736. LoadString(g_hInstance, IDS_VIEW_TEST_DESC, szTestDesc, 256);
  737. SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), szTestDesc);
  738. } else {
  739. LVITEM lvi;
  740. lvi.mask = LVIF_PARAM;
  741. lvi.iItem = nItem;
  742. lvi.iSubItem = 0;
  743. ListView_GetItem(hList, &lvi);
  744. CTestInfo *pTest = (CTestInfo*)lvi.lParam;
  745. SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), pTest->strTestDescription.c_str());
  746. }
  747. }
  748. void
  749. RefreshSettingsList(
  750. HWND hDlg
  751. )
  752. {
  753. HWND hSettingList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  754. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  755. static nLastItem = -1;
  756. int nItem = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  757. if (nItem == -1) {
  758. EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
  759. EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
  760. } else {
  761. EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), TRUE);
  762. EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), TRUE);
  763. }
  764. if (nItem == nLastItem) {
  765. return;
  766. }
  767. ListView_DeleteAllItems(hSettingList);
  768. DisplaySettingsDescription(hDlg);
  769. nLastItem = nItem;
  770. if (nItem != -1) {
  771. LVITEM lvi;
  772. lvi.mask = LVIF_PARAM;
  773. lvi.iItem = nItem;
  774. lvi.iSubItem = 0;
  775. ListView_GetItem(hAppList, &lvi);
  776. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  777. if (!pApp) {
  778. return;
  779. }
  780. CTestInfo* pTest;
  781. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  782. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  783. lvi.pszText = (LPWSTR)pTest->strTestName.c_str();
  784. lvi.lParam = (LPARAM)pTest;
  785. lvi.iItem = 9999;
  786. lvi.iSubItem = 0;
  787. int nItem = ListView_InsertItem(hSettingList, &lvi);
  788. BOOL bCheck = pApp->IsTestActive(*pTest);
  789. ListView_SetCheckState(hSettingList, nItem, bCheck);
  790. }
  791. }
  792. }
  793. void
  794. ReadOptions(
  795. void
  796. )
  797. {
  798. LONG lRet;
  799. HKEY hKey;
  800. DWORD cbData;
  801. lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  802. AV_OPTIONS_KEY,
  803. 0,
  804. NULL,
  805. 0,
  806. KEY_ALL_ACCESS,
  807. NULL,
  808. &hKey,
  809. NULL);
  810. if (lRet != ERROR_SUCCESS) {
  811. return;
  812. }
  813. cbData = sizeof(DWORD);
  814. RegQueryValueEx(hKey,
  815. AV_OPTION_CLEAR_LOG,
  816. NULL,
  817. NULL,
  818. (BYTE*)&g_bClearSessionLogBeforeRun,
  819. &cbData);
  820. RegQueryValueEx(hKey,
  821. AV_OPTION_BREAK_ON_LOG,
  822. NULL,
  823. NULL,
  824. (BYTE*)&g_bBreakOnLog,
  825. &cbData);
  826. RegQueryValueEx(hKey,
  827. AV_OPTION_FULL_PAGEHEAP,
  828. NULL,
  829. NULL,
  830. (BYTE*)&g_bFullPageHeap,
  831. &cbData);
  832. RegQueryValueEx(hKey,
  833. AV_OPTION_AV_DEBUGGER,
  834. NULL,
  835. NULL,
  836. (BYTE*)&g_bUseAVDebugger,
  837. &cbData);
  838. RegCloseKey(hKey);
  839. }
  840. void
  841. SaveOptions(
  842. void
  843. )
  844. {
  845. LONG lRet;
  846. HKEY hKey;
  847. lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  848. AV_OPTIONS_KEY,
  849. 0,
  850. NULL,
  851. 0,
  852. KEY_ALL_ACCESS,
  853. NULL,
  854. &hKey,
  855. NULL);
  856. if (lRet != ERROR_SUCCESS) {
  857. return;
  858. }
  859. RegSetValueEx(hKey,
  860. AV_OPTION_CLEAR_LOG,
  861. NULL,
  862. REG_DWORD,
  863. (BYTE*)&g_bClearSessionLogBeforeRun,
  864. sizeof(DWORD));
  865. RegSetValueEx(hKey,
  866. AV_OPTION_BREAK_ON_LOG,
  867. NULL,
  868. REG_DWORD,
  869. (BYTE*)&g_bBreakOnLog,
  870. sizeof(DWORD));
  871. RegSetValueEx(hKey,
  872. AV_OPTION_FULL_PAGEHEAP,
  873. NULL,
  874. REG_DWORD,
  875. (BYTE*)&g_bFullPageHeap,
  876. sizeof(DWORD));
  877. RegSetValueEx(hKey,
  878. AV_OPTION_AV_DEBUGGER,
  879. NULL,
  880. REG_DWORD,
  881. (BYTE*)&g_bUseAVDebugger,
  882. sizeof(DWORD));
  883. RegCloseKey(hKey);
  884. SetCurrentAppSettings();
  885. }
  886. LRESULT CALLBACK
  887. DlgViewOptions(
  888. HWND hDlg,
  889. UINT message,
  890. WPARAM wParam,
  891. LPARAM lParam
  892. )
  893. {
  894. switch (message) {
  895. case WM_INITDIALOG:
  896. ReadOptions();
  897. SendDlgItemMessage(hDlg,
  898. IDC_CLEAR_LOG_ON_CHANGES,
  899. BM_SETCHECK,
  900. (g_bClearSessionLogBeforeRun ? BST_CHECKED : BST_UNCHECKED),
  901. 0);
  902. SendDlgItemMessage(hDlg,
  903. IDC_BREAK_ON_LOG,
  904. BM_SETCHECK,
  905. (g_bBreakOnLog ? BST_CHECKED : BST_UNCHECKED),
  906. 0);
  907. SendDlgItemMessage(hDlg,
  908. IDC_FULL_PAGEHEAP,
  909. BM_SETCHECK,
  910. (g_bFullPageHeap ? BST_CHECKED : BST_UNCHECKED),
  911. 0);
  912. SendDlgItemMessage(hDlg,
  913. IDC_USE_AV_DEBUGGER,
  914. BM_SETCHECK,
  915. (g_bUseAVDebugger ? BST_CHECKED : BST_UNCHECKED),
  916. 0);
  917. return TRUE;
  918. case WM_COMMAND:
  919. switch (LOWORD(wParam)) {
  920. case IDOK:
  921. g_bClearSessionLogBeforeRun = (SendDlgItemMessage(hDlg,
  922. IDC_CLEAR_LOG_ON_CHANGES,
  923. BM_GETCHECK,
  924. 0,
  925. 0) == BST_CHECKED);
  926. g_bBreakOnLog = (SendDlgItemMessage(hDlg,
  927. IDC_BREAK_ON_LOG,
  928. BM_GETCHECK,
  929. 0,
  930. 0) == BST_CHECKED);
  931. g_bFullPageHeap = (SendDlgItemMessage(hDlg,
  932. IDC_FULL_PAGEHEAP,
  933. BM_GETCHECK,
  934. 0,
  935. 0) == BST_CHECKED);
  936. g_bUseAVDebugger = (SendDlgItemMessage(hDlg,
  937. IDC_USE_AV_DEBUGGER,
  938. BM_GETCHECK,
  939. 0,
  940. 0) == BST_CHECKED);
  941. SaveOptions();
  942. EndDialog(hDlg, LOWORD(wParam));
  943. return TRUE;
  944. case IDCANCEL:
  945. EndDialog(hDlg, LOWORD(wParam));
  946. return TRUE;
  947. }
  948. break;
  949. case WM_NOTIFY:
  950. break;
  951. }
  952. return FALSE;
  953. }
  954. void
  955. ViewOptions(
  956. HWND hDlg
  957. )
  958. {
  959. DialogBox(g_hInstance, (LPCTSTR)IDD_OPTIONS, hDlg, (DLGPROC)DlgViewOptions);
  960. }
  961. // Message handler for main dialog.
  962. LRESULT CALLBACK
  963. DlgMain(
  964. HWND hDlg,
  965. UINT message,
  966. WPARAM wParam,
  967. LPARAM lParam
  968. )
  969. {
  970. switch (message) {
  971. case WM_INITDIALOG:
  972. {
  973. wstring strTemp;
  974. //
  975. // set the caption to the appropriate version, etc.
  976. //
  977. if (GetAppTitleString(strTemp)) {
  978. SetWindowText(hDlg, strTemp.c_str());
  979. }
  980. EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
  981. EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
  982. EnableWindow(GetDlgItem(hDlg, IDC_BTN_SAVE_SETTINGS), FALSE);
  983. HWND hList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  984. if (hList) {
  985. LVCOLUMN lvc;
  986. lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  987. lvc.fmt = LVCFMT_LEFT;
  988. lvc.cx = 300;
  989. lvc.iSubItem = 0;
  990. lvc.pszText = L"xxx";
  991. ListView_InsertColumn(hList, 0, &lvc);
  992. ListView_SetExtendedListViewStyleEx(hList, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
  993. }
  994. hList = GetDlgItem(hDlg, IDC_LIST_APPS);
  995. if (hList) {
  996. LVITEM lvi;
  997. LVCOLUMN lvc;
  998. lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  999. lvc.fmt = LVCFMT_LEFT;
  1000. lvc.cx = 250;
  1001. lvc.iSubItem = 0;
  1002. lvc.pszText = L"xxx";
  1003. ListView_InsertColumn(hList, 0, &lvc);
  1004. RefreshAppList(hDlg);
  1005. SelectApp(hDlg, 0);
  1006. }
  1007. WCHAR szTestDesc[256];
  1008. LoadString(g_hInstance, IDS_VIEW_TEST_DESC, szTestDesc, 256);
  1009. SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), szTestDesc);
  1010. //
  1011. // Show the app icon.
  1012. //
  1013. HICON hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
  1014. SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)hIcon);
  1015. return TRUE;
  1016. }
  1017. break;
  1018. case WM_ACTIVATE:
  1019. if (LOWORD(wParam) == WA_INACTIVE) {
  1020. SaveSettingsIfDirty(hDlg);
  1021. }
  1022. break;
  1023. case WM_COMMAND:
  1024. switch (LOWORD(wParam)) {
  1025. case IDC_BTN_ADD:
  1026. AddAppToList(hDlg);
  1027. break;
  1028. case IDC_BTN_REMOVE:
  1029. RemoveSelectedApp(hDlg);
  1030. break;
  1031. case IDC_BTN_VIEW_LOG:
  1032. DisplayLog(hDlg);
  1033. break;
  1034. case IDC_BTN_VIEW_EXTERNAL_LOG:
  1035. DisplaySingleLog(hDlg);
  1036. break;
  1037. case IDC_BTN_OPTIONS:
  1038. ViewOptions(hDlg);
  1039. break;
  1040. case IDC_BTN_RUN:
  1041. RunSelectedApp(hDlg);
  1042. break;
  1043. case IDOK:
  1044. case IDCANCEL:
  1045. SaveSettings(hDlg);
  1046. EndDialog(hDlg, LOWORD(wParam));
  1047. PostQuitMessage(0);
  1048. return TRUE;
  1049. break;
  1050. }
  1051. break;
  1052. case WM_NOTIFY:
  1053. LPNMHDR pnmh = (LPNMHDR)lParam;
  1054. HWND hItem = pnmh->hwndFrom;
  1055. if (hItem == GetDlgItem(hDlg, IDC_LIST_APPS)) {
  1056. switch (pnmh->code) {
  1057. case LVN_KEYDOWN:
  1058. {
  1059. LPNMLVKEYDOWN pnmkd = (LPNMLVKEYDOWN)lParam;
  1060. if (pnmkd->wVKey == VK_DELETE) {
  1061. if (IsWindowEnabled(GetDlgItem(hDlg, IDC_BTN_RUN))) {
  1062. RemoveSelectedApp(hDlg);
  1063. }
  1064. }
  1065. }
  1066. break;
  1067. case LVN_ITEMCHANGED:
  1068. LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
  1069. if (!g_bRefreshingSettings && (pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED)) {
  1070. g_bRefreshingSettings = TRUE;
  1071. RefreshSettingsList(hDlg);
  1072. g_bRefreshingSettings = FALSE;
  1073. }
  1074. }
  1075. } else if (hItem == GetDlgItem(hDlg, IDC_LIST_SETTINGS)) {
  1076. switch (pnmh->code) {
  1077. case LVN_ITEMCHANGED:
  1078. LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
  1079. if (!g_bRefreshingSettings) {
  1080. if ((pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED)) {
  1081. DisplaySettingsDescription(hDlg);
  1082. }
  1083. if ((pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) >> 12) != 0) {
  1084. ScanSettingsList(hDlg, pnmv->iItem);
  1085. }
  1086. }
  1087. break;
  1088. }
  1089. }
  1090. break;
  1091. }
  1092. return FALSE;
  1093. }