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

826 lines
21 KiB

  1. /***************************************************************************
  2. * Quick shim application tools
  3. *
  4. * Author: clupu (Feb 16, 2000)
  5. *
  6. \**************************************************************************/
  7. #include "windows.h"
  8. #include "commctrl.h"
  9. #include "commdlg.h"
  10. #include "resource.h"
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <stdarg.h>
  14. #include "shimWin2000.h"
  15. #include "shimWhistler.h"
  16. #include "..\acFileAttr\acFileAttr.h"
  17. /*
  18. * Global Variables
  19. */
  20. HINSTANCE g_hInstance;
  21. HWND g_hDlg;
  22. char g_szBinary[MAX_PATH]; // the full path of the main binary being shimmed
  23. char g_szShortName[128]; // the short name of the main EXE
  24. char* g_pszShimDLL;
  25. char g_szBinaryOther[MAX_PATH]; // the full path of the optional EXE that will
  26. // be launched instead (setup case)
  27. HWND g_hwndShimTree; // the handle to the tree view control
  28. // containing all the shims available
  29. HWND g_hwndFilesTree; // the handle to the tree view control
  30. // containing the matching files selected
  31. BOOL g_bWin2k; // are we running on Win2k or Whistler
  32. BOOL g_bRunOther; // TRUE - run g_szBinaryOther instead
  33. BOOL g_bSimpleEdition; // simple or dev edition
  34. RECT g_rcDlgBig, g_rcDlgSmall; // rectangle of the simple and the dev edition
  35. // of the dialog
  36. #if DBG
  37. /*********************************************************************
  38. * LogMsgDbg
  39. *
  40. *********************************************************************/
  41. void LogMsgDbg(
  42. LPSTR pszFmt,
  43. ... )
  44. {
  45. CHAR gszT[1024];
  46. va_list arglist;
  47. va_start(arglist, pszFmt);
  48. _vsnprintf(gszT, 1023, pszFmt, arglist);
  49. gszT[1023] = 0;
  50. va_end(arglist);
  51. OutputDebugString(gszT);
  52. }
  53. #endif // DBG
  54. /*******************************************************************************
  55. * CenterWindow
  56. *
  57. * This function must be called at the WM_INIDIALOG in order to
  58. * move the dialog window centered in the client area of the
  59. * parent or owner window.
  60. *******************************************************************************/
  61. BOOL CenterWindow(
  62. HWND hWnd)
  63. {
  64. RECT rectWindow, rectParent, rectScreen;
  65. int nCX, nCY;
  66. HWND hParent;
  67. POINT ptPoint;
  68. hParent = GetParent(hWnd);
  69. if (hParent == NULL)
  70. hParent = GetDesktopWindow();
  71. GetWindowRect(hParent, (LPRECT)&rectParent);
  72. GetWindowRect(hWnd, (LPRECT)&rectWindow);
  73. GetWindowRect(GetDesktopWindow(), (LPRECT)&rectScreen);
  74. nCX = rectWindow.right - rectWindow.left;
  75. nCY = rectWindow.bottom - rectWindow.top;
  76. ptPoint.x = ((rectParent.right + rectParent.left) / 2) - (nCX / 2);
  77. ptPoint.y = ((rectParent.bottom + rectParent.top ) / 2) - (nCY / 2);
  78. if (ptPoint.x < rectScreen.left)
  79. ptPoint.x = rectScreen.left;
  80. if (ptPoint.x > rectScreen.right - nCX)
  81. ptPoint.x = rectScreen.right - nCX;
  82. if (ptPoint.y < rectScreen.top)
  83. ptPoint.y = rectScreen.top;
  84. if (ptPoint.y > rectScreen.bottom - nCY)
  85. ptPoint.y = rectScreen.bottom - nCY;
  86. if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
  87. ScreenToClient(hParent, (LPPOINT)&ptPoint);
  88. if (!MoveWindow(hWnd, ptPoint.x, ptPoint.y, nCX, nCY, TRUE))
  89. return FALSE;
  90. return TRUE;
  91. }
  92. /*********************************************************************
  93. * AddMatchingFile
  94. *
  95. * Adds a matching file and it's attributes to the tree
  96. *
  97. *********************************************************************/
  98. VOID
  99. AddMatchingFile(
  100. HWND hdlg,
  101. char* pszFullPath,
  102. char* pszRelativePath,
  103. BOOL bMainEXE)
  104. {
  105. HANDLE hMgr;
  106. TVINSERTSTRUCT is;
  107. HTREEITEM hParent;
  108. int i;
  109. int nAttrCount;
  110. char szItem[256];
  111. hMgr = ReadFileAttributes(pszFullPath, &nAttrCount);
  112. is.hParent = TVI_ROOT;
  113. is.hInsertAfter = TVI_LAST;
  114. is.item.lParam = (LONG)hMgr;
  115. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  116. is.item.pszText = pszRelativePath;
  117. hParent = TreeView_InsertItem(g_hwndFilesTree, &is);
  118. is.hParent = hParent;
  119. is.item.mask = TVIF_TEXT;
  120. is.item.pszText = szItem;
  121. is.item.mask |= TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  122. is.item.iImage = 0;
  123. is.item.iSelectedImage = 1;
  124. is.item.state = INDEXTOSTATEIMAGEMASK(1);
  125. is.item.stateMask = TVIS_STATEIMAGEMASK;
  126. for (i = 0; i < nAttrCount; i++) {
  127. PSTR pszValue;
  128. DWORD id;
  129. HTREEITEM hItem;
  130. if (!IsAttrAvailable(hMgr, i))
  131. continue;
  132. // filter the attributes for Whistler (temporary)
  133. if (!g_bWin2k) {
  134. id = GetAttrId(i);
  135. if (id != VTID_FILESIZE && id != VTID_CHECKSUM)
  136. continue;
  137. }
  138. pszValue = GetAttrValue(hMgr, i);
  139. if (pszValue == NULL)
  140. continue;
  141. wsprintf(szItem, "%s: %s", GetAttrName(i), pszValue);
  142. is.item.lParam = i;
  143. hItem = TreeView_InsertItem(g_hwndFilesTree, &is);
  144. }
  145. TreeView_Expand(g_hwndFilesTree, hParent, TVE_EXPAND);
  146. }
  147. /*********************************************************************
  148. * AddNewMainBinary
  149. *
  150. * Start with a new main executable
  151. *
  152. *********************************************************************/
  153. VOID
  154. AddNewMainBinary(
  155. HWND hdlg)
  156. {
  157. char szMainEXE[128];
  158. TreeView_DeleteAllItems(g_hwndFilesTree);
  159. wsprintf(szMainEXE, "Main executable (%s)", g_szShortName);
  160. AddMatchingFile(hdlg, g_szBinary, szMainEXE, TRUE);
  161. }
  162. /*********************************************************************
  163. * DoBrowseForApp
  164. *
  165. * Browse for the main executable for which a shim will be applied
  166. *
  167. *********************************************************************/
  168. VOID
  169. DoBrowseForApp(
  170. HWND hdlg)
  171. {
  172. OPENFILENAME ofn;
  173. g_szBinary[0] = 0;
  174. ofn.lStructSize = sizeof(OPENFILENAME);
  175. ofn.hwndOwner = hdlg;
  176. ofn.hInstance = 0;
  177. ofn.lpstrFilter = NULL;
  178. ofn.lpstrCustomFilter = NULL;
  179. ofn.nMaxCustFilter = 0;
  180. ofn.nFilterIndex = 0;
  181. ofn.lpstrFile = g_szBinary;
  182. ofn.nMaxFile = MAX_PATH;
  183. ofn.lpstrFileTitle = g_szShortName;
  184. ofn.nMaxFileTitle = 128;
  185. ofn.lpstrInitialDir = NULL;
  186. ofn.lpstrTitle = "Choose an executable binary to shim";
  187. ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOTESTFILECREATE |
  188. OFN_PATHMUSTEXIST;
  189. ofn.lpstrDefExt = "EXE";
  190. if (GetOpenFileName(&ofn)) {
  191. SetDlgItemText(hdlg, IDC_BINARY, g_szBinary);
  192. EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), TRUE);
  193. AddNewMainBinary(hdlg);
  194. }
  195. }
  196. /*********************************************************************
  197. * DoBrowseOther
  198. *
  199. * Browse for a different EXE that will be launched instead of the
  200. * main EXE selected. This is for the setup case where setup.exe
  201. * launches another process _INS0432._MP for example.
  202. *
  203. *********************************************************************/
  204. VOID
  205. DoBrowseOther(
  206. HWND hdlg)
  207. {
  208. OPENFILENAME ofn;
  209. g_szBinaryOther[0] = 0;
  210. ofn.lStructSize = sizeof(OPENFILENAME);
  211. ofn.hwndOwner = hdlg;
  212. ofn.hInstance = 0;
  213. ofn.lpstrFilter = NULL;
  214. ofn.lpstrCustomFilter = NULL;
  215. ofn.nMaxCustFilter = 0;
  216. ofn.nFilterIndex = 0;
  217. ofn.lpstrFile = g_szBinaryOther;
  218. ofn.nMaxFile = MAX_PATH;
  219. ofn.lpstrFileTitle = NULL;
  220. ofn.nMaxFileTitle = 0;
  221. ofn.lpstrInitialDir = NULL;
  222. ofn.lpstrTitle = "Choose the application to run";
  223. ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOTESTFILECREATE |
  224. OFN_PATHMUSTEXIST;
  225. ofn.lpstrDefExt = "EXE";
  226. if (GetOpenFileName(&ofn)) {
  227. SetDlgItemText(hdlg, IDC_RUN_OTHER, g_szBinaryOther);
  228. }
  229. }
  230. /*********************************************************************
  231. * DoAddMatchingFile
  232. *
  233. *********************************************************************/
  234. VOID
  235. DoAddMatchingFile(
  236. HWND hdlg)
  237. {
  238. char szFullPath[MAX_PATH];
  239. char szShortName[128];
  240. char szRelativePath[MAX_PATH];
  241. OPENFILENAME ofn;
  242. szFullPath[0] = 0;
  243. ofn.lStructSize = sizeof(OPENFILENAME);
  244. ofn.hwndOwner = hdlg;
  245. ofn.hInstance = 0;
  246. ofn.lpstrFilter = NULL;
  247. ofn.lpstrCustomFilter = NULL;
  248. ofn.nMaxCustFilter = 0;
  249. ofn.nFilterIndex = 0;
  250. ofn.lpstrFile = szFullPath;
  251. ofn.nMaxFile = MAX_PATH;
  252. ofn.lpstrFileTitle = szShortName;
  253. ofn.nMaxFileTitle = 128;
  254. ofn.lpstrInitialDir = NULL;
  255. ofn.lpstrTitle = "Choose the application to run";
  256. ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOTESTFILECREATE |
  257. OFN_PATHMUSTEXIST;
  258. ofn.lpstrDefExt = "EXE";
  259. if (GetOpenFileName(&ofn)) {
  260. char* pszBin;
  261. char* pszNew;
  262. // need to modify the path to be a relative path to g_szBinary
  263. if (g_szBinary[0] != szFullPath[0]) {
  264. MessageBox(hdlg, "A matching file must be located on the same drive",
  265. "Warning", MB_ICONEXCLAMATION | MB_OK);
  266. return;
  267. }
  268. // walk both strings untill they differ
  269. pszBin = g_szBinary;
  270. pszNew = szFullPath;
  271. szRelativePath[0] = 0;
  272. while (*pszBin == *pszNew) {
  273. pszBin++;
  274. pszNew++;
  275. }
  276. // go back to the last \
  277. while (*(pszBin - 1) != '\\') {
  278. pszBin--;
  279. pszNew--;
  280. }
  281. while (lstrcmp(pszBin, g_szShortName) != 0) {
  282. // add ..\ each time a subdir is identified (not the short name)
  283. lstrcat(szRelativePath, "..\\");
  284. while (*pszBin != '\\')
  285. pszBin++;
  286. pszBin++;
  287. }
  288. lstrcat(szRelativePath, pszNew);
  289. // finally add the maching file
  290. AddMatchingFile(hdlg, szFullPath, szRelativePath, FALSE);
  291. }
  292. }
  293. /*********************************************************************
  294. * PopulateTree
  295. *
  296. *********************************************************************/
  297. VOID
  298. PopulateTree(
  299. HWND hTree)
  300. {
  301. TVINSERTSTRUCT is;
  302. PFIX pFix;
  303. TreeView_DeleteAllItems(hTree);
  304. if (g_bWin2k) {
  305. pFix = ReadFixes_Win2000();
  306. if (pFix == NULL) {
  307. MessageBox(NULL,
  308. "You need to have a copy of the file Shim2000.txt"
  309. " in the directory where you started QShimApp.exe",
  310. "Error", MB_ICONEXCLAMATION | MB_OK);
  311. return;
  312. }
  313. } else {
  314. pFix = ReadFixes_Whistler();
  315. if (pFix == NULL) {
  316. MessageBox(NULL,
  317. "The shim database doesn't exist or it is corrupted",
  318. "Error", MB_ICONEXCLAMATION | MB_OK);
  319. return;
  320. }
  321. }
  322. is.hParent = TVI_ROOT;
  323. is.hInsertAfter = TVI_SORT;
  324. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  325. // walk the list and add all the fixes to the tree view
  326. while (pFix != NULL) {
  327. is.item.lParam = (LPARAM)pFix;
  328. is.item.pszText = pFix->pszName;
  329. TreeView_InsertItem(hTree, &is);
  330. pFix = pFix->pNext;
  331. }
  332. }
  333. /*********************************************************************
  334. * RunShimmedApp
  335. *
  336. *********************************************************************/
  337. DWORD WINAPI
  338. RunShimmedApp(
  339. LPVOID lParam)
  340. {
  341. STARTUPINFO si;
  342. PROCESS_INFORMATION pi;
  343. ZeroMemory(&si, sizeof(si));
  344. si.cb = sizeof(si);
  345. // Try to run the app
  346. if (!CreateProcess(NULL,
  347. (g_bRunOther ? g_szBinaryOther : g_szBinary),
  348. NULL,
  349. NULL,
  350. FALSE,
  351. NORMAL_PRIORITY_CLASS,
  352. NULL,
  353. NULL,
  354. &si,
  355. &pi)) {
  356. LogMsg("CreateProcess failed with status: 0x%X\n", GetLastError());
  357. return 0;
  358. }
  359. CloseHandle(pi.hThread);
  360. WaitForSingleObject(pi.hProcess, INFINITE);
  361. CloseHandle(pi.hProcess);
  362. if (g_bWin2k) {
  363. CleanupShimForApp_Win2000();
  364. } else {
  365. CleanupShimForApp_Whistler();
  366. }
  367. return 1;
  368. }
  369. /*********************************************************************
  370. * DoRunApp
  371. *
  372. *********************************************************************/
  373. VOID
  374. DoRunApp(
  375. HWND hdlg)
  376. {
  377. HANDLE hThread;
  378. DWORD dwThreadId;
  379. BOOL bCreateFile;
  380. // Make sure an app was selected first
  381. if (g_szBinary[0] == 0) {
  382. MessageBox(hdlg,
  383. "You need to select the application first",
  384. "Error", MB_ICONEXCLAMATION | MB_OK);
  385. return;
  386. }
  387. // check to see if another app was selected to run
  388. if (SendDlgItemMessage(hdlg, IDC_RUN_OTHER_CHECK, BM_GETCHECK, 0, 0) == BST_CHECKED) {
  389. g_bRunOther = TRUE;
  390. // Make sure the other app is selected
  391. if (g_szBinaryOther[0] == 0) {
  392. GetDlgItemText(hdlg, IDC_RUN_OTHER, g_szBinaryOther, MAX_PATH);
  393. if (g_szBinaryOther[0] == 0) {
  394. MessageBox(hdlg,
  395. "You need to select the other application first",
  396. "Error", MB_ICONEXCLAMATION | MB_OK);
  397. return;
  398. }
  399. }
  400. } else {
  401. g_bRunOther = FALSE;
  402. }
  403. bCreateFile = (SendDlgItemMessage(hdlg, IDC_CREATEFILE, BM_GETCHECK, 0, 0) == BST_CHECKED);
  404. if (g_bWin2k) {
  405. if (!AddShimForApp_Win2000(g_hwndShimTree, g_hwndFilesTree, g_szShortName, bCreateFile)) {
  406. LogMsg("AddShimForApp_Win2000 failed...\n");
  407. return;
  408. }
  409. } else {
  410. if (!AddShimForApp_Whistler(g_hwndShimTree, g_hwndFilesTree, g_szShortName, bCreateFile)) {
  411. LogMsg("AddShimForApp_Whistler failed...\n");
  412. return;
  413. }
  414. }
  415. // Create a thread that will run the app and wait on it to end.
  416. // This will allow the app to still process messages and thus it
  417. // will not block apps that broadcast messages blocking
  418. // themselves.
  419. hThread = CreateThread(
  420. NULL,
  421. 0,
  422. RunShimmedApp,
  423. NULL,
  424. 0,
  425. &dwThreadId);
  426. if (hThread != NULL) {
  427. CloseHandle(hThread);
  428. }
  429. }
  430. /*********************************************************************
  431. * HideStrictGroup
  432. *
  433. *********************************************************************/
  434. VOID
  435. HideStrictGroup(
  436. HWND hdlg,
  437. BOOL bHide)
  438. {
  439. static BOOL sbFirstTime = TRUE;
  440. int i, nShow;
  441. DWORD arrId[] = {IDC_STRICT_GROUP,
  442. IDC_COMMENT,
  443. IDC_ADD_MATCHING,
  444. IDC_FILE_ATTRIBUTES_STATIC,
  445. IDC_ATTRIBUTES,
  446. IDC_CREATEFILE,
  447. IDC_CREATEFILE_STATIC,
  448. 0};
  449. if (!bHide) {
  450. SetWindowPos(hdlg, NULL, 0, 0,
  451. g_rcDlgBig.right - g_rcDlgBig.left,
  452. g_rcDlgBig.bottom - g_rcDlgBig.top,
  453. SWP_NOMOVE | SWP_NOZORDER);
  454. nShow = SW_SHOW;
  455. g_bSimpleEdition = FALSE;
  456. SetDlgItemText(hdlg, IDC_DETAILS, "<< Simple");
  457. // The first time the user goes to the dev edition center
  458. // the big dialog on the screen
  459. if (sbFirstTime) {
  460. sbFirstTime = FALSE;
  461. CenterWindow(hdlg);
  462. }
  463. } else {
  464. nShow = SW_HIDE;
  465. g_bSimpleEdition = TRUE;
  466. SetDlgItemText(hdlg, IDC_DETAILS, "Advanced >>");
  467. }
  468. for (i = 0; arrId[i] != 0; i++) {
  469. ShowWindow(GetDlgItem(hdlg, arrId[i]), nShow);
  470. }
  471. if (bHide) {
  472. SetWindowPos(hdlg, NULL, 0, 0,
  473. g_rcDlgSmall.right - g_rcDlgSmall.left,
  474. g_rcDlgSmall.bottom - g_rcDlgSmall.top,
  475. SWP_NOMOVE | SWP_NOZORDER);
  476. }
  477. }
  478. /*********************************************************************
  479. * DoDetails
  480. *
  481. *********************************************************************/
  482. VOID
  483. DoDetails(
  484. HWND hdlg)
  485. {
  486. HideStrictGroup(hdlg, !g_bSimpleEdition);
  487. }
  488. /*********************************************************************
  489. * Restart
  490. *
  491. *********************************************************************/
  492. VOID
  493. Restart(
  494. HWND hdlg)
  495. {
  496. PopulateTree(g_hwndShimTree);
  497. }
  498. /*********************************************************************
  499. * DoInitDialog
  500. *
  501. *********************************************************************/
  502. VOID
  503. DoInitDialog(
  504. HWND hdlg)
  505. {
  506. HICON hIcon;
  507. RECT rcGroup, rcList;
  508. g_hDlg = hdlg;
  509. GetWindowRect(hdlg, &g_rcDlgBig);
  510. GetWindowRect(GetDlgItem(hdlg, IDC_STRICT_GROUP), &rcGroup);
  511. GetWindowRect(GetDlgItem(hdlg, IDC_ATTRIBUTES), &rcList);
  512. g_rcDlgSmall.left = g_rcDlgBig.left;
  513. g_rcDlgSmall.top = g_rcDlgBig.top;
  514. g_rcDlgSmall.bottom = g_rcDlgBig.bottom;
  515. g_rcDlgSmall.right = g_rcDlgBig.right -
  516. (rcGroup.right - rcGroup.left) -
  517. (rcList.left - rcGroup.left);
  518. HideStrictGroup(hdlg, TRUE);
  519. CenterWindow(hdlg);
  520. EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), FALSE);
  521. if (g_bWin2k) {
  522. SendDlgItemMessage(hdlg, IDC_WIN2K, BM_SETCHECK, BST_CHECKED, 0);
  523. } else {
  524. SendDlgItemMessage(hdlg, IDC_WHISTLER, BM_SETCHECK, BST_CHECKED, 0);
  525. }
  526. hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
  527. SetClassLongPtr(hdlg, GCLP_HICON, (LONG_PTR)hIcon);
  528. g_hwndShimTree = GetDlgItem(hdlg, IDC_TREE);
  529. g_hwndFilesTree = GetDlgItem(hdlg, IDC_ATTRIBUTES);
  530. HIMAGELIST hImage = ImageList_Create(
  531. int cx,
  532. int cy,
  533. UINT flags,
  534. int cInitial,
  535. int cGrow
  536. );
  537. g_szBinary[0] = 0;
  538. PopulateTree(g_hwndShimTree);
  539. }
  540. /*********************************************************************
  541. * QShimAppDlgProc
  542. *
  543. *********************************************************************/
  544. INT_PTR CALLBACK
  545. QShimAppDlgProc(
  546. HWND hdlg,
  547. UINT uMsg,
  548. WPARAM wParam,
  549. LPARAM lParam)
  550. {
  551. int wCode = LOWORD(wParam);
  552. int wNotifyCode = HIWORD(wParam);
  553. switch (uMsg) {
  554. case WM_INITDIALOG:
  555. DoInitDialog(hdlg);
  556. break;
  557. case WM_NOTIFY:
  558. if (wParam == IDC_TREE) {
  559. LPNMHDR pnm = (LPNMHDR)lParam;
  560. switch (pnm->code) {
  561. case TVN_SELCHANGED:
  562. {
  563. LPNMTREEVIEW lpnmtv;
  564. PFIX pFix;
  565. lpnmtv = (LPNMTREEVIEW)lParam;
  566. pFix = (PFIX)lpnmtv->itemNew.lParam;
  567. SetDlgItemText(hdlg, IDC_SHIM_DESCRIPTION, pFix->pszDesc);
  568. break;
  569. }
  570. default:
  571. break;
  572. }
  573. }
  574. break;
  575. case WM_DESTROY:
  576. if (g_bWin2k) {
  577. CleanupShimForApp_Win2000();
  578. } else {
  579. CleanupShimForApp_Whistler();
  580. }
  581. break;
  582. case WM_COMMAND:
  583. switch (wCode) {
  584. case IDC_RUN:
  585. DoRunApp(hdlg);
  586. break;
  587. case IDC_WIN2K:
  588. g_bWin2k = TRUE;
  589. Restart(hdlg);
  590. break;
  591. case IDC_WHISTLER:
  592. g_bWin2k = FALSE;
  593. Restart(hdlg);
  594. break;
  595. case IDC_BROWSE:
  596. DoBrowseForApp(hdlg);
  597. break;
  598. case IDC_BROWSE_OTHER:
  599. DoBrowseOther(hdlg);
  600. break;
  601. case IDC_DETAILS:
  602. DoDetails(hdlg);
  603. break;
  604. case IDC_ADD_MATCHING:
  605. DoAddMatchingFile(hdlg);
  606. break;
  607. case IDCANCEL:
  608. EndDialog(hdlg, TRUE);
  609. break;
  610. default:
  611. return FALSE;
  612. }
  613. break;
  614. default:
  615. return FALSE;
  616. }
  617. return TRUE;
  618. }
  619. /*********************************************************************
  620. * WinMain
  621. *
  622. *********************************************************************/
  623. int WINAPI
  624. WinMain(
  625. HINSTANCE hInst,
  626. HINSTANCE hInstPrev,
  627. LPSTR lpszCmd,
  628. int swShow)
  629. {
  630. char szShimDB[MAX_PATH];
  631. HANDLE hFile;
  632. InitCommonControls();
  633. g_hInstance = hInst;
  634. // find out if we're on Whistler or not
  635. GetSystemWindowsDirectory(szShimDB, MAX_PATH);
  636. lstrcat(szShimDB, "\\AppPatch\\sysmain.sdb");
  637. hFile = CreateFile(
  638. szShimDB,
  639. GENERIC_READ,
  640. 0,
  641. NULL,
  642. OPEN_EXISTING,
  643. FILE_ATTRIBUTE_NORMAL,
  644. NULL);
  645. if (hFile == INVALID_HANDLE_VALUE) {
  646. LogMsg("Running on Win2k\n");
  647. g_bWin2k = TRUE;
  648. } else {
  649. CloseHandle(hFile);
  650. LogMsg("Running on Whistler\n");
  651. g_bWin2k = FALSE;
  652. }
  653. DialogBox(hInst,
  654. MAKEINTRESOURCE(IDD_DIALOG),
  655. GetDesktopWindow(),
  656. QShimAppDlgProc);
  657. return 1;
  658. }