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.

1347 lines
33 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000
  5. //
  6. // File: xmlwiz.cpp
  7. //
  8. // Contents: code for generating app matching XML
  9. //
  10. // History: ~12-Jan-00 dmunsil created
  11. // 18-Feb-00 dmunsil ver 0.8 -- added changing '&' to "&amp"
  12. //
  13. //---------------------------------------------------------------------------
  14. #include "stdafx.h"
  15. #include "commdlg.h"
  16. #include "stdio.h"
  17. #include "assert.h"
  18. #include "xmlwizres.h"
  19. #include "verread.h"
  20. extern "C" {
  21. #include "shimdb.h"
  22. }
  23. #undef _GATHER_TIME
  24. #define MAX_LINE_LEN 500
  25. #define MAX_NUM_LINES 100
  26. #define MAX_TEXT_BUF 32768
  27. #define MAX_WORKING_BUFFER_SIZE 65536
  28. // Types
  29. typedef struct _MATCH_INFO {
  30. DWORD dwSize;
  31. DWORD dwChecksum;
  32. char szTime[20];
  33. LARGE_INTEGER liBinFileVersion;
  34. LARGE_INTEGER liBinProdVersion;
  35. char szProductName[50];
  36. } MATCH_INFO, *PMATCH_INFO;
  37. // Global Variables:
  38. HINSTANCE g_hInst; // current instance
  39. HWND g_hMainDlg;
  40. char g_szExeName[260];
  41. char g_szExeFullPath[1000];
  42. char g_szParentExeName[260];
  43. char g_szParentExeFullPath[1000];
  44. char g_szEditText[MAX_TEXT_BUF];
  45. char g_aszEditLines[MAX_NUM_LINES][MAX_LINE_LEN];
  46. UINT g_unEditLines;
  47. char g_szAppIndent[] = " "; // 4 spaces
  48. char g_szExeIndent[] = " "; // 8 spaces
  49. char g_szMatchIndent[] = " "; // 12 spaces
  50. char g_szMatchAttributeIndent[] = " "; // 27 spaces
  51. char g_szExeAttributeIndent[] = " "; // 13 spaces
  52. BOOL g_bSelectedParentExe = FALSE;
  53. DWORD g_dwSystemDlls = 0;
  54. HFONT g_hFont;
  55. // Foward declarations of functions included in this code module:
  56. ATOM MyRegisterClass(HINSTANCE hInstance);
  57. BOOL InitInstance(HINSTANCE, int);
  58. LRESULT CALLBACK DlgMain(HWND, UINT, WPARAM, LPARAM);
  59. LRESULT CALLBACK DlgDlls(HWND, UINT, WPARAM, LPARAM);
  60. void GetExeNames(HWND hDlg);
  61. void GetMatchFile(HWND hDlg);
  62. void UnpackEditLines(HWND hDlg);
  63. void PackEditLines(HWND hDlg);
  64. void DeleteLines(UINT unBegin, UINT unLen);
  65. void InsertLine(UINT unLine, char *szLine);
  66. void InsertExeLines(UINT unLine);
  67. BOOL bFindLine(char *szSearch, UINT *punLine);
  68. BOOL bFindLineFrom(char *szSearch, UINT unStart, UINT *punLine);
  69. void InitEditLines(void);
  70. void GetMatchInfo(char *szFile, PMATCH_INFO pMatch);
  71. DWORD GetFileChecksum(HANDLE handle);
  72. char *szGetRelativePath(char *pExeFile, char *pMatchFile);
  73. BOOL bSameDrive(char *szPath1, char *szPath2);
  74. void MySelectAll(HWND hDlg);
  75. void vEnumerateSystemDlls(HWND hDlg);
  76. void vAddSelectedDlls(HWND hDlg);
  77. void vWriteSysTest(void);
  78. char *szConvertSpecialChars(char *szString);
  79. int APIENTRY WinMain(HINSTANCE hInstance,
  80. HINSTANCE hPrevInstance,
  81. LPSTR lpCmdLine,
  82. int nCmdShow)
  83. {
  84. MSG msg;
  85. HACCEL hAccel;
  86. // Perform application initialization:
  87. if (!InitInstance (hInstance, nCmdShow))
  88. {
  89. return FALSE;
  90. }
  91. hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
  92. if (hAccel == NULL)
  93. {
  94. return FALSE;
  95. }
  96. g_hMainDlg = CreateDialog(hInstance, (LPCTSTR)IDD_MAIN, NULL, (DLGPROC)DlgMain);
  97. // Main message loop:
  98. while (GetMessage(&msg, NULL, 0, 0))
  99. {
  100. if (!TranslateAccelerator(g_hMainDlg, hAccel, &msg)) {
  101. TranslateMessage(&msg);
  102. DispatchMessage(&msg);
  103. }
  104. }
  105. return msg.wParam;
  106. }
  107. //
  108. // FUNCTION: InitInstance(HANDLE, int)
  109. //
  110. // PURPOSE: Saves instance handle and creates main window
  111. //
  112. // COMMENTS:
  113. //
  114. // In this function, we save the instance handle in a global variable and
  115. // create and display the main program window.
  116. //
  117. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  118. {
  119. //HWND hWnd;
  120. g_hInst = hInstance; // Store instance handle in our global variable
  121. g_szExeName[0] = '\0';
  122. g_szExeFullPath[0] = '\0';
  123. g_szParentExeName[0] = '\0';
  124. g_szParentExeFullPath[0] = '\0';
  125. InitEditLines();
  126. return TRUE;
  127. }
  128. // Message handler for DLL dialog.
  129. LRESULT CALLBACK DlgDlls(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  130. {
  131. switch (message)
  132. {
  133. case WM_INITDIALOG:
  134. vEnumerateSystemDlls(hDlg);
  135. return TRUE;
  136. break;
  137. case WM_COMMAND:
  138. switch LOWORD(wParam) {
  139. case IDOK:
  140. vAddSelectedDlls(hDlg);
  141. // falls through
  142. case IDCANCEL:
  143. EndDialog(hDlg, LOWORD(wParam));
  144. return TRUE;
  145. break;
  146. }
  147. }
  148. return FALSE;
  149. }
  150. // Message handler for main dialog.
  151. LRESULT CALLBACK DlgMain(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  152. {
  153. HDC hDC;
  154. switch (message)
  155. {
  156. case WM_INITDIALOG:
  157. if (!g_szExeName[0]) {
  158. HWND hBtn;
  159. hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_MATCH);
  160. EnableWindow(hBtn, FALSE);
  161. hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_DLL);
  162. EnableWindow(hBtn, FALSE);
  163. }
  164. // set the edit window to fixed-width font
  165. hDC = GetDC(hDlg);
  166. if (hDC) {
  167. g_hFont = CreateFont(
  168. -MulDiv(9, GetDeviceCaps(hDC, LOGPIXELSY), 72), // 9-pt font
  169. 0,
  170. 0,
  171. 0,
  172. FW_REGULAR,
  173. FALSE,
  174. FALSE,
  175. FALSE,
  176. ANSI_CHARSET,
  177. OUT_DEFAULT_PRECIS,
  178. CLIP_DEFAULT_PRECIS,
  179. ANTIALIASED_QUALITY,
  180. FIXED_PITCH | FF_MODERN,
  181. NULL);
  182. if (g_hFont) {
  183. HWND hEdit = GetDlgItem(hDlg, IDC_EDIT1);
  184. SendMessage(hEdit, WM_SETFONT, (WPARAM)g_hFont, TRUE);
  185. }
  186. ReleaseDC(hDlg, hDC);
  187. }
  188. return TRUE;
  189. break;
  190. case WM_COMMAND:
  191. switch LOWORD(wParam) {
  192. case IDA_SELECT_ALL:
  193. MySelectAll(hDlg);
  194. break;
  195. case IDC_BTN_SET_EXE:
  196. GetExeNames(hDlg);
  197. break;
  198. case IDC_BTN_ADD_MATCH:
  199. GetMatchFile(hDlg);
  200. break;
  201. case IDC_BTN_ADD_DLL:
  202. DialogBox(g_hInst, (LPCTSTR)IDD_DLL_LIST, hDlg, (DLGPROC)DlgDlls);
  203. break;
  204. case IDC_BTN_WRITE_SYSTEST:
  205. vWriteSysTest();
  206. break;
  207. case IDOK:
  208. case IDCANCEL:
  209. EndDialog(hDlg, LOWORD(wParam));
  210. PostQuitMessage(0);
  211. DeleteObject(g_hFont);
  212. return TRUE;
  213. break;
  214. }
  215. }
  216. return FALSE;
  217. }
  218. void GetMatchFile(HWND hDlg)
  219. {
  220. OPENFILENAME ofn;
  221. MATCH_INFO MatchInfo;
  222. char szMatchFile[1000];
  223. char szInitialPath[1000];
  224. char szFileTitle[260];
  225. char szDrive[_MAX_DRIVE];
  226. char szDir[_MAX_DIR];
  227. UINT unLine;
  228. char szTemp[MAX_LINE_LEN];
  229. char szTime[MAX_LINE_LEN];
  230. char szProdVer[MAX_LINE_LEN];
  231. char szFileVer[MAX_LINE_LEN];
  232. char szProdName[MAX_LINE_LEN];
  233. char *szMatch;
  234. szMatchFile[0] = '\0';
  235. szFileTitle[0] = '\0';
  236. szInitialPath[0] = '\0';
  237. if (g_szParentExeFullPath[0]) {
  238. _splitpath(g_szParentExeFullPath, szDrive, szDir, NULL, NULL);
  239. strcpy(szInitialPath, szDrive);
  240. strcat(szInitialPath, szDir);
  241. }
  242. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  243. ofn.lStructSize = sizeof(OPENFILENAME);
  244. ofn.hwndOwner = hDlg;
  245. ofn.lpstrFile = szMatchFile;
  246. ofn.nMaxFile = sizeof(szMatchFile);
  247. ofn.lpstrFilter = "All\0*.*\0Exe\0*.EXE\0";
  248. ofn.nFilterIndex = 1;
  249. ofn.lpstrFileTitle = szFileTitle;
  250. ofn.nMaxFileTitle = sizeof(szFileTitle);
  251. ofn.lpstrInitialDir = szInitialPath;
  252. ofn.lpstrTitle = "Select Matching File";
  253. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS;
  254. // get the matching file name
  255. if (GetOpenFileName(&ofn) == FALSE) {
  256. goto err1;
  257. }
  258. // get the lines out of the edit dialog
  259. UnpackEditLines(hDlg);
  260. // check if we need to get an parent exe
  261. if (!bSameDrive(szMatchFile, g_szParentExeFullPath) && !g_bSelectedParentExe) {
  262. char szParentFile[1000];
  263. // get the parent exe
  264. szParentFile[0] = '\0';
  265. szInitialPath[0] = '\0';
  266. if (szMatchFile[0]) {
  267. _splitpath(szMatchFile, szDrive, szDir, NULL, NULL);
  268. strcpy(szInitialPath, szDrive);
  269. strcat(szInitialPath, szDir);
  270. }
  271. // most of ofn is already filled-in
  272. ofn.lpstrTitle = "Select Parent Exe";
  273. ofn.lpstrFile = szParentFile;
  274. ofn.nMaxFile = sizeof(szParentFile);
  275. if (GetOpenFileName(&ofn) == TRUE) {
  276. strcpy(g_szParentExeName, szFileTitle);
  277. strcpy(g_szParentExeFullPath, szParentFile);
  278. g_bSelectedParentExe = TRUE;
  279. // delete any previous parent exe comments
  280. while (bFindLine("<!-- Parent exe", &unLine)) {
  281. DeleteLines(unLine, 1);
  282. }
  283. // reconstruct the EXE if necessary
  284. if (!bFindLine("<EXE", &unLine)) {
  285. // insert it right after <APP> or at the beginning
  286. if (bFindLine("<APP", &unLine)) {
  287. unLine += 1;
  288. } else {
  289. unLine = 0;
  290. }
  291. InsertExeLines(unLine);
  292. }
  293. // if the parent exe is different, insert a comment
  294. if (strcmp(g_szExeFullPath, g_szParentExeFullPath) != 0) {
  295. char *szPathWithoutDrive = g_szParentExeFullPath + 2;
  296. if (bSameDrive(g_szExeFullPath, g_szParentExeFullPath)) {
  297. sprintf(szTemp, "%s<!-- Parent exe \"%s\" on same drive.-->", g_szMatchIndent, szPathWithoutDrive);
  298. } else {
  299. sprintf(szTemp, "%s<!-- Parent exe \"%s\" on different drive.-->", g_szMatchIndent, szPathWithoutDrive);
  300. }
  301. if (bFindLine("<EXE", &unLine)) {
  302. if (bFindLineFrom(">", unLine, &unLine)) {
  303. InsertLine(unLine + 1, szTemp);
  304. }
  305. }
  306. }
  307. }
  308. }
  309. // check the drive letters to see which drive the match file is on
  310. // then calculate a relative path to the matching file
  311. if (bSameDrive(szMatchFile, g_szParentExeFullPath)) {
  312. szMatch = szGetRelativePath(g_szParentExeFullPath, szMatchFile);
  313. } else if (bSameDrive(szMatchFile, g_szExeFullPath)) {
  314. szMatch = szGetRelativePath(g_szExeFullPath, szMatchFile);
  315. } else {
  316. MessageBox(hDlg, "Match file is not on same drive as either EXE or Parent EXE. "
  317. "Can't generate relative path.", "Error", MB_ICONEXCLAMATION);
  318. goto err2;
  319. }
  320. // reconstruct the EXE if necessary
  321. if (!bFindLine("<EXE", &unLine)) {
  322. // insert it right after <APP> or at the beginning
  323. if (!bFindLine("<APP", &unLine)) {
  324. unLine = 0;
  325. } else {
  326. unLine += 1;
  327. }
  328. InsertExeLines(unLine);
  329. }
  330. // find the </EXE> line and insert if necessary
  331. if (!bFindLine("</EXE>", &unLine)) {
  332. if (!bFindLine("</APP>", &unLine)) {
  333. unLine = g_unEditLines + 1;
  334. }
  335. sprintf(szTemp, "%s</EXE>", g_szExeIndent);
  336. InsertLine(unLine, szTemp);
  337. }
  338. GetMatchInfo(szMatchFile, &MatchInfo);
  339. // now insert the line right before </EXE>
  340. #ifdef _SPLIT_LINES
  341. sprintf(szTemp, "%s<MATCHING_FILE NAME=\"%s\"",
  342. g_szMatchIndent,
  343. szMatch
  344. );
  345. InsertLine(unLine++, szTemp);
  346. sprintf(szTemp, "%sSIZE=\"%u\"",
  347. g_szMatchAttributeIndent,
  348. MatchInfo.dwSize
  349. );
  350. InsertLine(unLine++, szTemp);
  351. sprintf(szTemp, "%sCHECKSUM=\"0x%8.8X\"",
  352. g_szMatchAttributeIndent,
  353. MatchInfo.dwChecksum
  354. );
  355. InsertLine(unLine++, szTemp);
  356. sprintf(szTemp, "%sTIME=\"%s\"",
  357. g_szMatchAttributeIndent,
  358. MatchInfo.szTime
  359. );
  360. InsertLine(unLine++, szTemp);
  361. sprintf(szTemp, "%s/>",
  362. g_szMatchIndent
  363. );
  364. InsertLine(unLine++, szTemp);
  365. #else
  366. if (MatchInfo.szTime[0] != 0) {
  367. sprintf(szTime, " TIME=\"%s\"", MatchInfo.szTime);
  368. } else {
  369. szTime[0] = 0;
  370. }
  371. if (MatchInfo.liBinFileVersion.QuadPart) {
  372. sprintf(szFileVer, " BIN_FILE_VERSION=\"%d.%d.%d.%d\"",
  373. HIWORD(MatchInfo.liBinFileVersion.HighPart),
  374. LOWORD(MatchInfo.liBinFileVersion.HighPart),
  375. HIWORD(MatchInfo.liBinFileVersion.LowPart),
  376. LOWORD(MatchInfo.liBinFileVersion.LowPart));
  377. } else {
  378. szFileVer[0] = 0;
  379. }
  380. if (MatchInfo.liBinProdVersion.QuadPart) {
  381. sprintf(szProdVer, " BIN_PRODUCT_VERSION=\"%d.%d.%d.%d\"",
  382. HIWORD(MatchInfo.liBinProdVersion.HighPart),
  383. LOWORD(MatchInfo.liBinProdVersion.HighPart),
  384. HIWORD(MatchInfo.liBinProdVersion.LowPart),
  385. LOWORD(MatchInfo.liBinProdVersion.LowPart));
  386. } else {
  387. szProdVer[0] = 0;
  388. }
  389. if (MatchInfo.szProductName[0]) {
  390. sprintf(szProdName, " PRODUCT_NAME=\"%s\"", MatchInfo.szProductName);
  391. } else {
  392. szProdName[0] = 0;
  393. }
  394. sprintf(szTemp, "%s<MATCHING_FILE NAME=\"%s\" SIZE=\"%u\" CHECKSUM=\"0x%8.8X\"%s%s%s%s/>",
  395. g_szMatchIndent,
  396. szMatch,
  397. MatchInfo.dwSize,
  398. MatchInfo.dwChecksum,
  399. szTime,
  400. szFileVer,
  401. szProdVer,
  402. szProdName
  403. );
  404. InsertLine(unLine, szTemp);
  405. #endif
  406. err2:
  407. // put them back into the dialog
  408. PackEditLines(hDlg);
  409. err1:
  410. return;
  411. }
  412. void GetExeNames(HWND hDlg)
  413. {
  414. OPENFILENAME ofn;
  415. char szFile[1000];
  416. char szFileTitle[260];
  417. HWND hBtn;
  418. char szTemp[MAX_LINE_LEN];
  419. szFile[0] = '\0';
  420. szFileTitle[0] = '\0';
  421. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  422. ofn.lStructSize = sizeof(OPENFILENAME);
  423. ofn.hwndOwner = hDlg;
  424. ofn.lpstrFile = szFile;
  425. ofn.nMaxFile = sizeof(szFile);
  426. ofn.lpstrFilter = "All\0*.*\0Exe\0*.EXE\0";
  427. ofn.nFilterIndex = 1;
  428. ofn.lpstrFileTitle = szFileTitle;
  429. ofn.nMaxFileTitle = sizeof(szFileTitle);
  430. ofn.lpstrInitialDir = NULL;
  431. ofn.lpstrTitle = "Select Exe to Shim";
  432. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS;
  433. // get the main exe name
  434. if (GetOpenFileName(&ofn) == FALSE) {
  435. return;
  436. }
  437. strcpy(g_szExeName, szFileTitle);
  438. strcpy(g_szExeFullPath, szFile);
  439. // the parent exe defaults to the same as the EXE
  440. strcpy(g_szParentExeName, szFileTitle);
  441. strcpy(g_szParentExeFullPath, szFile);
  442. g_bSelectedParentExe = FALSE;
  443. // construct our new dialog text
  444. InitEditLines();
  445. sprintf(szTemp, "%s<APP NAME=\"\" VENDOR=\"\">", g_szAppIndent);
  446. InsertLine(0, szTemp);
  447. InsertExeLines(1);
  448. sprintf(szTemp, "%s</EXE>", g_szExeIndent);
  449. InsertLine(999, szTemp);
  450. sprintf(szTemp, "%s</APP>", g_szAppIndent);
  451. InsertLine(999, szTemp);
  452. // stick it in the dialog box
  453. PackEditLines(hDlg);
  454. hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_MATCH);
  455. EnableWindow(hBtn, TRUE);
  456. hBtn = GetDlgItem(hDlg, IDC_BTN_ADD_DLL);
  457. EnableWindow(hBtn, TRUE);
  458. }
  459. #define SECS_IN_DAY 86400
  460. #define HUNDRED_NSECS_IN_SEC 10000000
  461. void GetMatchInfo(char *szFile, PMATCH_INFO pMatch)
  462. {
  463. HANDLE hFile;
  464. FILETIME ft;
  465. SYSTEMTIME st;
  466. ZeroMemory(pMatch, sizeof(MATCH_INFO));
  467. hFile = CreateFile(
  468. szFile,
  469. GENERIC_READ,
  470. FILE_SHARE_READ,
  471. NULL,
  472. OPEN_EXISTING,
  473. FILE_ATTRIBUTE_NORMAL,
  474. NULL);
  475. if (hFile != INVALID_HANDLE_VALUE ) {
  476. DWORD dwAttributes;
  477. pMatch->dwSize = GetFileSize(hFile, NULL);
  478. pMatch->dwChecksum = GetFileChecksum(hFile);
  479. pMatch->szTime[0] = 0;
  480. #ifdef _GATHER_TIME
  481. // only get the time if the file is not read only, and the date is
  482. // not within 2 days of today
  483. dwAttributes = GetFileAttributes(szFile);
  484. if (dwAttributes != -1 && (dwAttributes & FILE_ATTRIBUTE_READONLY)) {
  485. SYSTEMTIME stMachine;
  486. FILETIME ftMachine;
  487. DWORD dwDayFile;
  488. DWORD dwDayMachine;
  489. LARGE_INTEGER liFile;
  490. LARGE_INTEGER liMachine;
  491. LARGE_INTEGER liDifference;
  492. GetFileTime(hFile, &ft, NULL, NULL);
  493. FileTimeToSystemTime(&ft, &st);
  494. GetSystemTime(&stMachine);
  495. SystemTimeToFileTime(&stMachine, &ftMachine);
  496. liFile.LowPart = ft.dwLowDateTime;
  497. liFile.HighPart = ft.dwHighDateTime;
  498. liMachine.LowPart = ftMachine.dwLowDateTime;
  499. liMachine.HighPart = ftMachine.dwHighDateTime;
  500. liDifference.QuadPart = liMachine.QuadPart - liFile.QuadPart;
  501. // this goofy math is because I can't specify more than a 32-bit
  502. // value as a constant in this compiler
  503. if ((liDifference.QuadPart / HUNDRED_NSECS_IN_SEC) > SECS_IN_DAY * 2) {
  504. sprintf(pMatch->szTime, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d",
  505. st.wMonth,
  506. st.wDay,
  507. st.wYear,
  508. st.wHour,
  509. st.wMinute,
  510. st.wSecond);
  511. }
  512. }
  513. #endif
  514. CloseHandle(hFile);
  515. // now get resource info
  516. VERSION_DATA VersionData;
  517. if (bInitVersionData(szFile, &VersionData)) {
  518. char *szProductName = NULL;
  519. pMatch->liBinFileVersion.QuadPart = qwGetBinFileVer(&VersionData);
  520. pMatch->liBinProdVersion.QuadPart = qwGetBinProdVer(&VersionData);
  521. #if 0
  522. szProductName = szGetVersionString(&VersionData, "ProductName");
  523. if (szProductName) {
  524. int nLen;
  525. nLen = sizeof(pMatch->szProductName) - 1;
  526. strncpy(pMatch->szProductName, szProductName, nLen);
  527. pMatch->szProductName[nLen] = 0;
  528. }
  529. #endif
  530. vReleaseVersionData(&VersionData);
  531. }
  532. } else {
  533. MessageBox(NULL, "Can't open match file for READ. Matching info inaccurate.",
  534. "Error", MB_ICONEXCLAMATION);
  535. pMatch->dwSize = 0;
  536. pMatch->dwChecksum = 0xDEADBEEF;
  537. pMatch->szTime[0] = 0;
  538. }
  539. }
  540. void InitEditLines(void)
  541. {
  542. g_unEditLines = 0;
  543. }
  544. void UnpackEditLines(HWND hDlg)
  545. {
  546. char *szTemp, *szBegin;
  547. GetDlgItemText(hDlg, IDC_EDIT1, g_szEditText, MAX_TEXT_BUF - 1);
  548. szBegin = g_szEditText;
  549. g_unEditLines = 0;
  550. if (!szBegin[0]) {
  551. return;
  552. }
  553. while (szTemp = strstr(szBegin, "\r\n")) {
  554. // temporarily terminate the string and copy
  555. *szTemp = '\0';
  556. strcpy(g_aszEditLines[g_unEditLines], szBegin);
  557. g_unEditLines++;
  558. // back to normal
  559. *szTemp = '\r';
  560. szBegin = szTemp + 2;
  561. }
  562. // copy in the final line, if any
  563. if (szBegin[0]) {
  564. strcpy(g_aszEditLines[g_unEditLines], szBegin);
  565. g_unEditLines++;
  566. }
  567. }
  568. void PackEditLines(HWND hDlg)
  569. {
  570. UINT i;
  571. char *szTemp = g_szEditText;
  572. HWND hEdit = GetDlgItem(hDlg, IDC_EDIT1);
  573. for (i = 0; i < g_unEditLines; ++i) {
  574. int nLen = strlen(g_aszEditLines[i]);
  575. memcpy(szTemp, g_aszEditLines[i], nLen);
  576. szTemp += nLen;
  577. memcpy(szTemp, "\r\n", 2 * sizeof(char));
  578. szTemp += 2;
  579. }
  580. *szTemp = '\0';
  581. SetDlgItemText(hDlg, IDC_EDIT1, g_szEditText);
  582. SendMessage(hEdit, EM_SETSEL, 0, -1); // select everything
  583. SetFocus(hEdit);
  584. }
  585. void MySelectAll(HWND hDlg)
  586. {
  587. HWND hEdit = GetDlgItem(hDlg, IDC_EDIT1);
  588. SendMessage(hEdit, EM_SETSEL, 0, -1); // select everything
  589. SetFocus(hEdit);
  590. }
  591. void DeleteLines(UINT unBegin, UINT unLen)
  592. {
  593. UINT unEnd = unBegin + unLen;
  594. if (unBegin > g_unEditLines) {
  595. return;
  596. }
  597. if (unEnd > g_unEditLines) {
  598. unEnd = g_unEditLines;
  599. }
  600. while (unEnd < g_unEditLines) {
  601. strcpy(g_aszEditLines[unBegin++], g_aszEditLines[unEnd++]);
  602. }
  603. g_unEditLines -= unLen;
  604. }
  605. void InsertLine(UINT unLine, char *szLine)
  606. {
  607. UINT unTemp;
  608. if (unLine > g_unEditLines) {
  609. unLine = g_unEditLines;
  610. }
  611. unTemp = g_unEditLines;
  612. while (unTemp != unLine) {
  613. strcpy(g_aszEditLines[unTemp], g_aszEditLines[unTemp - 1]);
  614. unTemp--;
  615. }
  616. strcpy(g_aszEditLines[unLine], szConvertSpecialChars(szLine));
  617. g_unEditLines++;
  618. }
  619. void InsertExeLines(UINT unLine)
  620. {
  621. char szTemp[MAX_LINE_LEN];
  622. MATCH_INFO MatchInfo;
  623. char szTime[MAX_LINE_LEN];
  624. char szProdVer[MAX_LINE_LEN];
  625. char szFileVer[MAX_LINE_LEN];
  626. GetMatchInfo(g_szExeFullPath, &MatchInfo);
  627. #ifdef _SPLIT_LINES
  628. sprintf(szTemp, "%s<EXE NAME=\"%s\"",
  629. g_szExeIndent,
  630. g_szExeName
  631. );
  632. InsertLine(unLine++, szTemp);
  633. sprintf(szTemp, "%sSIZE=\"%u\"",
  634. g_szExeAttributeIndent,
  635. MatchInfo.dwSize
  636. );
  637. InsertLine(unLine++, szTemp);
  638. sprintf(szTemp, "%sCHECKSUM=\"0x%8.8X\"",
  639. g_szExeAttributeIndent,
  640. MatchInfo.dwChecksum
  641. );
  642. InsertLine(unLine++, szTemp);
  643. if (MatchInfo.szTime[0] != 0) {
  644. sprintf(szTemp, "%sTIME=\"%s\"",
  645. g_szExeAttributeIndent,
  646. MatchInfo.szTime
  647. );
  648. InsertLine(unLine++, szTemp);
  649. }
  650. sprintf(szTemp, "%s>",
  651. g_szExeIndent
  652. );
  653. InsertLine(unLine++, szTemp);
  654. #else
  655. if (MatchInfo.szTime[0] != 0) {
  656. sprintf(szTime, " TIME=\"%s\"", MatchInfo.szTime);
  657. } else {
  658. szTime[0] = 0;
  659. }
  660. if (MatchInfo.liBinFileVersion.QuadPart) {
  661. sprintf(szFileVer, " BIN_FILE_VERSION=\"%d.%d.%d.%d\"",
  662. HIWORD(MatchInfo.liBinFileVersion.HighPart),
  663. LOWORD(MatchInfo.liBinFileVersion.HighPart),
  664. HIWORD(MatchInfo.liBinFileVersion.LowPart),
  665. LOWORD(MatchInfo.liBinFileVersion.LowPart));
  666. } else {
  667. szFileVer[0] = 0;
  668. }
  669. if (MatchInfo.liBinProdVersion.QuadPart) {
  670. sprintf(szProdVer, " BIN_PRODUCT_VERSION=\"%d.%d.%d.%d\"",
  671. HIWORD(MatchInfo.liBinProdVersion.HighPart),
  672. LOWORD(MatchInfo.liBinProdVersion.HighPart),
  673. HIWORD(MatchInfo.liBinProdVersion.LowPart),
  674. LOWORD(MatchInfo.liBinProdVersion.LowPart));
  675. } else {
  676. szProdVer[0] = 0;
  677. }
  678. sprintf(szTemp, "%s<EXE NAME=\"%s\" SIZE=\"%u\" CHECKSUM=\"0x%8.8X\"%s%s%s>",
  679. g_szExeIndent,
  680. g_szExeName,
  681. MatchInfo.dwSize,
  682. MatchInfo.dwChecksum,
  683. szTime,
  684. szFileVer,
  685. szProdVer
  686. );
  687. InsertLine(unLine, szTemp);
  688. #endif
  689. }
  690. BOOL bFindLine(char *szSearch, UINT *punLine)
  691. {
  692. UINT i;
  693. for (i = 0; i < g_unEditLines; ++i) {
  694. if (g_aszEditLines[i][0] && strstr(g_aszEditLines[i], szSearch)) {
  695. *punLine = i;
  696. return TRUE;
  697. }
  698. }
  699. return FALSE;
  700. }
  701. BOOL bFindLineFrom(char *szSearch, UINT unStart, UINT *punLine)
  702. {
  703. UINT i;
  704. for (i = unStart; i < g_unEditLines; ++i) {
  705. if (g_aszEditLines[i][0] && strstr(g_aszEditLines[i], szSearch)) {
  706. *punLine = i;
  707. return TRUE;
  708. }
  709. }
  710. return FALSE;
  711. }
  712. char *szGetRelativePath(char *pExeFile, char *pMatchFile)
  713. {
  714. int iLenp = 0;
  715. int iLenq = 0;
  716. //int index = 0;
  717. BOOL bCommonBegin = FALSE; // do the two paths have a common beginning
  718. char *p = NULL;
  719. char *q = NULL;
  720. // BUGBUG -- if you call this function twice in a row
  721. // without copying the result, the second call will overwrite
  722. // the first -- consider changing to a passed-in string
  723. //
  724. static char result[MAX_PATH] = { '\0' };
  725. char *resultIdx = result;
  726. p = strchr(pExeFile, '\\');
  727. q = strchr(pMatchFile, '\\');
  728. while( p && q )
  729. {
  730. iLenp = p - pExeFile;
  731. iLenq = q - pMatchFile;
  732. if ( iLenp != iLenq )
  733. break;
  734. if ( !(_strnicmp(pExeFile, pMatchFile, iLenp) == 0) )
  735. break;
  736. bCommonBegin = TRUE;
  737. pExeFile = p + 1;
  738. pMatchFile = q + 1;
  739. p = strchr(pExeFile, '\\');
  740. q = strchr(pMatchFile, '\\');
  741. }
  742. if (bCommonBegin)
  743. {
  744. while( p )
  745. {
  746. strcpy(resultIdx, "..\\");
  747. resultIdx = resultIdx + 3;
  748. pExeFile = p + 1;
  749. p = strchr(pExeFile, '\\');
  750. }
  751. strcpy(resultIdx, pMatchFile);
  752. return result;
  753. }
  754. // the two paths don't have a common beginning,
  755. // and there is no relative path
  756. return NULL;
  757. }
  758. BOOL bSameDrive(char *szPath1, char *szPath2)
  759. {
  760. char szDrive1[256];
  761. char szDrive2[256];
  762. char *szTemp1, *szTemp2;
  763. BOOL bReturn = FALSE;
  764. assert(szPath1 && szPath1[0] && szPath2 && szPath2[0]);
  765. if (szPath1[1] != szPath2[1]) {
  766. // if the 2nd characters don't match, then one
  767. // is a DOS style path and the other is UNC,
  768. // and we're definitely not on the same drive
  769. goto out;
  770. }
  771. if (szPath1[1] == ':') {
  772. // these are both DOS-style paths
  773. if (szPath1[0] == szPath2[0]) {
  774. // if the first characters match, it's the same drive
  775. bReturn = TRUE;
  776. }
  777. goto out;
  778. }
  779. // now we're sure we have two UNC-style paths
  780. // skip past the "\\"
  781. szTemp1 = szPath1 + 2;
  782. szTemp2 = szPath2 + 2;
  783. // skip to the next '\'
  784. szTemp1 = strchr(szTemp1, '\\');
  785. szTemp2 = strchr(szTemp2, '\\');
  786. // if we didn't find another backslash, bail
  787. if (!szTemp1 || !szTemp2) {
  788. goto out;
  789. }
  790. // skip to the next '\' again
  791. szTemp1++;
  792. szTemp2++;
  793. szTemp1 = strchr(szTemp1, '\\');
  794. szTemp2 = strchr(szTemp2, '\\');
  795. // if we didn't find another backslash, bail
  796. if (!szTemp1 || !szTemp2) {
  797. goto out;
  798. }
  799. // are they different sizes?
  800. if (szTemp1 - szPath1 != szTemp2 - szPath2) {
  801. goto out;
  802. }
  803. // they're the same size, are they the same string?
  804. if (memcmp(szPath1, szPath2, szTemp1-szPath1) == 0) {
  805. bReturn = TRUE;
  806. }
  807. out:
  808. return bReturn;
  809. }
  810. #define CHECKSUM_SIZE 4096
  811. #define CHECKSUM_OFFSET 512
  812. #define CHECKSUM_BUFFER (CHECKSUM_SIZE+CHECKSUM_OFFSET)
  813. DWORD GetFileChecksum(HANDLE handle)
  814. {
  815. PBYTE pBuffer;
  816. DWORD dwCheckSum;
  817. DWORD dwBytesRead;
  818. DWORD dwReadSize;
  819. dwCheckSum = 0;
  820. dwReadSize = GetFileSize(handle,
  821. NULL);
  822. if ( dwReadSize > CHECKSUM_BUFFER ) {
  823. dwReadSize = CHECKSUM_BUFFER;
  824. }
  825. pBuffer = new BYTE[dwReadSize];
  826. if ( !pBuffer ) {
  827. dwCheckSum = 0xDEADBEEF;
  828. goto err1;
  829. }
  830. SetFilePointer(handle,
  831. 0L,
  832. NULL,
  833. FILE_BEGIN);
  834. ZeroMemory(pBuffer, dwReadSize);
  835. //
  836. // We can get away with this since if the read fails then the check sum will also fail.
  837. //
  838. if ( !ReadFile(handle, (PBYTE)pBuffer, dwReadSize, &dwBytesRead, NULL) ) {
  839. dwCheckSum = 0xDEADBEEF;
  840. goto err2;
  841. }
  842. {
  843. INT i,size = CHECKSUM_SIZE;
  844. DWORD startAddr = CHECKSUM_OFFSET;
  845. PBYTE pTemp = pBuffer;
  846. if (dwBytesRead < (ULONG)size) {
  847. //
  848. // File size is less than 4096. We set the start address to 0 and set the size for the checksum
  849. // to the actual file size.
  850. //
  851. startAddr = 0;
  852. size = dwBytesRead;
  853. } else if (startAddr + size > dwBytesRead) {
  854. //
  855. // File size is too small. We set the start address so that size of checksum can be 4096 bytes
  856. //
  857. startAddr = dwBytesRead - size;
  858. }
  859. if (size < 4) {
  860. //
  861. // we need at least 4 bytes to be able to do something here.
  862. //
  863. dwCheckSum = 0;
  864. goto err2;
  865. }
  866. // start at the offset
  867. pTemp = pTemp + startAddr;
  868. // walk through adding in DWORDs and rotating the result to guard against
  869. // transposition
  870. for (i = 0; i < (size - 3); i += 4) {
  871. dwCheckSum += *((PDWORD) (pTemp + i));
  872. dwCheckSum = _rotr (dwCheckSum, 1);
  873. }
  874. }
  875. err2:
  876. delete [] pBuffer;
  877. err1:
  878. return dwCheckSum;
  879. }
  880. void vWriteSysTest(void)
  881. {
  882. char szHeader[] = "<?xml version=\"1.0\"?>\r\n<DATABASE>\r\n";
  883. char szTrailer[] = "\r\n</DATABASE>\r\n";
  884. char szCommand[_MAX_PATH * 3];
  885. char szSDBPath[_MAX_PATH];
  886. char szXMLPath[_MAX_PATH];
  887. char szLOGPath[_MAX_PATH];
  888. DWORD dwBytesWritten = 0;
  889. BOOL bRet;
  890. PROCESS_INFORMATION ProcInfo;
  891. STARTUPINFO si;
  892. GetDlgItemText(g_hMainDlg, IDC_EDIT1, g_szEditText, MAX_TEXT_BUF - 1);
  893. ExpandEnvironmentStrings("%windir%\\AppPatch\\systest.xml", szXMLPath, _MAX_PATH);
  894. ExpandEnvironmentStrings("%windir%\\AppPatch\\systest.sdb", szSDBPath, _MAX_PATH);
  895. ExpandEnvironmentStrings("%windir%\\AppPatch\\systest.log", szLOGPath, _MAX_PATH);
  896. HANDLE hFile = CreateFile(
  897. szXMLPath,
  898. GENERIC_WRITE,
  899. 0,
  900. NULL,
  901. CREATE_ALWAYS,
  902. FILE_ATTRIBUTE_NORMAL,
  903. NULL);
  904. if (hFile == INVALID_HANDLE_VALUE) {
  905. goto out;
  906. }
  907. if (!WriteFile(hFile, szHeader, sizeof(szHeader) - 1, &dwBytesWritten, NULL)) {
  908. goto out;
  909. }
  910. if (!WriteFile(hFile, g_szEditText, strlen(g_szEditText), &dwBytesWritten, NULL)) {
  911. goto out;
  912. }
  913. if (!WriteFile(hFile, szTrailer, sizeof(szTrailer) - 1, &dwBytesWritten, NULL)) {
  914. goto out;
  915. }
  916. CloseHandle(hFile);
  917. hFile = INVALID_HANDLE_VALUE;
  918. // Set up the start up info struct.
  919. ZeroMemory(&si,sizeof(STARTUPINFO));
  920. si.cb = sizeof(STARTUPINFO);
  921. ZeroMemory(&ProcInfo, sizeof(PROCESS_INFORMATION));
  922. sprintf(szCommand, "cmd /c shimdbc fix \"%s\" \"%s\" > \"%s\"", szXMLPath, szSDBPath, szLOGPath);
  923. bRet = CreateProcess(NULL,
  924. szCommand,
  925. NULL,
  926. NULL,
  927. FALSE,
  928. CREATE_NO_WINDOW,
  929. NULL,
  930. NULL,
  931. &si,
  932. &ProcInfo);
  933. if (!bRet) {
  934. MessageBox(g_hMainDlg, "Couldn't launch shimdbc to generate systest.sdb. Check systest.log for more.", "Error", MB_ICONEXCLAMATION);
  935. goto out;
  936. }
  937. if (WaitForSingleObject(ProcInfo.hProcess, 10000) == WAIT_OBJECT_0) {
  938. // wait a bit to ensure everything is all done, and the .SDB file is done closing.
  939. Sleep(100);
  940. // Set up the start up info struct.
  941. ZeroMemory(&si,sizeof(STARTUPINFO));
  942. si.cb = sizeof(STARTUPINFO);
  943. ZeroMemory(&ProcInfo, sizeof(PROCESS_INFORMATION));
  944. // pop open notepad to see the log
  945. sprintf(szCommand, "notepad \"%s\"", szLOGPath);
  946. bRet = CreateProcess(NULL,
  947. szCommand,
  948. NULL,
  949. NULL,
  950. FALSE,
  951. 0,
  952. NULL,
  953. NULL,
  954. &si,
  955. &ProcInfo);
  956. }
  957. out:
  958. if (hFile != INVALID_HANDLE_VALUE) {
  959. CloseHandle(hFile);
  960. }
  961. }
  962. void vEnumerateSystemDlls(HWND hDlg)
  963. {
  964. PDB pdb = NULL;
  965. WCHAR wszPath[_MAX_PATH];
  966. HWND hList;
  967. TAGID tiDatabase;
  968. TAGID tiLibrary;
  969. TAGID tiDll;
  970. hList = GetDlgItem(hDlg, IDC_DLL_LIST);
  971. if (!hList) {
  972. goto out;
  973. }
  974. g_dwSystemDlls = 0;
  975. ExpandEnvironmentStringsW(L"%windir%\\AppPatch\\sysmain.sdb", wszPath, _MAX_PATH);
  976. pdb = SdbOpenDatabase(wszPath, DOS_PATH);
  977. if (!pdb) {
  978. goto out;
  979. }
  980. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  981. if (!tiDatabase) {
  982. goto out;
  983. }
  984. tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
  985. if (!tiLibrary) {
  986. goto out;
  987. }
  988. tiDll = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM);
  989. while (tiDll) {
  990. TAGID tiName;
  991. WCHAR wszName[_MAX_PATH];
  992. wszName[0] = 0;
  993. tiName = SdbFindFirstTag(pdb, tiDll, TAG_NAME);
  994. if (tiName) {
  995. SdbReadStringTag(pdb, tiName, wszName, _MAX_PATH * sizeof(WCHAR));
  996. }
  997. if (wszName[0]) {
  998. char szName[_MAX_PATH];
  999. sprintf(szName, "%S", wszName);
  1000. SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)szName);
  1001. g_dwSystemDlls++;
  1002. }
  1003. tiDll = SdbFindNextTag(pdb, tiLibrary, tiDll);
  1004. }
  1005. out:
  1006. if (pdb) {
  1007. SdbCloseDatabase(pdb);
  1008. }
  1009. }
  1010. void vAddSelectedDlls(HWND hDlg)
  1011. {
  1012. HWND hList;
  1013. DWORD *pdwItems = new DWORD[g_dwSystemDlls];
  1014. DWORD dwItems = 0;
  1015. DWORD i;
  1016. UINT unLine;
  1017. char szTemp[MAX_LINE_LEN];
  1018. if (!pdwItems) {
  1019. goto out;
  1020. }
  1021. hList = GetDlgItem(hDlg, IDC_DLL_LIST);
  1022. if (!hList) {
  1023. goto out;
  1024. }
  1025. UnpackEditLines(g_hMainDlg);
  1026. // find the </EXE> line and insert if necessary
  1027. if (!bFindLine("</EXE>", &unLine)) {
  1028. if (!bFindLine("</APP>", &unLine)) {
  1029. unLine = g_unEditLines + 1;
  1030. }
  1031. sprintf(szTemp, "%s</EXE>", g_szExeIndent);
  1032. InsertLine(unLine, szTemp);
  1033. }
  1034. dwItems = SendMessage(hList, LB_GETSELITEMS, g_dwSystemDlls, (LPARAM)pdwItems);
  1035. for (i = 0; i < dwItems; ++i) {
  1036. char szName[_MAX_PATH];
  1037. szName[0] = 0;
  1038. SendMessage(hList, LB_GETTEXT, pdwItems[i], (LPARAM)szName);
  1039. if (szName[0]) {
  1040. sprintf(szTemp, "%s<DLL NAME=\"%s\"/>", g_szMatchIndent, szName);
  1041. InsertLine(unLine, szTemp);
  1042. }
  1043. }
  1044. PackEditLines(g_hMainDlg);
  1045. out:
  1046. return;
  1047. }
  1048. /*
  1049. Does an in-place expansion of special characters for XML into the equivalents.
  1050. Specifically, converts '&' to '&amp'.
  1051. */
  1052. char *szConvertSpecialChars(char *szString)
  1053. {
  1054. char *szPtr;
  1055. char *szEnd;
  1056. assert(szString);
  1057. szPtr = szString;
  1058. szEnd = szString;
  1059. while (*szEnd) {
  1060. szEnd++;
  1061. }
  1062. szEnd++; // now points one past end
  1063. //
  1064. // now go looking for ampersands
  1065. //
  1066. while (*szPtr) {
  1067. if (*szPtr == '&') {
  1068. memmove(szPtr + 3, szPtr, szEnd-szPtr);
  1069. memcpy(szPtr, "&amp", 4);
  1070. szPtr += 3;
  1071. szEnd += 3;
  1072. }
  1073. szPtr++;
  1074. }
  1075. return szString;
  1076. }