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.

3162 lines
82 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. QFixApp.cpp
  5. Abstract:
  6. Contains the application entry point, user interface code,
  7. and some supporting functions.
  8. Notes:
  9. ANSI & Unicode via TCHAR - runs on NT/2K/XP etc.
  10. History:
  11. 02/16/00 clupu Created
  12. 11/10/00 rparsons Minor common dialog change
  13. 11/23/00 rparsons Added save XML file capability
  14. 11/25/00 rparsons Matching file on a different drive
  15. can be selected
  16. 05/19/01 rparsons Added context menu for file tree.
  17. Added URL for WU package/helpcenter.
  18. Added Remove Matching File button.
  19. Converted shim list to list view.
  20. 07/06/01 rparsons Static tab control -> child dialogs
  21. 09/24/01 rparsons Spawn a separate VDM when running apps
  22. 10/09/01 rparsons Flags have a command-line
  23. 10/26/01 rparsons No change - 476903.
  24. 01/26/02 rparsons Fix bug # 491301
  25. 02/20/02 rparsons Implemented strsafe functions
  26. 03/22/02 rparsons Fix bug # 583475
  27. --*/
  28. #include "afxwin.h"
  29. #include "commctrl.h"
  30. #include "commdlg.h"
  31. #include "shlwapi.h"
  32. #include "shellapi.h"
  33. #include "shlobj.h"
  34. #include "shlobjp.h" // needed for Link Window support
  35. #include "uxtheme.h" // needed for tab control theme support
  36. #include "resource.h"
  37. #include <tchar.h>
  38. #include <aclapi.h>
  39. #include <strsafe.h>
  40. #include "QFixApp.h"
  41. #include "dbSupport.h"
  42. extern "C" {
  43. #include "shimdb.h"
  44. }
  45. CWinApp theApp;
  46. /*
  47. * Global Variables
  48. */
  49. HINSTANCE g_hInstance;
  50. HWND g_hDlg;
  51. HWND g_hLayersDlg;
  52. HWND g_hFixesDlg;
  53. HWND g_hwndTab;
  54. HWND g_hwndListLayers;
  55. TCHAR g_szAppTitle[64];
  56. TCHAR g_szWinDir[MAX_PATH]; // %windir%
  57. TCHAR g_szSysDir[MAX_PATH]; // %windir%\System32
  58. TCHAR g_szBinary[MAX_PATH]; // the full path of the main binary being shimmed
  59. TCHAR g_szShortName[128]; // the short name of the main EXE
  60. TCHAR g_szParentExeName[MAX_PATH]; // the short name of the parent EXE
  61. TCHAR g_szParentExeFullPath[MAX_PATH]; // the full path of the parent EXE
  62. TCHAR g_szSDBToDelete[MAX_PATH]; // the SDB file to delete from a previous 'Run'
  63. int g_nCrtTab;
  64. HWND g_hwndShimList; // the handle to the list view control
  65. // containing all the shims available
  66. HWND g_hwndFilesTree; // the handle to the tree view control
  67. // containing the matching files selected
  68. HWND g_hwndModuleList; // the handle to the list view control
  69. // containing module information
  70. BOOL g_bSimpleEdition; // simple or dev edition
  71. BOOL g_fW2K; // Win2K or XP
  72. BOOL g_fNETServer; // indicates if we're running on .NET Server
  73. RECT g_rcDlgBig, g_rcDlgSmall; // rectangle of the simple and the dev edition
  74. // of the dialog
  75. BOOL g_bAllShims; // indicates if all shims should be displayed
  76. BOOL g_bShowXML; // indicates if we should hide the 'Show XML' button
  77. BOOL g_bSelectedParentExe; // flag to indicate if a parent EXE has been
  78. // selected
  79. BOOL g_bSDBInstalled; // flag to indicate if the user installed the SDB
  80. // associated with the current EXE
  81. PFIX g_pFixHead;
  82. TCHAR g_szXPUrl[] = _T("hcp://services/subsite?node=TopLevelBucket_4/")
  83. _T("Fixing_a_problem&topic=MS-ITS%3A%25HELP_LOCATION")
  84. _T("%25%5Cmisc.chm%3A%3A/compatibility_tab_and_wizard.htm")
  85. _T("&select=TopLevelBucket_4/Fixing_a_problem/")
  86. _T("Application_and_software_problems");
  87. TCHAR g_szNETUrl[] = _T("hcp://services/subsite?node=Troubleshooting_Strategies&")
  88. _T("topic=MS-ITS%3A%25HELP_LOCATION%25%5Cmisc.chm%3A%3A/")
  89. _T("compatibility_tab_and_wizard.htm");
  90. TCHAR g_szW2KUrl[] = _T("http://www.microsoft.com/windows2000/")
  91. _T("downloads/tools/appcompat/");
  92. #define ID_COUNT_SHIMS 1234
  93. typedef HRESULT (*PFNEnableThemeDialogTexture)(HWND hwnd, DWORD dwFlags);
  94. /*++
  95. Routine Description:
  96. Prints a formatted string to the debugger.
  97. Arguments:
  98. dwDetail - Specifies the level of the information provided.
  99. pszFmt - The string to be displayed.
  100. ... - A va_list of insertion strings.
  101. Return Value:
  102. None.
  103. --*/
  104. void
  105. __cdecl
  106. DebugPrintfEx(
  107. IN LPSTR pszFmt,
  108. ...
  109. )
  110. {
  111. char szT[1024];
  112. va_list arglist;
  113. int len;
  114. va_start(arglist, pszFmt);
  115. //
  116. // Reserve one character for the potential '\n' that we may be adding.
  117. //
  118. StringCchVPrintfA(szT, sizeof(szT) - 1, pszFmt, arglist);
  119. va_end(arglist);
  120. //
  121. // Make sure we have a '\n' at the end of the string
  122. //
  123. len = strlen(szT);
  124. if (len > 0 && szT[len - 1] != '\n') {
  125. szT[len] = '\n';
  126. szT[len + 1] = 0;
  127. }
  128. OutputDebugStringA(szT);
  129. }
  130. BOOL
  131. SearchGroupForSID(
  132. IN DWORD dwGroup,
  133. OUT BOOL* pfIsMember
  134. )
  135. {
  136. PSID pSID;
  137. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  138. BOOL fRes = TRUE;
  139. if (!AllocateAndInitializeSid(&SIDAuth,
  140. 2,
  141. SECURITY_BUILTIN_DOMAIN_RID,
  142. dwGroup,
  143. 0,
  144. 0,
  145. 0,
  146. 0,
  147. 0,
  148. 0,
  149. &pSID)) {
  150. fRes = FALSE;
  151. }
  152. if (!CheckTokenMembership(NULL, pSID, pfIsMember)) {
  153. fRes = FALSE;
  154. }
  155. FreeSid(pSID);
  156. return fRes;
  157. }
  158. BOOL
  159. IsUserAnAdministrator(
  160. void
  161. )
  162. /*++
  163. IsUserAnAdministrator
  164. Description: Determine if the currently logged on user is an admin.
  165. --*/
  166. {
  167. BOOL fIsAdmin;
  168. if (!SearchGroupForSID(DOMAIN_ALIAS_RID_ADMINS, &fIsAdmin)) {
  169. return FALSE;
  170. }
  171. return fIsAdmin;
  172. }
  173. BOOL
  174. CheckForSDB(
  175. void
  176. )
  177. /*++
  178. CheckForSDB
  179. Description: Attempts to locate sysmain.sdb in the apppatch directory.
  180. --*/
  181. {
  182. TCHAR szSDBPath[MAX_PATH];
  183. BOOL fResult = FALSE;
  184. HRESULT hr;
  185. hr = StringCchPrintf(szSDBPath,
  186. ARRAYSIZE(szSDBPath),
  187. _T("%s\\AppPatch\\sysmain.sdb"),
  188. g_szWinDir);
  189. if (FAILED(hr)) {
  190. DPF("[CheckForSDB] 0x%08X Buffer too small", HRESULT_CODE(hr));
  191. return FALSE;
  192. }
  193. if (GetFileAttributes(szSDBPath) != -1) {
  194. fResult = TRUE;
  195. }
  196. return fResult;
  197. }
  198. void
  199. AddModuleToListView(
  200. TCHAR* pModuleName,
  201. UINT uOption
  202. )
  203. /*++
  204. AddModuleToListView
  205. Description: Adds the specified module to the list view.
  206. --*/
  207. {
  208. LVITEM lvi;
  209. int nIndex;
  210. TCHAR szInclude[MAX_PATH];
  211. TCHAR szExclude[MAX_PATH];
  212. LoadString(g_hInstance, IDS_INCLUDE_HDR, szInclude, ARRAYSIZE(szInclude));
  213. LoadString(g_hInstance, IDS_EXCLUDE_HDR, szExclude, ARRAYSIZE(szExclude));
  214. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  215. lvi.lParam = uOption == BST_CHECKED ? 1 : 0;
  216. lvi.pszText = uOption == BST_CHECKED ? szInclude : szExclude;
  217. lvi.iItem = ListView_GetItemCount(g_hwndModuleList);
  218. lvi.iSubItem = 0;
  219. nIndex = ListView_InsertItem(g_hwndModuleList, &lvi);
  220. ListView_SetItemText(g_hwndModuleList,
  221. nIndex,
  222. 1,
  223. pModuleName);
  224. }
  225. void
  226. BuildModuleListForShim(
  227. PFIX pFix,
  228. DWORD dwFlags
  229. )
  230. /*++
  231. BuildModuleListForShim
  232. Description: Based on the flag, adds modules to the list view for
  233. the specified shim or retrieves them and adds them
  234. to the linked list.
  235. --*/
  236. {
  237. PMODULE pModule, pModuleTmp, pModuleNew;
  238. int cItems, nIndex, nLen;
  239. LVITEM lvi;
  240. TCHAR szBuffer[MAX_PATH];
  241. if (dwFlags & BML_ADDTOLISTVIEW) {
  242. //
  243. // Walk the linked list and add the modules to the list view.
  244. //
  245. pModule = pFix->pModule;
  246. while (pModule) {
  247. AddModuleToListView(pModule->pszName,
  248. pModule->fInclude ? BST_CHECKED : 0);
  249. pModule = pModule->pNext;
  250. }
  251. }
  252. if (dwFlags & BML_DELFRLISTVIEW) {
  253. pModule = pFix->pModule;
  254. while (NULL != pModule) {
  255. pModuleTmp = pModule->pNext;
  256. HeapFree(GetProcessHeap(), 0, pModule->pszName);
  257. HeapFree(GetProcessHeap(), 0, pModule);
  258. pModule = pModuleTmp;
  259. }
  260. pFix->pModule = NULL;
  261. }
  262. if (dwFlags & BML_GETFRLISTVIEW) {
  263. pModule = pFix->pModule;
  264. while (NULL != pModule) {
  265. pModuleTmp = pModule->pNext;
  266. HeapFree(GetProcessHeap(), 0, pModule->pszName);
  267. HeapFree(GetProcessHeap(), 0, pModule);
  268. pModule = pModuleTmp;
  269. }
  270. pFix->pModule = NULL;
  271. //
  272. // Get each module from the list view and add it to the linked list.
  273. //
  274. cItems = ListView_GetItemCount(g_hwndModuleList);
  275. if (cItems == 0) {
  276. return;
  277. }
  278. for (nIndex = cItems - 1; nIndex >= 0; nIndex--) {
  279. lvi.mask = LVIF_PARAM;
  280. lvi.iItem = nIndex;
  281. lvi.iSubItem = 0;
  282. ListView_GetItem(g_hwndModuleList, &lvi);
  283. ListView_GetItemText(g_hwndModuleList,
  284. nIndex,
  285. 1,
  286. szBuffer,
  287. ARRAYSIZE(szBuffer));
  288. pModuleNew = (PMODULE)HeapAlloc(GetProcessHeap(),
  289. HEAP_ZERO_MEMORY,
  290. sizeof(MODULE));
  291. if (!pModuleNew) {
  292. DPF("[BuildModuleListForShim] Couldn't allocate memory for node");
  293. return;
  294. }
  295. nLen = _tcslen(szBuffer) + 1;
  296. pModuleNew->pszName = (TCHAR*)HeapAlloc(GetProcessHeap(),
  297. HEAP_ZERO_MEMORY,
  298. nLen * sizeof(TCHAR));
  299. if (!pModuleNew->pszName) {
  300. DPF("[BuildModuleListForShim] Couldn't allocate memory to store module info");
  301. HeapFree(GetProcessHeap(), 0, pModuleNew);
  302. return;
  303. }
  304. StringCchCopy(pModuleNew->pszName, nLen, szBuffer);
  305. pModuleNew->fInclude = (BOOL)lvi.lParam;
  306. pModuleNew->pNext = pFix->pModule;
  307. pFix->pModule = pModuleNew;
  308. }
  309. }
  310. }
  311. int
  312. CountShims(
  313. BOOL fCountSelected
  314. )
  315. /*++
  316. CountShims
  317. Description: Counts the number of selected shims in the list and
  318. updates the text on the dialog.
  319. --*/
  320. {
  321. int cShims = 0, nTotalShims, nShims = 0;
  322. BOOL fReturn;
  323. TCHAR szShims[MAX_PATH];
  324. TCHAR szTemp[MAX_PATH];
  325. HRESULT hr;
  326. cShims = ListView_GetItemCount(g_hwndShimList);
  327. if (fCountSelected) {
  328. for (nTotalShims = 0; nTotalShims < cShims; nTotalShims++) {
  329. fReturn = ListView_GetCheckState(g_hwndShimList, nTotalShims);
  330. if (fReturn) {
  331. nShims++;
  332. }
  333. }
  334. }
  335. LoadString(g_hInstance, IDS_SEL_CAPTION, szTemp, ARRAYSIZE(szTemp));
  336. hr = StringCchPrintf(szShims,
  337. ARRAYSIZE(szShims),
  338. szTemp,
  339. nShims,
  340. cShims);
  341. if (FAILED(hr)) {
  342. DPF("[CountShims] 0x%08X Buffer too small", HRESULT_CODE(hr));
  343. return 0;
  344. }
  345. SetDlgItemText(g_hFixesDlg, IDC_SELECTED_SHIMS, szShims);
  346. return cShims;
  347. }
  348. void
  349. DisplayAttrContextMenu(
  350. POINT* pt
  351. )
  352. /*++
  353. DisplayAttrContextMenu
  354. Description: Displays a popup menu for the attributes tree.
  355. --*/
  356. {
  357. HMENU hPopupMenu, hTrackPopup;
  358. //
  359. // Load the popup menu and display it.
  360. //
  361. hPopupMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_ATTR_POPUP));
  362. if (hPopupMenu == NULL) {
  363. return;
  364. }
  365. hTrackPopup = GetSubMenu(hPopupMenu, 0);
  366. TrackPopupMenu(hTrackPopup,
  367. TPM_LEFTBUTTON | TPM_NOANIMATION | TPM_LEFTALIGN,
  368. pt->x, pt->y, 0, g_hDlg, NULL);
  369. DestroyMenu(hPopupMenu);
  370. }
  371. void
  372. InsertListViewColumn(
  373. HWND hWndListView,
  374. LPTSTR lpColumnName,
  375. BOOL fCenter,
  376. int nColumnID,
  377. int nSize
  378. )
  379. /*++
  380. InsertListViewColumn
  381. Description: Wrapper for ListView_InsertColumn.
  382. --*/
  383. {
  384. LV_COLUMN lvColumn;
  385. if (fCenter) {
  386. lvColumn.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
  387. } else {
  388. lvColumn.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  389. }
  390. //
  391. // Fill in the structure and add the column.
  392. //
  393. lvColumn.fmt = LVCFMT_CENTER;
  394. lvColumn.cx = nSize;
  395. lvColumn.iSubItem = 0;
  396. lvColumn.pszText = lpColumnName;
  397. ListView_InsertColumn(hWndListView, nColumnID, &lvColumn);
  398. }
  399. void
  400. EnableTabBackground(
  401. HWND hDlg
  402. )
  403. {
  404. PFNEnableThemeDialogTexture pFnEnableThemeDialogTexture;
  405. HMODULE hUxTheme;
  406. hUxTheme = (HMODULE)LoadLibrary(_T("uxtheme.dll"));
  407. if (hUxTheme) {
  408. pFnEnableThemeDialogTexture = (PFNEnableThemeDialogTexture)
  409. GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
  410. if (pFnEnableThemeDialogTexture) {
  411. pFnEnableThemeDialogTexture(hDlg, ETDT_USETABTEXTURE);
  412. }
  413. FreeLibrary(hUxTheme);
  414. }
  415. }
  416. void
  417. HandleLayersDialogInit(
  418. HWND hDlg
  419. )
  420. {
  421. HWND hParent;
  422. DLGHDR* pHdr;
  423. g_hLayersDlg = hDlg;
  424. hParent = GetParent(hDlg);
  425. pHdr = (DLGHDR*)GetWindowLongPtr(hParent, DWLP_USER);
  426. //
  427. // Position the dialog within the tab.
  428. //
  429. SetWindowPos(hDlg, HWND_TOP,
  430. pHdr->rcDisplay.left,
  431. pHdr->rcDisplay.top,
  432. pHdr->rcDisplay.right - pHdr->rcDisplay.left,
  433. pHdr->rcDisplay.bottom - pHdr->rcDisplay.top,
  434. 0);
  435. g_hwndListLayers = GetDlgItem(hDlg, IDC_LAYERS);
  436. EnableTabBackground(hDlg);
  437. }
  438. BOOL
  439. HandleFixesDialogInit(
  440. HWND hDlg
  441. )
  442. {
  443. HWND hParent;
  444. DLGHDR* pHdr;
  445. int nCount = 0;
  446. TCHAR szColumn[MAX_PATH];
  447. g_hFixesDlg = hDlg;
  448. hParent = GetParent(hDlg);
  449. pHdr = (DLGHDR*)GetWindowLongPtr(hParent, DWLP_USER);
  450. //
  451. // Position the dialog within the tab.
  452. //
  453. SetWindowPos(hDlg, HWND_TOP,
  454. pHdr->rcDisplay.left, pHdr->rcDisplay.top,
  455. pHdr->rcDisplay.right - pHdr->rcDisplay.left,
  456. pHdr->rcDisplay.bottom - pHdr->rcDisplay.top,
  457. 0);
  458. g_hwndShimList = GetDlgItem(hDlg, IDC_SHIMS);
  459. //
  460. // Set up the shim list.
  461. //
  462. LoadString(g_hInstance, IDS_FIXNAME_COLUMN, szColumn, ARRAYSIZE(szColumn));
  463. InsertListViewColumn(g_hwndShimList, szColumn, FALSE, 0, 200);
  464. LoadString(g_hInstance, IDS_CMDLINE_COLUMN, szColumn, ARRAYSIZE(szColumn));
  465. InsertListViewColumn(g_hwndShimList, szColumn, TRUE, 1, 59);
  466. LoadString(g_hInstance, IDS_MODULE_COLUMN, szColumn, ARRAYSIZE(szColumn));
  467. InsertListViewColumn(g_hwndShimList, szColumn, TRUE, 2, 52);
  468. ListView_SetExtendedListViewStyle(g_hwndShimList,
  469. LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
  470. //
  471. // Query the database and show the available general purpose fixes.
  472. //
  473. ShowAvailableFixes(g_hwndShimList);
  474. nCount = CountShims(FALSE);
  475. if (!nCount) {
  476. return FALSE;
  477. }
  478. ListView_SetItemCount(g_hwndShimList, nCount);
  479. EnableTabBackground(hDlg);
  480. return TRUE;
  481. }
  482. DLGTEMPLATE*
  483. LockDlgRes(
  484. LPCTSTR lpResName
  485. )
  486. {
  487. HRSRC hrsrc = FindResource(NULL, lpResName, RT_DIALOG);
  488. if (NULL == hrsrc) {
  489. return NULL;
  490. }
  491. HGLOBAL hglb = LoadResource(g_hInstance, hrsrc);
  492. if (NULL == hglb) {
  493. return NULL;
  494. }
  495. return (DLGTEMPLATE*)LockResource(hglb);
  496. }
  497. void
  498. InitTabs(
  499. HWND hMainDlg,
  500. HWND hTab
  501. )
  502. {
  503. DLGHDR* pHdr;
  504. TCITEM tcitem;
  505. RECT rcTab;
  506. int nCount;
  507. TCHAR szTabText[MAX_PATH];
  508. TCHAR szError[MAX_PATH];
  509. pHdr = (DLGHDR*)HeapAlloc(GetProcessHeap(),
  510. HEAP_ZERO_MEMORY,
  511. sizeof(DLGHDR));
  512. if (NULL == pHdr) {
  513. LoadString(g_hInstance, IDS_TAB_SETUP_FAIL, szError, ARRAYSIZE(szError));
  514. MessageBox(hMainDlg, szError, g_szAppTitle, MB_ICONERROR);
  515. return;
  516. }
  517. //
  518. // Save away a pointer to the structure.
  519. //
  520. SetWindowLongPtr(hMainDlg, DWLP_USER, (LONG_PTR)pHdr);
  521. //
  522. // Save away the handle to the tab control.
  523. //
  524. pHdr->hTab = hTab;
  525. //
  526. // Add the tabs.
  527. //
  528. LoadString(g_hInstance, IDS_TAB_FIRST_TEXT, szTabText, ARRAYSIZE(szTabText));
  529. tcitem.mask = TCIF_TEXT | TCIF_PARAM;
  530. tcitem.pszText = szTabText;
  531. tcitem.lParam = 0;
  532. TabCtrl_InsertItem(pHdr->hTab, 0, &tcitem);
  533. LoadString(g_hInstance, IDS_TAB_SECOND_TEXT, szTabText, ARRAYSIZE(szTabText));
  534. tcitem.pszText = szTabText;
  535. tcitem.lParam = 1;
  536. TabCtrl_InsertItem(pHdr->hTab, 1, &tcitem);
  537. //
  538. // Lock the resources for two child dialog boxes.
  539. //
  540. pHdr->pRes[0] = LockDlgRes(MAKEINTRESOURCE(IDD_LAYERS_TAB));
  541. pHdr->pDlgProc[0] = LayersTabDlgProc;
  542. pHdr->pRes[1] = LockDlgRes(MAKEINTRESOURCE(IDD_FIXES_TAB));
  543. pHdr->pDlgProc[1] = FixesTabDlgProc;
  544. //
  545. // Determine the bounding rectangle for all child dialog boxes.
  546. //
  547. GetWindowRect(pHdr->hTab, &rcTab);
  548. TabCtrl_AdjustRect(pHdr->hTab, FALSE, &rcTab);
  549. InflateRect(&rcTab, 1, 1);
  550. rcTab.left -= 2;
  551. MapWindowPoints(NULL, hMainDlg, (LPPOINT)&rcTab, 2);
  552. pHdr->rcDisplay = rcTab;
  553. //
  554. // Create both dialog boxes.
  555. //
  556. for (nCount = 0; nCount < NUM_TABS; nCount++) {
  557. pHdr->hDisplay[nCount] = CreateDialogIndirect(g_hInstance,
  558. pHdr->pRes[nCount],
  559. hMainDlg,
  560. pHdr->pDlgProc[nCount]);
  561. }
  562. }
  563. TCHAR*
  564. GetRelativePath(
  565. TCHAR* pExeFile,
  566. TCHAR* pMatchFile
  567. )
  568. /*++
  569. GetRelativePath
  570. Description: Returns a relative path based on an EXE and a matching file.
  571. The caller must free the memory using HeapFree.
  572. --*/
  573. {
  574. int nLenExe = 0;
  575. int nLenMatch = 0;
  576. TCHAR* pExe = NULL;
  577. TCHAR* pMatch = NULL;
  578. TCHAR* pReturn = NULL;
  579. TCHAR result[MAX_PATH] = { _T('\0') };
  580. TCHAR* resultIdx = result;
  581. BOOL bCommonBegin = FALSE; // Indicates if the paths have a common beginning
  582. pExe = _tcschr(pExeFile, _T('\\'));
  583. pMatch = _tcschr(pMatchFile, _T('\\'));
  584. while (pExe && pMatch) {
  585. nLenExe = (int)(pExe - pExeFile);
  586. nLenMatch = (int)(pMatch - pMatchFile);
  587. if (nLenExe != nLenMatch) {
  588. break;
  589. }
  590. if (!(_tcsnicmp(pExeFile, pMatchFile, nLenExe) == 0)) {
  591. break;
  592. }
  593. bCommonBegin = TRUE;
  594. pExeFile = pExe + 1;
  595. pMatchFile = pMatch + 1;
  596. pExe = _tcschr(pExeFile, _T('\\'));
  597. pMatch = _tcschr(pMatchFile, _T('\\'));
  598. }
  599. //
  600. // Walk the path and put '..\' where necessary
  601. //
  602. if (bCommonBegin) {
  603. while (pExe) {
  604. StringCchCopy(resultIdx, ARRAYSIZE(result), _T("..\\"));
  605. resultIdx = resultIdx + 3;
  606. pExeFile = pExe + 1;
  607. pExe = _tcschr(pExeFile, _T('\\'));
  608. }
  609. StringCchCopy(resultIdx, ARRAYSIZE(result), pMatchFile);
  610. nLenExe = _tcslen(result) + 1;
  611. pReturn = (TCHAR*)HeapAlloc(GetProcessHeap(),
  612. HEAP_ZERO_MEMORY,
  613. nLenExe * sizeof(TCHAR));
  614. if (!pReturn) {
  615. return NULL;
  616. }
  617. StringCchCopy(pReturn, nLenExe, result);
  618. return pReturn;
  619. }
  620. return NULL;
  621. }
  622. void
  623. SaveEntryToFile(
  624. HWND hDlg,
  625. HWND hEdit,
  626. LPCTSTR lpFileName
  627. )
  628. /*++
  629. SaveEntryToFile
  630. Description: Writes the XML out to a file.
  631. --*/
  632. {
  633. int cchSize = 0;
  634. DWORD cbBytesWritten;
  635. HANDLE hFile = NULL;
  636. LPTSTR lpData = NULL;
  637. TCHAR szError[MAX_PATH];
  638. //
  639. // Determine how much space we need for the buffer, then allocate it.
  640. //
  641. cchSize = GetWindowTextLength(hEdit);
  642. if (cchSize) {
  643. //
  644. // Account for the additional byte & the NULL that we're storing
  645. // in the file.
  646. //
  647. cchSize += 2;
  648. lpData = (LPTSTR)HeapAlloc(GetProcessHeap(),
  649. HEAP_ZERO_MEMORY,
  650. cchSize * sizeof(TCHAR));
  651. if (!lpData) {
  652. LoadString(g_hInstance, IDS_BUFFER_ALLOC_FAIL, szError, ARRAYSIZE(szError));
  653. MessageBox(hDlg, szError, g_szAppTitle, MB_ICONERROR);
  654. return;
  655. }
  656. //
  657. // Ensure that the file is saved as Unicode.
  658. //
  659. lpData[0] = 0xFEFF;
  660. //
  661. // Get the text out of the text box and write it out to our file.
  662. //
  663. if (!GetWindowText(hEdit, lpData + 1, cchSize - 1)) {
  664. goto Cleanup;
  665. }
  666. hFile = CreateFile(lpFileName,
  667. GENERIC_WRITE,
  668. 0,
  669. NULL,
  670. CREATE_ALWAYS,
  671. FILE_ATTRIBUTE_NORMAL,
  672. NULL);
  673. if (hFile == INVALID_HANDLE_VALUE) {
  674. LoadString(g_hInstance, IDS_FILE_CREATE_FAIL, szError, ARRAYSIZE(szError));
  675. MessageBox(hDlg, szError, g_szAppTitle, MB_ICONERROR);
  676. goto Cleanup;
  677. }
  678. WriteFile(hFile, lpData, cchSize * sizeof(TCHAR), &cbBytesWritten, NULL);
  679. CloseHandle(hFile);
  680. }
  681. Cleanup:
  682. HeapFree(GetProcessHeap(), 0, lpData);
  683. }
  684. void
  685. DoFileSave(
  686. HWND hDlg
  687. )
  688. /*++
  689. DoFileSave
  690. Description: Displays the common dialog allowing for file save.
  691. --*/
  692. {
  693. TCHAR szFilter[MAX_PATH] = _T("");
  694. TCHAR szTemp[MAX_PATH] = _T("");
  695. OPENFILENAME ofn = {0};
  696. *szTemp = 0;
  697. LoadString(g_hInstance, IDS_SAVE_FILTER, szFilter, ARRAYSIZE(szFilter));
  698. ofn.lStructSize = sizeof(OPENFILENAME);
  699. ofn.hwndOwner = hDlg;
  700. ofn.hInstance = NULL;
  701. ofn.lpstrFilter = szFilter;
  702. ofn.lpstrCustomFilter = (LPTSTR)NULL;
  703. ofn.nMaxCustFilter = 0;
  704. ofn.nFilterIndex = 1;
  705. ofn.lpstrFile = szTemp;
  706. ofn.nMaxFile = sizeof(szTemp);
  707. ofn.lpstrTitle = NULL;
  708. ofn.lpstrFileTitle = NULL;
  709. ofn.nMaxFileTitle = 0;
  710. ofn.lpstrInitialDir = NULL;
  711. ofn.nFileOffset = 0;
  712. ofn.nFileExtension = 0;
  713. ofn.lpstrDefExt = _T("xml");
  714. ofn.lCustData = 0;
  715. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST |
  716. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
  717. if (GetSaveFileName(&ofn)) {
  718. SaveEntryToFile(hDlg, GetDlgItem(hDlg, IDC_XML), szTemp);
  719. }
  720. }
  721. void
  722. GetTopLevelWindowIntoView(
  723. HWND hwnd
  724. )
  725. {
  726. RECT rectWindow, rectScreen;
  727. int nCx, nCy, nCxScreen, nCyScreen;
  728. int dx = 0, dy = 0;
  729. HWND hwndDesktop;
  730. if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD) {
  731. return;
  732. }
  733. hwndDesktop = GetDesktopWindow();
  734. GetWindowRect(hwnd, &rectWindow);
  735. GetWindowRect(hwndDesktop, &rectScreen);
  736. nCx = rectWindow.right - rectWindow.left;
  737. nCy = rectWindow.bottom - rectWindow.top;
  738. nCxScreen = rectScreen.right - rectScreen.left;
  739. nCyScreen = rectScreen.bottom - rectScreen.top;
  740. //
  741. // Make it fix on the x coord.
  742. //
  743. if (rectWindow.left < rectScreen.left) {
  744. dx = rectScreen.left - rectWindow.left;
  745. rectWindow.left += dx;
  746. rectWindow.right += dx;
  747. }
  748. if (rectWindow.right > rectScreen.right) {
  749. if (nCx < nCxScreen) {
  750. dx = rectScreen.right - rectWindow.right;
  751. rectWindow.left += dx;
  752. rectWindow.right += dx;
  753. }
  754. }
  755. //
  756. // Make it fix on the y coord.
  757. //
  758. if (rectWindow.top < rectScreen.top) {
  759. dy = rectScreen.top - rectWindow.top;
  760. rectWindow.top += dy;
  761. rectWindow.bottom += dy;
  762. }
  763. if (rectWindow.bottom > rectScreen.bottom) {
  764. if (nCy < nCyScreen) {
  765. dy = rectScreen.bottom - rectWindow.bottom;
  766. rectWindow.top += dy;
  767. rectWindow.bottom += dy;
  768. }
  769. }
  770. if (dx != 0 || dy != 0) {
  771. MoveWindow(hwnd, rectWindow.left, rectWindow.top, nCx, nCy, TRUE);
  772. }
  773. }
  774. void
  775. ReplaceCmdLine(
  776. PFIX pFix,
  777. TCHAR* pszNewCmdLine
  778. )
  779. /*++
  780. ReplaceCmdLine
  781. Description: Replaces the command line for a shim DLL.
  782. --*/
  783. {
  784. TCHAR szError[MAX_PATH];
  785. int nLen;
  786. if (pFix->pszCmdLine != NULL) {
  787. HeapFree(GetProcessHeap(), 0, pFix->pszCmdLine);
  788. pFix->pszCmdLine = NULL;
  789. }
  790. if (pszNewCmdLine == NULL) {
  791. return;
  792. } else if ((*pszNewCmdLine == '"') && (_tcslen(pszNewCmdLine) == 1)) {
  793. LoadString(g_hInstance, IDS_INVALID_CMD_LINE, szError, ARRAYSIZE(szError));
  794. MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  795. return;
  796. }
  797. nLen = _tcslen(pszNewCmdLine) + 1;
  798. pFix->pszCmdLine = (TCHAR*)HeapAlloc(GetProcessHeap(),
  799. HEAP_ZERO_MEMORY,
  800. nLen * sizeof(TCHAR));
  801. if (pFix->pszCmdLine != NULL) {
  802. StringCchCopy(pFix->pszCmdLine, nLen, pszNewCmdLine);
  803. } else {
  804. DPF("[ReplaceCmdLine] Failed to replace the cmd line for '%S'",
  805. pFix->pszName);
  806. }
  807. }
  808. void
  809. DeselectAllShims(
  810. HWND hdlg
  811. )
  812. /*++
  813. DeselectAllShims
  814. Description: Removes selections for all shims listed.
  815. --*/
  816. {
  817. int cShims, nIndex;
  818. LVITEM lvi;
  819. //
  820. // Walk all the shims in the list view and deselect them.
  821. //
  822. ZeroMemory(&lvi, sizeof(lvi));
  823. cShims = ListView_GetItemCount(g_hwndShimList);
  824. for (nIndex = 0; nIndex < cShims; nIndex++) {
  825. PFIX pFix;
  826. lvi.iItem = nIndex;
  827. lvi.mask = LVIF_STATE | LVIF_PARAM;
  828. lvi.stateMask = LVIS_STATEIMAGEMASK;
  829. ListView_GetItem(g_hwndShimList, &lvi);
  830. pFix = (PFIX)lvi.lParam;
  831. //
  832. // Clear the check box, removes the 'X', clear the command line,
  833. // and clear the modules.
  834. //
  835. ListView_SetItemText(g_hwndShimList, nIndex, 1, _T(""));
  836. ListView_SetItemText(g_hwndShimList, nIndex, 2, _T(""));
  837. ListView_SetCheckState(g_hwndShimList, nIndex, FALSE);
  838. ReplaceCmdLine(pFix, NULL);
  839. BuildModuleListForShim(pFix, BML_DELFRLISTVIEW);
  840. }
  841. //
  842. // Update the count of selected shims.
  843. //
  844. SetTimer(hdlg, ID_COUNT_SHIMS, 100, NULL);
  845. }
  846. void
  847. AddMatchingFile(
  848. HWND hdlg,
  849. LPCTSTR pszFullPath,
  850. LPCTSTR pszRelativePath,
  851. BOOL bMainEXE
  852. )
  853. /*++
  854. AddMatchingFile
  855. Description: Adds a matching file and it's attributes to the tree.
  856. --*/
  857. {
  858. TVINSERTSTRUCT is;
  859. HTREEITEM hParent;
  860. DWORD dwCount;
  861. DWORD dwAttrCount;
  862. TCHAR szItem[MAX_PATH];
  863. PATTRINFO pAttrInfo = NULL;
  864. //
  865. // Call the attribute manager to get all the attributes for this file.
  866. //
  867. if (!SdbGetFileAttributes(pszFullPath, &pAttrInfo, &dwAttrCount)) {
  868. DPF("[AddMatchingFile] Failed to get attributes for %S",
  869. pszFullPath);
  870. return;
  871. }
  872. is.hParent = TVI_ROOT;
  873. is.hInsertAfter = TVI_LAST;
  874. is.item.lParam = (LPARAM)pAttrInfo;
  875. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  876. is.item.pszText = (LPTSTR)pszRelativePath;
  877. hParent = TreeView_InsertItem(g_hwndFilesTree, &is);
  878. is.hParent = hParent;
  879. is.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  880. is.item.pszText = szItem;
  881. is.item.iImage = 0;
  882. is.item.iSelectedImage = 1;
  883. //
  884. // By default the attributes are not selected. To have them selected
  885. // by default you need to replace the following 1 with 2.
  886. //
  887. is.item.state = INDEXTOSTATEIMAGEMASK(1);
  888. is.item.stateMask = TVIS_STATEIMAGEMASK;
  889. //
  890. // Loop through all the attributes and show the ones that are available.
  891. //
  892. for (dwCount = 0; dwCount < dwAttrCount; dwCount++) {
  893. if (!SdbFormatAttribute(&pAttrInfo[dwCount], szItem, ARRAYSIZE(szItem))) {
  894. continue;
  895. }
  896. //
  897. // EXETYPE is a bogus attribute. Don't show it!
  898. //
  899. is.item.lParam = dwCount;
  900. TreeView_InsertItem(g_hwndFilesTree, &is);
  901. }
  902. TreeView_Expand(g_hwndFilesTree, hParent, TVE_EXPAND);
  903. }
  904. void
  905. BrowseForApp(
  906. HWND hdlg
  907. )
  908. /*++
  909. BrowseForApp
  910. Description: Browse for the main executable for which a shim
  911. will be applied.
  912. --*/
  913. {
  914. TCHAR szFilter[MAX_PATH] = _T("");
  915. TCHAR szTitle[MAX_PATH] = _T("");
  916. TCHAR szExe[MAX_PATH] = _T("");
  917. TCHAR szShortName[MAX_PATH] = _T("");
  918. OPENFILENAME ofn = {0};
  919. HRESULT hr;
  920. LoadString(g_hInstance, IDS_BROWSE_FILTER, szFilter, ARRAYSIZE(szFilter));
  921. LoadString(g_hInstance, IDS_BROWSE_TITLE, szTitle, ARRAYSIZE(szTitle));
  922. //
  923. // Use locals instead of globals because if the user cancels
  924. // the dialog without selecting, we'll ruin whatever app is
  925. // already selected.
  926. // rparsons - 14 Jan 02
  927. //
  928. ofn.lStructSize = sizeof(OPENFILENAME);
  929. ofn.hwndOwner = hdlg;
  930. ofn.hInstance = NULL;
  931. ofn.lpstrFilter = szFilter;
  932. ofn.lpstrCustomFilter = NULL;
  933. ofn.nMaxCustFilter = 0;
  934. ofn.nFilterIndex = 0;
  935. ofn.lpstrFile = szExe;
  936. ofn.nMaxFile = ARRAYSIZE(szExe);
  937. ofn.lpstrFileTitle = szShortName;
  938. ofn.nMaxFileTitle = ARRAYSIZE(szShortName);
  939. ofn.lpstrInitialDir = NULL;
  940. ofn.lpstrTitle = szTitle;
  941. ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  942. ofn.lpstrDefExt = _T("exe");
  943. if (GetOpenFileName(&ofn)) {
  944. TCHAR szMainEXE[128];
  945. g_bSDBInstalled = FALSE;
  946. StringCchCopy(g_szBinary, ARRAYSIZE(g_szBinary), szExe);
  947. StringCchCopy(g_szShortName, ARRAYSIZE(g_szShortName), szShortName);
  948. //
  949. // The parent exe defaults to the same as the EXE.
  950. //
  951. StringCchCopy(g_szParentExeName,
  952. ARRAYSIZE(g_szParentExeName),
  953. g_szShortName);
  954. StringCchCopy(g_szParentExeFullPath,
  955. ARRAYSIZE(g_szParentExeFullPath),
  956. g_szBinary);
  957. g_bSelectedParentExe = FALSE;
  958. SetDlgItemText(hdlg, IDC_BINARY, g_szBinary);
  959. EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), TRUE);
  960. EnableWindow(GetDlgItem(hdlg, IDC_RUN), TRUE);
  961. EnableWindow(GetDlgItem(hdlg, IDC_CREATEFILE), TRUE);
  962. EnableWindow(GetDlgItem(hdlg, IDC_SHOWXML), TRUE);
  963. TreeView_DeleteAllItems(g_hwndFilesTree);
  964. hr = StringCchPrintf(szMainEXE,
  965. ARRAYSIZE(szMainEXE),
  966. _T("Main executable (%s)"),
  967. g_szShortName);
  968. if (FAILED(hr)) {
  969. DPF("[BrowseForApp] 0x%08X Buffer too small", HRESULT_CODE(hr));
  970. return;
  971. }
  972. AddMatchingFile(hdlg, g_szBinary, szMainEXE, TRUE);
  973. }
  974. }
  975. void
  976. PromptAddMatchingFile(
  977. HWND hdlg
  978. )
  979. /*++
  980. PromptAddMatchingFile
  981. Description: Show the open file dialog to allow the user
  982. to add a matching file.
  983. --*/
  984. {
  985. TCHAR szFullPath[MAX_PATH] = _T("");
  986. TCHAR szShortName[MAX_PATH] = _T("");
  987. TCHAR szFilter[MAX_PATH] = _T("");
  988. TCHAR szTitle[MAX_PATH] = _T("");
  989. TCHAR szParentTitle[MAX_PATH] = _T("");
  990. TCHAR szInitialPath[MAX_PATH] = _T("");
  991. TCHAR szDrive[_MAX_DRIVE] = _T("");
  992. TCHAR szDir[_MAX_DIR] = _T("");
  993. TCHAR* pMatch = NULL;
  994. TCHAR szError[MAX_PATH];
  995. OPENFILENAME ofn = {0};
  996. *szInitialPath = 0;
  997. LoadString(g_hInstance, IDS_MATCH_FILTER, szFilter, ARRAYSIZE(szFilter));
  998. LoadString(g_hInstance, IDS_MATCH_TITLE, szTitle, ARRAYSIZE(szTitle));
  999. if (*g_szParentExeFullPath) {
  1000. _tsplitpath(g_szParentExeFullPath, szDrive, szDir, NULL, NULL);
  1001. StringCchCopy(szInitialPath, ARRAYSIZE(szInitialPath), szDrive);
  1002. StringCchCat(szInitialPath, ARRAYSIZE(szInitialPath), szDir);
  1003. }
  1004. ofn.lStructSize = sizeof(OPENFILENAME);
  1005. ofn.hwndOwner = hdlg;
  1006. ofn.hInstance = NULL;
  1007. ofn.lpstrFilter = szFilter;
  1008. ofn.lpstrCustomFilter = NULL;
  1009. ofn.nMaxCustFilter = 0;
  1010. ofn.nFilterIndex = 0;
  1011. ofn.lpstrFile = szFullPath;
  1012. ofn.nMaxFile = ARRAYSIZE(szFullPath);
  1013. ofn.lpstrFileTitle = szShortName;
  1014. ofn.nMaxFileTitle = ARRAYSIZE(szShortName);
  1015. ofn.lpstrInitialDir = NULL;
  1016. ofn.lpstrTitle = szTitle;
  1017. ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  1018. ofn.lpstrDefExt = _T("exe");
  1019. if (GetOpenFileName(&ofn)) {
  1020. //
  1021. // Determine if the matching file is on the same drive
  1022. // as the EXE that was selected.
  1023. //
  1024. if (!PathIsSameRoot(szFullPath,
  1025. g_szParentExeFullPath) && !g_bSelectedParentExe) {
  1026. TCHAR szParentFile[MAX_PATH];
  1027. //
  1028. // Prompt the user for the parent EXE.
  1029. //
  1030. *szParentFile = 0;
  1031. *szInitialPath = 0;
  1032. if (*szFullPath) {
  1033. _tsplitpath(szFullPath, szDrive, szDir, NULL, NULL);
  1034. StringCchCopy(szInitialPath, ARRAYSIZE(szInitialPath), szDrive);
  1035. StringCchCat(szInitialPath, ARRAYSIZE(szInitialPath), szDir);
  1036. }
  1037. LoadString(g_hInstance,
  1038. IDS_PARENT_TITLE,
  1039. szParentTitle,
  1040. ARRAYSIZE(szParentTitle));
  1041. ofn.lpstrTitle = szParentTitle;
  1042. ofn.lpstrFile = szParentFile;
  1043. ofn.nMaxFile = sizeof(szParentFile);
  1044. if (GetOpenFileName(&ofn) == TRUE) {
  1045. StringCchCopy(g_szParentExeName,
  1046. ARRAYSIZE(g_szParentExeName),
  1047. szShortName);
  1048. StringCchCopy(g_szParentExeFullPath,
  1049. ARRAYSIZE(g_szParentExeFullPath),
  1050. szParentFile);
  1051. g_bSelectedParentExe = TRUE;
  1052. }
  1053. }
  1054. //
  1055. // Check the drive letters to see which drive the match file is on
  1056. // then calculate a relative path to the matching file.
  1057. //
  1058. if (PathIsSameRoot(szFullPath, g_szParentExeFullPath)) {
  1059. pMatch = GetRelativePath(g_szParentExeFullPath, szFullPath);
  1060. } else if (PathIsSameRoot(szFullPath, g_szBinary)) {
  1061. pMatch = GetRelativePath(g_szBinary, szFullPath);
  1062. } else {
  1063. LoadString(g_hInstance, IDS_MATCH_PATH_NOT_RELATIVE, szError, ARRAYSIZE(szError));
  1064. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  1065. return;
  1066. }
  1067. if (pMatch) {
  1068. //
  1069. // Finally add the maching file and free the memory
  1070. //
  1071. AddMatchingFile(hdlg, szFullPath, pMatch, FALSE);
  1072. HeapFree(GetProcessHeap(), 0, pMatch);
  1073. }
  1074. }
  1075. }
  1076. void
  1077. ShowAvailableFixes(
  1078. HWND hList
  1079. )
  1080. /*++
  1081. ShowAvailableFixes
  1082. Description: Query the shim database and populate the
  1083. shim list with all the available shims.
  1084. --*/
  1085. {
  1086. LVITEM lvitem;
  1087. PFIX pFix;
  1088. TCHAR szError[MAX_PATH];
  1089. UINT uCount = 0;
  1090. g_pFixHead = ReadFixesFromSdb(_T("sysmain.sdb"), g_bAllShims);
  1091. if (g_pFixHead == NULL) {
  1092. LoadString(g_hInstance, IDS_SDB_READ_FAIL, szError, ARRAYSIZE(szError));
  1093. MessageBox(NULL, szError, g_szAppTitle, MB_ICONERROR);
  1094. return;
  1095. }
  1096. //
  1097. // Walk the list and add all the fixes to the list view.
  1098. //
  1099. pFix = g_pFixHead;
  1100. while (pFix != NULL) {
  1101. if (pFix->dwFlags & FIX_TYPE_LAYER) {
  1102. LPARAM lInd;
  1103. lInd = SendMessage(g_hwndListLayers, LB_ADDSTRING, 0, (LPARAM)pFix->pszName);
  1104. SendMessage(g_hwndListLayers, LB_SETITEMDATA, lInd, (LPARAM)pFix);
  1105. } else {
  1106. lvitem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  1107. lvitem.lParam = (LPARAM)pFix;
  1108. lvitem.pszText = pFix->pszName;
  1109. lvitem.iItem = ListView_GetItemCount(g_hwndShimList);
  1110. lvitem.iSubItem = 0;
  1111. lvitem.state = INDEXTOSTATEIMAGEMASK(1);
  1112. lvitem.stateMask = LVIS_STATEIMAGEMASK;
  1113. ListView_InsertItem(hList, &lvitem);
  1114. }
  1115. pFix = pFix->pNext;
  1116. }
  1117. }
  1118. BOOL
  1119. InstallSDB(
  1120. TCHAR* pszFileName,
  1121. BOOL fInstall
  1122. )
  1123. /*++
  1124. InstallSDB
  1125. Description: Launch sdbinst.exe to install or uninstall the specified SDB.
  1126. --*/
  1127. {
  1128. HRESULT hr;
  1129. TCHAR szAppName[MAX_PATH];
  1130. TCHAR szCmdLine[MAX_PATH];
  1131. STARTUPINFO si;
  1132. PROCESS_INFORMATION pi;
  1133. //
  1134. // Build a path to our application name and command-line.
  1135. //
  1136. hr = StringCchPrintf(szAppName,
  1137. ARRAYSIZE(szAppName),
  1138. _T("%s\\sdbinst.exe"),
  1139. g_szSysDir);
  1140. if (FAILED(hr)) {
  1141. DPF("[InstallSDB] 0x%08X Buffer too small (1)", HRESULT_CODE(hr));
  1142. return FALSE;
  1143. }
  1144. hr = StringCchPrintf(szCmdLine,
  1145. ARRAYSIZE(szCmdLine),
  1146. fInstall ?
  1147. _T("\"%s\" -q \"%s\"") :
  1148. _T("\"%s\" -q -u \"%s\""),
  1149. szAppName,
  1150. pszFileName);
  1151. if (FAILED(hr)) {
  1152. DPF("[InstallSDB] 0x%08X Buffer too small (2)", HRESULT_CODE(hr));
  1153. return FALSE;
  1154. }
  1155. ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
  1156. ZeroMemory(&si, sizeof(STARTUPINFO));
  1157. si.cb = sizeof(si);
  1158. DPF("[InstallSDB] AppName: %S CmdLine: %S\n", szAppName, szCmdLine);
  1159. if (!CreateProcess(szAppName,
  1160. szCmdLine,
  1161. NULL,
  1162. NULL,
  1163. FALSE,
  1164. NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
  1165. NULL,
  1166. NULL,
  1167. &si,
  1168. &pi)) {
  1169. DPF("[InstallSDB] 0x%08X CreateProcess '%S %S' failed",
  1170. szAppName,
  1171. szCmdLine,
  1172. GetLastError());
  1173. return FALSE;
  1174. }
  1175. //
  1176. // Wait for SDBInst to complete it's work.
  1177. //
  1178. WaitForSingleObject(pi.hProcess, INFINITE);
  1179. CloseHandle(pi.hThread);
  1180. CloseHandle(pi.hProcess);
  1181. return TRUE;
  1182. }
  1183. void
  1184. CreateSupportForApp(
  1185. HWND hdlg
  1186. )
  1187. /*++
  1188. CreateSupportForApp
  1189. Description: Build an SDB for the application and offer the user
  1190. the chance to install it.
  1191. --*/
  1192. {
  1193. BOOL bok;
  1194. TCHAR szFileCreated[MAX_PATH];
  1195. TCHAR szError[MAX_PATH];
  1196. TCHAR szTemp[MAX_PATH];
  1197. HRESULT hr;
  1198. int nAnswer;
  1199. CleanupSupportForApp(g_szShortName);
  1200. bok = CollectFix(g_hwndListLayers,
  1201. g_hwndShimList,
  1202. g_hwndFilesTree,
  1203. g_szShortName,
  1204. g_szBinary,
  1205. (g_nCrtTab == 0 ? CFF_USELAYERTAB : 0) |
  1206. (g_fW2K ? CFF_ADDW2KSUPPORT : 0),
  1207. szFileCreated);
  1208. if (!bok) {
  1209. LoadString(g_hInstance, IDS_FIX_CREATE_FAIL, szError, ARRAYSIZE(szError));
  1210. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONERROR);
  1211. } else {
  1212. LoadString(g_hInstance, IDS_CREATE_FIX, szTemp, ARRAYSIZE(szTemp));
  1213. hr = StringCchPrintf(szError,
  1214. ARRAYSIZE(szError),
  1215. szTemp,
  1216. szFileCreated);
  1217. if (FAILED(hr)) {
  1218. DPF("[CreateSupportForApp] 0x%08X Buffer too small", HRESULT_CODE(hr));
  1219. return;
  1220. }
  1221. nAnswer = MessageBox(hdlg, szError, g_szAppTitle, MB_YESNO | MB_ICONQUESTION);
  1222. if (IDYES == nAnswer) {
  1223. bok = InstallSDB(szFileCreated, TRUE);
  1224. if (!bok) {
  1225. LoadString(g_hInstance, IDS_INSTALL_FIX_FAIL, szError, ARRAYSIZE(szError));
  1226. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONERROR);
  1227. } else {
  1228. LoadString(g_hInstance, IDS_INSTALL_FIX_OK, szError, ARRAYSIZE(szError));
  1229. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONINFORMATION);
  1230. g_bSDBInstalled = TRUE;
  1231. }
  1232. } else {
  1233. //
  1234. // NTRAID#583475-rparsons The user decided not to install the database.
  1235. // Ensure that we do not remove the file that we created upon exit.
  1236. //
  1237. *g_szSDBToDelete = 0;
  1238. }
  1239. }
  1240. }
  1241. BOOL
  1242. ShowXML(
  1243. HWND hdlg
  1244. )
  1245. /*++
  1246. ShowXML
  1247. Description: Show the XML for the current selections.
  1248. --*/
  1249. {
  1250. BOOL bok;
  1251. TCHAR szError[MAX_PATH];
  1252. bok = CollectFix(g_hwndListLayers,
  1253. g_hwndShimList,
  1254. g_hwndFilesTree,
  1255. g_szShortName,
  1256. g_szBinary,
  1257. CFF_SHOWXML |
  1258. (g_nCrtTab == 0 ? CFF_USELAYERTAB : 0) |
  1259. (g_fW2K ? CFF_ADDW2KSUPPORT : 0),
  1260. NULL);
  1261. if (!bok) {
  1262. LoadString(g_hInstance, IDS_TOO_MANY_FILES, szError, ARRAYSIZE(szError));
  1263. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  1264. }
  1265. return bok;
  1266. }
  1267. void
  1268. RunTheApp(
  1269. HWND hdlg
  1270. )
  1271. /*++
  1272. RunTheApp
  1273. Description: Run the selected app.
  1274. --*/
  1275. {
  1276. STARTUPINFO si;
  1277. PROCESS_INFORMATION pi;
  1278. TCHAR szFileCreated[MAX_PATH];
  1279. TCHAR szCmdLine[MAX_PATH];
  1280. TCHAR szFullCmdLine[MAX_PATH];
  1281. TCHAR szError[MAX_PATH];
  1282. TCHAR szRun[MAX_PATH];
  1283. TCHAR* pszCmd;
  1284. TCHAR* pszDir;
  1285. TCHAR* psz;
  1286. BOOL bok;
  1287. HRESULT hr;
  1288. //
  1289. // Cleanup for the previous app.
  1290. //
  1291. CleanupSupportForApp(g_szShortName);
  1292. bok = CollectFix(g_hwndListLayers,
  1293. g_hwndShimList,
  1294. g_hwndFilesTree,
  1295. g_szShortName,
  1296. g_szBinary,
  1297. CFF_SHIMLOG |
  1298. CFF_APPENDLAYER |
  1299. (g_nCrtTab == 0 ? CFF_USELAYERTAB : 0) |
  1300. (g_fW2K ? CFF_ADDW2KSUPPORT : 0),
  1301. szFileCreated);
  1302. if (!bok) {
  1303. LoadString(g_hInstance, IDS_ADD_SUPPORT_FAIL, szError, ARRAYSIZE(szError));
  1304. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONERROR);
  1305. return;
  1306. }
  1307. //
  1308. // We need to install the fix for them.
  1309. //
  1310. if (!(InstallSDB(szFileCreated, TRUE))) {
  1311. LoadString(g_hInstance, IDS_INSTALL_FIX_FAIL, szError, ARRAYSIZE(szError));
  1312. MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONERROR);
  1313. return;
  1314. }
  1315. ZeroMemory(&si, sizeof(si));
  1316. si.cb = sizeof(si);
  1317. //
  1318. // Get the command line, if there is one.
  1319. //
  1320. *szCmdLine = 0;
  1321. *szFullCmdLine = 0;
  1322. GetDlgItemText(hdlg, IDC_CMD_LINE, szCmdLine, ARRAYSIZE(szCmdLine));
  1323. //
  1324. // To have a proper command-line, we need to the module name.
  1325. //
  1326. if (*szCmdLine) {
  1327. hr = StringCchPrintf(szFullCmdLine,
  1328. ARRAYSIZE(szFullCmdLine),
  1329. _T("%s %s"),
  1330. g_szBinary,
  1331. szCmdLine);
  1332. if (FAILED(hr)) {
  1333. DPF("[RunTheApp] 0x%08X Buffer too small", HRESULT_CODE(hr));
  1334. LoadString(g_hInstance, IDS_RUNAPP_FAILED, szError, ARRAYSIZE(szError));
  1335. MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONERROR);
  1336. return;
  1337. }
  1338. }
  1339. StringCchCopy(szRun, ARRAYSIZE(szRun), g_szBinary);
  1340. pszCmd = szRun;
  1341. pszDir = g_szBinary;
  1342. //
  1343. // We need to change the current directory or some apps won't run.
  1344. //
  1345. psz = pszDir + _tcslen(pszDir) - 1;
  1346. while (psz > pszDir && *psz != _T('\\')) {
  1347. psz--;
  1348. }
  1349. if (psz > pszDir) {
  1350. *psz = 0;
  1351. SetCurrentDirectory(pszDir);
  1352. *psz = _T('\\');
  1353. }
  1354. DPF("[RunTheApp] AppName: %S CmdLine: %S", szRun, szCmdLine);
  1355. if (!CreateProcess(szRun,
  1356. *szFullCmdLine ? szFullCmdLine : NULL,
  1357. NULL,
  1358. NULL,
  1359. FALSE,
  1360. NORMAL_PRIORITY_CLASS | CREATE_SEPARATE_WOW_VDM,
  1361. NULL,
  1362. NULL,
  1363. &si,
  1364. &pi)) {
  1365. LoadString(g_hInstance, IDS_RUNAPP_FAILED, szError, ARRAYSIZE(szError));
  1366. MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONERROR);
  1367. DPF("[RunTheApp] CreateProcess failed 0x%08X", GetLastError());
  1368. } else {
  1369. CloseHandle(pi.hThread);
  1370. CloseHandle(pi.hProcess);
  1371. }
  1372. //
  1373. // Save this SDB for later so we can remove it.
  1374. //
  1375. StringCchCopy(g_szSDBToDelete, ARRAYSIZE(g_szSDBToDelete), szFileCreated);
  1376. }
  1377. void
  1378. ExpandCollapseDialog(
  1379. HWND hdlg,
  1380. BOOL bHide
  1381. )
  1382. /*++
  1383. ExpandCollapseDialog
  1384. Description: Change the current view of the dialog.
  1385. --*/
  1386. {
  1387. TCHAR szSimple[64];
  1388. TCHAR szAdvanced[64];
  1389. int i, nShow;
  1390. DWORD arrId[] = {IDC_ADD_MATCHING,
  1391. IDC_FILE_ATTRIBUTES_STATIC,
  1392. IDC_ATTRIBUTES,
  1393. IDC_CREATEFILE,
  1394. 0};
  1395. if (!bHide) {
  1396. SetWindowPos(hdlg, NULL, 0, 0,
  1397. g_rcDlgBig.right - g_rcDlgBig.left,
  1398. g_rcDlgBig.bottom - g_rcDlgBig.top,
  1399. SWP_NOMOVE | SWP_NOZORDER);
  1400. nShow = SW_SHOW;
  1401. g_bSimpleEdition = FALSE;
  1402. LoadString(g_hInstance, IDS_SIMPLE_TEXT, szSimple, ARRAYSIZE(szSimple));
  1403. SetDlgItemText(hdlg, IDC_DETAILS, szSimple);
  1404. SendDlgItemMessage(hdlg, IDC_CREATEFILE, BM_SETCHECK, BST_CHECKED, 0);
  1405. //
  1406. // Make sure the dialog is in view.
  1407. //
  1408. GetTopLevelWindowIntoView(hdlg);
  1409. } else {
  1410. nShow = SW_HIDE;
  1411. g_bSimpleEdition = TRUE;
  1412. LoadString(g_hInstance, IDS_ADVANCED_TEXT, szAdvanced, ARRAYSIZE(szAdvanced));
  1413. SetDlgItemText(hdlg, IDC_DETAILS, szAdvanced);
  1414. SendDlgItemMessage(hdlg, IDC_CREATEFILE, BM_SETCHECK, BST_UNCHECKED, 0);
  1415. }
  1416. for (i = 0; arrId[i] != 0; i++) {
  1417. ShowWindow(GetDlgItem(hdlg, arrId[i]), nShow);
  1418. }
  1419. if (bHide) {
  1420. SetWindowPos(hdlg, NULL, 0, 0,
  1421. g_rcDlgSmall.right - g_rcDlgSmall.left,
  1422. g_rcDlgSmall.bottom - g_rcDlgSmall.top,
  1423. SWP_NOMOVE | SWP_NOZORDER);
  1424. }
  1425. }
  1426. void
  1427. LayerChanged(
  1428. HWND hdlg
  1429. )
  1430. /*++
  1431. LayerChanged
  1432. Description: Changing the layer has the effect of selecting the
  1433. shims that the layer consists of.
  1434. --*/
  1435. {
  1436. LRESULT lSel;
  1437. PFIX pFix;
  1438. LVITEM lvi;
  1439. int nIndex, cShims = 0;
  1440. lSel = SendMessage(g_hwndListLayers, LB_GETCURSEL, 0, 0);
  1441. if (lSel == LB_ERR) {
  1442. DPF("[LayerChanged] No layer selected");
  1443. return;
  1444. }
  1445. pFix = (PFIX)SendMessage(g_hwndListLayers, LB_GETITEMDATA, lSel, 0);
  1446. if (pFix->parrShim == NULL) {
  1447. DPF("[LayerChanged] No array of DLLs");
  1448. return;
  1449. }
  1450. // Remove any prior selections.
  1451. DeselectAllShims(g_hFixesDlg);
  1452. //
  1453. // Loop through all the items in the shim list and make the
  1454. // appropriate selections.
  1455. //
  1456. cShims = ListView_GetItemCount(g_hwndShimList);
  1457. for (nIndex = 0; nIndex < cShims; nIndex++) {
  1458. PFIX pFixItem;
  1459. int nInd = 0;
  1460. lvi.mask = LVIF_PARAM;
  1461. lvi.iItem = nIndex;
  1462. lvi.iSubItem = 0;
  1463. ListView_GetItem(g_hwndShimList, &lvi);
  1464. pFixItem = (PFIX)lvi.lParam;
  1465. //
  1466. // See if this shim DLL is in the array for the selected layer.
  1467. //
  1468. while (pFix->parrShim[nInd] != NULL) {
  1469. if (pFix->parrShim[nInd] == pFixItem) {
  1470. break;
  1471. }
  1472. nInd++;
  1473. }
  1474. //
  1475. // Put a check next to this shim DLL. If he has a command line,
  1476. // put an 'X' in the CmdLine subitem.
  1477. //
  1478. if (pFix->parrShim[nInd] != NULL) {
  1479. ListView_SetCheckState(g_hwndShimList, nIndex, TRUE);
  1480. } else {
  1481. ListView_SetCheckState(g_hwndShimList, nIndex, FALSE);
  1482. }
  1483. if (pFix->parrCmdLine[nInd] != NULL) {
  1484. ReplaceCmdLine(pFixItem, pFix->parrCmdLine[nInd]);
  1485. ListView_SetItemText(g_hwndShimList, nIndex, 1, _T("X"));
  1486. }
  1487. ListView_SetItem(g_hwndShimList, &lvi);
  1488. }
  1489. //
  1490. // Update the count of selected shims.
  1491. //
  1492. SetTimer(g_hFixesDlg, ID_COUNT_SHIMS, 100, NULL);
  1493. }
  1494. BOOL
  1495. InitMainDialog(
  1496. HWND hdlg
  1497. )
  1498. /*++
  1499. InitMainDialog
  1500. Description: Init routine called during WM_INITDIALOG for
  1501. the main dialog of QFixApp.
  1502. --*/
  1503. {
  1504. HICON hIcon;
  1505. RECT rcList, rcTree;
  1506. HIMAGELIST hImage;
  1507. TCHAR szText[MAX_PATH];
  1508. //
  1509. // Initialize globals.
  1510. //
  1511. g_bSDBInstalled = FALSE;
  1512. g_szParentExeFullPath[0] = 0;
  1513. g_szBinary[0] = 0;
  1514. g_hDlg = hdlg;
  1515. //
  1516. // If we didn't get the proper command-line, disable the 'Show XML'
  1517. // button.
  1518. //
  1519. if (!g_bShowXML) {
  1520. ShowWindow(GetDlgItem(hdlg, IDC_SHOWXML), SW_HIDE);
  1521. }
  1522. //
  1523. // The dialog has two views. Calculate the size of the smaller
  1524. // view and show the simpler view by default.
  1525. //
  1526. GetWindowRect(hdlg, &g_rcDlgBig);
  1527. GetWindowRect(GetDlgItem(hdlg, IDC_ATTRIBUTES), &rcList);
  1528. GetWindowRect(GetDlgItem(hdlg, IDC_TAB_FIXES), &rcTree);
  1529. g_rcDlgSmall.left = g_rcDlgBig.left;
  1530. g_rcDlgSmall.top = g_rcDlgBig.top;
  1531. g_rcDlgSmall.bottom = g_rcDlgBig.bottom;
  1532. g_rcDlgSmall.right = g_rcDlgBig.right -
  1533. (rcList.right - rcList.left) -
  1534. (rcList.left - rcTree.right);
  1535. ExpandCollapseDialog(hdlg, TRUE);
  1536. //
  1537. // Disable a bunch of controls.
  1538. //
  1539. EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), FALSE);
  1540. EnableWindow(GetDlgItem(hdlg, IDC_REMOVE_MATCHING), FALSE);
  1541. EnableWindow(GetDlgItem(hdlg, IDC_RUN), FALSE);
  1542. EnableWindow(GetDlgItem(hdlg, IDC_CREATEFILE), FALSE);
  1543. EnableWindow(GetDlgItem(hdlg, IDC_SHOWXML), FALSE);
  1544. //
  1545. // Show the app icon.
  1546. //
  1547. hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
  1548. SetClassLongPtr(hdlg, GCLP_HICON, (LONG_PTR)hIcon);
  1549. g_hwndTab = GetDlgItem(hdlg, IDC_TAB_FIXES);
  1550. g_hwndFilesTree = GetDlgItem(hdlg, IDC_ATTRIBUTES);
  1551. //
  1552. // Set up the tab control.
  1553. //
  1554. InitTabs(hdlg, g_hwndTab);
  1555. hImage = ImageList_LoadImage(g_hInstance,
  1556. MAKEINTRESOURCE(IDB_BMP_CHECK),
  1557. 16,
  1558. 0,
  1559. CLR_DEFAULT,
  1560. IMAGE_BITMAP,
  1561. LR_LOADTRANSPARENT);
  1562. if (hImage != NULL) {
  1563. TreeView_SetImageList(g_hwndFilesTree, hImage, TVSIL_STATE);
  1564. } else {
  1565. DPF("[InitMainDialog] Failed to load imagelist");
  1566. }
  1567. //
  1568. // Set the text for the link window.
  1569. //
  1570. LoadString(g_hInstance,
  1571. g_fW2K ? IDS_W2K_LINK : IDS_XP_LINK,
  1572. szText,
  1573. ARRAYSIZE(szText));
  1574. SetDlgItemText(g_hDlg, IDC_DOWNLOAD_WU, szText);
  1575. //
  1576. // Limit the amount of text that can be typed into the command-line
  1577. // edit box for safety.
  1578. //
  1579. SendDlgItemMessage(hdlg,
  1580. IDC_CMD_LINE,
  1581. EM_LIMITTEXT,
  1582. (WPARAM)MAX_COMMAND_LINE,
  1583. 0);
  1584. //
  1585. // Try selecting the Win95 layer.
  1586. //
  1587. SendMessage(g_hwndListLayers, LB_SELECTSTRING, (WPARAM)(-1), (LPARAM)_T("Win95"));
  1588. LayerChanged(hdlg);
  1589. TabCtrl_SetCurFocus(g_hwndTab, 0);
  1590. ShowWindow(g_hLayersDlg, SW_SHOWNORMAL);
  1591. return TRUE;
  1592. }
  1593. void
  1594. FileTreeToggleSelection(
  1595. HTREEITEM hItem,
  1596. int uMode
  1597. )
  1598. /*++
  1599. FileTreeToggleSelection
  1600. Description: Changes the selection on the attributes tree.
  1601. --*/
  1602. {
  1603. UINT State;
  1604. TVITEM item;
  1605. switch (uMode)
  1606. {
  1607. case uSelect:
  1608. State = INDEXTOSTATEIMAGEMASK(2);
  1609. break;
  1610. case uDeselect:
  1611. State = INDEXTOSTATEIMAGEMASK(1);
  1612. break;
  1613. case uReverse:
  1614. {
  1615. item.mask = TVIF_HANDLE | TVIF_STATE;
  1616. item.hItem = hItem;
  1617. item.stateMask = TVIS_STATEIMAGEMASK;
  1618. TreeView_GetItem(g_hwndFilesTree, &item);
  1619. State = item.state & TVIS_STATEIMAGEMASK;
  1620. if (State) {
  1621. if (((State >> 12) & 0x03) == 2) {
  1622. State = INDEXTOSTATEIMAGEMASK(1);
  1623. } else {
  1624. State = INDEXTOSTATEIMAGEMASK(2);
  1625. }
  1626. }
  1627. break;
  1628. }
  1629. default:
  1630. DPF("[FileTreeToggleSelection] Invalid mode %u", uMode);
  1631. return;
  1632. }
  1633. item.mask = TVIF_HANDLE | TVIF_STATE;
  1634. item.hItem = hItem;
  1635. item.state = State;
  1636. item.stateMask = TVIS_STATEIMAGEMASK;
  1637. TreeView_SetItem(g_hwndFilesTree, &item);
  1638. }
  1639. void
  1640. SelectAttrsInTree(
  1641. BOOL fSelect
  1642. )
  1643. /*++
  1644. SelectAttrsInTree
  1645. Description: Walks each attribute in tree and reverses it's selection.
  1646. --*/
  1647. {
  1648. HTREEITEM hItem, hChildItem;
  1649. hItem = TreeView_GetSelection(g_hwndFilesTree);
  1650. hChildItem = TreeView_GetChild(g_hwndFilesTree, hItem);
  1651. FileTreeToggleSelection(hChildItem, fSelect ? uSelect : uDeselect);
  1652. while (hChildItem) {
  1653. hChildItem = TreeView_GetNextSibling(g_hwndFilesTree, hChildItem);
  1654. FileTreeToggleSelection(hChildItem, fSelect ? uSelect : uDeselect);
  1655. }
  1656. }
  1657. void
  1658. ShimListToggleSelection(
  1659. int nItem,
  1660. int uMode
  1661. )
  1662. /*++
  1663. ShimListToggleSelection
  1664. Description: Changes the selection on the shim list.
  1665. --*/
  1666. {
  1667. UINT uState;
  1668. switch (uMode)
  1669. {
  1670. case uSelect:
  1671. ListView_SetCheckState(g_hwndShimList, nItem, TRUE);
  1672. break;
  1673. case uDeselect:
  1674. ListView_SetCheckState(g_hwndShimList, nItem, FALSE);
  1675. break;
  1676. case uReverse:
  1677. uState = ListView_GetItemState(g_hwndShimList,
  1678. nItem,
  1679. LVIS_STATEIMAGEMASK);
  1680. if (uState) {
  1681. if (((uState >> 12) & 0x03) == 2) {
  1682. uState = INDEXTOSTATEIMAGEMASK(2);
  1683. } else {
  1684. uState = INDEXTOSTATEIMAGEMASK(1);
  1685. }
  1686. }
  1687. ListView_SetItemState(g_hwndShimList, nItem, uState,
  1688. LVIS_STATEIMAGEMASK);
  1689. break;
  1690. }
  1691. }
  1692. void
  1693. HandleTabNotification(
  1694. HWND hdlg,
  1695. LPARAM lParam
  1696. )
  1697. /*++
  1698. HandleTabNotification
  1699. Description: Handle all the notifications we care about for the tab.
  1700. --*/
  1701. {
  1702. LPNMHDR pnm = (LPNMHDR)lParam;
  1703. int ind = 0;
  1704. switch (pnm->code) {
  1705. case TCN_SELCHANGE:
  1706. {
  1707. int nSel;
  1708. DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, DWLP_USER);
  1709. nSel = TabCtrl_GetCurSel(pHdr->hTab);
  1710. if (-1 == nSel) {
  1711. break;
  1712. }
  1713. g_nCrtTab = nSel;
  1714. if (nSel == 0) {
  1715. ShowWindow(pHdr->hDisplay[1], SW_HIDE);
  1716. ShowWindow(pHdr->hDisplay[0], SW_SHOW);
  1717. } else {
  1718. ShowWindow(pHdr->hDisplay[0], SW_HIDE);
  1719. ShowWindow(pHdr->hDisplay[1], SW_SHOW);
  1720. }
  1721. break;
  1722. }
  1723. default:
  1724. break;
  1725. }
  1726. }
  1727. INT_PTR CALLBACK
  1728. OptionsDlgProc(
  1729. HWND hdlg,
  1730. UINT uMsg,
  1731. WPARAM wParam,
  1732. LPARAM lParam
  1733. )
  1734. /*++
  1735. OptionsDlgProc
  1736. Description: Handles messages for the options dialog.
  1737. --*/
  1738. {
  1739. int wCode = LOWORD(wParam);
  1740. int wNotifyCode = HIWORD(wParam);
  1741. switch (uMsg) {
  1742. case WM_INITDIALOG:
  1743. {
  1744. PFIX pFix;
  1745. TCHAR szTitle[MAX_PATH];
  1746. TCHAR szTemp[MAX_PATH];
  1747. TCHAR szType[64];
  1748. TCHAR szModuleName[128];
  1749. HRESULT hr;
  1750. pFix = (PFIX)lParam;
  1751. //
  1752. // Limit the amount of text that can be typed into the command-line
  1753. // and module name edit boxes for safety.
  1754. //
  1755. SendDlgItemMessage(hdlg,
  1756. IDC_SHIM_CMD_LINE,
  1757. EM_LIMITTEXT,
  1758. (WPARAM)SHIM_COMMAND_LINE_MAX_BUFFER,
  1759. 0);
  1760. SendDlgItemMessage(hdlg,
  1761. IDC_MOD_NAME,
  1762. EM_LIMITTEXT,
  1763. (WPARAM)MAX_PATH,
  1764. 0);
  1765. LoadString(g_hInstance, IDS_MOD_TYPE, szType, ARRAYSIZE(szType));
  1766. LoadString(g_hInstance, IDS_MOD_NAME, szModuleName, ARRAYSIZE(szModuleName));
  1767. LoadString(g_hInstance, IDS_OPTIONS_TITLE, szTemp, ARRAYSIZE(szTemp));
  1768. SetWindowLongPtr(hdlg, DWLP_USER, lParam);
  1769. EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), FALSE);
  1770. g_hwndModuleList = GetDlgItem(hdlg, IDC_MOD_LIST);
  1771. InsertListViewColumn(g_hwndModuleList, szType, FALSE, 0, 75);
  1772. InsertListViewColumn(g_hwndModuleList, szModuleName, FALSE, 1, 115);
  1773. ListView_SetExtendedListViewStyle(g_hwndModuleList, LVS_EX_FULLROWSELECT);
  1774. hr = StringCchPrintf(szTitle,
  1775. ARRAYSIZE(szTitle),
  1776. szTemp,
  1777. pFix->pszName);
  1778. if (FAILED(hr)) {
  1779. DPF("[OptionsDlgProc] 0x%08X Buffer too small", HRESULT_CODE(hr));
  1780. return 0;
  1781. }
  1782. SetWindowText(hdlg, szTitle);
  1783. if (NULL != pFix->pszCmdLine) {
  1784. SetDlgItemText(hdlg, IDC_SHIM_CMD_LINE, pFix->pszCmdLine);
  1785. }
  1786. //
  1787. // If this is a flag, disable the module include/exclude controls.
  1788. //
  1789. if (pFix->dwFlags & FIX_TYPE_FLAGVDM) {
  1790. EnableWindow(g_hwndModuleList, FALSE);
  1791. EnableWindow(GetDlgItem(hdlg, IDC_ADD), FALSE);
  1792. EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), FALSE);
  1793. EnableWindow(GetDlgItem(hdlg, IDC_INCLUDE), FALSE);
  1794. EnableWindow(GetDlgItem(hdlg, IDC_EXCLUDE), FALSE);
  1795. EnableWindow(GetDlgItem(hdlg, IDC_MOD_NAME), FALSE);
  1796. } else {
  1797. CheckDlgButton(hdlg, IDC_INCLUDE, BST_CHECKED);
  1798. // Add any modules to the list view.
  1799. BuildModuleListForShim(pFix, BML_ADDTOLISTVIEW);
  1800. }
  1801. break;
  1802. }
  1803. case WM_NOTIFY:
  1804. HandleModuleListNotification(hdlg, lParam);
  1805. break;
  1806. case WM_COMMAND:
  1807. switch (wCode) {
  1808. case IDC_ADD:
  1809. {
  1810. TCHAR szModName[MAX_PATH];
  1811. TCHAR szError[MAX_PATH];
  1812. UINT uInclude, uExclude;
  1813. GetDlgItemText(hdlg, IDC_MOD_NAME, szModName, ARRAYSIZE(szModName));
  1814. if (*szModName == 0) {
  1815. LoadString(g_hInstance, IDS_NO_MOD, szError, ARRAYSIZE(szError));
  1816. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  1817. SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME));
  1818. break;
  1819. }
  1820. uInclude = IsDlgButtonChecked(hdlg, IDC_INCLUDE);
  1821. uExclude = IsDlgButtonChecked(hdlg, IDC_EXCLUDE);
  1822. if ((BST_CHECKED == uInclude) || (BST_CHECKED == uExclude)) {
  1823. AddModuleToListView(szModName, uInclude);
  1824. SetDlgItemText(hdlg, IDC_MOD_NAME, _T(""));
  1825. SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME));
  1826. } else {
  1827. LoadString(g_hInstance, IDS_NO_INCEXC, szError, ARRAYSIZE(szError));
  1828. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  1829. SetFocus(GetDlgItem(hdlg, IDC_INCLUDE));
  1830. break;
  1831. }
  1832. break;
  1833. }
  1834. case IDC_REMOVE:
  1835. { int nIndex;
  1836. nIndex = ListView_GetSelectionMark(g_hwndModuleList);
  1837. ListView_DeleteItem(g_hwndModuleList, nIndex);
  1838. EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), FALSE);
  1839. SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME));
  1840. break;
  1841. }
  1842. case IDOK:
  1843. {
  1844. PFIX pFix;
  1845. TCHAR szCmdLine[1024] = _T("");
  1846. pFix = (PFIX)GetWindowLongPtr(hdlg, DWLP_USER);
  1847. GetDlgItemText(hdlg, IDC_SHIM_CMD_LINE, szCmdLine, 1023);
  1848. if (*szCmdLine != 0) {
  1849. ReplaceCmdLine(pFix, szCmdLine);
  1850. } else {
  1851. ReplaceCmdLine(pFix, NULL);
  1852. }
  1853. // Retrieve any modules from the list view.
  1854. BuildModuleListForShim(pFix, BML_GETFRLISTVIEW);
  1855. EndDialog(hdlg, TRUE);
  1856. break;
  1857. }
  1858. case IDCANCEL:
  1859. EndDialog(hdlg, FALSE);
  1860. break;
  1861. default:
  1862. return FALSE;
  1863. }
  1864. break;
  1865. default:
  1866. return FALSE;
  1867. }
  1868. return TRUE;
  1869. }
  1870. INT_PTR CALLBACK
  1871. MsgBoxDlgProc(
  1872. HWND hdlg,
  1873. UINT uMsg,
  1874. WPARAM wParam,
  1875. LPARAM lParam
  1876. )
  1877. /*++
  1878. MsgBoxDlgProc
  1879. Description: Displays a message box dialog so we can use the hyperlink.
  1880. --*/
  1881. {
  1882. int wCode = LOWORD(wParam);
  1883. int wNotifyCode = HIWORD(wParam);
  1884. switch (uMsg) {
  1885. case WM_INITDIALOG:
  1886. {
  1887. TCHAR szLink[MAX_PATH];
  1888. UINT uNoSDB;
  1889. uNoSDB = (UINT)lParam;
  1890. //
  1891. // Use the parameter to determine what text to display.
  1892. //
  1893. if (uNoSDB) {
  1894. LoadString(g_hInstance, IDS_W2K_NO_SDB, szLink, ARRAYSIZE(szLink));
  1895. SetDlgItemText(hdlg, IDC_MESSAGE, szLink);
  1896. } else {
  1897. LoadString(g_hInstance, IDS_SP2_SDB, szLink, ARRAYSIZE(szLink));
  1898. SetDlgItemText(hdlg, IDC_MESSAGE, szLink);
  1899. }
  1900. LoadString(g_hInstance, IDS_MSG_LINK, szLink, ARRAYSIZE(szLink));
  1901. SetDlgItemText(hdlg, IDC_MSG_LINK, szLink);
  1902. break;
  1903. }
  1904. case WM_NOTIFY:
  1905. if (wParam == IDC_MSG_LINK) {
  1906. NMHDR* pHdr = (NMHDR*)lParam;
  1907. if (pHdr->code == NM_CLICK || pHdr->code == NM_RETURN) {
  1908. SHELLEXECUTEINFO sei = { 0 };
  1909. sei.cbSize = sizeof(SHELLEXECUTEINFO);
  1910. sei.fMask = SEE_MASK_DOENVSUBST;
  1911. sei.hwnd = hdlg;
  1912. sei.nShow = SW_SHOWNORMAL;
  1913. sei.lpFile = g_szW2KUrl;
  1914. ShellExecuteEx(&sei);
  1915. break;
  1916. }
  1917. }
  1918. break;
  1919. case WM_COMMAND:
  1920. switch (wCode) {
  1921. case IDCANCEL:
  1922. EndDialog(hdlg, TRUE);
  1923. break;
  1924. default:
  1925. return FALSE;
  1926. }
  1927. break;
  1928. default:
  1929. return FALSE;
  1930. }
  1931. return TRUE;
  1932. }
  1933. INT_PTR CALLBACK
  1934. LayersTabDlgProc(
  1935. HWND hdlg,
  1936. UINT uMsg,
  1937. WPARAM wParam,
  1938. LPARAM lParam
  1939. )
  1940. /*++
  1941. LayersTabDlgProc
  1942. Description: Handle messages for the layers tab.
  1943. --*/
  1944. {
  1945. int wCode = LOWORD(wParam);
  1946. int wNotifyCode = HIWORD(wParam);
  1947. switch (uMsg) {
  1948. case WM_INITDIALOG:
  1949. HandleLayersDialogInit(hdlg);
  1950. break;
  1951. case WM_COMMAND:
  1952. if (wNotifyCode == LBN_SELCHANGE && wCode == IDC_LAYERS) {
  1953. LayerChanged(hdlg);
  1954. break;
  1955. }
  1956. switch (wCode) {
  1957. case IDCANCEL:
  1958. EndDialog(hdlg, TRUE);
  1959. break;
  1960. default:
  1961. return FALSE;
  1962. }
  1963. break;
  1964. default:
  1965. return FALSE;
  1966. }
  1967. return TRUE;
  1968. }
  1969. INT_PTR CALLBACK
  1970. FixesTabDlgProc(
  1971. HWND hdlg,
  1972. UINT uMsg,
  1973. WPARAM wParam,
  1974. LPARAM lParam
  1975. )
  1976. /*++
  1977. LayersDlgProc
  1978. Description: Handle messages for the fixes tab.
  1979. --*/
  1980. {
  1981. int wCode = LOWORD(wParam);
  1982. int wNotifyCode = HIWORD(wParam);
  1983. switch (uMsg) {
  1984. case WM_INITDIALOG:
  1985. if (!HandleFixesDialogInit(hdlg)) {
  1986. EndDialog(g_hDlg, 0);
  1987. }
  1988. break;
  1989. case WM_NOTIFY:
  1990. if (wParam == IDC_SHIMS) {
  1991. HandleShimListNotification(hdlg, lParam);
  1992. }
  1993. break;
  1994. case WM_TIMER:
  1995. if (wParam == ID_COUNT_SHIMS) {
  1996. KillTimer(hdlg, ID_COUNT_SHIMS);
  1997. CountShims(TRUE);
  1998. }
  1999. break;
  2000. case WM_COMMAND:
  2001. switch (wCode) {
  2002. case IDCANCEL:
  2003. EndDialog(hdlg, TRUE);
  2004. break;
  2005. case IDC_CLEAR_SHIMS:
  2006. DeselectAllShims(hdlg);
  2007. break;
  2008. default:
  2009. return FALSE;
  2010. }
  2011. break;
  2012. default:
  2013. return FALSE;
  2014. }
  2015. return TRUE;
  2016. }
  2017. void
  2018. HandleModuleListNotification(
  2019. HWND hdlg,
  2020. LPARAM lParam
  2021. )
  2022. /*++
  2023. HandleModuleListNotification
  2024. Description: Handle all the notifications we care about for the
  2025. shim list.
  2026. --*/
  2027. {
  2028. LPNMHDR pnm = (LPNMHDR)lParam;
  2029. switch (pnm->code) {
  2030. case NM_CLICK:
  2031. {
  2032. LVHITTESTINFO lvhti;
  2033. GetCursorPos(&lvhti.pt);
  2034. ScreenToClient(g_hwndShimList, &lvhti.pt);
  2035. ListView_HitTest(g_hwndShimList, &lvhti);
  2036. //
  2037. // If the user clicked on a list view item,
  2038. // enable the Remove button.
  2039. //
  2040. if (lvhti.flags & LVHT_ONITEMLABEL) {
  2041. EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), TRUE);
  2042. }
  2043. break;
  2044. }
  2045. default:
  2046. break;
  2047. }
  2048. }
  2049. void
  2050. HandleShimListNotification(
  2051. HWND hdlg,
  2052. LPARAM lParam
  2053. )
  2054. /*++
  2055. HandleShimListNotification
  2056. Description: Handle all the notifications we care about for the
  2057. shim list.
  2058. --*/
  2059. {
  2060. LPNMHDR pnm = (LPNMHDR)lParam;
  2061. switch (pnm->code) {
  2062. case NM_CLICK:
  2063. {
  2064. LVHITTESTINFO lvhti;
  2065. GetCursorPos(&lvhti.pt);
  2066. ScreenToClient(g_hwndShimList, &lvhti.pt);
  2067. ListView_HitTest(g_hwndShimList, &lvhti);
  2068. //
  2069. // If the check box state has changed,
  2070. // toggle the selection. Either way,
  2071. // maintain selection as we go.
  2072. //
  2073. if (lvhti.flags & LVHT_ONITEMSTATEICON) {
  2074. ShimListToggleSelection(lvhti.iItem, uReverse);
  2075. }
  2076. ListView_SetItemState(g_hwndShimList,
  2077. lvhti.iItem,
  2078. LVIS_FOCUSED | LVIS_SELECTED,
  2079. 0x000F);
  2080. SetTimer(hdlg, ID_COUNT_SHIMS, 100, NULL);
  2081. break;
  2082. }
  2083. case NM_DBLCLK:
  2084. {
  2085. LVITEM lvi;
  2086. int nItem;
  2087. PFIX pFix;
  2088. nItem = ListView_GetSelectionMark(g_hwndShimList);
  2089. if (-1 == nItem) {
  2090. break;
  2091. }
  2092. lvi.mask = LVIF_PARAM;
  2093. lvi.iItem = nItem;
  2094. ListView_GetItem(g_hwndShimList, &lvi);
  2095. pFix = (PFIX)lvi.lParam;
  2096. if ((pFix->dwFlags & FIX_TYPE_SHIM) || (pFix->dwFlags & FIX_TYPE_FLAGVDM)) {
  2097. if (DialogBoxParam(g_hInstance,
  2098. MAKEINTRESOURCE(IDD_OPTIONS),
  2099. hdlg,
  2100. OptionsDlgProc,
  2101. (LPARAM)pFix)) {
  2102. if (NULL != pFix->pszCmdLine) {
  2103. ListView_SetItemText(g_hwndShimList, nItem, 1, _T("X"));
  2104. } else {
  2105. ListView_SetItemText(g_hwndShimList, nItem, 1, _T(""));
  2106. }
  2107. if (NULL != pFix->pModule) {
  2108. ListView_SetItemText(g_hwndShimList, nItem, 2, _T("X"));
  2109. } else {
  2110. ListView_SetItemText(g_hwndShimList, nItem, 2, _T(""));
  2111. }
  2112. }
  2113. }
  2114. break;
  2115. }
  2116. case LVN_ITEMCHANGED:
  2117. {
  2118. LPNMLISTVIEW lpnmlv;
  2119. PFIX pFix;
  2120. lpnmlv = (LPNMLISTVIEW)lParam;
  2121. pFix = (PFIX)lpnmlv->lParam;
  2122. //
  2123. // Only change the text if our selection has changed.
  2124. // If we don't do this, the text goes bye-bye when
  2125. // the user clicks the Clear button.
  2126. //
  2127. if ((lpnmlv->uChanged & LVIF_STATE) &&
  2128. (lpnmlv->uNewState & LVIS_SELECTED)) {
  2129. SetDlgItemText(hdlg, IDC_SHIM_DESCRIPTION, pFix->pszDesc);
  2130. ListView_SetSelectionMark(g_hwndShimList, lpnmlv->iItem);
  2131. }
  2132. break;
  2133. }
  2134. default:
  2135. break;
  2136. }
  2137. }
  2138. void
  2139. HandleAttributeTreeNotification(
  2140. HWND hdlg,
  2141. LPARAM lParam
  2142. )
  2143. /*++
  2144. HandleAttributeTreeNotification
  2145. Description: Handle all the notifications we care about for the
  2146. file attributes tree.
  2147. --*/
  2148. {
  2149. LPNMHDR pnm = (LPNMHDR)lParam;
  2150. switch (pnm->code) {
  2151. case NM_CLICK:
  2152. {
  2153. TVHITTESTINFO HitTest;
  2154. GetCursorPos(&HitTest.pt);
  2155. ScreenToClient(g_hwndFilesTree, &HitTest.pt);
  2156. TreeView_HitTest(g_hwndFilesTree, &HitTest);
  2157. if (HitTest.flags & TVHT_ONITEMSTATEICON) {
  2158. FileTreeToggleSelection(HitTest.hItem, uReverse);
  2159. } else if (HitTest.flags & TVHT_ONITEMLABEL) {
  2160. HWND hwndButton;
  2161. HTREEITEM hItem, hRoot;
  2162. hwndButton = GetDlgItem(hdlg, IDC_REMOVE_MATCHING);
  2163. hItem = TreeView_GetParent(g_hwndFilesTree, HitTest.hItem);
  2164. hRoot = TreeView_GetRoot(g_hwndFilesTree);
  2165. //
  2166. // If the selected item has no parent and it's not
  2167. // the root, enable the remove matching button.
  2168. //
  2169. if ((NULL == hItem) && (hRoot != HitTest.hItem)) {
  2170. EnableWindow(hwndButton, TRUE);
  2171. } else {
  2172. EnableWindow(hwndButton, FALSE);
  2173. }
  2174. }
  2175. break;
  2176. }
  2177. case NM_RCLICK:
  2178. {
  2179. TVHITTESTINFO HitTest;
  2180. POINT pt;
  2181. GetCursorPos(&HitTest.pt);
  2182. pt.x = HitTest.pt.x;
  2183. pt.y = HitTest.pt.y;
  2184. ScreenToClient(g_hwndFilesTree, &HitTest.pt);
  2185. TreeView_HitTest(g_hwndFilesTree, &HitTest);
  2186. if (HitTest.flags & TVHT_ONITEMLABEL)
  2187. {
  2188. HTREEITEM hParentItem;
  2189. TreeView_SelectItem(g_hwndFilesTree, HitTest.hItem);
  2190. //
  2191. // If the selected item has no parent, we assume that a
  2192. // matching file was right-clicked.
  2193. //
  2194. hParentItem = TreeView_GetParent(g_hwndFilesTree, HitTest.hItem);
  2195. if (NULL == hParentItem) {
  2196. DisplayAttrContextMenu(&pt);
  2197. }
  2198. }
  2199. break;
  2200. }
  2201. case TVN_KEYDOWN:
  2202. {
  2203. LPNMTVKEYDOWN lpKeyDown = (LPNMTVKEYDOWN)lParam;
  2204. HTREEITEM hItem;
  2205. if (lpKeyDown->wVKey == VK_SPACE) {
  2206. hItem = TreeView_GetSelection(g_hwndFilesTree);
  2207. if (hItem != NULL) {
  2208. FileTreeToggleSelection(hItem, uReverse);
  2209. }
  2210. } else if (lpKeyDown->wVKey == VK_DELETE) {
  2211. HTREEITEM hParentItem;
  2212. hItem = TreeView_GetSelection(g_hwndFilesTree);
  2213. hParentItem = TreeView_GetParent(g_hwndFilesTree, hItem);
  2214. if (hParentItem == NULL) {
  2215. if (TreeView_GetPrevSibling(g_hwndFilesTree, hItem) != NULL) {
  2216. TreeView_DeleteItem(g_hwndFilesTree, hItem);
  2217. }
  2218. }
  2219. }
  2220. break;
  2221. }
  2222. default:
  2223. break;
  2224. }
  2225. }
  2226. INT_PTR CALLBACK
  2227. QFixAppDlgProc(
  2228. HWND hdlg,
  2229. UINT uMsg,
  2230. WPARAM wParam,
  2231. LPARAM lParam
  2232. )
  2233. /*++
  2234. QFixAppDlgProc
  2235. Description: The dialog proc of QFixApp.
  2236. --*/
  2237. {
  2238. int wCode = LOWORD(wParam);
  2239. int wNotifyCode = HIWORD(wParam);
  2240. switch (uMsg) {
  2241. case WM_INITDIALOG:
  2242. if (!InitMainDialog(hdlg)) {
  2243. EndDialog(hdlg, TRUE);
  2244. }
  2245. break;
  2246. case WM_NOTIFY:
  2247. if (wParam == IDC_SHIMS) {
  2248. HandleShimListNotification(hdlg, lParam);
  2249. } else if (wParam == IDC_ATTRIBUTES) {
  2250. HandleAttributeTreeNotification(hdlg, lParam);
  2251. } else if (wParam == IDC_TAB_FIXES) {
  2252. HandleTabNotification(hdlg, lParam);
  2253. } else if (wParam == IDC_DOWNLOAD_WU) {
  2254. NMHDR* pHdr = (NMHDR*)lParam;
  2255. if (pHdr->code == NM_CLICK || pHdr->code == NM_RETURN) {
  2256. SHELLEXECUTEINFO sei = { 0 };
  2257. sei.cbSize = sizeof(SHELLEXECUTEINFO);
  2258. sei.fMask = SEE_MASK_DOENVSUBST;
  2259. sei.hwnd = hdlg;
  2260. sei.nShow = SW_SHOWNORMAL;
  2261. if (g_fW2K) {
  2262. sei.lpFile = g_szW2KUrl;
  2263. } else if (g_fNETServer) {
  2264. sei.lpFile = g_szNETUrl;
  2265. } else {
  2266. sei.lpFile = g_szXPUrl;
  2267. }
  2268. ShellExecuteEx(&sei);
  2269. break;
  2270. }
  2271. }
  2272. break;
  2273. case WM_DESTROY:
  2274. {
  2275. DLGHDR* pHdr;
  2276. //
  2277. // Destory the dialogs and remove any misc files.
  2278. //
  2279. pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, DWLP_USER);
  2280. DestroyWindow(pHdr->hDisplay[0]);
  2281. DestroyWindow(pHdr->hDisplay[1]);
  2282. CleanupSupportForApp(g_szShortName);
  2283. break;
  2284. }
  2285. case WM_COMMAND:
  2286. if (wNotifyCode == LBN_SELCHANGE && wCode == IDC_LAYERS) {
  2287. LayerChanged(hdlg);
  2288. break;
  2289. }
  2290. switch (wCode) {
  2291. case IDC_RUN:
  2292. RunTheApp(hdlg);
  2293. break;
  2294. case IDC_BROWSE:
  2295. BrowseForApp(hdlg);
  2296. break;
  2297. case IDC_DETAILS:
  2298. ExpandCollapseDialog(hdlg, !g_bSimpleEdition);
  2299. break;
  2300. case IDC_CREATEFILE:
  2301. CreateSupportForApp(hdlg);
  2302. break;
  2303. case IDC_SHOWXML:
  2304. ShowXML(hdlg);
  2305. break;
  2306. case IDC_ADD_MATCHING:
  2307. PromptAddMatchingFile(hdlg);
  2308. break;
  2309. case IDC_VIEW_LOG:
  2310. ShowShimLog();
  2311. break;
  2312. case IDCANCEL:
  2313. EndDialog(hdlg, TRUE);
  2314. break;
  2315. case IDM_SELECT_ALL:
  2316. SelectAttrsInTree(TRUE);
  2317. break;
  2318. case IDM_CLEAR_ALL:
  2319. SelectAttrsInTree(FALSE);
  2320. break;
  2321. case IDC_REMOVE_MATCHING:
  2322. {
  2323. HTREEITEM hParentItem, hItem;
  2324. TCHAR szError[MAX_PATH];
  2325. hItem = TreeView_GetSelection(g_hwndFilesTree);
  2326. if (NULL == hItem) {
  2327. LoadString(g_hInstance, IDS_NO_SELECTION, szError, ARRAYSIZE(szError));
  2328. MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  2329. return TRUE;
  2330. }
  2331. hParentItem = TreeView_GetParent(g_hwndFilesTree, hItem);
  2332. if (hParentItem == NULL) {
  2333. if (TreeView_GetPrevSibling(g_hwndFilesTree, hItem) != NULL) {
  2334. TreeView_DeleteItem(g_hwndFilesTree, hItem);
  2335. EnableWindow(GetDlgItem(hdlg, IDC_REMOVE_MATCHING), FALSE);
  2336. }
  2337. }
  2338. break;
  2339. }
  2340. default:
  2341. return FALSE;
  2342. }
  2343. break;
  2344. default:
  2345. return FALSE;
  2346. }
  2347. return TRUE;
  2348. }
  2349. BOOL
  2350. QFixAppInitialize(
  2351. void
  2352. )
  2353. /*++
  2354. QFixAppInitialize
  2355. Description: Initializes common paths, etc.
  2356. --*/
  2357. {
  2358. UINT cchSize;
  2359. INITCOMMONCONTROLSEX icex;
  2360. icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  2361. icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_TAB_CLASSES;
  2362. //
  2363. // Initialize the common controls.
  2364. //
  2365. if (!InitCommonControlsEx(&icex)) {
  2366. InitCommonControls();
  2367. }
  2368. //
  2369. // Set up our hyperlink control.
  2370. //
  2371. LinkWindow_RegisterClass();
  2372. //
  2373. // Save away common paths for later use.
  2374. //
  2375. cchSize = GetSystemDirectory(g_szSysDir, ARRAYSIZE(g_szSysDir));
  2376. if (cchSize > ARRAYSIZE(g_szSysDir) || cchSize == 0) {
  2377. DPF("[QFixAppInitialize] 0x%08X Failed to get system directory",
  2378. GetLastError());
  2379. return FALSE;
  2380. }
  2381. cchSize = GetSystemWindowsDirectory(g_szWinDir, ARRAYSIZE(g_szWinDir));
  2382. if (cchSize > ARRAYSIZE(g_szWinDir) || cchSize == 0) {
  2383. DPF("[QFixAppInitialize] 0x%08X Failed to get windows directory",
  2384. GetLastError());
  2385. return FALSE;
  2386. }
  2387. return TRUE;
  2388. }
  2389. int WINAPI
  2390. wWinMain(
  2391. HINSTANCE hInst,
  2392. HINSTANCE hInstPrev,
  2393. LPTSTR lpszCmd,
  2394. int swShow
  2395. )
  2396. /*++
  2397. WinMain
  2398. Description: Application entry point.
  2399. --*/
  2400. {
  2401. BOOL fSP2 = FALSE;
  2402. TCHAR szError[MAX_PATH];
  2403. OSVERSIONINFOEX osviex;
  2404. LoadString(g_hInstance, IDS_APP_TITLE, g_szAppTitle, ARRAYSIZE(g_szAppTitle));
  2405. g_hInstance = hInst;
  2406. osviex.dwOSVersionInfoSize = sizeof(osviex);
  2407. GetVersionEx((OSVERSIONINFO*)&osviex);
  2408. //
  2409. // See if they're an administrator - bail if not.
  2410. //
  2411. if (!(IsUserAnAdministrator())) {
  2412. LoadString(g_hInstance, IDS_NOT_ADMIN, szError, ARRAYSIZE(szError));
  2413. MessageBox(NULL, szError, g_szAppTitle, MB_ICONERROR);
  2414. return 0;
  2415. }
  2416. //
  2417. // See if we're running on Windows 2000, then check for SP2, then
  2418. // check for .NET Server.
  2419. //
  2420. if ((osviex.dwMajorVersion == 5 && osviex.dwMinorVersion == 0)) {
  2421. g_fW2K = TRUE;
  2422. }
  2423. if (g_fW2K && (!_tcscmp(osviex.szCSDVersion, _T("Service Pack 2")))) {
  2424. fSP2 = TRUE;
  2425. }
  2426. if (!(osviex.wProductType == VER_NT_WORKSTATION)) {
  2427. g_fNETServer = TRUE;
  2428. }
  2429. //
  2430. // Perform some necessary initialization.
  2431. //
  2432. if (!QFixAppInitialize()) {
  2433. LoadString(g_hInstance, IDS_INIT_FAILED, szError, ARRAYSIZE(szError));
  2434. MessageBox(GetDesktopWindow(), szError, g_szAppTitle, MB_ICONERROR);
  2435. return 0;
  2436. }
  2437. //
  2438. // Attempt to locate the SDB in the AppPatch directory.
  2439. //
  2440. if (!CheckForSDB()) {
  2441. if (g_fW2K) {
  2442. DialogBoxParam(hInst,
  2443. MAKEINTRESOURCE(IDD_MSGBOX_SDB),
  2444. GetDesktopWindow(),
  2445. MsgBoxDlgProc,
  2446. (LPARAM)1);
  2447. return 0;
  2448. } else {
  2449. LoadString(g_hInstance, IDS_XP_NO_SDB, szError, ARRAYSIZE(szError));
  2450. MessageBox(GetDesktopWindow(), szError, g_szAppTitle, MB_ICONEXCLAMATION);
  2451. return 0;
  2452. }
  2453. }
  2454. //
  2455. // If this is SP2, and the SDB is older, bail out.
  2456. //
  2457. if (fSP2) {
  2458. if (IsSDBFromSP2()) {
  2459. DialogBoxParam(hInst,
  2460. MAKEINTRESOURCE(IDD_MSGBOX_SP2),
  2461. GetDesktopWindow(),
  2462. MsgBoxDlgProc,
  2463. (LPARAM)0);
  2464. return 0;
  2465. }
  2466. }
  2467. //
  2468. // Check for command line options.
  2469. //
  2470. if (lpszCmd) {
  2471. DPF("[WinMain] Command line '%S'", lpszCmd);
  2472. while (*lpszCmd) {
  2473. if (*lpszCmd == _T('a') || *lpszCmd == _T('A')) {
  2474. g_bAllShims = TRUE;
  2475. }
  2476. else if (*lpszCmd == _T('x') || *lpszCmd == _T('X')) {
  2477. g_bShowXML = TRUE;
  2478. }
  2479. lpszCmd++;
  2480. }
  2481. }
  2482. DialogBox(hInst,
  2483. MAKEINTRESOURCE(IDD_DIALOG),
  2484. GetDesktopWindow(),
  2485. QFixAppDlgProc);
  2486. return 1;
  2487. }