Leaked source code of windows server 2003
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.

1978 lines
52 KiB

  1. #include "precomp.h"
  2. #include "dbsupport.h"
  3. #include "viewlog.h"
  4. using namespace ShimLib;
  5. //#define AV_OPTIONS_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\AppVerifier"
  6. #define AV_OPTION_CLEAR_LOG L"ClearLogsBeforeRun"
  7. #define AV_OPTION_BREAK_ON_LOG L"BreakOnLog"
  8. #define AV_OPTION_FULL_PAGEHEAP L"FullPageHeap"
  9. #define AV_OPTION_AV_DEBUGGER L"UseAVDebugger"
  10. #define AV_OPTION_DEBUGGER L"Debugger"
  11. #define AV_OPTION_PROPAGATE L"PropagateTests"
  12. //
  13. // Forward declarations
  14. //
  15. CWinApp theApp;
  16. HINSTANCE g_hInstance = NULL;
  17. BOOL g_bSettingsDirty = FALSE;
  18. BOOL g_bRefreshingSettings = FALSE;
  19. BOOL g_bConsoleMode = FALSE;
  20. BOOL g_bWin2KMode = FALSE;
  21. BOOL g_bInternalMode = FALSE;
  22. //
  23. // dialog handles
  24. //
  25. HWND g_hDlgMain = NULL;
  26. HWND g_hDlgOptions = NULL;
  27. // forward function declarations
  28. INT_PTR CALLBACK
  29. DlgMain(
  30. HWND hDlg,
  31. UINT message,
  32. WPARAM wParam,
  33. LPARAM lParam
  34. );
  35. INT_PTR CALLBACK
  36. DlgRunAlone(
  37. HWND hDlg,
  38. UINT message,
  39. WPARAM wParam,
  40. LPARAM lParam
  41. );
  42. INT_PTR CALLBACK
  43. DlgConflict(
  44. HWND hDlg,
  45. UINT message,
  46. WPARAM wParam,
  47. LPARAM lParam
  48. );
  49. void
  50. RefreshSettingsList(
  51. HWND hDlg,
  52. BOOL bForceRefresh = FALSE
  53. );
  54. void
  55. ReadOptions(
  56. void
  57. );
  58. BOOL
  59. GetAppTitleString(
  60. wstring &strTitle
  61. )
  62. {
  63. wstring strVersion;
  64. if (!AVLoadString(IDS_APP_NAME, strTitle)) {
  65. return FALSE;
  66. }
  67. #if defined(_WIN64)
  68. if (!AVLoadString(IDS_VERSION_STRING_64, strVersion)) {
  69. return FALSE;
  70. }
  71. #else
  72. if (!AVLoadString(IDS_VERSION_STRING, strVersion)) {
  73. return FALSE;
  74. }
  75. #endif
  76. strTitle += L" ";
  77. strTitle += strVersion;
  78. return TRUE;
  79. }
  80. void
  81. ShowHTMLHelp(
  82. void
  83. )
  84. {
  85. SHELLEXECUTEINFOW sei;
  86. WCHAR szPath[MAX_PATH];
  87. WCHAR* pszBackSlash;
  88. DWORD dwLen = GetModuleFileName(NULL, szPath, ARRAY_LENGTH(szPath));
  89. if (!dwLen) {
  90. return;
  91. }
  92. pszBackSlash = wcsrchr(szPath, L'\\');
  93. if (pszBackSlash) {
  94. pszBackSlash++;
  95. *pszBackSlash = 0;
  96. } else {
  97. //
  98. // punt and just try to find it on the path
  99. //
  100. szPath[0] = 0;
  101. }
  102. StringCchCatW(szPath, ARRAY_LENGTH(szPath), L"appverif.chm");
  103. ZeroMemory(&sei, sizeof(sei));
  104. sei.cbSize = sizeof(sei);
  105. sei.lpVerb = L"open";
  106. sei.lpFile = szPath;
  107. sei.nShow = SW_SHOWNORMAL;
  108. ShellExecuteExW(&sei);
  109. }
  110. BOOL
  111. SearchGroupForSID(
  112. DWORD dwGroup,
  113. BOOL* pfIsMember
  114. )
  115. {
  116. PSID pSID = NULL;
  117. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  118. BOOL fRes = TRUE;
  119. if (!AllocateAndInitializeSid(&SIDAuth,
  120. 2,
  121. SECURITY_BUILTIN_DOMAIN_RID,
  122. dwGroup,
  123. 0,
  124. 0,
  125. 0,
  126. 0,
  127. 0,
  128. 0,
  129. &pSID)) {
  130. return FALSE;
  131. }
  132. if (!pSID) {
  133. return FALSE;
  134. }
  135. if (!CheckTokenMembership(NULL, pSID, pfIsMember)) {
  136. fRes = FALSE;
  137. }
  138. FreeSid(pSID);
  139. return fRes;
  140. }
  141. BOOL
  142. CanRun(
  143. void
  144. )
  145. {
  146. BOOL fIsAdmin;
  147. if (!SearchGroupForSID(DOMAIN_ALIAS_RID_ADMINS, &fIsAdmin))
  148. {
  149. return FALSE;
  150. }
  151. return fIsAdmin;
  152. }
  153. void
  154. DumpResourceStringsToConsole(ULONG ulBegin, ULONG ulEnd)
  155. {
  156. ULONG ulRes;
  157. wstring strText;
  158. for (ulRes = ulBegin; ulRes != ulEnd + 1; ++ulRes) {
  159. if (AVLoadString(ulRes, strText)) {
  160. printf("%ls\n", strText.c_str());
  161. }
  162. }
  163. }
  164. void
  165. DumpCurrentSettingsToConsole(void)
  166. {
  167. CAVAppInfo *pApp;
  168. DumpResourceStringsToConsole(IDS_CURRENT_SETTINGS, IDS_CURRENT_SETTINGS);
  169. for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
  170. printf("%ls:\n", pApp->wstrExeName.c_str());
  171. CTestInfo *pTest;
  172. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  173. if (pApp->IsTestActive(*pTest)) {
  174. printf(" %ls\n", pTest->strTestName.c_str());
  175. }
  176. }
  177. printf("\n");
  178. }
  179. DumpResourceStringsToConsole(IDS_DONE, IDS_DONE);
  180. }
  181. void
  182. DumpHelpToConsole(void)
  183. {
  184. DumpResourceStringsToConsole(IDS_HELP_INTRO_00, IDS_HELP_INTRO_10);
  185. CTestInfo *pTest;
  186. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  187. if (pTest->eTestType == TEST_KERNEL &&
  188. ((pTest->bInternal && g_bInternalMode) || (pTest->bExternal && !g_bInternalMode)) &&
  189. (pTest->bWin2KCompatible || !g_bWin2KMode)) {
  190. printf(" %ls\n", pTest->strTestName.c_str());
  191. }
  192. }
  193. DumpResourceStringsToConsole(IDS_HELP_SHIM_TESTS, IDS_HELP_SHIM_TESTS);
  194. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  195. if (pTest->eTestType == TEST_SHIM &&
  196. ((pTest->bInternal && g_bInternalMode) || (pTest->bExternal && !g_bInternalMode)) &&
  197. (pTest->bWin2KCompatible || !g_bWin2KMode)) {
  198. printf(" %ls\n", pTest->strTestName.c_str());
  199. }
  200. }
  201. DumpResourceStringsToConsole(IDS_HELP_EXAMPLE_00, IDS_HELP_EXAMPLE_11);
  202. }
  203. void
  204. HandleCommandLine(int argc, LPWSTR *argv)
  205. {
  206. WCHAR szApp[MAX_PATH];
  207. wstring strTemp;
  208. CWStringArray astrApps;
  209. szApp[0] = 0;
  210. g_bConsoleMode = TRUE;
  211. //
  212. // print the title
  213. //
  214. if (GetAppTitleString(strTemp)) {
  215. printf("\n%ls\n", strTemp.c_str());
  216. }
  217. if (AVLoadString(IDS_COPYRIGHT, strTemp)) {
  218. printf("%ls\n\n", strTemp.c_str());
  219. }
  220. //
  221. // check for global operations
  222. //
  223. if (_wcsnicmp(argv[0], L"/q", 2) == 0) { // querysettings
  224. DumpCurrentSettingsToConsole();
  225. return;
  226. }
  227. if (_wcsicmp(argv[0], L"/?") == 0) { // help
  228. DumpHelpToConsole();
  229. return;
  230. }
  231. if (_wcsnicmp(argv[0], L"/r", 2) == 0) { // reset
  232. g_aAppInfo.clear();
  233. goto out;
  234. }
  235. //
  236. // first get a list of the app names
  237. //
  238. for (int nArg = 0 ; nArg != argc; nArg++) {
  239. WCHAR wc = argv[nArg][0];
  240. if (wc != L'/' && wc != L'-' && wc != L'+') {
  241. astrApps.push_back(argv[nArg]);
  242. }
  243. }
  244. if (astrApps.size() == 0) {
  245. AVErrorResourceFormat(IDS_NO_APP);
  246. DumpHelpToConsole();
  247. return;
  248. }
  249. //
  250. // now for each app name, parse the list and adjust its settings
  251. //
  252. for (wstring *pStr = astrApps.begin(); pStr != astrApps.end(); pStr++) {
  253. CAVAppInfo *pApp;
  254. BOOL bFound = FALSE;
  255. //
  256. // check to see if they submitted a full path
  257. //
  258. const WCHAR * pExe = NULL;
  259. const WCHAR * pPath = NULL;
  260. pExe = wcsrchr(pStr->c_str(), L'\\');
  261. if (!pExe) {
  262. if ((*pStr)[1] == L':') {
  263. pExe = pStr->c_str() + 2;
  264. }
  265. } else {
  266. pExe++;
  267. }
  268. if (pExe) {
  269. pPath = pStr->c_str();
  270. } else {
  271. pExe = pStr->c_str();
  272. }
  273. //
  274. // first, find or add the app to the list, and get a pointer to it
  275. //
  276. for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
  277. if (_wcsicmp(pApp->wstrExeName.c_str(), pExe) == 0) {
  278. bFound = TRUE;
  279. break;
  280. }
  281. }
  282. if (!bFound) {
  283. CAVAppInfo App;
  284. App.wstrExeName = pExe;
  285. g_aAppInfo.push_back(App);
  286. pApp = g_aAppInfo.end() - 1;
  287. }
  288. //
  289. // if they submitted a full path, update the records
  290. //
  291. if (pPath) {
  292. pApp->wstrExePath = pPath;
  293. }
  294. //
  295. // now walk the command line again and make the adjustments
  296. //
  297. for (int nArg = 0 ; nArg != argc; nArg++) {
  298. if (argv[nArg][0] == L'/') {
  299. if (_wcsnicmp(argv[nArg], L"/a", 2) == 0) { // all
  300. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  301. pApp->AddTest(*pTest);
  302. }
  303. } else if (_wcsnicmp(argv[nArg], L"/n", 2) == 0) { // none
  304. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  305. pApp->RemoveTest(*pTest);
  306. }
  307. } else if (_wcsnicmp(argv[nArg], L"/d", 2) == 0) { // default
  308. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  309. if (pTest->bDefault) {
  310. pApp->AddTest(*pTest);
  311. } else {
  312. pApp->RemoveTest(*pTest);
  313. }
  314. }
  315. } else {
  316. //
  317. // unknown parameter
  318. //
  319. AVErrorResourceFormat(IDS_INVALID_PARAMETER, argv[nArg]);
  320. DumpHelpToConsole();
  321. return;
  322. }
  323. } else if (argv[nArg][0] == L'+' || argv[nArg][0] == L'-') {
  324. BOOL bAdd = (argv[nArg][0] == L'+');
  325. LPWSTR szParam = argv[nArg] + 1;
  326. //
  327. // see if it's a shim name
  328. //
  329. CTestInfo *pTest;
  330. bFound = FALSE;
  331. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  332. if (_wcsicmp(szParam, pTest->strTestName.c_str()) == 0) {
  333. if (bAdd) {
  334. pApp->AddTest(*pTest);
  335. } else {
  336. pApp->RemoveTest(*pTest);
  337. }
  338. bFound = TRUE;
  339. break;
  340. }
  341. }
  342. if (!bFound) {
  343. //
  344. // unknown test
  345. //
  346. AVErrorResourceFormat(IDS_INVALID_TEST, szParam);
  347. DumpHelpToConsole();
  348. return;
  349. }
  350. }
  351. //
  352. // anything that doesn't begin with a slash, plus, or minus
  353. // is an app name, so we'll ignore it
  354. //
  355. }
  356. }
  357. out:
  358. //
  359. // save them to disk/registry
  360. //
  361. SetCurrentAppSettings();
  362. //
  363. // show them the current settings, for verification
  364. //
  365. DumpCurrentSettingsToConsole();
  366. }
  367. BOOL
  368. CheckWindowsVersion(void)
  369. {
  370. OSVERSIONINFOEXW VersionInfo;
  371. ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFOEXW));
  372. VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
  373. GetVersionEx((LPOSVERSIONINFOW)&VersionInfo);
  374. if (VersionInfo.dwMajorVersion < 5 ||
  375. (VersionInfo.dwMajorVersion == 5 && VersionInfo.dwMinorVersion == 0 && VersionInfo.wServicePackMajor < 3)) {
  376. //
  377. // too early - can't run
  378. //
  379. AVErrorResourceFormat(IDS_INVALID_VERSION);
  380. return FALSE;
  381. } else if (VersionInfo.dwMajorVersion == 5 && VersionInfo.dwMinorVersion == 0) {
  382. //
  383. // Win2K
  384. //
  385. g_bWin2KMode = TRUE;
  386. } else {
  387. //
  388. // WinXP or above -- all is well
  389. //
  390. g_bWin2KMode = FALSE;
  391. }
  392. return TRUE;
  393. }
  394. extern "C" int APIENTRY
  395. wWinMain(
  396. HINSTANCE hInstance,
  397. HINSTANCE hPrevInstance,
  398. LPWSTR lpCmdLine,
  399. int nCmdShow
  400. )
  401. {
  402. LPWSTR* argv = NULL;
  403. int argc = 0;
  404. g_hInstance = hInstance;
  405. //
  406. // check for appropriate version
  407. //
  408. if (!CheckWindowsVersion()) {
  409. return 0;
  410. }
  411. //
  412. // check for administrator access
  413. //
  414. if (!CanRun()) {
  415. AVErrorResourceFormat(IDS_ACCESS_IS_DENIED);
  416. return 0;
  417. }
  418. //
  419. // check for internal mode
  420. //
  421. g_bInternalMode = IsInternalModeEnabled();
  422. InitTestInfo();
  423. GetCurrentAppSettings();
  424. ReadOptions();
  425. if (lpCmdLine && lpCmdLine[0]) {
  426. argv = CommandLineToArgvW(lpCmdLine, &argc);
  427. }
  428. if (argc > 0) {
  429. //
  430. // we're in console mode, so handle everything as a console
  431. //
  432. HandleCommandLine(argc, argv);
  433. return 1;
  434. }
  435. FreeConsole();
  436. InitCommonControls();
  437. LinkWindow_RegisterClass();
  438. HACCEL hAccelMain = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCEL_MAIN));
  439. HWND hMainDlg = CreateDialog(g_hInstance, (LPCTSTR)IDD_DLG_MAIN, NULL, DlgMain);
  440. MSG msg;
  441. //
  442. // Main message loop:
  443. //
  444. while (GetMessage(&msg, NULL, 0, 0)) {
  445. if (!hAccelMain || !TranslateAccelerator(hMainDlg, hAccelMain, &msg)) {
  446. if (!IsDialogMessage(hMainDlg, &msg)) {
  447. TranslateMessage(&msg);
  448. DispatchMessage(&msg);
  449. }
  450. }
  451. }
  452. return 0;
  453. }
  454. void
  455. RefreshAppList(
  456. HWND hDlg
  457. )
  458. {
  459. CAVAppInfoArray::iterator it;
  460. HWND hList = GetDlgItem(hDlg, IDC_LIST_APPS);
  461. ListView_DeleteAllItems(hList);
  462. for (it = g_aAppInfo.begin(); it != g_aAppInfo.end(); it++) {
  463. LVITEM lvi;
  464. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  465. lvi.pszText = (LPWSTR)it->wstrExeName.c_str();
  466. lvi.lParam = (LPARAM)it;
  467. lvi.iItem = 9999;
  468. lvi.iSubItem = 0;
  469. ListView_InsertItem(hList, &lvi);
  470. }
  471. RefreshSettingsList(hDlg);
  472. }
  473. void
  474. DirtySettings(
  475. HWND hDlg,
  476. BOOL bDirty
  477. )
  478. {
  479. g_bSettingsDirty = bDirty;
  480. }
  481. void
  482. SaveSettings(
  483. HWND hDlg
  484. )
  485. {
  486. DirtySettings(hDlg, FALSE);
  487. SetCurrentAppSettings();
  488. }
  489. void
  490. SaveSettingsIfDirty(HWND hDlg)
  491. {
  492. if (g_bSettingsDirty) {
  493. SaveSettings(hDlg);
  494. }
  495. }
  496. void
  497. DisplayLog(
  498. HWND hDlg
  499. )
  500. {
  501. g_szSingleLogFile[0] = 0;
  502. DialogBox(g_hInstance, (LPCTSTR)IDD_VIEWLOG_PAGE, hDlg, DlgViewLog);
  503. }
  504. void
  505. DisplaySingleLog(HWND hDlg)
  506. {
  507. WCHAR wszFilter[] = L"Log files (*.log)\0*.log\0";
  508. OPENFILENAME ofn;
  509. WCHAR wszAppFullPath[MAX_PATH];
  510. WCHAR wszAppShortName[MAX_PATH];
  511. HRESULT hr;
  512. wstring wstrLogTitle;
  513. if (!AVLoadString(IDS_VIEW_EXPORTED_LOG_TITLE, wstrLogTitle)) {
  514. wstrLogTitle = _T("View Exported Log");
  515. }
  516. wszAppFullPath[0] = 0;
  517. ofn.lStructSize = sizeof(OPENFILENAME);
  518. ofn.hwndOwner = hDlg;
  519. ofn.hInstance = NULL;
  520. ofn.lpstrFilter = wszFilter;
  521. ofn.lpstrCustomFilter = NULL;
  522. ofn.nMaxCustFilter = 0;
  523. ofn.nFilterIndex = 0;
  524. ofn.lpstrFile = wszAppFullPath;
  525. ofn.nMaxFile = MAX_PATH;
  526. ofn.lpstrFileTitle = wszAppShortName;
  527. ofn.nMaxFileTitle = MAX_PATH;
  528. ofn.lpstrInitialDir = NULL;
  529. ofn.lpstrTitle = wstrLogTitle.c_str();
  530. ofn.Flags = OFN_PATHMUSTEXIST |
  531. OFN_HIDEREADONLY | // hide the "open read-only" checkbox
  532. OFN_NONETWORKBUTTON | // no network button
  533. OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
  534. OFN_SHAREAWARE; // don't check the existance of file with OpenFile
  535. ofn.lpstrDefExt = _T("log");
  536. if ( !GetOpenFileName(&ofn) )
  537. {
  538. goto out;
  539. }
  540. hr = StringCchCopyW(g_szSingleLogFile, ARRAY_LENGTH(g_szSingleLogFile), wszAppFullPath);
  541. if (FAILED(hr)) {
  542. AVErrorResourceFormat(IDS_PATH_TOO_LONG, wszAppFullPath);
  543. goto out;
  544. }
  545. DialogBox(g_hInstance, (LPCTSTR)IDD_VIEWLOG_PAGE, hDlg, DlgViewLog);
  546. out:
  547. g_szSingleLogFile[0] = 0;
  548. }
  549. void
  550. SelectApp(
  551. HWND hDlg,
  552. int nWhich
  553. )
  554. {
  555. HWND hList = GetDlgItem(hDlg, IDC_LIST_APPS);
  556. int nItems = ListView_GetItemCount(hList);
  557. if (nItems == 0) {
  558. return;
  559. }
  560. if (nWhich > nItems - 1) {
  561. nWhich = nItems - 1;
  562. }
  563. ListView_SetItemState(hList, nWhich, LVIS_SELECTED, LVIS_SELECTED);
  564. }
  565. void
  566. RunSelectedApp(
  567. HWND hDlg
  568. )
  569. {
  570. WCHAR wszCommandLine[MAX_PATH];
  571. HRESULT hr;
  572. SaveSettings(hDlg);
  573. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  574. int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  575. if (nApp == -1) {
  576. return;
  577. }
  578. LVITEM lvi;
  579. lvi.mask = LVIF_PARAM;
  580. lvi.iItem = nApp;
  581. lvi.iSubItem = 0;
  582. ListView_GetItem(hAppList, &lvi);
  583. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  584. if (pApp->wstrExePath.size()) {
  585. //
  586. // first set the current directory properly, if possible
  587. //
  588. LPWSTR pwsz;
  589. hr = StringCchCopyW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), pApp->wstrExePath.c_str());
  590. if (FAILED(hr)) {
  591. AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
  592. goto out;
  593. }
  594. pwsz = wcsrchr(wszCommandLine, L'\\');
  595. if (pwsz) {
  596. *pwsz = 0;
  597. SetCurrentDirectory(wszCommandLine);
  598. *pwsz = L'\\';
  599. }
  600. //
  601. // then prepare the command line
  602. //
  603. hr = StringCchPrintfW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), L"\"%s\"", pApp->wstrExePath.c_str());
  604. if (FAILED(hr)) {
  605. AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
  606. goto out;
  607. }
  608. } else {
  609. hr = StringCchPrintfW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), L"\"%s\"", pApp->wstrExeName.c_str());
  610. if (FAILED(hr)) {
  611. AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExeName.c_str());
  612. goto out;
  613. }
  614. }
  615. PROCESS_INFORMATION ProcessInfo;
  616. BOOL bRet;
  617. STARTUPINFO StartupInfo;
  618. ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  619. StartupInfo.cb = sizeof(StartupInfo);
  620. ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
  621. bRet = CreateProcess(NULL,
  622. wszCommandLine,
  623. NULL,
  624. NULL,
  625. FALSE,
  626. 0,
  627. NULL,
  628. NULL,
  629. &StartupInfo,
  630. &ProcessInfo);
  631. if (!bRet) {
  632. WCHAR wszFilter[] = L"Executable files (*.exe)\0*.exe\0";
  633. OPENFILENAME ofn;
  634. WCHAR wszAppFullPath[MAX_PATH];
  635. WCHAR wszAppShortName[MAX_PATH];
  636. wstring strCaption;
  637. if (!AVLoadString(IDS_LOCATE_APP, strCaption)) {
  638. strCaption = _T("Please locate application");
  639. }
  640. if (pApp->wstrExePath.size()) {
  641. hr = StringCchCopyW(wszAppFullPath, ARRAY_LENGTH(wszAppFullPath), pApp->wstrExePath.c_str());
  642. if (FAILED(hr)) {
  643. AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
  644. goto out;
  645. }
  646. } else {
  647. hr = StringCchCopyW(wszAppFullPath, ARRAY_LENGTH(wszAppFullPath), pApp->wstrExeName.c_str());
  648. if (FAILED(hr)) {
  649. AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExeName.c_str());
  650. goto out;
  651. }
  652. }
  653. ofn.lStructSize = sizeof(OPENFILENAME);
  654. ofn.hwndOwner = hDlg;
  655. ofn.hInstance = NULL;
  656. ofn.lpstrFilter = wszFilter;
  657. ofn.lpstrCustomFilter = NULL;
  658. ofn.nMaxCustFilter = 0;
  659. ofn.nFilterIndex = 0;
  660. ofn.lpstrFile = wszAppFullPath;
  661. ofn.nMaxFile = MAX_PATH;
  662. ofn.lpstrFileTitle = wszAppShortName;
  663. ofn.nMaxFileTitle = MAX_PATH;
  664. ofn.lpstrInitialDir = NULL;
  665. ofn.lpstrTitle = strCaption.c_str();
  666. ofn.Flags = OFN_PATHMUSTEXIST |
  667. OFN_HIDEREADONLY | // hide the "open read-only" checkbox
  668. OFN_NONETWORKBUTTON | // no network button
  669. OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
  670. OFN_SHAREAWARE; // don't check the existance of file with OpenFile
  671. ofn.lpstrDefExt = NULL;
  672. if (!GetOpenFileName(&ofn)) {
  673. return;
  674. }
  675. pApp->wstrExePath = wszAppFullPath;
  676. pApp->wstrExeName = wszAppShortName;
  677. hr = StringCchPrintfW(wszCommandLine, ARRAY_LENGTH(wszCommandLine), L"\"%s\"", pApp->wstrExePath.c_str());
  678. if (FAILED(hr)) {
  679. AVErrorResourceFormat(IDS_PATH_TOO_LONG, pApp->wstrExePath.c_str());
  680. goto out;
  681. }
  682. RefreshAppList(hDlg);
  683. ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  684. StartupInfo.cb = sizeof(StartupInfo);
  685. ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
  686. bRet = CreateProcess(NULL,
  687. wszCommandLine,
  688. NULL,
  689. NULL,
  690. FALSE,
  691. 0,
  692. NULL,
  693. NULL,
  694. &StartupInfo,
  695. &ProcessInfo);
  696. if (!bRet) {
  697. AVErrorResourceFormat(IDS_CANT_LAUNCH_EXE);
  698. }
  699. }
  700. out:
  701. return;
  702. }
  703. void
  704. AddAppToList(
  705. HWND hDlg
  706. )
  707. {
  708. WCHAR wszFilter[] = L"Executable files (*.exe)\0*.exe\0";
  709. OPENFILENAME ofn;
  710. WCHAR wszAppFullPath[MAX_PATH];
  711. WCHAR wszAppShortName[MAX_PATH];
  712. wstring wstrTitle;
  713. if (!AVLoadString(IDS_ADD_APPLICATION_TITLE, wstrTitle)) {
  714. wstrTitle = _T("Add Application");
  715. }
  716. wszAppFullPath[0] = 0;
  717. ofn.lStructSize = sizeof(OPENFILENAME);
  718. ofn.hwndOwner = hDlg;
  719. ofn.hInstance = NULL;
  720. ofn.lpstrFilter = wszFilter;
  721. ofn.lpstrCustomFilter = NULL;
  722. ofn.nMaxCustFilter = 0;
  723. ofn.nFilterIndex = 0;
  724. ofn.lpstrFile = wszAppFullPath;
  725. ofn.nMaxFile = MAX_PATH;
  726. ofn.lpstrFileTitle = wszAppShortName;
  727. ofn.nMaxFileTitle = MAX_PATH;
  728. ofn.lpstrInitialDir = NULL;
  729. ofn.lpstrTitle = wstrTitle.c_str();
  730. ofn.Flags = OFN_HIDEREADONLY | // hide the "open read-only" checkbox
  731. OFN_NONETWORKBUTTON | // no network button
  732. OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
  733. OFN_SHAREAWARE; // don't check the existance of file with OpenFile
  734. ofn.lpstrDefExt = _T("EXE");
  735. if (!GetOpenFileName(&ofn)) {
  736. return;
  737. }
  738. //
  739. // check to see if the app is already in the list
  740. //
  741. CAVAppInfo *pApp;
  742. BOOL bFound = FALSE;
  743. for (pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); pApp++) {
  744. if (_wcsicmp(pApp->wstrExeName.c_str(), wszAppShortName) == 0) {
  745. //
  746. // the app is already in the list, so just update the full
  747. // path, if it's good
  748. //
  749. if (GetFileAttributes(wszAppFullPath) != -1) {
  750. pApp->wstrExePath = wszAppFullPath;
  751. }
  752. bFound = TRUE;
  753. }
  754. }
  755. //
  756. // if the app wasn't already in the list, add it to the list
  757. //
  758. if (!bFound) {
  759. CAVAppInfo AppInfo;
  760. AppInfo.wstrExeName = wszAppShortName;
  761. //
  762. // check to see if the file actually exists
  763. //
  764. if (GetFileAttributes(wszAppFullPath) != -1) {
  765. AppInfo.wstrExePath = wszAppFullPath;
  766. }
  767. //
  768. // init the default tests
  769. //
  770. CAVAppInfo *pDefaultApp = &g_aAppInfo[0];
  771. CTestInfo *pTest;
  772. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  773. if (pDefaultApp->IsTestActive(*pTest)) {
  774. AppInfo.AddTest(*pTest);
  775. }
  776. }
  777. g_aAppInfo.push_back(AppInfo);
  778. RefreshAppList(hDlg);
  779. SelectApp(hDlg, 9999);
  780. DirtySettings(hDlg, TRUE);
  781. }
  782. }
  783. void
  784. RemoveSelectedApp(
  785. HWND hDlg
  786. )
  787. {
  788. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  789. int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  790. if (nApp == -1) {
  791. return;
  792. }
  793. LVITEM lvi;
  794. lvi.mask = LVIF_PARAM;
  795. lvi.iItem = nApp;
  796. lvi.iSubItem = 0;
  797. ListView_GetItem(hAppList, &lvi);
  798. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  799. //
  800. // if there is a debugger set for this app, for various reasons we want to
  801. // kill the debugger before removing the app, or the debugger may linger forever
  802. //
  803. if (pApp->bBreakOnLog || pApp->bUseAVDebugger) {
  804. pApp->bBreakOnLog = FALSE;
  805. pApp->bUseAVDebugger = FALSE;
  806. SetCurrentAppSettings();
  807. }
  808. g_aAppInfo.erase(pApp);
  809. RefreshAppList(hDlg);
  810. SelectApp(hDlg, nApp);
  811. DirtySettings(hDlg, TRUE);
  812. }
  813. typedef struct _CONFLICT_DLG_INFO {
  814. CTestInfo *pTest1;
  815. CTestInfo *pTest2;
  816. } CONFLICT_DLG_INFO, *PCONFLICT_DLG_INFO;
  817. void
  818. CheckForRunAlone(
  819. CAVAppInfo *pApp
  820. )
  821. {
  822. if (!pApp) {
  823. return;
  824. }
  825. DWORD dwTests = 0;
  826. //
  827. // count the number of tests active
  828. //
  829. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  830. if (pApp->IsTestActive(*pTest)) {
  831. dwTests++;
  832. }
  833. }
  834. //
  835. // look for conflicts
  836. //
  837. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  838. //
  839. // if there are less than two, no chance for conflict
  840. //
  841. if (dwTests < 2) {
  842. return;
  843. }
  844. if (pTest->bRunAlone && pApp->IsTestActive(*pTest)) {
  845. CONFLICT_DLG_INFO DlgInfo;
  846. ZeroMemory(&DlgInfo, sizeof(DlgInfo));
  847. DlgInfo.pTest1 = pTest; // pTest2 is unused in this case
  848. INT_PTR nResult = DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_MUST_RUN_ALONE), g_hDlgMain, DlgRunAlone, (LPARAM)&DlgInfo);
  849. switch (nResult) {
  850. case IDC_BTN_DISABLE1:
  851. pApp->RemoveTest(*pTest);
  852. DirtySettings(g_hDlgMain, TRUE);
  853. RefreshSettingsList(g_hDlgMain, TRUE);
  854. dwTests--;
  855. break;
  856. case IDC_BTN_DISABLE2:
  857. //
  858. // disable all the tests except the one passed in
  859. //
  860. for (CTestInfo *pTestTemp = g_aTestInfo.begin(); pTestTemp != g_aTestInfo.end(); pTestTemp++) {
  861. if (pTest != pTestTemp) {
  862. pApp->RemoveTest(*pTestTemp);
  863. }
  864. }
  865. DirtySettings(g_hDlgMain, TRUE);
  866. RefreshSettingsList(g_hDlgMain, TRUE);
  867. dwTests = 1;
  868. break;
  869. }
  870. }
  871. }
  872. }
  873. void
  874. CheckForConflictingTests(
  875. CAVAppInfo *pApp,
  876. LPCWSTR wszTest1,
  877. LPCWSTR wszTest2
  878. )
  879. {
  880. CONFLICT_DLG_INFO DlgInfo;
  881. ZeroMemory(&DlgInfo, sizeof(DlgInfo));
  882. //
  883. // get the test pointers from the names
  884. //
  885. for (CTestInfo *pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  886. if (pTest->strTestName == wszTest1) {
  887. DlgInfo.pTest1 = pTest;
  888. }
  889. if (pTest->strTestName == wszTest2) {
  890. DlgInfo.pTest2 = pTest;
  891. }
  892. }
  893. //
  894. // if we didn't find one or the other tests, get out
  895. //
  896. if (!DlgInfo.pTest1 || !DlgInfo.pTest2) {
  897. return;
  898. }
  899. if (pApp->IsTestActive(*DlgInfo.pTest1) && pApp->IsTestActive(*DlgInfo.pTest2)) {
  900. INT_PTR nResult = DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_CONFLICT), g_hDlgMain, DlgConflict, (LPARAM)&DlgInfo);
  901. switch (nResult) {
  902. case IDC_BTN_DISABLE1:
  903. pApp->RemoveTest(*DlgInfo.pTest1);
  904. DirtySettings(g_hDlgMain, TRUE);
  905. RefreshSettingsList(g_hDlgMain, TRUE);
  906. break;
  907. case IDC_BTN_DISABLE2:
  908. pApp->RemoveTest(*DlgInfo.pTest2);
  909. DirtySettings(g_hDlgMain, TRUE);
  910. RefreshSettingsList(g_hDlgMain, TRUE);
  911. break;
  912. }
  913. }
  914. }
  915. void
  916. ScanSettingsList(
  917. HWND hDlg,
  918. int nItem
  919. )
  920. {
  921. HWND hSettingList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  922. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  923. int nBegin, nEnd;
  924. int nApp = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  925. if (nApp == -1) {
  926. return;
  927. }
  928. LVITEM lvi;
  929. lvi.mask = LVIF_PARAM;
  930. lvi.iItem = nApp;
  931. lvi.iSubItem = 0;
  932. ListView_GetItem(hAppList, &lvi);
  933. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  934. if (!pApp) {
  935. return;
  936. }
  937. int nItems = ListView_GetItemCount(hSettingList);
  938. if (!nItems) {
  939. //
  940. // nothing in list
  941. //
  942. return;
  943. }
  944. if (nItem == -1 || nItem >= nItems) {
  945. nBegin = 0;
  946. nEnd = nItems;
  947. } else {
  948. nBegin = nItem;
  949. nEnd = nItem + 1;
  950. }
  951. for (int i = nBegin; i < nEnd; ++i) {
  952. BOOL bTestEnabled = FALSE;
  953. BOOL bChecked = FALSE;
  954. lvi.iItem = i;
  955. ListView_GetItem(hSettingList, &lvi);
  956. CTestInfo *pTest = (CTestInfo*)lvi.lParam;
  957. bChecked = ListView_GetCheckState(hSettingList, i);
  958. bTestEnabled = pApp->IsTestActive(*pTest);
  959. if (bTestEnabled != bChecked) {
  960. DirtySettings(hDlg, TRUE);
  961. if (bChecked) {
  962. pApp->AddTest(*pTest);
  963. } else {
  964. pApp->RemoveTest(*pTest);
  965. }
  966. }
  967. CheckForRunAlone(pApp);
  968. }
  969. CheckForConflictingTests(pApp, L"LogFileChanges", L"WindowsFileProtection");
  970. }
  971. void
  972. DisplaySettingsDescription(
  973. HWND hDlg
  974. )
  975. {
  976. HWND hList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  977. int nItem = ListView_GetNextItem(hList, -1, LVNI_SELECTED);
  978. if (nItem == -1) {
  979. WCHAR szTestDesc[256];
  980. LoadString(g_hInstance, IDS_VIEW_TEST_DESC, szTestDesc, ARRAY_LENGTH(szTestDesc));
  981. SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), szTestDesc);
  982. } else {
  983. LVITEM lvi;
  984. lvi.mask = LVIF_PARAM;
  985. lvi.iItem = nItem;
  986. lvi.iSubItem = 0;
  987. ListView_GetItem(hList, &lvi);
  988. CTestInfo *pTest = (CTestInfo*)lvi.lParam;
  989. SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), pTest->strTestDescription.c_str());
  990. }
  991. }
  992. CAVAppInfo *
  993. GetCurrentAppSelection(
  994. void
  995. )
  996. {
  997. if (!g_hDlgMain) {
  998. return NULL;
  999. }
  1000. HWND hAppList = GetDlgItem(g_hDlgMain, IDC_LIST_APPS);
  1001. int nItem = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  1002. if (nItem == -1) {
  1003. return NULL;
  1004. }
  1005. LVITEM lvi;
  1006. lvi.mask = LVIF_PARAM;
  1007. lvi.iItem = nItem;
  1008. lvi.iSubItem = 0;
  1009. ListView_GetItem(hAppList, &lvi);
  1010. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  1011. return pApp;
  1012. }
  1013. void
  1014. RefreshSettingsList(
  1015. HWND hDlg,
  1016. BOOL bForceRefresh
  1017. )
  1018. {
  1019. g_bRefreshingSettings = TRUE;
  1020. HWND hSettingList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  1021. HWND hAppList = GetDlgItem(hDlg, IDC_LIST_APPS);
  1022. static nLastItem = -1;
  1023. int nItem = ListView_GetNextItem(hAppList, -1, LVNI_SELECTED);
  1024. if (nItem == -1) {
  1025. EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
  1026. EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
  1027. EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), FALSE);
  1028. } else if (nItem == 0) {
  1029. EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
  1030. EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
  1031. EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), TRUE);
  1032. } else {
  1033. EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), TRUE);
  1034. EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), TRUE);
  1035. EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), TRUE);
  1036. }
  1037. if (nItem == nLastItem && !bForceRefresh) {
  1038. goto out;
  1039. }
  1040. ListView_DeleteAllItems(hSettingList);
  1041. DisplaySettingsDescription(hDlg);
  1042. nLastItem = nItem;
  1043. if (nItem != -1) {
  1044. LVITEM lvi;
  1045. lvi.mask = LVIF_PARAM;
  1046. lvi.iItem = nItem;
  1047. lvi.iSubItem = 0;
  1048. ListView_GetItem(hAppList, &lvi);
  1049. CAVAppInfo *pApp = (CAVAppInfo*)lvi.lParam;
  1050. if (!pApp) {
  1051. return;
  1052. }
  1053. CTestInfo* pTest;
  1054. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  1055. //
  1056. // continue if this test isn't win2K compatible, and we're running on win2k
  1057. //
  1058. if (g_bWin2KMode && !pTest->bWin2KCompatible) {
  1059. continue;
  1060. }
  1061. //
  1062. // continue if this test is invalid for the current internal/external mode
  1063. //
  1064. if ((g_bInternalMode && !pTest->bInternal) || (!g_bInternalMode && !pTest->bExternal)) {
  1065. continue;
  1066. }
  1067. WCHAR szText[256];
  1068. //
  1069. // don't check the return, because if it's truncated, that's acceptable
  1070. //
  1071. StringCchPrintfW(szText, ARRAY_LENGTH(szText), L"%s - %s", pTest->strTestName.c_str(), pTest->strTestFriendlyName.c_str());
  1072. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  1073. lvi.pszText = (LPWSTR)szText;
  1074. lvi.lParam = (LPARAM)pTest;
  1075. lvi.iItem = 9999;
  1076. lvi.iSubItem = 0;
  1077. nItem = ListView_InsertItem(hSettingList, &lvi);
  1078. BOOL bCheck = pApp->IsTestActive(*pTest);
  1079. ListView_SetCheckState(hSettingList, nItem, bCheck);
  1080. }
  1081. }
  1082. out:
  1083. g_bRefreshingSettings = FALSE;
  1084. return;
  1085. }
  1086. static const DWORD MAX_DEBUGGER_LEN = 1024;
  1087. void
  1088. ReadOptions(
  1089. void
  1090. )
  1091. {
  1092. for (CAVAppInfo *pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); ++pApp) {
  1093. LPCWSTR szExe = pApp->wstrExeName.c_str();
  1094. WCHAR szDebugger[MAX_DEBUGGER_LEN];
  1095. pApp->bBreakOnLog = GetShimSettingDWORD(L"General", szExe, AV_OPTION_BREAK_ON_LOG, FALSE);
  1096. pApp->bFullPageHeap = GetShimSettingDWORD(L"General", szExe, AV_OPTION_FULL_PAGEHEAP, FALSE);
  1097. pApp->bUseAVDebugger = GetShimSettingDWORD(L"General", szExe, AV_OPTION_AV_DEBUGGER, FALSE);
  1098. pApp->bPropagateTests = GetShimSettingDWORD(L"General", szExe, AV_OPTION_PROPAGATE, FALSE);
  1099. szDebugger[0] = 0;
  1100. GetShimSettingString(L"General", szExe, AV_OPTION_DEBUGGER, szDebugger, MAX_DEBUGGER_LEN);
  1101. pApp->wstrDebugger = szDebugger;
  1102. }
  1103. }
  1104. void
  1105. SaveOptions(
  1106. void
  1107. )
  1108. {
  1109. for (CAVAppInfo *pApp = g_aAppInfo.begin(); pApp != g_aAppInfo.end(); ++pApp) {
  1110. LPCWSTR szExe = pApp->wstrExeName.c_str();
  1111. SaveShimSettingDWORD(L"General", szExe, AV_OPTION_BREAK_ON_LOG, (DWORD)pApp->bBreakOnLog);
  1112. SaveShimSettingDWORD(L"General", szExe, AV_OPTION_FULL_PAGEHEAP, (DWORD)pApp->bFullPageHeap);
  1113. SaveShimSettingDWORD(L"General", szExe, AV_OPTION_AV_DEBUGGER, (DWORD)pApp->bUseAVDebugger);
  1114. SaveShimSettingDWORD(L"General", szExe, AV_OPTION_PROPAGATE, (DWORD)pApp->bPropagateTests);
  1115. SaveShimSettingString(L"General", szExe, AV_OPTION_DEBUGGER, pApp->wstrDebugger.c_str());
  1116. }
  1117. SetCurrentAppSettings();
  1118. }
  1119. INT_PTR CALLBACK
  1120. DlgRunAlone(
  1121. HWND hDlg,
  1122. UINT message,
  1123. WPARAM wParam,
  1124. LPARAM lParam
  1125. )
  1126. {
  1127. switch (message) {
  1128. case WM_INITDIALOG:
  1129. {
  1130. WCHAR wszTemp[256];
  1131. WCHAR wszExpandedTemp[512];
  1132. PCONFLICT_DLG_INFO pDlgInfo;
  1133. pDlgInfo = (PCONFLICT_DLG_INFO)lParam;
  1134. wszTemp[0] = 0;
  1135. AVLoadString(IDS_RUN_ALONE_MESSAGE, wszTemp, ARRAY_LENGTH(wszTemp));
  1136. StringCchPrintfW(
  1137. wszExpandedTemp,
  1138. ARRAY_LENGTH(wszExpandedTemp),
  1139. wszTemp,
  1140. pDlgInfo->pTest1->strTestFriendlyName.c_str()
  1141. );
  1142. SetDlgItemTextW(hDlg, IDC_CONFLICT_STATIC, wszExpandedTemp);
  1143. return TRUE;
  1144. }
  1145. case WM_COMMAND:
  1146. switch (LOWORD(wParam)) {
  1147. case IDC_BTN_DISABLE1:
  1148. case IDC_BTN_DISABLE2:
  1149. case IDCANCEL:
  1150. //
  1151. // return the button that was pressed
  1152. //
  1153. EndDialog(hDlg, (INT_PTR)LOWORD(wParam));
  1154. break;
  1155. }
  1156. break;
  1157. }
  1158. return FALSE;
  1159. }
  1160. INT_PTR CALLBACK
  1161. DlgConflict(
  1162. HWND hDlg,
  1163. UINT message,
  1164. WPARAM wParam,
  1165. LPARAM lParam
  1166. )
  1167. {
  1168. switch (message) {
  1169. case WM_INITDIALOG:
  1170. {
  1171. WCHAR wszTemp[256];
  1172. WCHAR wszExpandedTemp[512];
  1173. PCONFLICT_DLG_INFO pDlgInfo;
  1174. pDlgInfo = (PCONFLICT_DLG_INFO)lParam;
  1175. wszTemp[0] = 0;
  1176. AVLoadString(IDS_CONFLICT_MESSAGE, wszTemp, ARRAY_LENGTH(wszTemp));
  1177. StringCchPrintf(
  1178. wszExpandedTemp,
  1179. ARRAY_LENGTH(wszExpandedTemp),
  1180. wszTemp,
  1181. pDlgInfo->pTest1->strTestFriendlyName.c_str(),
  1182. pDlgInfo->pTest2->strTestFriendlyName.c_str()
  1183. );
  1184. SetDlgItemTextW(hDlg, IDC_CONFLICT_STATIC, wszExpandedTemp);
  1185. return TRUE;
  1186. }
  1187. case WM_COMMAND:
  1188. switch (LOWORD(wParam)) {
  1189. case IDC_BTN_DISABLE1:
  1190. case IDC_BTN_DISABLE2:
  1191. case IDCANCEL:
  1192. //
  1193. // return the button that was pressed
  1194. //
  1195. EndDialog(hDlg, (INT_PTR)LOWORD(wParam));
  1196. break;
  1197. }
  1198. break;
  1199. }
  1200. return FALSE;
  1201. }
  1202. INT_PTR CALLBACK
  1203. DlgViewOptions(
  1204. HWND hDlg,
  1205. UINT message,
  1206. WPARAM wParam,
  1207. LPARAM lParam
  1208. )
  1209. {
  1210. static CAVAppInfo *pApp;
  1211. switch (message) {
  1212. case WM_INITDIALOG:
  1213. g_hDlgOptions = hDlg;
  1214. pApp = GetCurrentAppSelection();
  1215. if (!pApp) {
  1216. return FALSE;
  1217. }
  1218. ReadOptions();
  1219. //
  1220. // initialize the combo box options
  1221. //
  1222. SendDlgItemMessage(hDlg,
  1223. IDC_COMBO_DEBUGGER,
  1224. CB_ADDSTRING,
  1225. 0,
  1226. (LPARAM)L"ntsd");
  1227. SendDlgItemMessage(hDlg,
  1228. IDC_COMBO_DEBUGGER,
  1229. CB_ADDSTRING,
  1230. 0,
  1231. (LPARAM)L"windbg");
  1232. if (pApp->bBreakOnLog) {
  1233. pApp->bUseAVDebugger = FALSE;
  1234. EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), FALSE);
  1235. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), TRUE);
  1236. EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), TRUE);
  1237. if (!pApp->wstrDebugger.size()) {
  1238. SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, L"ntsd");
  1239. } else {
  1240. SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, pApp->wstrDebugger.c_str());
  1241. }
  1242. } else {
  1243. EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), TRUE);
  1244. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), FALSE);
  1245. EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), FALSE);
  1246. }
  1247. /*SendDlgItemMessage(hDlg,
  1248. IDC_CLEAR_LOG_ON_CHANGES,
  1249. BM_SETCHECK,
  1250. (pApp->bClearSessionLogBeforeRun ? BST_CHECKED : BST_UNCHECKED),
  1251. 0);*/
  1252. SendDlgItemMessage(hDlg,
  1253. IDC_BREAK_ON_LOG,
  1254. BM_SETCHECK,
  1255. (pApp->bBreakOnLog ? BST_CHECKED : BST_UNCHECKED),
  1256. 0);
  1257. SendDlgItemMessage(hDlg,
  1258. IDC_FULL_PAGEHEAP,
  1259. BM_SETCHECK,
  1260. (pApp->bFullPageHeap ? BST_CHECKED : BST_UNCHECKED),
  1261. 0);
  1262. SendDlgItemMessage(hDlg,
  1263. IDC_USE_AV_DEBUGGER,
  1264. BM_SETCHECK,
  1265. (pApp->bUseAVDebugger ? BST_CHECKED : BST_UNCHECKED),
  1266. 0);
  1267. SendDlgItemMessage(hDlg,
  1268. IDC_PROPAGATE_TESTS,
  1269. BM_SETCHECK,
  1270. (pApp->bPropagateTests ? BST_CHECKED : BST_UNCHECKED),
  1271. 0);
  1272. return TRUE;
  1273. case WM_COMMAND:
  1274. switch (LOWORD(wParam)) {
  1275. case IDC_BREAK_ON_LOG:
  1276. {
  1277. BOOL bChecked = IsDlgButtonChecked(hDlg, IDC_BREAK_ON_LOG);
  1278. if (bChecked) {
  1279. WCHAR szTemp[256];
  1280. CheckDlgButton(hDlg, IDC_USE_AV_DEBUGGER, BST_UNCHECKED);
  1281. EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), FALSE);
  1282. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), TRUE);
  1283. EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), TRUE);
  1284. GetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, szTemp, ARRAY_LENGTH(szTemp));
  1285. if (!szTemp[0]) {
  1286. if (!pApp->wstrDebugger.size()) {
  1287. SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, L"ntsd");
  1288. } else {
  1289. SetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, pApp->wstrDebugger.c_str());
  1290. }
  1291. }
  1292. } else {
  1293. EnableWindow(GetDlgItem(hDlg, IDC_USE_AV_DEBUGGER), TRUE);
  1294. EnableWindow(GetDlgItem(hDlg, IDC_STATIC_DEBUGGER), FALSE);
  1295. EnableWindow(GetDlgItem(hDlg, IDC_COMBO_DEBUGGER), FALSE);
  1296. }
  1297. }
  1298. break;
  1299. }
  1300. break;
  1301. case WM_NOTIFY:
  1302. switch (((NMHDR FAR *) lParam)->code) {
  1303. case PSN_APPLY:
  1304. /* pApp->bClearSessionLogBeforeRun = (SendDlgItemMessage(hDlg,
  1305. IDC_CLEAR_LOG_ON_CHANGES,
  1306. BM_GETCHECK,
  1307. 0,
  1308. 0) == BST_CHECKED);*/
  1309. pApp->bBreakOnLog = (SendDlgItemMessage(hDlg,
  1310. IDC_BREAK_ON_LOG,
  1311. BM_GETCHECK,
  1312. 0,
  1313. 0) == BST_CHECKED);
  1314. pApp->bFullPageHeap = (SendDlgItemMessage(hDlg,
  1315. IDC_FULL_PAGEHEAP,
  1316. BM_GETCHECK,
  1317. 0,
  1318. 0) == BST_CHECKED);
  1319. pApp->bUseAVDebugger = (SendDlgItemMessage(hDlg,
  1320. IDC_USE_AV_DEBUGGER,
  1321. BM_GETCHECK,
  1322. 0,
  1323. 0) == BST_CHECKED);
  1324. pApp->bPropagateTests = (SendDlgItemMessage(hDlg,
  1325. IDC_PROPAGATE_TESTS,
  1326. BM_GETCHECK,
  1327. 0,
  1328. 0) == BST_CHECKED);
  1329. WCHAR szDebugger[MAX_DEBUGGER_LEN];
  1330. szDebugger[0] = 0;
  1331. GetDlgItemText(hDlg, IDC_COMBO_DEBUGGER, szDebugger, ARRAY_LENGTH(szDebugger));
  1332. pApp->wstrDebugger = szDebugger;
  1333. SaveOptions();
  1334. g_hDlgOptions = NULL;
  1335. break;
  1336. }
  1337. }
  1338. return FALSE;
  1339. }
  1340. void
  1341. ViewOptions(
  1342. HWND hDlg
  1343. )
  1344. {
  1345. HPROPSHEETPAGE *phPages = NULL;
  1346. PROPSHEETPAGE PageGlobal;
  1347. PROPSHEETHEADER psh;
  1348. CTestInfo* pTest;
  1349. DWORD dwPages = 1;
  1350. DWORD dwPage = 0;
  1351. CAVAppInfo *pApp = GetCurrentAppSelection();
  1352. if (!pApp) {
  1353. return;
  1354. }
  1355. LPCWSTR szExe = pApp->wstrExeName.c_str();
  1356. //
  1357. // count the number of pages
  1358. //
  1359. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  1360. if (pTest->PropSheetPage.pfnDlgProc) {
  1361. dwPages++;
  1362. }
  1363. }
  1364. phPages = new HPROPSHEETPAGE[dwPages];
  1365. if (!phPages) {
  1366. return;
  1367. }
  1368. //
  1369. // init the global page
  1370. //
  1371. PageGlobal.dwSize = sizeof(PROPSHEETPAGE);
  1372. PageGlobal.dwFlags = PSP_USETITLE;
  1373. PageGlobal.hInstance = g_hInstance;
  1374. PageGlobal.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS);
  1375. PageGlobal.pfnDlgProc = DlgViewOptions;
  1376. PageGlobal.pszTitle = MAKEINTRESOURCE(IDS_GLOBAL_OPTIONS);
  1377. PageGlobal.lParam = 0;
  1378. PageGlobal.pfnCallback = NULL;
  1379. phPages[0] = CreatePropertySheetPage(&PageGlobal);
  1380. if (!phPages[0]) {
  1381. //
  1382. // we need the global page minimum
  1383. //
  1384. return;
  1385. }
  1386. //
  1387. // add the pages for the various tests
  1388. //
  1389. dwPage = 1;
  1390. for (pTest = g_aTestInfo.begin(); pTest != g_aTestInfo.end(); pTest++) {
  1391. if (pTest->PropSheetPage.pfnDlgProc) {
  1392. //
  1393. // we use the lParam to identify the exe involved
  1394. //
  1395. pTest->PropSheetPage.lParam = (LPARAM)szExe;
  1396. phPages[dwPage] = CreatePropertySheetPage(&(pTest->PropSheetPage));
  1397. if (!phPages[dwPage]) {
  1398. dwPages--;
  1399. } else {
  1400. dwPage++;
  1401. }
  1402. }
  1403. }
  1404. wstring wstrOptions;
  1405. AVLoadString(IDS_OPTIONS_TITLE, wstrOptions);
  1406. wstrOptions += L" - ";
  1407. wstrOptions += szExe;
  1408. psh.dwSize = sizeof(PROPSHEETHEADER);
  1409. psh.dwFlags = PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP;
  1410. psh.hwndParent = hDlg;
  1411. psh.hInstance = g_hInstance;
  1412. psh.pszCaption = wstrOptions.c_str();
  1413. psh.nPages = dwPages;
  1414. psh.nStartPage = 0;
  1415. psh.phpage = phPages;
  1416. psh.pfnCallback = NULL;
  1417. PropertySheet(&psh);
  1418. }
  1419. // Message handler for main dialog.
  1420. INT_PTR CALLBACK
  1421. DlgMain(
  1422. HWND hDlg,
  1423. UINT message,
  1424. WPARAM wParam,
  1425. LPARAM lParam
  1426. )
  1427. {
  1428. switch (message) {
  1429. case WM_INITDIALOG:
  1430. {
  1431. wstring strTemp;
  1432. g_hDlgMain = hDlg;
  1433. //
  1434. // set the caption to the appropriate version, etc.
  1435. //
  1436. if (GetAppTitleString(strTemp)) {
  1437. SetWindowText(hDlg, strTemp.c_str());
  1438. }
  1439. EnableWindow(GetDlgItem(hDlg, IDC_BTN_RUN), FALSE);
  1440. EnableWindow(GetDlgItem(hDlg, IDC_BTN_REMOVE), FALSE);
  1441. EnableWindow(GetDlgItem(hDlg, IDC_BTN_SAVE_SETTINGS), FALSE);
  1442. EnableWindow(GetDlgItem(hDlg, IDC_BTN_OPTIONS), FALSE);
  1443. HWND hList = GetDlgItem(hDlg, IDC_LIST_SETTINGS);
  1444. if (hList) {
  1445. LVCOLUMN lvc;
  1446. lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  1447. lvc.fmt = LVCFMT_LEFT;
  1448. lvc.cx = 700;
  1449. lvc.iSubItem = 0;
  1450. lvc.pszText = L"xxx";
  1451. ListView_InsertColumn(hList, 0, &lvc);
  1452. ListView_SetExtendedListViewStyleEx(hList, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
  1453. }
  1454. hList = GetDlgItem(hDlg, IDC_LIST_APPS);
  1455. if (hList) {
  1456. LVITEM lvi;
  1457. LVCOLUMN lvc;
  1458. lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH;
  1459. lvc.fmt = LVCFMT_LEFT;
  1460. lvc.cx = 250;
  1461. lvc.iSubItem = 0;
  1462. lvc.pszText = L"xxx";
  1463. ListView_InsertColumn(hList, 0, &lvc);
  1464. RefreshAppList(hDlg);
  1465. SelectApp(hDlg, 0);
  1466. }
  1467. WCHAR szTestDesc[256];
  1468. LoadString(g_hInstance, IDS_VIEW_TEST_DESC, szTestDesc, ARRAY_LENGTH(szTestDesc));
  1469. SetWindowText(GetDlgItem(hDlg, IDC_STATIC_DESC), szTestDesc);
  1470. //
  1471. // Show the app icon.
  1472. //
  1473. HICON hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
  1474. SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)hIcon);
  1475. return TRUE;
  1476. }
  1477. break;
  1478. case WM_ACTIVATE:
  1479. if (LOWORD(wParam) == WA_INACTIVE) {
  1480. SaveSettingsIfDirty(hDlg);
  1481. }
  1482. break;
  1483. case WM_COMMAND:
  1484. switch (LOWORD(wParam)) {
  1485. case IDC_BTN_ADD:
  1486. AddAppToList(hDlg);
  1487. break;
  1488. case IDC_BTN_REMOVE:
  1489. RemoveSelectedApp(hDlg);
  1490. break;
  1491. case IDC_BTN_VIEW_LOG:
  1492. DisplayLog(hDlg);
  1493. break;
  1494. case IDC_BTN_VIEW_EXTERNAL_LOG:
  1495. DisplaySingleLog(hDlg);
  1496. break;
  1497. case IDC_BTN_OPTIONS:
  1498. ViewOptions(hDlg);
  1499. break;
  1500. case IDC_BTN_RUN:
  1501. RunSelectedApp(hDlg);
  1502. break;
  1503. case IDC_BTN_HELP:
  1504. ShowHTMLHelp();
  1505. break;
  1506. case IDOK:
  1507. case IDCANCEL:
  1508. SaveSettings(hDlg);
  1509. EndDialog(hDlg, LOWORD(wParam));
  1510. g_hDlgMain = NULL;
  1511. PostQuitMessage(0);
  1512. return TRUE;
  1513. break;
  1514. }
  1515. break;
  1516. case WM_NOTIFY:
  1517. LPNMHDR pnmh = (LPNMHDR)lParam;
  1518. HWND hItem = pnmh->hwndFrom;
  1519. if (hItem == GetDlgItem(hDlg, IDC_LIST_APPS)) {
  1520. switch (pnmh->code) {
  1521. case LVN_KEYDOWN:
  1522. {
  1523. LPNMLVKEYDOWN pnmkd = (LPNMLVKEYDOWN)lParam;
  1524. if (pnmkd->wVKey == VK_DELETE) {
  1525. if (IsWindowEnabled(GetDlgItem(hDlg, IDC_BTN_RUN))) {
  1526. RemoveSelectedApp(hDlg);
  1527. }
  1528. }
  1529. }
  1530. break;
  1531. case LVN_ITEMCHANGED:
  1532. LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
  1533. if (!g_bRefreshingSettings && (pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED)) {
  1534. RefreshSettingsList(hDlg);
  1535. }
  1536. }
  1537. } else if (hItem == GetDlgItem(hDlg, IDC_LIST_SETTINGS)) {
  1538. switch (pnmh->code) {
  1539. case LVN_ITEMCHANGED:
  1540. LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
  1541. if (!g_bRefreshingSettings) {
  1542. //
  1543. // check for change in selection
  1544. //
  1545. if ((pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) & LVIS_SELECTED)) {
  1546. DisplaySettingsDescription(hDlg);
  1547. }
  1548. //
  1549. // check for change in checkbox
  1550. //
  1551. if ((pnmv->uChanged & LVIF_STATE) && ((pnmv->uNewState ^ pnmv->uOldState) >> 12) != 0) {
  1552. ScanSettingsList(hDlg, pnmv->iItem);
  1553. }
  1554. }
  1555. break;
  1556. }
  1557. }
  1558. break;
  1559. }
  1560. return FALSE;
  1561. }