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.

1680 lines
44 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. dbSupport.cpp
  5. Abstract:
  6. Contains code that allows us to read/create SDBs.
  7. Notes:
  8. ANSI & Unicode via TCHAR - runs on NT/2K/XP etc.
  9. History:
  10. 02/16/00 clupu Created
  11. 02/20/02 rparsons Implemented strsafe functions
  12. --*/
  13. #include "windows.h"
  14. #include "commctrl.h"
  15. #include "shlwapi.h"
  16. #include <tchar.h>
  17. #include "qfixapp.h"
  18. #include "dbSupport.h"
  19. #include "resource.h"
  20. #include <strsafe.h>
  21. #define _WANT_TAG_INFO
  22. extern "C" {
  23. #include "shimdb.h"
  24. BOOL
  25. ShimdbcExecute(
  26. LPCWSTR lpszCmdLine
  27. );
  28. }
  29. extern HINSTANCE g_hInstance;
  30. extern HWND g_hDlg;
  31. extern TCHAR g_szSDBToDelete[MAX_PATH];
  32. extern BOOL g_bSDBInstalled;
  33. extern TCHAR g_szAppTitle[64];
  34. extern TCHAR g_szWinDir[MAX_PATH];
  35. extern TCHAR g_szSysDir[MAX_PATH];
  36. #define MAX_CMD_LINE 1024
  37. #define MAX_SHIM_DESCRIPTION 1024
  38. #define MAX_SHIM_NAME 128
  39. #define MAX_BUFFER_SIZE 1024
  40. #define SHIM_FILE_LOG_NAME _T("QFixApp.log")
  41. // Temp buffer to read UNICODE strings from the database.
  42. TCHAR g_szData[MAX_BUFFER_SIZE];
  43. #define MAX_XML_SIZE 1024 * 16
  44. //
  45. // Buffers for display XML and SDB XML.
  46. //
  47. TCHAR g_szDisplayXML[MAX_XML_SIZE];
  48. TCHAR g_szSDBXML[MAX_XML_SIZE];
  49. TCHAR g_szLayerName[] = _T("!#RunLayer");
  50. INT_PTR
  51. CALLBACK
  52. ShowXMLDlgProc(
  53. HWND hdlg,
  54. UINT uMsg,
  55. WPARAM wParam,
  56. LPARAM lParam
  57. )
  58. /*++
  59. ShowXMLDlgProc
  60. Description: Show the dialog with the XML for the current selections.
  61. --*/
  62. {
  63. int wCode = LOWORD(wParam);
  64. int wNotifyCode = HIWORD(wParam);
  65. switch (uMsg) {
  66. case WM_INITDIALOG:
  67. //
  68. // By default we'll show the 'display XML'.
  69. //
  70. CheckDlgButton(hdlg, IDC_DISPLAY_XML, BST_CHECKED);
  71. SetDlgItemText(hdlg, IDC_XML, (LPTSTR)lParam);
  72. break;
  73. case WM_COMMAND:
  74. switch (wCode) {
  75. case IDC_DISPLAY_XML:
  76. case IDC_SDB_XML:
  77. if (BN_CLICKED == wNotifyCode) {
  78. if (IsDlgButtonChecked(hdlg, IDC_DISPLAY_XML)) {
  79. SetDlgItemText(hdlg, IDC_XML, g_szDisplayXML);
  80. }
  81. else if (IsDlgButtonChecked(hdlg, IDC_SDB_XML)) {
  82. SetDlgItemText(hdlg, IDC_XML, g_szSDBXML + 1);
  83. }
  84. SendDlgItemMessage(hdlg, IDC_XML, EM_SETSEL, 0, -1);
  85. SetFocus(GetDlgItem(hdlg, IDC_XML));
  86. }
  87. break;
  88. case IDCANCEL:
  89. EndDialog(hdlg, TRUE);
  90. break;
  91. case IDC_SAVE_XML:
  92. DoFileSave(hdlg);
  93. EndDialog(hdlg, TRUE);
  94. break;
  95. default:
  96. return FALSE;
  97. }
  98. break;
  99. default:
  100. return FALSE;
  101. }
  102. return TRUE;
  103. }
  104. LPTSTR
  105. ReadAndAllocateString(
  106. PDB pdb,
  107. TAGID tiString
  108. )
  109. {
  110. TCHAR* psz = NULL;
  111. int nLen;
  112. *g_szData = 0;
  113. SdbReadStringTag(pdb, tiString, g_szData, MAX_BUFFER_SIZE);
  114. if (!*g_szData) {
  115. DPF("[ReadAndAllocateString] Couldn't read the string");
  116. return NULL;
  117. }
  118. nLen = _tcslen(g_szData) + 1;
  119. psz = (LPTSTR)HeapAlloc(GetProcessHeap(),
  120. HEAP_ZERO_MEMORY,
  121. nLen * sizeof(TCHAR));
  122. if (!psz) {
  123. return NULL;
  124. } else {
  125. StringCchCopy(psz, nLen, g_szData);
  126. }
  127. return psz;
  128. }
  129. BOOL
  130. GetShimsFlagsForLayer(
  131. PDB pdb,
  132. PFIX pFixHead,
  133. PFIX* parrShim,
  134. TCHAR** parrCmdLine,
  135. TAGID tiLayer,
  136. BOOL fGetShims
  137. )
  138. /*++
  139. GetShimsFlagsForLayer
  140. Description: Based on the flag, get the shims or flags for the given
  141. layer and put them in the array.
  142. --*/
  143. {
  144. TAGID tiTmp, tiName;
  145. int nInd = 0;
  146. TCHAR szName[MAX_SHIM_NAME] = _T("");
  147. //
  148. // If we're going to get flags, find the next available element
  149. // in the array so we can perform an insertion.
  150. //
  151. if (!fGetShims) {
  152. while (parrShim[nInd]) {
  153. nInd++;
  154. }
  155. }
  156. //
  157. // Based on the flag, find the first tag ID in the layer.
  158. //
  159. tiTmp = SdbFindFirstTag(pdb, tiLayer, fGetShims ? TAG_SHIM_REF : TAG_FLAG_REF);
  160. while (tiTmp != TAGID_NULL) {
  161. *szName = 0;
  162. PFIX pFixWalk = NULL;
  163. tiName = SdbFindFirstTag(pdb, tiTmp, TAG_NAME);
  164. if (tiName == TAGID_NULL) {
  165. DPF("[GetShimsFlagForLayer] Failed to get the name of shim/flag");
  166. return FALSE;
  167. }
  168. SdbReadStringTag(pdb, tiName, szName, MAX_SHIM_NAME);
  169. if (!*szName) {
  170. DPF("[GetShimsFlagForLayer] Couldn't read the name of shim/flag");
  171. return FALSE;
  172. }
  173. pFixWalk = pFixHead;
  174. while (pFixWalk != NULL) {
  175. if (!(pFixWalk->dwFlags & FIX_TYPE_LAYER)) {
  176. if (_tcsicmp(pFixWalk->pszName, szName) == 0) {
  177. parrShim[nInd] = pFixWalk;
  178. if (fGetShims) {
  179. //
  180. // Now get the command line for this shim in the layer.
  181. //
  182. tiName = SdbFindFirstTag(pdb, tiTmp, TAG_COMMAND_LINE);
  183. if (tiName != TAGID_NULL) {
  184. parrCmdLine[nInd] = ReadAndAllocateString(pdb, tiName);
  185. }
  186. }
  187. nInd++;
  188. break;
  189. }
  190. }
  191. pFixWalk = pFixWalk->pNext;
  192. }
  193. tiTmp = SdbFindNextTag(pdb, tiLayer, tiTmp);
  194. }
  195. return TRUE;
  196. }
  197. PFIX
  198. ParseTagFlag(
  199. PDB pdb,
  200. TAGID tiFlag,
  201. BOOL bAllFlags
  202. )
  203. /*++
  204. ParseTagFlag
  205. Description: Parse a Flag tag for the NAME, DESCRIPTION and MASK
  206. --*/
  207. {
  208. TAGID tiFlagInfo;
  209. TAG tWhichInfo;
  210. PFIX pFix = NULL;
  211. TCHAR* pszName = NULL;
  212. TCHAR* pszDesc = NULL;
  213. DWORD dwFlags = 0;
  214. BOOL bGeneral = (bAllFlags ? TRUE : FALSE);
  215. tiFlagInfo = SdbGetFirstChild(pdb, tiFlag);
  216. while (tiFlagInfo != 0) {
  217. tWhichInfo = SdbGetTagFromTagID(pdb, tiFlagInfo);
  218. switch (tWhichInfo) {
  219. case TAG_GENERAL:
  220. bGeneral = TRUE;
  221. break;
  222. case TAG_NAME:
  223. pszName = ReadAndAllocateString(pdb, tiFlagInfo);
  224. break;
  225. case TAG_DESCRIPTION:
  226. pszDesc = ReadAndAllocateString(pdb, tiFlagInfo);
  227. break;
  228. case TAG_FLAGS_NTVDM1:
  229. case TAG_FLAGS_NTVDM2:
  230. case TAG_FLAGS_NTVDM3:
  231. dwFlags = FIX_TYPE_FLAGVDM;
  232. break;
  233. default:
  234. break;
  235. }
  236. tiFlagInfo = SdbGetNextChild(pdb, tiFlag, tiFlagInfo);
  237. }
  238. if (!bGeneral) {
  239. goto cleanup;
  240. }
  241. //
  242. // Done. Add the fix to the list.
  243. //
  244. pFix = (PFIX)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FIX));
  245. if (pFix == NULL || pszName == NULL) {
  246. cleanup:
  247. if (pFix != NULL) {
  248. HeapFree(GetProcessHeap(), 0, pFix);
  249. }
  250. if (pszName != NULL) {
  251. HeapFree(GetProcessHeap(), 0, pszName);
  252. }
  253. if (pszDesc != NULL) {
  254. HeapFree(GetProcessHeap(), 0, pszDesc);
  255. }
  256. return NULL;
  257. }
  258. pFix->pszName = pszName;
  259. pFix->dwFlags |= dwFlags | FIX_TYPE_FLAG;
  260. if (pszDesc) {
  261. pFix->pszDesc = pszDesc;
  262. } else {
  263. TCHAR* pszNone = NULL;
  264. pszNone = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
  265. if (!pszNone) {
  266. return NULL;
  267. }
  268. *pszNone = 0;
  269. LoadString(g_hInstance, IDS_NO_DESCR_AVAIL, pszNone, MAX_PATH);
  270. pFix->pszDesc = pszNone;
  271. }
  272. return pFix;
  273. }
  274. PFIX
  275. ParseTagShim(
  276. PDB pdb,
  277. TAGID tiShim,
  278. BOOL bAllShims
  279. )
  280. /*++
  281. ParseTagShim
  282. Description: Parse a Shim tag for the NAME, SHORTNAME, DESCRIPTION ...
  283. --*/
  284. {
  285. TAGID tiShimInfo;
  286. TAG tWhichInfo;
  287. PFIX pFix = NULL;
  288. TCHAR* pszName = NULL;
  289. TCHAR* pszDesc = NULL;
  290. BOOL bGeneral = (bAllShims ? TRUE : FALSE);
  291. tiShimInfo = SdbGetFirstChild(pdb, tiShim);
  292. while (tiShimInfo != 0) {
  293. tWhichInfo = SdbGetTagFromTagID(pdb, tiShimInfo);
  294. switch (tWhichInfo) {
  295. case TAG_GENERAL:
  296. bGeneral = TRUE;
  297. break;
  298. case TAG_NAME:
  299. pszName = ReadAndAllocateString(pdb, tiShimInfo);
  300. break;
  301. case TAG_DESCRIPTION:
  302. pszDesc = ReadAndAllocateString(pdb, tiShimInfo);
  303. break;
  304. default:
  305. break;
  306. }
  307. tiShimInfo = SdbGetNextChild(pdb, tiShim, tiShimInfo);
  308. }
  309. if (!bGeneral) {
  310. goto cleanup;
  311. }
  312. //
  313. // Done. Add the fix to the list.
  314. //
  315. pFix = (PFIX)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FIX));
  316. if (pFix == NULL || pszName == NULL) {
  317. cleanup:
  318. if (pFix != NULL) {
  319. HeapFree(GetProcessHeap(), 0, pFix);
  320. }
  321. if (pszName != NULL) {
  322. HeapFree(GetProcessHeap(), 0, pszName);
  323. }
  324. if (pszDesc != NULL) {
  325. HeapFree(GetProcessHeap(), 0, pszDesc);
  326. }
  327. return NULL;
  328. }
  329. pFix->pszName = pszName;
  330. pFix->dwFlags = FIX_TYPE_SHIM;
  331. //
  332. // If we didn't find a description, load it from the resource table.
  333. //
  334. if (pszDesc) {
  335. pFix->pszDesc = pszDesc;
  336. } else {
  337. TCHAR* pszNone;
  338. pszNone = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
  339. if (!pszNone) {
  340. return NULL;
  341. }
  342. *pszNone = 0;
  343. LoadString(g_hInstance, IDS_NO_DESCR_AVAIL, pszNone, MAX_PATH);
  344. pFix->pszDesc = pszNone;
  345. }
  346. return pFix;
  347. }
  348. PFIX
  349. ParseTagLayer(
  350. PDB pdb,
  351. TAGID tiLayer,
  352. PFIX pFixHead
  353. )
  354. /*++
  355. ParseTagLayer
  356. Description: Parse a LAYER tag for the NAME and the SHIMs that it contains.
  357. --*/
  358. {
  359. PFIX pFix = NULL;
  360. TAGID tiFlag, tiShim, tiName;
  361. int nShimCount;
  362. TCHAR* pszName = NULL;
  363. PFIX* parrShim = NULL;
  364. TCHAR** parrCmdLine = NULL;
  365. tiName = SdbFindFirstTag(pdb, tiLayer, TAG_NAME);
  366. if (tiName == TAGID_NULL) {
  367. DPF("[ParseTagLayer] Failed to get the name of the layer");
  368. return NULL;
  369. }
  370. pszName = ReadAndAllocateString(pdb, tiName);
  371. //
  372. // Now loop through all the SHIMs that this LAYER consists of and
  373. // allocate an array to keep all the pointers to the SHIMs' pFix
  374. // structures. We do this in 2 passes. First we calculate how many
  375. // SHIMs are in the layer, then we lookup their appropriate pFix-es.
  376. //
  377. tiShim = SdbFindFirstTag(pdb, tiLayer, TAG_SHIM_REF);
  378. nShimCount = 0;
  379. while (tiShim != TAGID_NULL) {
  380. nShimCount++;
  381. tiShim = SdbFindNextTag(pdb, tiLayer, tiShim);
  382. }
  383. //
  384. // We have a count of the shims in the layer. Now we need to
  385. // add the flags that are included in this layer to the count.
  386. //
  387. tiFlag = SdbFindFirstTag(pdb, tiLayer, TAG_FLAG_REF);
  388. while (tiFlag != TAGID_NULL) {
  389. nShimCount++;
  390. tiFlag = SdbFindNextTag(pdb, tiLayer, tiFlag);
  391. }
  392. parrShim = (PFIX*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PFIX) * (nShimCount + 1));
  393. parrCmdLine = (TCHAR**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR*) * (nShimCount + 1));
  394. //
  395. // Done. Add the fix to the list.
  396. //
  397. pFix = (PFIX)HeapAlloc(GetProcessHeap(), 0, sizeof(FIX));
  398. if (pFix == NULL || parrCmdLine == NULL || pszName == NULL || parrShim == NULL) {
  399. cleanup:
  400. if (pFix != NULL) {
  401. HeapFree(GetProcessHeap(), 0, pFix);
  402. }
  403. if (parrCmdLine != NULL) {
  404. HeapFree(GetProcessHeap(), 0, parrCmdLine);
  405. }
  406. if (parrShim != NULL) {
  407. HeapFree(GetProcessHeap(), 0, parrShim);
  408. }
  409. if (pszName != NULL) {
  410. HeapFree(GetProcessHeap(), 0, pszName);
  411. }
  412. DPF("[ParseTagLayer] Memory allocation error");
  413. return NULL;
  414. }
  415. //
  416. // Call the function that will fill in the array of PFIX
  417. // pointers and their corresponding command lines.
  418. // We do this for shims first.
  419. //
  420. if (!GetShimsFlagsForLayer(pdb,
  421. pFixHead,
  422. parrShim,
  423. parrCmdLine,
  424. tiLayer,
  425. TRUE)) {
  426. DPF("[ParseTagLayer] Failed to get shims for layer");
  427. goto cleanup;
  428. }
  429. //
  430. // Now do the same thing for flags.
  431. //
  432. if (!GetShimsFlagsForLayer(pdb,
  433. pFixHead,
  434. parrShim,
  435. NULL,
  436. tiLayer,
  437. FALSE)) {
  438. DPF("[ParseTagLayer] Failed to get flags for layer");
  439. goto cleanup;
  440. }
  441. pFix->pszName = pszName;
  442. pFix->dwFlags = FIX_TYPE_LAYER;
  443. pFix->parrShim = parrShim;
  444. pFix->parrCmdLine = parrCmdLine;
  445. return pFix;
  446. }
  447. BOOL
  448. IsSDBFromSP2(
  449. void
  450. )
  451. /*++
  452. IsSDBFromSP2
  453. Description: Determine if the SDB is from Service Pack 2.
  454. --*/
  455. {
  456. BOOL fResult = FALSE;
  457. PDB pdb;
  458. TAGID tiDatabase;
  459. TAGID tiLibrary;
  460. TAGID tiChild;
  461. PFIX pFix = NULL;;
  462. TCHAR szSDBPath[MAX_PATH];
  463. HRESULT hr;
  464. hr = StringCchPrintf(szSDBPath,
  465. ARRAYSIZE(szSDBPath) - 1,
  466. _T("%s\\AppPatch\\sysmain.sdb"),
  467. g_szWinDir);
  468. if (FAILED(hr)) {
  469. DPF("[IsSDBFromSP2] 0x%08X Buffer too small", HRESULT_CODE(hr));
  470. return FALSE;
  471. }
  472. //
  473. // Open the shim database.
  474. //
  475. pdb = SdbOpenDatabase(szSDBPath, DOS_PATH);
  476. if (!pdb) {
  477. DPF("[IsSDBFromSP2] Cannot open shim DB '%S'", szSDBPath);
  478. return FALSE;
  479. }
  480. //
  481. // Now browse the shim DB and look only for tags Shim within
  482. // the LIBRARY list tag.
  483. //
  484. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  485. if (tiDatabase == TAGID_NULL) {
  486. DPF("[IsSDBFromSP2] Cannot find TAG_DATABASE under the root tag");
  487. goto cleanup;
  488. }
  489. //
  490. // Get TAG_LIBRARY.
  491. //
  492. tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
  493. if (tiLibrary == TAGID_NULL) {
  494. DPF("[IsSDBFromSP2] Cannot find TAG_LIBRARY under the TAG_DATABASE tag");
  495. goto cleanup;
  496. }
  497. //
  498. // Loop get the first shim in the library.
  499. //
  500. tiChild = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM);
  501. if (tiChild == NULL) {
  502. goto cleanup;
  503. }
  504. //
  505. // Get information about the first shim listed.
  506. //
  507. pFix = ParseTagShim(pdb, tiChild, TRUE);
  508. if (!pFix) {
  509. goto cleanup;
  510. }
  511. //
  512. // If the first shim listed is 2GbGetDiskFreeSpace, this is SP2.
  513. //
  514. if (!(_tcsicmp(pFix->pszName, _T("2GbGetDiskFreeSpace.dll")))) {
  515. fResult = TRUE;
  516. }
  517. cleanup:
  518. SdbCloseDatabase(pdb);
  519. return fResult;
  520. }
  521. PFIX
  522. ReadFixesFromSdb(
  523. LPTSTR pszSdb,
  524. BOOL bAllFixes
  525. )
  526. /*++
  527. ReadFixesFromSdb
  528. Description: Query the database and enumerate all available shims fixes.
  529. --*/
  530. {
  531. PDB pdb;
  532. TAGID tiDatabase;
  533. TAGID tiLibrary;
  534. TAGID tiChild;
  535. PFIX pFixHead = NULL;
  536. PFIX pFix = NULL;
  537. TCHAR szSDBPath[MAX_PATH];
  538. HRESULT hr;
  539. hr = StringCchPrintf(szSDBPath,
  540. ARRAYSIZE(szSDBPath),
  541. _T("%s\\AppPatch\\%s"),
  542. g_szWinDir,
  543. pszSdb);
  544. if (FAILED(hr)) {
  545. DPF("[ReadFixesFromSdb] 0x%08X Buffer too small", HRESULT_CODE(hr));
  546. return NULL;
  547. }
  548. //
  549. // Open the shim database.
  550. //
  551. pdb = SdbOpenDatabase(szSDBPath, DOS_PATH);
  552. if (!pdb) {
  553. DPF("[ReadFixesFromSdb] Cannot open shim DB '%S'", szSDBPath);
  554. return NULL;
  555. }
  556. //
  557. // Now browse the shim DB and look only for tags Shim within
  558. // the LIBRARY list tag.
  559. //
  560. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  561. if (tiDatabase == TAGID_NULL) {
  562. DPF("[ReadFixesFromSdb] Cannot find TAG_DATABASE under the root tag");
  563. goto Cleanup;
  564. }
  565. //
  566. // Get TAG_LIBRARY.
  567. //
  568. tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
  569. if (tiLibrary == TAGID_NULL) {
  570. DPF("[ReadFixesFromSdb] Cannot find TAG_LIBRARY under the TAG_DATABASE tag");
  571. goto Cleanup;
  572. }
  573. //
  574. // Loop through all TAG_SHIM tags within TAG_LIBRARY.
  575. //
  576. tiChild = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM);
  577. while (tiChild != TAGID_NULL) {
  578. pFix = ParseTagShim(pdb, tiChild, bAllFixes);
  579. if (pFix != NULL) {
  580. pFix->pNext = pFixHead;
  581. pFixHead = pFix;
  582. }
  583. tiChild = SdbFindNextTag(pdb, tiLibrary, tiChild);
  584. }
  585. //
  586. // Loop through all TAG_FLAG tags within TAG_LIBRARY.
  587. //
  588. tiChild = SdbFindFirstTag(pdb, tiLibrary, TAG_FLAG);
  589. while (tiChild != TAGID_NULL) {
  590. pFix = ParseTagFlag(pdb, tiChild, bAllFixes);
  591. if (pFix != NULL) {
  592. pFix->pNext = pFixHead;
  593. pFixHead = pFix;
  594. }
  595. tiChild = SdbFindNextTag(pdb, tiLibrary, tiChild);
  596. }
  597. //
  598. // Loop through all TAG_LAYER tags within TAG_DATABASE.
  599. //
  600. tiChild = SdbFindFirstTag(pdb, tiDatabase, TAG_LAYER);
  601. while (tiChild != TAGID_NULL) {
  602. pFix = ParseTagLayer(pdb, tiChild, pFixHead);
  603. if (pFix != NULL) {
  604. pFix->pNext = pFixHead;
  605. pFixHead = pFix;
  606. }
  607. tiChild = SdbFindNextTag(pdb, tiDatabase, tiChild);
  608. }
  609. Cleanup:
  610. SdbCloseDatabase(pdb);
  611. return pFixHead;
  612. }
  613. #define ADD_AND_CHECK(cbSizeX, cbCrtSizeX, pszDst) \
  614. { \
  615. TCHAR* pszSrc = szBuffer; \
  616. \
  617. while (*pszSrc != 0) { \
  618. \
  619. if (cbSizeX - cbCrtSizeX <= 5) { \
  620. DPF("[ADD_AND_CHECK] Out of space"); \
  621. return FALSE; \
  622. } \
  623. \
  624. if (*pszSrc == _T('&') && *(pszSrc + 1) != _T('q')) { \
  625. StringCbCopy(pszDst, cbSizeX, _T("&amp;")); \
  626. pszDst += 5; \
  627. cbCrtSizeX += 5; \
  628. } else { \
  629. *pszDst++ = *pszSrc; \
  630. cbCrtSizeX++; \
  631. } \
  632. pszSrc++; \
  633. } \
  634. *pszDst = 0; \
  635. cbCrtSizeX++; \
  636. }
  637. BOOL
  638. CollectShims(
  639. HWND hListShims,
  640. LPTSTR pszXML,
  641. int cbSize
  642. )
  643. /*++
  644. CollectShims
  645. Description: Collects all the shims from the list view
  646. and generates the XML in pszXML
  647. --*/
  648. {
  649. int cShims = 0, nShimsApplied = 0, nIndex;
  650. int cbCrtSize = 0;
  651. BOOL fSelected = FALSE;
  652. LVITEM lvi;
  653. TCHAR szBuffer[1024];
  654. cShims = ListView_GetItemCount(hListShims);
  655. for (nIndex = 0; nIndex < cShims; nIndex++) {
  656. fSelected = ListView_GetCheckState(hListShims, nIndex);
  657. if (fSelected) {
  658. //
  659. // This shim is selected - add it to the XML.
  660. //
  661. lvi.mask = LVIF_PARAM;
  662. lvi.iItem = nIndex;
  663. lvi.iSubItem = 0;
  664. ListView_GetItem(hListShims, &lvi);
  665. PFIX pFix = (PFIX)lvi.lParam;
  666. PMODULE pModule = pFix->pModule;
  667. if (pFix->dwFlags & FIX_TYPE_FLAG) {
  668. if (NULL != pFix->pszCmdLine) {
  669. StringCchPrintf(szBuffer,
  670. ARRAYSIZE(szBuffer),
  671. _T(" <FLAG NAME=\"%s\" COMMAND_LINE=\"%s\"/>\r\n"),
  672. pFix->pszName,
  673. pFix->pszCmdLine);
  674. } else {
  675. StringCchPrintf(szBuffer,
  676. ARRAYSIZE(szBuffer),
  677. _T(" <FLAG NAME=\"%s\"/>\r\n"),
  678. pFix->pszName);
  679. }
  680. } else {
  681. //
  682. // Check for module include/exclude so we know how to open/close the XML.
  683. //
  684. if (NULL != pModule) {
  685. if (NULL != pFix->pszCmdLine) {
  686. StringCchPrintf(szBuffer,
  687. ARRAYSIZE(szBuffer),
  688. _T(" <SHIM NAME=\"%s\" COMMAND_LINE=\"%s\">\r\n"),
  689. pFix->pszName,
  690. pFix->pszCmdLine);
  691. } else {
  692. StringCchPrintf(szBuffer,
  693. ARRAYSIZE(szBuffer),
  694. _T(" <SHIM NAME=\"%s\">\r\n"),
  695. pFix->pszName);
  696. }
  697. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  698. //
  699. // Add the modules to the XML.
  700. //
  701. while (NULL != pModule) {
  702. StringCchPrintf(szBuffer,
  703. ARRAYSIZE(szBuffer),
  704. _T(" <%s MODULE=\"%s\"/>\r\n"),
  705. pModule->fInclude ? _T("INCLUDE") : _T("EXCLUDE"),
  706. pModule->pszName);
  707. pModule = pModule->pNext;
  708. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  709. }
  710. //
  711. // Close the SHIM tag.
  712. //
  713. StringCchPrintf(szBuffer,
  714. ARRAYSIZE(szBuffer),
  715. _T(" </SHIM>\r\n"));
  716. } else {
  717. //
  718. // No include/exclude was provided - just build the shim tag normally.
  719. //
  720. if (NULL != pFix->pszCmdLine) {
  721. StringCchPrintf(szBuffer,
  722. ARRAYSIZE(szBuffer),
  723. _T(" <SHIM NAME=\"%s\" COMMAND_LINE=\"%s\"/>\r\n"),
  724. pFix->pszName,
  725. pFix->pszCmdLine);
  726. } else {
  727. StringCchPrintf(szBuffer,
  728. ARRAYSIZE(szBuffer),
  729. _T(" <SHIM NAME=\"%s\"/>\r\n"),
  730. pFix->pszName);
  731. }
  732. }
  733. }
  734. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  735. nShimsApplied++;
  736. }
  737. }
  738. DPF("[CollectShims] %d shim(s) selected", nShimsApplied);
  739. return TRUE;
  740. }
  741. BOOL
  742. CollectFileAttributes(
  743. HWND hTreeFiles,
  744. LPTSTR pszXML,
  745. int cbSize
  746. )
  747. /*++
  748. CollectFileAttributes
  749. Description: Collects the attributes of all the files in the tree
  750. and generates the XML in pszXML.
  751. --*/
  752. {
  753. HTREEITEM hBinItem;
  754. HTREEITEM hItem;
  755. PATTRINFO pAttrInfo;
  756. UINT State;
  757. TVITEM item;
  758. int cbCrtSize = 0;
  759. TCHAR szItem[MAX_PATH];
  760. TCHAR szBuffer[1024];
  761. //
  762. // First get the main EXE.
  763. //
  764. hBinItem = TreeView_GetChild(hTreeFiles, TVI_ROOT);
  765. item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
  766. item.hItem = hBinItem;
  767. item.pszText = szItem;
  768. item.cchTextMax = MAX_PATH;
  769. TreeView_GetItem(hTreeFiles, &item);
  770. pAttrInfo = (PATTRINFO)(item.lParam);
  771. hItem = TreeView_GetChild(hTreeFiles, hBinItem);
  772. while (hItem != NULL) {
  773. item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT;
  774. item.hItem = hItem;
  775. TreeView_GetItem(hTreeFiles, &item);
  776. State = item.state & TVIS_STATEIMAGEMASK;
  777. if (State) {
  778. if (((State >> 12) & 0x03) == 2) {
  779. StringCchPrintf(szBuffer,
  780. ARRAYSIZE(szBuffer),
  781. _T(" %s"),
  782. (LPTSTR)item.pszText);
  783. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  784. }
  785. }
  786. hItem = TreeView_GetNextSibling(hTreeFiles, hItem);
  787. }
  788. StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), _T(">\r\n"));
  789. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  790. //
  791. // Done with the main binary. Now enumerate the matching files.
  792. //
  793. hBinItem = TreeView_GetNextSibling(hTreeFiles, hBinItem);
  794. while (hBinItem != NULL) {
  795. item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT;
  796. item.hItem = hBinItem;
  797. item.pszText = szItem;
  798. item.cchTextMax = MAX_PATH;
  799. TreeView_GetItem(hTreeFiles, &item);
  800. pAttrInfo = (PATTRINFO)(item.lParam);
  801. StringCchPrintf(szBuffer,
  802. ARRAYSIZE(szBuffer),
  803. _T(" <MATCHING_FILE NAME=\"%s\""),
  804. szItem);
  805. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  806. hItem = TreeView_GetChild(hTreeFiles, hBinItem);
  807. while (hItem != NULL) {
  808. item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT;
  809. item.hItem = hItem;
  810. TreeView_GetItem(hTreeFiles, &item);
  811. State = item.state & TVIS_STATEIMAGEMASK;
  812. if (State) {
  813. if (((State >> 12) & 0x03) == 2) {
  814. StringCchPrintf(szBuffer,
  815. ARRAYSIZE(szBuffer),
  816. _T(" %s"),
  817. (LPTSTR)item.pszText);
  818. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  819. }
  820. }
  821. hItem = TreeView_GetNextSibling(hTreeFiles, hItem);
  822. }
  823. StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), _T("/>\r\n"));
  824. ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
  825. hBinItem = TreeView_GetNextSibling(hTreeFiles, hBinItem);
  826. }
  827. return TRUE;
  828. }
  829. BOOL
  830. CreateSDBFile(
  831. LPCTSTR pszShortName,
  832. LPTSTR pszSDBName
  833. )
  834. /*++
  835. CreateSDBFile
  836. Description: Creates the XML file on the user's hard drive and
  837. generates the SDB using shimdbc.
  838. --*/
  839. {
  840. TCHAR* psz = NULL;
  841. TCHAR szShortName[MAX_PATH];
  842. TCHAR szAppPatchDir[MAX_PATH];
  843. TCHAR szSDBFile[MAX_PATH];
  844. TCHAR szXMLFile[MAX_PATH];
  845. TCHAR szCompiler[MAX_PATH];
  846. HANDLE hFile;
  847. DWORD cbBytesWritten;
  848. HRESULT hr;
  849. hr = StringCchPrintf(szAppPatchDir,
  850. ARRAYSIZE(szAppPatchDir),
  851. _T("%s\\AppPatch"),
  852. g_szWinDir);
  853. if (FAILED(hr)) {
  854. DPF("[CreateSDBFile] 0x%08X Buffer too small (1)", HRESULT_CODE(hr));
  855. return FALSE;
  856. }
  857. SetCurrentDirectory(szAppPatchDir);
  858. hr = StringCchCopy(szShortName, ARRAYSIZE(szShortName), pszShortName);
  859. if (FAILED(hr)) {
  860. DPF("[CreateSDBFile] 0x%08X Buffer too small (2)", HRESULT_CODE(hr));
  861. return FALSE;
  862. }
  863. psz = PathFindExtension(szShortName);
  864. if (!psz) {
  865. return FALSE;
  866. } else {
  867. *psz = '\0';
  868. }
  869. hr = StringCchPrintf(szXMLFile,
  870. ARRAYSIZE(szXMLFile),
  871. _T("%s\\%s.xml"),
  872. szAppPatchDir,
  873. szShortName);
  874. if (FAILED(hr)) {
  875. DPF("[CreateSDBFile] 0x%08X Buffer too small (3)", HRESULT_CODE(hr));
  876. return FALSE;
  877. }
  878. hr = StringCchPrintf(szSDBFile,
  879. ARRAYSIZE(szSDBFile),
  880. _T("%s\\%s.sdb"),
  881. szAppPatchDir,
  882. szShortName);
  883. if (FAILED(hr)) {
  884. DPF("[CreateSDBFile] 0x%08X Buffer too small (4)", HRESULT_CODE(hr));
  885. return FALSE;
  886. }
  887. hFile = CreateFile(szXMLFile,
  888. GENERIC_WRITE,
  889. 0,
  890. NULL,
  891. CREATE_ALWAYS,
  892. FILE_ATTRIBUTE_NORMAL,
  893. NULL);
  894. if (hFile == INVALID_HANDLE_VALUE) {
  895. DPF("[CreateSDBFile] 0x%08X CreateFile '%S' failed",
  896. szXMLFile,
  897. GetLastError());
  898. return FALSE;
  899. }
  900. if (!(WriteFile(hFile,
  901. g_szSDBXML,
  902. _tcslen(g_szSDBXML) * sizeof(TCHAR),
  903. &cbBytesWritten,
  904. NULL))) {
  905. DPF("[CreateSDBFile] 0x%08X WriteFile '%S' failed",
  906. szXMLFile,
  907. GetLastError());
  908. CloseHandle(hFile);
  909. return FALSE;
  910. }
  911. CloseHandle(hFile);
  912. hr = StringCchPrintf(szCompiler,
  913. ARRAYSIZE(szCompiler),
  914. _T("shimdbc.exe fix -q \"%s\" \"%s\""),
  915. szXMLFile,
  916. szSDBFile);
  917. if (FAILED(hr)) {
  918. DPF("[CreateSDBFile] 0x%08X Buffer too small (5)", HRESULT_CODE(hr));
  919. return FALSE;
  920. }
  921. if (!ShimdbcExecute(szCompiler)) {
  922. DPF("[CreateSDBFile] 0x%08X CreateProcess '%S' failed",
  923. szCompiler,
  924. GetLastError());
  925. return FALSE;
  926. }
  927. //
  928. // Give the SDB name back to the caller if they want it.
  929. //
  930. if (pszSDBName) {
  931. StringCchCopy(pszSDBName, MAX_PATH, szSDBFile);
  932. }
  933. return TRUE;
  934. }
  935. BOOL
  936. BuildDisplayXML(
  937. HWND hTreeFiles,
  938. HWND hListShims,
  939. LPCTSTR pszLayerName,
  940. LPCTSTR pszShortName,
  941. DWORD dwBinaryType,
  942. BOOL fAddW2K
  943. )
  944. /*++
  945. BuildDisplayXML
  946. Description: Builds the XML that will be inserted into DBU.XML.
  947. --*/
  948. {
  949. TCHAR szBuffer[1024];
  950. TCHAR* pszXML = NULL;
  951. int cbCrtXmlSize = 0, cbLength;
  952. int cbXmlSize = MAX_XML_SIZE;
  953. //
  954. // Initialize our global and point to it.
  955. //
  956. *g_szDisplayXML = 0;
  957. pszXML = g_szDisplayXML;
  958. //
  959. // Build the header for the XML.
  960. //
  961. StringCchPrintf(szBuffer,
  962. ARRAYSIZE(szBuffer),
  963. _T("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n")
  964. _T("<DATABASE NAME=\"%s custom database\">\r\n"),
  965. pszShortName);
  966. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  967. //
  968. // Add the APP and EXE elements to the XML.
  969. //
  970. StringCchPrintf(szBuffer,
  971. ARRAYSIZE(szBuffer),
  972. _T(" <APP NAME=\"%s\" VENDOR=\"Unknown\">\r\n")
  973. _T(" <%s NAME=\"%s\""),
  974. pszShortName,
  975. (dwBinaryType == SCS_32BIT_BINARY ? _T("EXE") : _T("EXE - ERROR: 16-BIT BINARY")),
  976. pszShortName);
  977. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  978. //
  979. // Add the matching files and their attributes to the XML.
  980. //
  981. if (!CollectFileAttributes(hTreeFiles,
  982. pszXML,
  983. cbXmlSize - cbCrtXmlSize)) {
  984. return FALSE;
  985. }
  986. cbLength = _tcslen(pszXML);
  987. pszXML += cbLength;
  988. cbCrtXmlSize += cbLength + 1;
  989. //
  990. // If a layer was provided, use it. Otherwise, build the list
  991. // of shims and add it to the XML.
  992. //
  993. if (pszLayerName) {
  994. StringCchPrintf(szBuffer,
  995. ARRAYSIZE(szBuffer),
  996. _T(" <LAYER NAME=\"%s\"/>\r\n"),
  997. pszLayerName);
  998. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  999. } else {
  1000. if (!CollectShims(hListShims, pszXML, cbXmlSize - cbCrtXmlSize)) {
  1001. return FALSE;
  1002. }
  1003. cbLength = _tcslen(pszXML);
  1004. pszXML += cbLength;
  1005. cbCrtXmlSize += cbLength + 1;
  1006. }
  1007. //
  1008. // If this is Windows 2000, add Win2kPropagateLayer.
  1009. //
  1010. if (fAddW2K) {
  1011. StringCchCopy(szBuffer,
  1012. ARRAYSIZE(szBuffer),
  1013. _T(" <SHIM NAME=\"Win2kPropagateLayer\"/>\r\n"));
  1014. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1015. }
  1016. //
  1017. // Finally, close the open tags.
  1018. //
  1019. StringCchCopy(szBuffer,
  1020. ARRAYSIZE(szBuffer),
  1021. _T(" </EXE>\r\n </APP>\r\n</DATABASE>"));
  1022. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1023. DPF("[BuildDisplayXML] XML:\n %S", g_szDisplayXML);
  1024. return TRUE;
  1025. }
  1026. BOOL
  1027. BuildSDBXML(
  1028. HWND hTreeFiles,
  1029. HWND hListShims,
  1030. LPCTSTR pszLayerName,
  1031. LPCTSTR pszShortName,
  1032. DWORD dwBinaryType,
  1033. BOOL fAddW2K
  1034. )
  1035. /*++
  1036. BuildSDBXML
  1037. Description: Builds the XML that will be used for SDB generation.
  1038. --*/
  1039. {
  1040. TCHAR szBuffer[1024];
  1041. TCHAR* pszXML = NULL;
  1042. WCHAR wszUnicodeHdr = 0xFEFF;
  1043. int cbCrtXmlSize = 0, cbLength;
  1044. int cbXmlSize = MAX_XML_SIZE;
  1045. //
  1046. // Initialize our global and point to it.
  1047. //
  1048. g_szSDBXML[0] = 0;
  1049. pszXML = g_szSDBXML;
  1050. //
  1051. // Build the header for the XML.
  1052. //
  1053. StringCchPrintf(szBuffer,
  1054. ARRAYSIZE(szBuffer),
  1055. _T("%lc<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n")
  1056. _T("<DATABASE NAME=\"%s custom database\">\r\n"),
  1057. wszUnicodeHdr,
  1058. pszShortName);
  1059. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1060. //
  1061. // If no layer was provided, this indicates that the user has
  1062. // selected individual shims and we need to build our own layer.
  1063. //
  1064. if (!pszLayerName) {
  1065. StringCchPrintf(szBuffer,
  1066. ARRAYSIZE(szBuffer),
  1067. _T(" <LIBRARY>\r\n <LAYER NAME=\"%s\">\r\n"),
  1068. g_szLayerName + 2);
  1069. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1070. if (!CollectShims(hListShims,
  1071. pszXML,
  1072. cbXmlSize - cbCrtXmlSize)) {
  1073. return FALSE;
  1074. }
  1075. cbLength = _tcslen(pszXML);
  1076. pszXML += cbLength;
  1077. cbCrtXmlSize += cbLength + 1;
  1078. //
  1079. // If this is Windows 2000, add Win2kPropagateLayer.
  1080. //
  1081. if (fAddW2K) {
  1082. StringCchCopy(szBuffer,
  1083. ARRAYSIZE(szBuffer),
  1084. _T(" <SHIM NAME=\"Win2kPropagateLayer\"/>\r\n"));
  1085. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1086. }
  1087. //
  1088. // Close the open tags.
  1089. //
  1090. StringCchCopy(szBuffer,
  1091. ARRAYSIZE(szBuffer),
  1092. _T(" </LAYER>\r\n </LIBRARY>\r\n"));
  1093. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1094. }
  1095. //
  1096. // Add the APP and EXE elements to the XML.
  1097. //
  1098. StringCchPrintf(szBuffer,
  1099. ARRAYSIZE(szBuffer),
  1100. _T(" <APP NAME=\"%s\" VENDOR=\"Unknown\">\r\n")
  1101. _T(" <EXE NAME=\"%s\""),
  1102. pszShortName,
  1103. pszShortName);
  1104. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1105. //
  1106. // Add the matching files and their attributes to the XML.
  1107. //
  1108. if (!CollectFileAttributes(hTreeFiles,
  1109. pszXML,
  1110. cbXmlSize - cbCrtXmlSize)) {
  1111. return FALSE;
  1112. }
  1113. cbLength = _tcslen(pszXML);
  1114. pszXML += cbLength;
  1115. cbCrtXmlSize += cbLength + 1;
  1116. //
  1117. // Add the LAYER element to the XML. This will either be a predefined
  1118. // layer name or the special 'RunLayer' indicating we built our own.
  1119. //
  1120. if (!pszLayerName) {
  1121. StringCchPrintf(szBuffer,
  1122. ARRAYSIZE(szBuffer),
  1123. _T(" <LAYER NAME=\"%s\"/>\r\n"),
  1124. g_szLayerName + 2);
  1125. } else {
  1126. StringCchPrintf(szBuffer,
  1127. ARRAYSIZE(szBuffer),
  1128. _T(" <LAYER NAME=\"%s\"/>\r\n"),
  1129. pszLayerName);
  1130. }
  1131. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1132. //
  1133. // Finally, close the open tags.
  1134. //
  1135. StringCchCopy(szBuffer,
  1136. ARRAYSIZE(szBuffer),
  1137. _T(" </EXE>\r\n </APP>\r\n</DATABASE>"));
  1138. ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
  1139. DPF("[BuildSDBXML] XML:\n %S", g_szSDBXML);
  1140. return TRUE;
  1141. }
  1142. BOOL
  1143. CollectFix(
  1144. HWND hListLayers,
  1145. HWND hListShims,
  1146. HWND hTreeFiles,
  1147. LPCTSTR pszShortName,
  1148. LPCTSTR pszFullPath,
  1149. DWORD dwFlags,
  1150. LPTSTR pszFileCreated
  1151. )
  1152. /*++
  1153. CollectFix
  1154. Description: Adds the necessary support to apply shim(s) for
  1155. the specified app.
  1156. --*/
  1157. {
  1158. BOOL fAddW2K = FALSE;
  1159. TCHAR szError[MAX_PATH];
  1160. TCHAR szXmlFile[MAX_PATH];
  1161. TCHAR* pszLayerName = NULL;
  1162. TCHAR szLayer[128];
  1163. DWORD dwBinaryType = SCS_32BIT_BINARY;
  1164. //
  1165. // If the user has selected a predefined layer, we'll use that.
  1166. // Otherwise, assign the 'RunLayer' name which has a special
  1167. // meaning.
  1168. //
  1169. if (dwFlags & CFF_USELAYERTAB) {
  1170. LRESULT lSel;
  1171. lSel = SendMessage(hListLayers, LB_GETCURSEL, 0, 0);
  1172. if (lSel == LB_ERR) {
  1173. LoadString(g_hInstance, IDS_LAYER_SELECT, szError, ARRAYSIZE(szError));
  1174. MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  1175. return TRUE;
  1176. }
  1177. SendMessage(hListLayers, LB_GETTEXT, lSel, (LPARAM)szLayer);
  1178. pszLayerName = szLayer;
  1179. }
  1180. //
  1181. // Determine the binary type.
  1182. //
  1183. GetBinaryType(pszFullPath, &dwBinaryType);
  1184. //
  1185. // If this is Windows 2000 and they're not using
  1186. // a predefined layer, add Win2kPropagateLayer.
  1187. //
  1188. if ((dwFlags & CFF_ADDW2KSUPPORT) && !(dwFlags & CFF_USELAYERTAB)) {
  1189. fAddW2K = TRUE;
  1190. }
  1191. //
  1192. // Build the display version of the XML.
  1193. //
  1194. if (!BuildDisplayXML(hTreeFiles,
  1195. hListShims,
  1196. pszLayerName,
  1197. pszShortName,
  1198. dwBinaryType,
  1199. fAddW2K)) {
  1200. DPF("Failed to build display XML");
  1201. return FALSE;
  1202. }
  1203. //
  1204. // Build the version of the XML that we'll use to generate the SDB.
  1205. //
  1206. if (!BuildSDBXML(hTreeFiles,
  1207. hListShims,
  1208. pszLayerName,
  1209. pszShortName,
  1210. dwBinaryType,
  1211. fAddW2K)) {
  1212. DPF("Failed to build SDB XML");
  1213. return FALSE;
  1214. }
  1215. //
  1216. // Display the XML if the user wants to see it.
  1217. //
  1218. if (dwFlags & CFF_SHOWXML) {
  1219. DialogBoxParam(g_hInstance,
  1220. MAKEINTRESOURCE(IDD_XML),
  1221. g_hDlg,
  1222. ShowXMLDlgProc,
  1223. (LPARAM)(g_szDisplayXML));
  1224. return TRUE;
  1225. }
  1226. //
  1227. // Create the SDB file for the user.
  1228. //
  1229. if (!(CreateSDBFile(pszShortName, pszFileCreated))) {
  1230. return FALSE;
  1231. }
  1232. //
  1233. // Delete the XML file that we created.
  1234. //
  1235. StringCchCopy(szXmlFile, ARRAYSIZE(szXmlFile), pszFileCreated);
  1236. PathRenameExtension(szXmlFile, _T(".xml"));
  1237. DeleteFile(szXmlFile);
  1238. //
  1239. // Set the SHIM_FILE_LOG env var.
  1240. //
  1241. if (dwFlags & CFF_SHIMLOG) {
  1242. DeleteFile(SHIM_FILE_LOG_NAME);
  1243. SetEnvironmentVariable(_T("SHIM_FILE_LOG"), SHIM_FILE_LOG_NAME);
  1244. }
  1245. return TRUE;
  1246. }
  1247. void
  1248. CleanupSupportForApp(
  1249. TCHAR* pszShortName
  1250. )
  1251. /*++
  1252. CleanupSupportForApp
  1253. Description: Cleanup the mess after we're done with the specified app.
  1254. --*/
  1255. {
  1256. TCHAR szSDBPath[MAX_PATH];
  1257. HRESULT hr;
  1258. hr = StringCchPrintf(szSDBPath,
  1259. ARRAYSIZE(szSDBPath),
  1260. _T("%s\\AppPatch\\%s"),
  1261. g_szWinDir,
  1262. pszShortName);
  1263. if (FAILED(hr)) {
  1264. DPF("[CleanupSupportForApp] 0x%08X Buffer too small", HRESULT_CODE(hr));
  1265. return;
  1266. }
  1267. //
  1268. // Attempt to delete the XML file.
  1269. //
  1270. PathRenameExtension(szSDBPath, _T(".xml"));
  1271. DeleteFile(szSDBPath);
  1272. //
  1273. // Remove the previous SDB file, if one exists.
  1274. //
  1275. // NTRAID#583475-rparsons Don't remove the SDB if the user
  1276. // installed it.
  1277. //
  1278. //
  1279. if (*g_szSDBToDelete && !g_bSDBInstalled) {
  1280. InstallSDB(g_szSDBToDelete, FALSE);
  1281. DeleteFile(g_szSDBToDelete);
  1282. }
  1283. }
  1284. void
  1285. ShowShimLog(
  1286. void
  1287. )
  1288. /*++
  1289. ShowShimLog
  1290. Description: Show the shim log file in notepad.
  1291. --*/
  1292. {
  1293. STARTUPINFO si;
  1294. PROCESS_INFORMATION pi;
  1295. TCHAR szAppName[MAX_PATH];
  1296. TCHAR szCmdLine[MAX_PATH];
  1297. TCHAR szError[MAX_PATH];
  1298. HRESULT hr;
  1299. hr = StringCchPrintf(szAppName,
  1300. ARRAYSIZE(szAppName),
  1301. _T("%s\\notepad.exe"),
  1302. g_szSysDir);
  1303. if (FAILED(hr)) {
  1304. DPF("[ShowShimLog] 0x%08X Buffer too small (1)", HRESULT_CODE(hr));
  1305. return;
  1306. }
  1307. hr = StringCchPrintf(szCmdLine,
  1308. ARRAYSIZE(szCmdLine),
  1309. _T("%s\\AppPatch\\")SHIM_FILE_LOG_NAME,
  1310. g_szWinDir);
  1311. if (FAILED(hr)) {
  1312. DPF("[ShowShimLog] 0x%08X Buffer too small (2)", HRESULT_CODE(hr));
  1313. return;
  1314. }
  1315. if (GetFileAttributes(szCmdLine) == -1) {
  1316. LoadString(g_hInstance, IDS_NO_LOGFILE, szError, ARRAYSIZE(szError));
  1317. MessageBox(NULL, szError, g_szAppTitle, MB_ICONEXCLAMATION);
  1318. return;
  1319. }
  1320. hr = StringCchPrintf(szCmdLine,
  1321. ARRAYSIZE(szCmdLine),
  1322. _T("%s %s\\AppPatch\\")SHIM_FILE_LOG_NAME,
  1323. szAppName,
  1324. g_szWinDir);
  1325. if (FAILED(hr)) {
  1326. DPF("[ShowShimLog] 0x%08X Buffer too small (3)", HRESULT_CODE(hr));
  1327. return;
  1328. }
  1329. ZeroMemory(&si, sizeof(si));
  1330. si.cb = sizeof(si);
  1331. if (!CreateProcess(szAppName,
  1332. szCmdLine,
  1333. NULL,
  1334. NULL,
  1335. FALSE,
  1336. NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
  1337. NULL,
  1338. NULL,
  1339. &si,
  1340. &pi)) {
  1341. DPF("[ShowShimLog] 0x%08X CreateProcess '%S %S' failed",
  1342. szAppName,
  1343. szCmdLine,
  1344. GetLastError());
  1345. return;
  1346. }
  1347. CloseHandle(pi.hThread);
  1348. CloseHandle(pi.hProcess);
  1349. }