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.

6391 lines
168 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. dbsupport.cpp
  5. Abstract:
  6. Code for the functions that perform most of the database related tasks
  7. Author:
  8. kinshu created July 2, 2001
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. //////////////////////// Extern variables /////////////////////////////////////
  13. extern BOOL g_bWin2K;
  14. extern HINSTANCE g_hInstance;
  15. extern HWND g_hDlg;
  16. extern HWND g_hwndContentsList;
  17. extern TCHAR g_szData[1024];
  18. extern CSTRINGLIST g_strMRU;
  19. extern PDBENTRY g_pEntrySelApp;
  20. extern HWND g_hwndEntryTree;
  21. extern UINT g_uNextDataBaseIndex;
  22. extern BOOL g_bIsCut;
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //////////////////////// Defines //////////////////////////////////////////////
  25. // Size of a temporary buffer that is used to read in strings from the database
  26. #define MAX_DATA_SIZE 1024
  27. // The size of a buffer that holds the names of shims, layers, patches
  28. #define MAX_NAME MAX_PATH
  29. //
  30. // The guid of the system db. Note that on Win2kSP3, it is not this constant, so we should
  31. // NOT rely on this.
  32. #define GUID_SYSMAIN_SDB _T("{11111111-1111-1111-1111-111111111111}")
  33. // Guid of apphelp.sdb. There is no apphelp.sdb in Win2K
  34. #define GUID_APPHELP_SDB _T("{22222222-2222-2222-2222-222222222222}")
  35. // Guid of systest.sdb. This is no longer used
  36. #define GUID_SYSTEST_SDB _T("{33333333-3333-3333-3333-333333333333}")
  37. // Guid of drvmain.sdb
  38. #define GUID_DRVMAIN_SDB _T("{F9AB2228-3312-4A73-B6F9-936D70E112EF}")
  39. // Guid of msimain.sdb
  40. #define GUID_MSI_SDB _T("{d8ff6d16-6a3a-468a-8b44-01714ddc49ea}")
  41. // Used to check if the entry is disabled
  42. #define APPCOMPAT_DISABLED 0x03
  43. // Key of AppCompat data in the registry. This will contain the disable status of
  44. // various entries
  45. #define APPCOMPAT_KEY TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags")
  46. ///////////////////////////////////////////////////////////////////////////////
  47. //////////////////////// Function Declarations /////////////////////////////////
  48. INT_PTR CALLBACK
  49. DatabaseRenameDlgProc(
  50. HWND hdlg,
  51. UINT uMsg,
  52. WPARAM wParam,
  53. LPARAM lParam
  54. );
  55. BOOL
  56. HandleFirstEntryofAppDeletion(
  57. PDATABASE pDataBase,
  58. PDBENTRY pApp,
  59. BOOL bRepaint
  60. );
  61. BOOL
  62. GetEntryXML(
  63. CSTRINGLIST* strlXML,
  64. PDBENTRY pEntry
  65. );
  66. ///////////////////////////////////////////////////////////////////////////////
  67. //////////////////////// Global Variables /////////////////////////////////////
  68. // This is the system database
  69. struct DataBase GlobalDataBase(DATABASE_TYPE_GLOBAL);
  70. // The list of custom databases
  71. struct tagDataBaseList DataBaseList;
  72. // The list of installed databases
  73. struct tagDataBaseList InstalledDataBaseList;
  74. // Should we show the entry conflict dialog. Presently this is not used and is always FALSE
  75. BOOL g_bEntryConflictDonotShow = FALSE;
  76. // Temporary buffer for reading strings from the database
  77. WCHAR g_wszData[MAX_DATA_SIZE];
  78. // Used to convert from special chars to valid XML and vice-versa
  79. SpecialCharMap g_rgSpecialCharMap[4][2] = {
  80. TEXT("&"), 1, TEXT("&"), 5, // 5 is the length of the string in the prev. column
  81. TEXT("\""), 1, TEXT("""), 6,
  82. TEXT("<"), 1, TEXT("&lt;"), 4,
  83. TEXT(">"), 1, TEXT("&gt;"), 4
  84. };
  85. //
  86. // The various possible attributes for matching files
  87. //
  88. // Caution:
  89. // If you change g_Attributes or their order,
  90. // you will have to change DEFAULT_MASK in CompatAdmin.h
  91. //
  92. TAG g_Attributes[] = {
  93. TAG_SIZE,
  94. TAG_CHECKSUM,
  95. TAG_BIN_FILE_VERSION,
  96. TAG_BIN_PRODUCT_VERSION,
  97. TAG_PRODUCT_VERSION,
  98. TAG_FILE_DESCRIPTION,
  99. TAG_COMPANY_NAME,
  100. TAG_PRODUCT_NAME,
  101. TAG_FILE_VERSION,
  102. TAG_ORIGINAL_FILENAME,
  103. TAG_INTERNAL_NAME,
  104. TAG_LEGAL_COPYRIGHT,
  105. TAG_VERDATEHI,
  106. TAG_VERDATELO,
  107. TAG_VERFILEOS,
  108. TAG_VERFILETYPE,
  109. TAG_MODULE_TYPE,
  110. TAG_PE_CHECKSUM,
  111. TAG_LINKER_VERSION,
  112. #ifndef KERNEL_MODE
  113. TAG_16BIT_DESCRIPTION,
  114. TAG_16BIT_MODULE_NAME,
  115. #endif
  116. TAG_UPTO_BIN_FILE_VERSION,
  117. TAG_UPTO_BIN_PRODUCT_VERSION,
  118. TAG_LINK_DATE,
  119. TAG_UPTO_LINK_DATE,
  120. TAG_VER_LANGUAGE
  121. };
  122. // Total number of attributes available
  123. DWORD ATTRIBUTE_COUNT = ARRAYSIZE(g_Attributes);
  124. ///////////////////////////////////////////////////////////////////////////////
  125. BOOL
  126. CheckRegistry(
  127. IN HKEY hkeyRoot,
  128. IN LPCTSTR pszGUID
  129. )
  130. /*++
  131. CheckRegistry
  132. Desc: Checks if the entry with GUID pszGUID is disabled
  133. Params:
  134. IN HKEY hkeyRoot: The key under which to search
  135. IN LPCTSTR pszGUID: The guid of the entry
  136. Return:
  137. TRUE: The entry is disabled
  138. FALSE: The entry is enabled or there was some error
  139. --*/
  140. {
  141. LONG status;
  142. HKEY hkey = NULL;
  143. BOOL bDisabled = FALSE;
  144. DWORD dwFlags;
  145. DWORD type;
  146. DWORD cbSize = sizeof(DWORD);
  147. status = RegOpenKey(hkeyRoot, APPCOMPAT_KEY, &hkey);
  148. if (status != ERROR_SUCCESS) {
  149. return FALSE;
  150. }
  151. status = RegQueryValueEx(hkey, pszGUID, NULL, &type, (LPBYTE)&dwFlags, &cbSize);
  152. if (status == ERROR_SUCCESS && type == REG_DWORD && (dwFlags & APPCOMPAT_DISABLED)) {
  153. bDisabled = TRUE;
  154. }
  155. REGCLOSEKEY(hkey);
  156. return bDisabled;
  157. }
  158. BOOL
  159. SetDisabledStatus(
  160. IN HKEY hKeyRoot,
  161. IN PCTSTR pszGuid,
  162. IN BOOL bDisabled
  163. )
  164. /*++
  165. SetDisabledStatus
  166. Desc: Sets the disabled status of a entry
  167. Params:
  168. IN HKEY hkeyRoot: The AppCompat Key
  169. IN PCTSTR pszGUID: The guid of the entry
  170. IN BOOL bDisabled: Do we want to make it disabled?
  171. Return:
  172. TRUE: The entry's status has been changed
  173. FALSE: There was some error
  174. --*/
  175. {
  176. DWORD dwFlags = 0;
  177. HKEY hkey = NULL;
  178. DWORD dwValue = 0x03;
  179. DWORD dwDisposition = 0;
  180. LONG status;
  181. if (bDisabled == TRUE) {
  182. dwFlags = 0x1;
  183. }
  184. status = RegOpenKey(hKeyRoot, APPCOMPAT_KEY, &hkey);
  185. if (status != ERROR_SUCCESS) {
  186. status = RegCreateKeyEx(hKeyRoot,
  187. APPCOMPAT_KEY,
  188. 0,
  189. NULL,
  190. REG_OPTION_NON_VOLATILE,
  191. KEY_ALL_ACCESS,
  192. NULL,
  193. &hkey,
  194. &dwDisposition);
  195. if (status != ERROR_SUCCESS) {
  196. return FALSE;
  197. }
  198. }
  199. status = RegSetValueEx(hkey,
  200. pszGuid,
  201. 0,
  202. REG_DWORD,
  203. (LPBYTE) &dwFlags,
  204. sizeof(DWORD));
  205. REGCLOSEKEY(hkey);
  206. return ((status == ERROR_SUCCESS) ? TRUE : FALSE);
  207. }
  208. BOOL
  209. RemoveEntry(
  210. IN PDATABASE pDataBase,
  211. IN PDBENTRY pEntryToRemove,
  212. IN PDBENTRY pApp,
  213. IN BOOL bRepaint //def = TRUE
  214. )
  215. /*++
  216. RemoveEntry
  217. Desc: Remove an Entry from the database. This will also do any UI updates.
  218. Params:
  219. IN PDATABASE pDataBase: The database in which the entry being removed lives
  220. IN PDBENTRY pEntryToRemove: The entry to remove
  221. IN PDBENTRY pApp: The fist entry for the app to which this entry belongs
  222. IN BOOL bRepaint: <TODO>
  223. Return:
  224. TRUE: The entry has been removed
  225. FALSE: There was some error
  226. --*/
  227. {
  228. if (pEntryToRemove == NULL) {
  229. return FALSE;
  230. }
  231. PDBENTRY pPrev = NULL;
  232. PDBENTRY pEntry = pApp;
  233. HTREEITEM hItemEntryExe = NULL, htemEntrySibling = NULL;
  234. while (pEntry) {
  235. if (pEntry == pEntryToRemove) {
  236. break;
  237. }
  238. pPrev = pEntry;
  239. pEntry = pEntry->pSameAppExe;
  240. }
  241. if (pEntry == pEntryToRemove && pEntry != NULL) {
  242. if (pEntry == pApp) {
  243. //
  244. // First entry for the app. Note that this routine does not actually remove this
  245. // pEntry. Does stuff only on the UI
  246. //
  247. HandleFirstEntryofAppDeletion(pDataBase, pEntry, bRepaint);
  248. } else {
  249. assert(pPrev);
  250. if (pPrev) {
  251. pPrev->pSameAppExe = pEntry->pSameAppExe;
  252. }
  253. }
  254. // [BUGBUG]: We need to keep this in the destructor of PDBENTRY
  255. if (pEntry->appHelp.bPresent) {
  256. DeleteAppHelp(pDataBase, pEntry->appHelp.HTMLHELPID);
  257. pEntry->appHelp.bBlock = pEntry->appHelp.bPresent = FALSE;
  258. pEntry->appHelp.severity = APPTYPE_NONE;
  259. }
  260. //
  261. // Now we have to set the focus to some sibling of the deleted entry and
  262. // Update the g_pSelEntry
  263. //
  264. if (!(pApp == pEntryToRemove && pApp->pSameAppExe == NULL)) {
  265. //
  266. // The previous entry tree will be still there only if the condition is true
  267. // Otherwise the old tree will have gone because HandleFirstEntryofAppDeletion
  268. // will have caused the sibling of the app being deleted to be selected and the
  269. // previous entry tree will no
  270. // longer be there
  271. // We will have a new entry tree of the second app.
  272. //
  273. hItemEntryExe = NULL, htemEntrySibling = NULL;
  274. hItemEntryExe = CTree::FindChild(g_hwndEntryTree, TVI_ROOT, (LPARAM)pEntryToRemove);
  275. if (hItemEntryExe) {
  276. htemEntrySibling = TreeView_GetNextSibling(g_hwndEntryTree, hItemEntryExe);
  277. if (htemEntrySibling == NULL) {
  278. htemEntrySibling = TreeView_GetPrevSibling(g_hwndEntryTree,
  279. hItemEntryExe);
  280. }
  281. SendMessage(g_hwndEntryTree, WM_SETREDRAW, FALSE, 0);
  282. TreeView_DeleteItem(g_hwndEntryTree, hItemEntryExe);
  283. SendMessage(g_hwndEntryTree, WM_SETREDRAW, TRUE, 0);
  284. //
  285. // g_pSelEntry will get changed in the notification handler for the tree
  286. //
  287. if (htemEntrySibling && bRepaint) {
  288. TreeView_SelectItem(g_hwndEntryTree, htemEntrySibling);
  289. }
  290. }
  291. }
  292. ValidateClipBoard(NULL, pEntry);
  293. //
  294. // Has destructor
  295. //
  296. delete pEntry;
  297. } else {
  298. assert(FALSE);
  299. return FALSE;
  300. }
  301. return TRUE;
  302. }
  303. LPVOID
  304. FindFix(
  305. IN PCTSTR pszFixName,
  306. IN TYPE fixType,
  307. IN PDATABASE pDataBase // (NULL)
  308. )
  309. /*++
  310. FindFix
  311. Desc: Searches for a fix of type fixType in pDataBase with name pszFixName
  312. Params:
  313. IN LPCTSTR pszFixName: The fix to search for
  314. IN TYPE fixType: The type of the fix. One of
  315. a) FIX_SHIM
  316. b) FIX_FLAG
  317. c) FIX_LAYER
  318. d) FIX_PATCH
  319. IN PDATABASE pDataBase(NULL): The database in which to search.
  320. If this is NULL we search in the GlobalDatabase
  321. Return:
  322. The pointer to the fix if found
  323. NULL otherwise
  324. --*/
  325. {
  326. if (pszFixName == NULL) {
  327. assert(FALSE);
  328. return NULL;
  329. }
  330. switch (fixType) {
  331. case FIX_SHIM:
  332. {
  333. PSHIM_FIX pFix = GlobalDataBase.pShimFixes;
  334. while (pFix) {
  335. if (pFix->strName.Length() && !lstrcmpi(pszFixName, pFix->strName)) {
  336. return pFix;
  337. }
  338. pFix = pFix->pNext;
  339. }
  340. break;
  341. }
  342. case FIX_FLAG:
  343. {
  344. PFLAG_FIX pFix = GlobalDataBase.pFlagFixes;
  345. while (pFix) {
  346. if (pFix->strName.Length() && !lstrcmpi(pszFixName, pFix->strName)) {
  347. return pFix;
  348. }
  349. pFix = pFix->pNext;
  350. }
  351. break;
  352. }
  353. case FIX_LAYER:
  354. {
  355. //
  356. // Search in the local database.
  357. //
  358. if (pDataBase == NULL || pDataBase == &GlobalDataBase) {
  359. goto SearchGlobal;
  360. }
  361. PLAYER_FIX pFix = pDataBase->pLayerFixes;
  362. while (pFix) {
  363. if (pFix->strName.Length() && !lstrcmpi(pszFixName, pFix->strName)) {
  364. return pFix;
  365. }
  366. pFix = pFix->pNext;
  367. }
  368. //
  369. // Search in the global database.
  370. //
  371. SearchGlobal:
  372. pFix = GlobalDataBase.pLayerFixes;
  373. while (pFix) {
  374. if (pFix->strName.Length() && !lstrcmpi(pszFixName, pFix->strName)) {
  375. return pFix;
  376. }
  377. pFix = pFix->pNext;
  378. }
  379. break;
  380. }
  381. case FIX_PATCH:
  382. {
  383. PPATCH_FIX pFix = GlobalDataBase.pPatchFixes;
  384. while (pFix) {
  385. if (pFix->strName.Length() && !lstrcmpi(pszFixName, pFix->strName)) {
  386. return pFix;
  387. }
  388. pFix = pFix->pNext;
  389. }
  390. break;
  391. }
  392. }
  393. return NULL;
  394. }
  395. CSTRING
  396. ReadDBString(
  397. IN PDB pDB,
  398. IN TAGID tagID
  399. )
  400. /*++
  401. ReadDBString
  402. Desc: Reads a string from the database
  403. Params:
  404. IN PDB pDB: The database
  405. IN TAGID tagID: The tag id for the string type
  406. Return: The string read. Will return a string of zero length if there is some error
  407. --*/
  408. {
  409. CSTRING Str;
  410. K_SIZE k_pszAppName = MAX_STRING_SIZE;
  411. PTSTR pszAppName = new TCHAR[k_pszAppName];
  412. if (pszAppName == NULL) {
  413. MEM_ERR;
  414. goto End;
  415. }
  416. if (pDB == NULL) {
  417. goto End;
  418. }
  419. if (!SdbReadStringTag(pDB, tagID, pszAppName, k_pszAppName)) {
  420. assert(FALSE);
  421. goto End;
  422. }
  423. pszAppName[k_pszAppName - 1] = 0;
  424. Str = pszAppName;
  425. Str.XMLToSpecialChar();
  426. End:
  427. if (pszAppName) {
  428. delete[] pszAppName;
  429. pszAppName = NULL;
  430. }
  431. return Str;
  432. }
  433. BOOL
  434. ReadAppHelp(
  435. IN PDB pdb,
  436. IN TAGID tiAppHelp,
  437. IN PDATABASE pDataBase
  438. )
  439. /*++
  440. ReadAppHelp
  441. Desc: Reads the apphelp from the library section of the database
  442. Params:
  443. IN PDB pdb: The database pdb
  444. IN TAGID tiAppHelp: The TAGID for the apphelp
  445. IN PDATABASE pDataBase: The database in which to add the apphelp
  446. Return:
  447. TRUE: The apphelp was read and added to the database
  448. FALSE: There was some error
  449. Notes: We do not read the apphelp for system database. The apphelp for system database
  450. is kept in apphelp.sdb. For system database, this function will apparently not get
  451. called
  452. --*/
  453. {
  454. TAGID tiInfo;
  455. PAPPHELP pAppHelp = NULL;
  456. if (pDataBase == NULL) {
  457. assert(FALSE);
  458. Dbg(dlError, "ReadAppHelp NULL pDataBase passed");
  459. return FALSE;
  460. }
  461. pAppHelp = new APPHELP;
  462. if (pAppHelp == NULL) {
  463. MEM_ERR;
  464. goto error;
  465. }
  466. //
  467. // Add for the specified database.
  468. //
  469. pAppHelp->pNext = pDataBase->pAppHelp;
  470. pDataBase->pAppHelp = pAppHelp;
  471. tiInfo = SdbGetFirstChild(pdb, tiAppHelp);
  472. while (0 != tiInfo) {
  473. TAG tag;
  474. tag = SdbGetTagFromTagID(pdb, tiInfo);
  475. switch (tag) {
  476. case TAG_HTMLHELPID:
  477. pAppHelp->HTMLHELPID = SdbReadDWORDTag(pdb, tiInfo, 0);
  478. //
  479. // Set the highest html id for the database. The next apphelp message
  480. // should have a value one more than this
  481. //
  482. if (pAppHelp->HTMLHELPID > pDataBase->m_nMAXHELPID) {
  483. pDataBase->m_nMAXHELPID = pAppHelp->HTMLHELPID;
  484. }
  485. break;
  486. case TAG_LINK:
  487. {
  488. TAGID tagLink = SdbFindFirstTag(pdb, tiAppHelp, TAG_LINK);
  489. //
  490. // Get the apphelp URL
  491. //
  492. if (tagLink) {
  493. tagLink = SdbFindFirstTag(pdb, tagLink, TAG_LINK_URL);
  494. pAppHelp->strURL = ReadDBString(pdb, tagLink);
  495. }
  496. }
  497. break;
  498. case TAG_APPHELP_DETAILS:
  499. //
  500. // Get the apphelp text message
  501. //
  502. pAppHelp->strMessage = ReadDBString(pdb, tiInfo);
  503. break;
  504. }
  505. tiInfo = SdbGetNextChild(pdb, tiAppHelp, tiInfo);
  506. }
  507. return TRUE;
  508. error:
  509. if (pAppHelp) {
  510. delete pAppHelp;
  511. pAppHelp = NULL;
  512. }
  513. return FALSE;
  514. }
  515. BOOL
  516. ReadIncludeExlude(
  517. IN PDB pdb,
  518. IN TAGID tiShim,
  519. OUT CSTRINGLIST& strlInExclude
  520. )
  521. /*++
  522. ReadIncludeExlude
  523. Desc: Reads the include-exclude list for a shim
  524. Params:
  525. IN PDB pdb: The database pdb
  526. IN TAGID tiShim: TAGID for TAG_SHIM or TAG_SHIM_REF
  527. OUT CSTRINGLIST& strlInExclude: The include-exclude module names will be stored in
  528. this
  529. Return:
  530. TRUE: The include-exclude list was read properly
  531. FALSE: There was some error
  532. Notes: In the .sdb the include exclude modules are arranged in this way
  533. 0x0000012E | 0x7003 | INEXCLUDE | LIST | Size 0x00000006
  534. 0x00000134 | 0x6003 | MODULE | STRINGREF | out.dll
  535. -end- INEXCLUDE
  536. 0x0000013A | 0x7003 | INEXCLUDE | LIST | Size 0x00000008
  537. 0x00000140 | 0x1001 | INCLUDE | NULL |
  538. 0x00000142 | 0x6003 | MODULE | STRINGREF | IN.DLL
  539. -end- INEXCLUDE
  540. The above means that first exclude the module out.dll then
  541. include the module in.dll
  542. --*/
  543. {
  544. TAGID tiInExclude;
  545. BOOL bReturn = FALSE;
  546. CSTRING strTemp;
  547. //
  548. // Read the INCLUSION list
  549. //
  550. tiInExclude = SdbFindFirstTag(pdb, tiShim, TAG_INEXCLUDE);
  551. if (tiInExclude == TAGID_NULL) {
  552. return FALSE;
  553. }
  554. while (tiInExclude) {
  555. TAGID tiInfo = SdbFindFirstTag(pdb, tiInExclude, TAG_INCLUDE);
  556. if (tiInfo != TAGID_NULL) {
  557. tiInfo = SdbFindFirstTag(pdb, tiInExclude, TAG_MODULE);
  558. if (tiInfo != 0) {
  559. strTemp = ReadDBString(pdb, tiInfo);
  560. if (strTemp == TEXT("$")) {
  561. //
  562. // Means include the module being fixed
  563. //
  564. strTemp = GetString(IDS_INCLUDEMODULE);
  565. }
  566. strlInExclude.AddStringAtBeg(strTemp, INCLUDE);
  567. bReturn= TRUE;
  568. }
  569. } else {
  570. //
  571. // Look for exclusions
  572. //
  573. tiInfo = SdbFindFirstTag(pdb, tiInExclude, TAG_MODULE);
  574. if (tiInfo != 0) {
  575. strTemp = ReadDBString(pdb, tiInfo);
  576. strlInExclude.AddStringAtBeg(strTemp, EXCLUDE);
  577. bReturn= TRUE;
  578. }
  579. }
  580. tiInExclude = SdbFindNextTag(pdb, tiShim, tiInExclude);
  581. }
  582. return bReturn;
  583. }
  584. BOOL
  585. AddShimFix(
  586. IN PDB pdb,
  587. IN TAGID tiFix,
  588. IN OUT PDBENTRY pEntry,
  589. IN OUT PLAYER_FIX pLayerFix,
  590. IN BOOL bAddToLayer
  591. )
  592. /*++
  593. AddShimFix
  594. Desc: Adds a shim fix list in an entry or a layer
  595. Params:
  596. IN PDB pdb: The database pdb
  597. IN TAGID tiFix: TAG_SHIM_REF
  598. IN OUT PDBENTRY pEntry: The pointer to entry if we want to add this shim to an entry
  599. IN OUT PLAYER_FIX pLayerFix: The pointer to a layer if we want to add this shim to a layer
  600. IN BOOL bAddToLayer: Do we want to add this to a layer or an entry?
  601. Return:
  602. TRUE: Shim was added properly
  603. FALSE: There was some error
  604. --*/
  605. {
  606. TAGID tiName;
  607. TCHAR szFixName[MAX_NAME];
  608. PSHIM_FIX pFix;
  609. PSHIM_FIX_LIST pFixList;
  610. BOOL bOk = TRUE;
  611. tiName = SdbFindFirstTag(pdb, tiFix, TAG_NAME);
  612. if (!SdbReadStringTag(pdb, tiName, g_wszData, ARRAYSIZE(g_wszData))) {
  613. Dbg(dlError, "Cannot read the name of the fix\n");
  614. return FALSE;
  615. }
  616. SafeCpyN(szFixName, g_wszData, ARRAYSIZE(szFixName));
  617. pFix = (PSHIM_FIX)FindFix(CSTRING(szFixName).XMLToSpecialChar(), FIX_SHIM);
  618. if (pFix == NULL) {
  619. Dbg(dlError, "Cannot find fix ref for: \"%S\" type %d\n", szFixName, FIX_SHIM);
  620. return FALSE;
  621. }
  622. pFixList = new SHIM_FIX_LIST;
  623. if (pFixList == NULL) {
  624. Dbg(dlError, "Cannot allocate %d bytes\n", sizeof(SHIM_FIX_LIST));
  625. return FALSE;
  626. }
  627. pFixList->pShimFix = pFix;
  628. tiName = SdbFindFirstTag(pdb, tiFix, TAG_COMMAND_LINE);
  629. if (tiName != TAGID_NULL) {
  630. pFixList->strCommandLine = ReadDBString(pdb, tiName);
  631. }
  632. tiName = SdbFindFirstTag(pdb, tiFix, TAG_INEXCLUDE);
  633. if (tiName != TAGID_NULL) {
  634. ReadIncludeExlude(pdb, tiFix, pFixList->strlInExclude);
  635. }
  636. if (pFix->strName.BeginsWith(TEXT("LUARedirectFS"))) {
  637. //
  638. // Get the data for LUARedirectFS shim
  639. //
  640. pFixList->pLuaData = LuaProcessLUAData(pdb, tiFix);
  641. }
  642. if (bAddToLayer == FALSE) {
  643. if (pEntry) {
  644. pFixList->pNext = pEntry->pFirstShim;
  645. pEntry->pFirstShim = pFixList;
  646. } else {
  647. assert(FALSE);
  648. Dbg(dlError, "AddShimFix bAddLayer == FALSE and pEntry == NULL");
  649. bOk = FALSE;
  650. }
  651. } else {
  652. //
  653. // We want to put this in the layer list of the library.
  654. //
  655. if (pLayerFix) {
  656. pFixList->pNext = pLayerFix->pShimFixList;
  657. pLayerFix->pShimFixList = pFixList;
  658. ++pLayerFix->uShimCount;
  659. } else {
  660. bOk = FALSE;
  661. assert(FALSE);
  662. Dbg(dlError, "AddShimFix bAddLayer == TRUE and pLayerFix == NULL");
  663. }
  664. }
  665. if (bOk == FALSE && pFixList) {
  666. assert(FALSE);
  667. delete pFixList;
  668. pFixList = NULL;
  669. }
  670. return bOk;
  671. }
  672. BOOL
  673. AddFlagFix(
  674. IN PDB pdb,
  675. IN TAGID tiFix,
  676. IN OUT PDBENTRY pEntry,
  677. IN OUT PLAYER_FIX pLayerFix,
  678. IN BOOL bAddToLayer
  679. )
  680. /*++
  681. AddFlagFix
  682. Desc: Adds a flag fix list in an entry or a layer
  683. Params:
  684. IN PDB pdb: The database pdb
  685. IN TAGID tiFix: TAG_FLAG_REF
  686. IN OUT PDBENTRY pEntry: The pointer to entry if we want to add this flag to an entry
  687. IN OUT PLAYER_FIX pLayerFix: The pointer to a layer if we want to add this flag to a layer
  688. IN BOOL bAddToLayer: Do we want to add this to a layer or an entry?
  689. Return:
  690. TRUE: Flag was added properly
  691. FALSE: There was some error
  692. --*/
  693. {
  694. TAGID tiName;
  695. TCHAR szFixName[MAX_NAME];
  696. PFLAG_FIX pFix = NULL;
  697. PFLAG_FIX_LIST pFixList = NULL;
  698. BOOL bOk = TRUE;
  699. tiName = SdbFindFirstTag(pdb, tiFix, TAG_NAME);
  700. if (!SdbReadStringTag(pdb, tiName, g_wszData, ARRAYSIZE(g_wszData))) {
  701. Dbg(dlError, "Cannot read the name of the fix\n");
  702. bOk = FALSE;
  703. goto End;
  704. }
  705. SafeCpyN(szFixName, g_wszData, ARRAYSIZE(szFixName));
  706. szFixName[ARRAYSIZE(szFixName) - 1] = 0;
  707. pFix = (PFLAG_FIX)FindFix(CSTRING(szFixName).XMLToSpecialChar(), FIX_FLAG);
  708. if (pFix == NULL) {
  709. Dbg(dlError, "Cannot find fix ref for: \"%S\" type %d\n", szFixName, FIX_FLAG);
  710. bOk = FALSE;
  711. goto End;
  712. }
  713. pFixList = new FLAG_FIX_LIST;
  714. if (pFixList == NULL) {
  715. Dbg(dlError, "Cannot allocate %d bytes\n", sizeof(FLAG_FIX_LIST));
  716. bOk = FALSE;
  717. goto End;
  718. }
  719. pFixList->pFlagFix = pFix;
  720. //
  721. // Add the commandline for flags
  722. //
  723. tiName = SdbFindFirstTag(pdb, tiFix, TAG_COMMAND_LINE);
  724. if (tiName != TAGID_NULL) {
  725. pFixList->strCommandLine = ReadDBString(pdb, tiName);
  726. }
  727. if (bAddToLayer == FALSE) {
  728. if (pEntry == NULL) {
  729. //
  730. // We wanted this flag to be added to an entry but did not give a pointer to the entry
  731. //
  732. assert(FALSE);
  733. bOk = FALSE;
  734. goto End;
  735. }
  736. pFixList->pNext = pEntry->pFirstFlag;
  737. pEntry->pFirstFlag = pFixList;
  738. } else {
  739. //
  740. // We want to put this in the layer list of the library.
  741. //
  742. if (pLayerFix == NULL) {
  743. assert(FALSE);
  744. bOk = FALSE;
  745. goto End;
  746. }
  747. pFixList->pNext = pLayerFix->pFlagFixList;
  748. pLayerFix->pFlagFixList = pFixList;
  749. ++pLayerFix->uShimCount;
  750. }
  751. End:
  752. if (bOk == FALSE) {
  753. //
  754. // There was some error, free any memory that we might have allocated in this routine
  755. //
  756. assert(FALSE);
  757. if (pFixList) {
  758. delete pFixList;
  759. pFixList = NULL;
  760. }
  761. }
  762. return bOk;
  763. }
  764. BOOL
  765. AddPatchFix(
  766. IN PDB pdb,
  767. IN TAGID tiFix,
  768. IN OUT PDBENTRY pEntry
  769. )
  770. /*++
  771. AddPatchFix
  772. Desc: Adds a patch fix list in an entry
  773. Params:
  774. IN PDB pdb: The database pdb
  775. IN TAGID tiFix: TAG_PATCH_REF
  776. IN OUT PDBENTRY pEntry: The pointer to entry that we want the patch to be added
  777. Return:
  778. TRUE: Patch was added properly
  779. FALSE: There was some error
  780. --*/
  781. {
  782. TAGID tiName;
  783. TCHAR szFixName[MAX_NAME];
  784. PPATCH_FIX pFix;
  785. PPATCH_FIX_LIST* ppHead;
  786. PPATCH_FIX_LIST pFixList;
  787. if (pEntry == NULL) {
  788. assert(FALSE);
  789. return FALSE;
  790. }
  791. tiName = SdbFindFirstTag(pdb, tiFix, TAG_NAME);
  792. if (!SdbReadStringTag(pdb, tiName, g_wszData, ARRAYSIZE(g_wszData))) {
  793. Dbg(dlError, "Cannot read the name of the fix\n");
  794. return FALSE;
  795. }
  796. SafeCpyN(szFixName, g_wszData, ARRAYSIZE(szFixName));
  797. CSTRING strTemp = szFixName;
  798. strTemp.XMLToSpecialChar();
  799. pFix = (PPATCH_FIX)FindFix(strTemp, FIX_PATCH);
  800. if (pFix == NULL) {
  801. Dbg(dlError, "Cannot find fix ref for: \"%S\" type %d\n", szFixName, FIX_PATCH);
  802. return FALSE;
  803. }
  804. ppHead = &pEntry->pFirstPatch;
  805. pFixList = new PATCH_FIX_LIST;
  806. if (pFixList == NULL) {
  807. Dbg(dlError, "Cannot allocate %d bytes\n", sizeof(PATCH_FIX_LIST));
  808. return FALSE;
  809. }
  810. pFixList->pPatchFix = pFix;
  811. pFixList->pNext = *ppHead;
  812. *ppHead = pFixList;
  813. return TRUE;
  814. }
  815. BOOL
  816. AddLayerFix(
  817. IN PDB pdb,
  818. IN TAGID tiFix,
  819. IN OUT PDBENTRY pEntry,
  820. IN PDATABASE pDataBase
  821. )
  822. /*++
  823. AddLayerFix
  824. Desc: Adds a layer fix list in an entry
  825. Params:
  826. IN PDB pdb: The database pdb
  827. IN TAGID tiFix: TAG_LAYER_REF
  828. IN OUT PDBENTRY pEntry: The pointer to entry that we want the layer to be added
  829. IN PDATABASE pDataBase: The database where this entry lives in.
  830. We need this because we need to pass the database to FindFix in case of layers.
  831. Layers can be present in the custom database as well as system database
  832. and we have to search in the custom database also to make sure that
  833. the layer name in the TAG_LAYER_REF is a valid layer.
  834. Return:
  835. TRUE: Layer was added properly
  836. FALSE: There was some error
  837. --*/
  838. {
  839. TAGID tiName;
  840. TCHAR szFixName[MAX_NAME];
  841. PLAYER_FIX pFix;
  842. PLAYER_FIX_LIST* ppHead;
  843. PLAYER_FIX_LIST pFixList;
  844. if (pEntry == NULL) {
  845. assert(FALSE);
  846. return FALSE;
  847. }
  848. tiName = SdbFindFirstTag(pdb, tiFix, TAG_NAME);
  849. if (!SdbReadStringTag(pdb, tiName, g_wszData, ARRAYSIZE(g_wszData))) {
  850. Dbg(dlError, "Cannot read the name of the fix\n");
  851. return FALSE;
  852. }
  853. SafeCpyN(szFixName, g_wszData, ARRAYSIZE(szFixName));
  854. CSTRING strTemp = szFixName;
  855. strTemp.XMLToSpecialChar();
  856. pFix = (PLAYER_FIX)FindFix(strTemp, FIX_LAYER, pDataBase);
  857. if (pFix == NULL) {
  858. assert(FALSE);
  859. Dbg(dlError, "Cannot find fix ref for: \"%S\" type %d\n", szFixName, FIX_LAYER);
  860. return FALSE;
  861. }
  862. ppHead = &pEntry->pFirstLayer;
  863. pFixList = new LAYER_FIX_LIST;
  864. if (pFixList == NULL) {
  865. Dbg(dlError, "Cannot allocate %d bytes\n", sizeof(LAYER_FIX_LIST));
  866. return FALSE;
  867. }
  868. pFixList->pLayerFix = pFix;
  869. pFixList->pNext = *ppHead;
  870. *ppHead = pFixList;
  871. return TRUE;
  872. }
  873. void
  874. ReadShimFix(
  875. IN PDB pdb,
  876. IN TAGID tiFix,
  877. IN PDATABASE pDataBase
  878. )
  879. /*++
  880. ReadShimFix
  881. Desc: Adds the shim to the database
  882. Params:
  883. IN PDB pdb: The database pdb
  884. IN TAGID tiFix: The TAGID for the shim
  885. IN PDATABASE pDataBase: The database in which to add the shim fix
  886. Return:
  887. void
  888. --*/
  889. {
  890. TAGID tiInfo;
  891. TAG tWhich;
  892. BOOL bInExcludeProcessed = FALSE;
  893. PSHIM_FIX pFix = NULL;
  894. if (pDataBase == NULL) {
  895. assert(FALSE);
  896. Dbg(dlError, "ReadShimFix NULL pDataBase passed");
  897. return;
  898. }
  899. pFix = new SHIM_FIX;
  900. if (pFix == NULL) {
  901. MEM_ERR;
  902. return;
  903. }
  904. pFix->pNext = NULL;
  905. tiInfo = SdbGetFirstChild(pdb, tiFix);
  906. while (tiInfo != 0) {
  907. tWhich = SdbGetTagFromTagID(pdb, tiInfo);
  908. switch (tWhich) {
  909. case TAG_NAME:
  910. pFix->strName = ReadDBString(pdb, tiInfo);
  911. break;
  912. case TAG_DESCRIPTION:
  913. pFix->strDescription = ReadDBString(pdb, tiInfo);
  914. break;
  915. case TAG_COMMAND_LINE:
  916. pFix->strCommandLine = ReadDBString(pdb, tiInfo);
  917. break;
  918. case TAG_GENERAL:
  919. pFix->bGeneral = TRUE;
  920. break;
  921. case TAG_INEXCLUDE:
  922. if (bInExcludeProcessed == FALSE) {
  923. ReadIncludeExlude(pdb, tiFix, pFix->strlInExclude);
  924. bInExcludeProcessed = TRUE;
  925. }
  926. break;
  927. }
  928. tiInfo = SdbGetNextChild(pdb, tiFix, tiInfo);
  929. }
  930. //
  931. // Add for the specified database.
  932. //
  933. pFix->pNext = pDataBase->pShimFixes;
  934. pDataBase->pShimFixes = pFix;
  935. if (pFix->bGeneral || g_bExpert) {
  936. ++pDataBase->uShimCount;
  937. }
  938. }
  939. void
  940. ReadLayerFix(
  941. IN PDB pdb,
  942. IN TAGID tiFix,
  943. IN PDATABASE pDataBase
  944. )
  945. /*++
  946. ReadLayerFix
  947. Desc: Adds the layer to the database
  948. Params:
  949. IN PDB pdb: The database pdb
  950. IN TAGID tiFix: The TAGID for the layer
  951. IN PDATABASE pDataBase: The database in which to add the layer
  952. Return:
  953. void
  954. --*/
  955. {
  956. TAGID tiInfo;
  957. TAG tWhich;
  958. PLAYER_FIX pFix = NULL;
  959. if (pDataBase == NULL) {
  960. assert(FALSE);
  961. Dbg(dlError, "ReadLayerFix NULL pDataBase passed");
  962. return;
  963. }
  964. pFix = new LAYER_FIX(pDataBase != &GlobalDataBase);
  965. if (!pFix) {
  966. MEM_ERR;
  967. return;
  968. }
  969. tiInfo = SdbGetFirstChild(pdb, tiFix);
  970. while (tiInfo != 0) {
  971. tWhich = SdbGetTagFromTagID(pdb, tiInfo);
  972. switch (tWhich) {
  973. case TAG_NAME:
  974. pFix->strName = ReadDBString(pdb, tiInfo);
  975. break;
  976. case TAG_SHIM_REF:
  977. AddShimFix(pdb, tiInfo, NULL, pFix, TRUE);
  978. break;
  979. case TAG_FLAG_REF:
  980. AddFlagFix(pdb, tiInfo, NULL, pFix, TRUE);
  981. break;
  982. }
  983. tiInfo = SdbGetNextChild(pdb, tiFix, tiInfo);
  984. }
  985. //
  986. // Add for the specified database.
  987. //
  988. pFix->pNext = pDataBase->pLayerFixes;
  989. pDataBase->pLayerFixes = pFix;
  990. ++pDataBase->uLayerCount;
  991. }
  992. void
  993. ReadPatchFix(
  994. IN PDB pdb,
  995. IN TAGID tiFix,
  996. IN PDATABASE pDataBase
  997. )
  998. /*++
  999. ReadPatchFix
  1000. Desc: Adds the patch to the database
  1001. Params:
  1002. IN PDB pdb: The database pdb
  1003. IN TAGID tiFix: The TAGID for the patch
  1004. IN PDATABASE pDataBase: The database in which to add the apphelp
  1005. Return:
  1006. void
  1007. --*/
  1008. {
  1009. TAGID tiInfo;
  1010. TAG tWhich;
  1011. PPATCH_FIX pFix = NULL;
  1012. if (pDataBase == NULL) {
  1013. assert(FALSE);
  1014. Dbg(dlError, "ReadPatchFix NULL pDataBase passed");
  1015. return;
  1016. }
  1017. pFix = new PATCH_FIX;
  1018. if (pFix == NULL) {
  1019. MEM_ERR;
  1020. return;
  1021. }
  1022. tiInfo = SdbGetFirstChild(pdb, tiFix);
  1023. while (tiInfo != 0) {
  1024. tWhich = SdbGetTagFromTagID(pdb, tiInfo);
  1025. switch (tWhich) {
  1026. case TAG_NAME:
  1027. pFix->strName = ReadDBString(pdb, tiInfo);
  1028. break;
  1029. case TAG_DESCRIPTION:
  1030. pFix->strDescription = ReadDBString(pdb, tiInfo);
  1031. break;
  1032. }
  1033. tiInfo = SdbGetNextChild(pdb, tiFix, tiInfo);
  1034. }
  1035. //
  1036. // Add for the specified database.
  1037. //
  1038. pFix->pNext = pDataBase->pPatchFixes;
  1039. pDataBase->pPatchFixes = pFix;
  1040. }
  1041. void
  1042. ReadFlagFix(
  1043. IN PDB pdb,
  1044. IN TAGID tiFix,
  1045. IN PDATABASE pDataBase
  1046. )
  1047. /*++
  1048. ReadFlagFix
  1049. Desc: Adds the flag to the database
  1050. Params:
  1051. IN PDB pdb: The database pdb
  1052. IN TAGID tiFix: The TAGID for the flag
  1053. IN PDATABASE pDataBase: The database in which to add the FlagFix
  1054. Return:
  1055. void
  1056. --*/
  1057. {
  1058. TAGID tiInfo;
  1059. TAG tWhich;
  1060. ULONGLONG ullUser = 0;
  1061. ULONGLONG ullKernel = 0;
  1062. PFLAG_FIX pFix = NULL;
  1063. if (pDataBase == NULL) {
  1064. assert(FALSE);
  1065. Dbg(dlError, "ReadFlagFix NULL pDataBase passed");
  1066. return;
  1067. }
  1068. pFix = new FLAG_FIX;
  1069. if (pFix == NULL) {
  1070. MEM_ERR;
  1071. return;
  1072. }
  1073. tiInfo = SdbGetFirstChild(pdb, tiFix);
  1074. while (tiInfo != 0) {
  1075. tWhich = SdbGetTagFromTagID(pdb, tiInfo);
  1076. switch (tWhich) {
  1077. case TAG_NAME:
  1078. pFix->strName = ReadDBString(pdb, tiInfo);
  1079. break;
  1080. case TAG_DESCRIPTION:
  1081. pFix->strDescription = ReadDBString(pdb, tiInfo);
  1082. break;
  1083. case TAG_COMMAND_LINE:
  1084. pFix->strCommandLine = ReadDBString(pdb, tiInfo);
  1085. break;
  1086. case TAG_GENERAL:
  1087. pFix->bGeneral = TRUE;
  1088. break;
  1089. case TAG_FLAG_MASK_USER:
  1090. ullUser = SdbReadQWORDTag(pdb, tiInfo, 0);
  1091. break;
  1092. case TAG_FLAG_MASK_KERNEL:
  1093. ullKernel = SdbReadQWORDTag(pdb, tiInfo, 0);
  1094. break;
  1095. }
  1096. tiInfo = SdbGetNextChild(pdb, tiFix, tiInfo);
  1097. }
  1098. if (ullKernel == 0) {
  1099. pFix->flagType = FLAG_USER;
  1100. pFix->ullMask = ullUser;
  1101. } else {
  1102. pFix->flagType = FLAG_KERNEL;
  1103. pFix->ullMask = ullKernel;
  1104. }
  1105. //
  1106. // Add for the specified database.
  1107. //
  1108. pFix->pNext = pDataBase->pFlagFixes;
  1109. pDataBase->pFlagFixes = pFix;
  1110. if (pFix->bGeneral || g_bExpert) {
  1111. ++pDataBase->uShimCount;
  1112. }
  1113. }
  1114. void
  1115. ReadFixes(
  1116. IN PDB pdb,
  1117. IN TAGID tiDatabase,
  1118. IN TAGID tiLibrary,
  1119. IN PDATABASE pDataBase
  1120. )
  1121. /*++
  1122. ReadFixes
  1123. Desc: Reads the apphelps, shims, patch, flag, layers for the main database
  1124. Params:
  1125. IN PDB pdb: The pdb for the database
  1126. IN TAGID tiDatabase: The tagid for the database
  1127. IN TAGID tiLibrary: The tagid for the library
  1128. IN PDATABASE pDataBase: The database in which to add all the fixes
  1129. Return:
  1130. void
  1131. --*/
  1132. {
  1133. TAGID tiFix;
  1134. if (pDataBase == NULL) {
  1135. assert(FALSE);
  1136. Dbg(dlError, "ReadFixes NULL pDataBase passed");
  1137. return;
  1138. }
  1139. tiFix = SdbFindFirstTag(pdb, tiDatabase, TAG_APPHELP);
  1140. //
  1141. // Read all apphelp messages for this database
  1142. //
  1143. while (tiFix) {
  1144. ReadAppHelp(pdb, tiFix, pDataBase);
  1145. tiFix = SdbFindNextTag(pdb, tiDatabase, tiFix);
  1146. }
  1147. tiFix = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM);
  1148. //
  1149. // Read all shims for this database
  1150. //
  1151. while (tiFix != 0) {
  1152. ReadShimFix(pdb, tiFix, pDataBase);
  1153. tiFix = SdbFindNextTag(pdb, tiLibrary, tiFix);
  1154. }
  1155. tiFix = SdbFindFirstTag(pdb, tiLibrary, TAG_PATCH);
  1156. //
  1157. // Read all patches for this database
  1158. //
  1159. while (tiFix != 0) {
  1160. ReadPatchFix(pdb, tiFix, pDataBase);
  1161. tiFix = SdbFindNextTag(pdb, tiLibrary, tiFix);
  1162. }
  1163. tiFix = SdbFindFirstTag(pdb, tiLibrary, TAG_FLAG);
  1164. //
  1165. // Read all flags for this database
  1166. //
  1167. while (tiFix != 0) {
  1168. ReadFlagFix(pdb, tiFix, pDataBase);
  1169. tiFix = SdbFindNextTag(pdb, tiLibrary, tiFix);
  1170. }
  1171. //
  1172. // Note: The LAYERs are under the DATABASE tag instead of LIBRARY
  1173. //
  1174. tiFix = SdbFindFirstTag(pdb, tiDatabase, TAG_LAYER);
  1175. //
  1176. // Read all layers for this database
  1177. //
  1178. while (tiFix != 0) {
  1179. ReadLayerFix(pdb, tiFix, pDataBase);
  1180. tiFix = SdbFindNextTag(pdb, tiDatabase, tiFix);
  1181. }
  1182. }
  1183. BOOL
  1184. AddMatchingFile(
  1185. IN PDB pdb,
  1186. IN TAGID tiMatch,
  1187. IN PDBENTRY pEntry
  1188. )
  1189. /*++
  1190. AddMatchingFile
  1191. Desc: Reads the matching file entry from the database and adds it to the entry
  1192. Params:
  1193. IN PDB pdb: The database pdb
  1194. IN TAGID tiMatch: The tag id for the matching file
  1195. IN PDBENTRY pEntry: The entry in which we want to add the matching file
  1196. Return:
  1197. FALSE: There was some error
  1198. TRUE: Successful
  1199. --*/
  1200. {
  1201. TAGID tiMatchInfo;
  1202. TAG tWhich;
  1203. PMATCHINGFILE pMatch;
  1204. DWORD dwValue;
  1205. DWORD dwPos; //Position of the tag in the g_rgAttributeTags array.
  1206. LARGE_INTEGER ullValue;
  1207. if (pEntry == NULL) {
  1208. assert(FALSE);
  1209. return FALSE;
  1210. }
  1211. pMatch = (PMATCHINGFILE) new MATCHINGFILE;
  1212. if (pMatch == NULL) {
  1213. MEM_ERR;
  1214. return FALSE;
  1215. }
  1216. pMatch->dwMask = 0;
  1217. PATTRINFO_NEW pAttr = pMatch->attributeList.pAttribute;
  1218. tiMatchInfo = SdbGetFirstChild(pdb, tiMatch);
  1219. while (tiMatchInfo != 0) {
  1220. tWhich = SdbGetTagFromTagID(pdb, tiMatchInfo);
  1221. dwPos = TagToIndex(tWhich);
  1222. UINT tagType = GETTAGTYPE(tWhich);
  1223. switch (tagType) {
  1224. case TAG_TYPE_DWORD:
  1225. dwValue = SdbReadDWORDTag(pdb, tiMatchInfo, -1);
  1226. if (dwValue != -1 && dwPos != -1) {
  1227. pMatch->dwMask |= (1 << (dwPos + 1));
  1228. pAttr[dwPos].tAttrID = tWhich;
  1229. pAttr[dwPos].dwFlags |= ATTRIBUTE_AVAILABLE;
  1230. pAttr[dwPos].dwAttr = dwValue;
  1231. }
  1232. break;
  1233. case TAG_TYPE_QWORD:
  1234. ullValue.QuadPart = SdbReadQWORDTag(pdb, tiMatchInfo, 0);
  1235. if ((ullValue.HighPart != 0 || ullValue.LowPart != 0) && dwPos != -1) {
  1236. pMatch->dwMask |= (1 << (dwPos + 1));
  1237. pAttr[dwPos].tAttrID = tWhich;
  1238. pAttr[dwPos].dwFlags |= ATTRIBUTE_AVAILABLE;
  1239. pAttr[dwPos].ullAttr = ullValue.QuadPart;
  1240. }
  1241. break;
  1242. case TAG_TYPE_STRINGREF:
  1243. {
  1244. CSTRING str = ReadDBString(pdb, tiMatchInfo);
  1245. //
  1246. // NOTE: The TAG_NAME is not present in the g_rgAttributeTags array !!!
  1247. //
  1248. if (str.Length() > 0 && (tWhich == TAG_NAME || dwPos != -1)) {
  1249. if (tWhich == TAG_NAME) {
  1250. pMatch->strMatchName = str;
  1251. } else {
  1252. pMatch->dwMask |= (1 << (dwPos + 1));
  1253. pAttr[dwPos].tAttrID = tWhich;
  1254. pAttr[dwPos].dwFlags |= ATTRIBUTE_AVAILABLE;
  1255. pAttr[dwPos].strValue = str;
  1256. pAttr[dwPos].lpAttr = pAttr[dwPos].strValue.pszString;
  1257. }
  1258. }
  1259. }
  1260. break;
  1261. }
  1262. tiMatchInfo = SdbGetNextChild(pdb, tiMatch, tiMatchInfo);
  1263. }
  1264. pMatch->pNext = pEntry->pFirstMatchingFile;
  1265. pEntry->pFirstMatchingFile = pMatch;
  1266. (pEntry->nMatchingFiles)++;
  1267. return TRUE;
  1268. }
  1269. PAPPHELP
  1270. FindAppHelp(
  1271. IN DWORD HTMLHELPID,
  1272. IN PDATABASE pDataBase
  1273. )
  1274. /*++
  1275. FindAppHelp
  1276. Desc: Finds the apphelp with id HTMLHELPID in the database pDataBaseIn
  1277. Params:
  1278. IN DWORD HTMLHELPID: The htmlhelp id to look for
  1279. IN PDATABASE pDataBase: The database to look in.
  1280. Return: If found the corresponding PAPPHELP or NULL if not found
  1281. --*/
  1282. {
  1283. PAPPHELP pAppHelp = NULL;
  1284. if (pDataBase == NULL) {
  1285. assert(FALSE);
  1286. Dbg(dlError, "FindAppHelp NULL pDataBase passed");
  1287. return NULL;
  1288. }
  1289. pAppHelp = pDataBase->pAppHelp;
  1290. while (pAppHelp) {
  1291. if (pAppHelp->HTMLHELPID == HTMLHELPID) {
  1292. return pAppHelp;
  1293. } else {
  1294. pAppHelp = pAppHelp->pNext;
  1295. }
  1296. }
  1297. return NULL;
  1298. }
  1299. PDBENTRY
  1300. AddExeInApp(
  1301. IN PDBENTRY pEntry,
  1302. OUT BOOL* pbNew,
  1303. IN PDATABASE pDataBase
  1304. )
  1305. /*++
  1306. AddExeInApp
  1307. Desc: Adds the entry pEntry in the database pDataBaseIn
  1308. Params:
  1309. IN PDBENTRY pEntry: The entry to add
  1310. OUT BOOL* pbNew: Will be true if this is a new app
  1311. IN PDATABASE pDataBase: The database to add into
  1312. Return: Returns the PDBENTRY for the parent App.
  1313. --*/
  1314. {
  1315. if (pDataBase == NULL) {
  1316. assert(FALSE);
  1317. Dbg(dlError, "AddExeInApp NULL pDataBase passed");
  1318. return NULL;
  1319. }
  1320. //
  1321. // Now add this entry in its correct position for the app.
  1322. //
  1323. for (PDBENTRY pApps = pDataBase->pEntries, pAppsPrev = NULL;
  1324. pApps;
  1325. pAppsPrev = pApps, pApps = pApps->pNext) {
  1326. if (pApps->strAppName == pEntry->strAppName) {
  1327. //
  1328. // We insert the new entry at the head of the app
  1329. //
  1330. if (pAppsPrev == NULL) {
  1331. pDataBase->pEntries = pEntry;
  1332. } else {
  1333. pAppsPrev->pNext = pEntry;
  1334. }
  1335. pEntry->pNext = pApps->pNext;
  1336. pApps->pNext = NULL;
  1337. pEntry->pSameAppExe = pApps;
  1338. if (pbNew != NULL) {
  1339. *pbNew = FALSE;
  1340. }
  1341. return pApps;
  1342. }
  1343. }
  1344. //
  1345. // This an entry for a new app.
  1346. //
  1347. pEntry->pNext = pDataBase->pEntries;
  1348. pDataBase->pEntries = pEntry;
  1349. ++pDataBase->uAppCount;
  1350. if (pbNew != NULL) {
  1351. *pbNew = TRUE;
  1352. }
  1353. return pEntry;
  1354. }
  1355. PDBENTRY
  1356. AddEntry(
  1357. IN PDB pdb,
  1358. IN TAGID tiExe,
  1359. IN PDATABASE pDataBase
  1360. )
  1361. /*++
  1362. AddEntry
  1363. Desc: Reads a new entry from the database
  1364. Params:
  1365. IN PDB pdb: The database pdb
  1366. IN TAGID tiExe: The tagid of the exe
  1367. IN PDATABASE pDataBase: The database in which to perform this operation
  1368. Return: Pointer to the entry read. PDBENTRY
  1369. --*/
  1370. {
  1371. TAGID tiExeInfo;
  1372. TAGID tiSeverity, tiHelpId;
  1373. TAG tWhich;
  1374. PDBENTRY pEntry = NULL;
  1375. if (pDataBase == NULL) {
  1376. assert(FALSE);
  1377. Dbg(dlError, "AddEntry NULL pDataBase passed");
  1378. return NULL;
  1379. }
  1380. tiExeInfo = SdbGetFirstChild(pdb, tiExe);
  1381. pEntry = new DBENTRY;
  1382. if (pEntry == NULL) {
  1383. Dbg(dlError, "Cannot allocate %d bytes\n", sizeof(DBENTRY));
  1384. MEM_ERR;
  1385. return NULL;
  1386. }
  1387. pEntry->tiExe = tiExe;
  1388. while (tiExeInfo != 0) {
  1389. tWhich = SdbGetTagFromTagID(pdb, tiExeInfo);
  1390. switch (tWhich) {
  1391. case TAG_NAME:
  1392. pEntry->strExeName = ReadDBString(pdb, tiExeInfo);
  1393. break;
  1394. case TAG_APP_NAME:
  1395. pEntry->strAppName = ReadDBString(pdb, tiExeInfo);
  1396. break;
  1397. case TAG_VENDOR:
  1398. pEntry->strVendor = ReadDBString(pdb, tiExeInfo);
  1399. break;
  1400. case TAG_MATCHING_FILE:
  1401. AddMatchingFile(pdb, tiExeInfo, pEntry);
  1402. break;
  1403. case TAG_APPHELP:
  1404. pEntry->appHelp.bPresent = TRUE;
  1405. tiSeverity = SdbFindFirstTag(pdb, tiExeInfo, TAG_PROBLEMSEVERITY);
  1406. pEntry->appHelp.severity = (SEVERITY)SdbReadDWORDTag(pdb, tiSeverity, 0);
  1407. if (pEntry->appHelp.severity == APPTYPE_INC_HARDBLOCK) {
  1408. pEntry->appHelp.bBlock = TRUE;
  1409. } else {
  1410. pEntry->appHelp.bBlock = FALSE;
  1411. }
  1412. tiHelpId = SdbFindFirstTag(pdb, tiExeInfo, TAG_HTMLHELPID);
  1413. pEntry->appHelp.HTMLHELPID = SdbReadDWORDTag(pdb, tiHelpId, 0);
  1414. if (pDataBase == &GlobalDataBase) {
  1415. //
  1416. // We do not wish to keep the apphelp data for main database in memory
  1417. // Too big.. So we will load it from apphelp.sdb whenever we will need it
  1418. // But still we will have to do the following so that the type of the lParam of
  1419. // the tree-item in the entry tree is TYPE_APPHELP, so that when we select that
  1420. // we know that it is for apphelp
  1421. //
  1422. pEntry->appHelp.pAppHelpinLib = (PAPPHELP)TYPE_APPHELP_ENTRY;
  1423. } else {
  1424. pEntry->appHelp.pAppHelpinLib = FindAppHelp(pEntry->appHelp.HTMLHELPID, pDataBase);
  1425. }
  1426. break;
  1427. case TAG_SHIM_REF:
  1428. AddShimFix(pdb, tiExeInfo, pEntry, NULL, FALSE);
  1429. break;
  1430. case TAG_FLAG_REF:
  1431. AddFlagFix(pdb, tiExeInfo, pEntry, NULL, FALSE);
  1432. break;
  1433. case TAG_PATCH_REF:
  1434. AddPatchFix(pdb, tiExeInfo, pEntry);
  1435. break;
  1436. case TAG_LAYER:
  1437. AddLayerFix(pdb, tiExeInfo, pEntry, pDataBase);
  1438. break;
  1439. case TAG_EXE_ID:
  1440. {
  1441. GUID* pGuid = NULL;
  1442. pGuid = (GUID*)SdbGetBinaryTagData(pdb, tiExeInfo);
  1443. if (pGuid != NULL) {
  1444. StringCchPrintf(pEntry->szGUID,
  1445. ARRAYSIZE(pEntry->szGUID),
  1446. TEXT ("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  1447. pGuid->Data1,
  1448. pGuid->Data2,
  1449. pGuid->Data3,
  1450. pGuid->Data4[0],
  1451. pGuid->Data4[1],
  1452. pGuid->Data4[2],
  1453. pGuid->Data4[3],
  1454. pGuid->Data4[4],
  1455. pGuid->Data4[5],
  1456. pGuid->Data4[6],
  1457. pGuid->Data4[7]);
  1458. }
  1459. break;
  1460. }
  1461. default:
  1462. break;
  1463. }
  1464. tiExeInfo = SdbGetNextChild(pdb, tiExe, tiExeInfo);
  1465. }
  1466. pEntry->bDisablePerMachine = CheckRegistry(HKEY_LOCAL_MACHINE, pEntry->szGUID);
  1467. pEntry->bDisablePerUser = CheckRegistry(HKEY_CURRENT_USER, pEntry->szGUID);
  1468. //
  1469. // Search the application where this entry should go and add it
  1470. //
  1471. AddExeInApp(pEntry, (BOOL*)NULL, pDataBase);
  1472. return pEntry;
  1473. }
  1474. BOOL
  1475. LookUpEntryProperties(
  1476. IN PDB pdb,
  1477. IN TAGID tiExe,
  1478. OUT BOOL* pbLayers,
  1479. OUT BOOL* pbShims,
  1480. OUT BOOL* pbPatches,
  1481. OUT BOOL* pbFlags,
  1482. OUT BOOL* pbAppHelp,
  1483. OUT CSTRING& strAppName
  1484. )
  1485. /*++
  1486. LookUpEntryProperties
  1487. Desc: Checks if the entry has shims, layers, flags, patches, or apphelp. NULL values
  1488. for the various BOOL* is allowed
  1489. Params:
  1490. IN PDB pdb: The database pdb
  1491. IN TAGID tiExe: The TAGID of the entry whose properties we want to check
  1492. OUT BOOL* pbLayers: Does the entry have layers?
  1493. OUT BOOL* pbShims: Does the entry have shims?
  1494. OUT BOOL* pbPatches: Does the entry have patches?
  1495. OUT BOOL* pbFlags: Does the entry have flags?
  1496. OUT BOOL* pbAppHelp: Does the entry have apphelp?
  1497. OUT CSTRING& strAppName: The name of the application of this entry
  1498. Return: TRUE: The routine was able to obtain the info for the entry,
  1499. FALSE: otherwise
  1500. --*/
  1501. {
  1502. TAGID tiExeInfo;
  1503. TAG tWhich;
  1504. BOOL bOk = TRUE;
  1505. tiExeInfo = SdbGetFirstChild(pdb, tiExe);
  1506. while (tiExeInfo != 0) {
  1507. tWhich = SdbGetTagFromTagID(pdb, tiExeInfo);
  1508. switch (tWhich) {
  1509. case TAG_APP_NAME:
  1510. strAppName = ReadDBString(pdb, tiExeInfo);
  1511. break;
  1512. case TAG_APPHELP:
  1513. if (pbAppHelp) {
  1514. *pbAppHelp = TRUE;
  1515. }
  1516. break;
  1517. case TAG_SHIM_REF:
  1518. if (pbShims) {
  1519. *pbShims = TRUE;
  1520. }
  1521. break;
  1522. case TAG_FLAG_REF:
  1523. if (pbFlags) {
  1524. *pbFlags = TRUE;
  1525. }
  1526. break;
  1527. case TAG_PATCH_REF:
  1528. if (pbPatches) {
  1529. *pbPatches = TRUE;
  1530. }
  1531. break;
  1532. case TAG_LAYER:
  1533. if (pbLayers) {
  1534. *pbLayers = TRUE;
  1535. }
  1536. break;
  1537. }
  1538. tiExeInfo = SdbGetNextChild(pdb, tiExe, tiExeInfo);
  1539. }
  1540. return bOk;
  1541. }
  1542. void
  1543. DeleteShimFixList(
  1544. IN PSHIM_FIX_LIST psl
  1545. )
  1546. /*++
  1547. DeleteShimFixList
  1548. Desc: Deletes this PSHIM_FIX_LIST and all PSHIM_FIX_LIST in this chain
  1549. Params:
  1550. IN PSHIM_FIX_LIST psl: The PSHIM_FIX_LIST to delete.
  1551. Note: Caller must NULLify this argument
  1552. Return:
  1553. void
  1554. --*/
  1555. {
  1556. PSHIM_FIX_LIST pslNext;
  1557. while (psl) {
  1558. pslNext = psl->pNext;
  1559. if (psl->pLuaData) {
  1560. delete psl->pLuaData;
  1561. psl->pLuaData = NULL;
  1562. }
  1563. delete psl;
  1564. psl = pslNext;
  1565. }
  1566. }
  1567. void
  1568. DeletePatchFixList(
  1569. IN PPATCH_FIX_LIST pPat
  1570. )
  1571. /*++
  1572. DeletePatchFixList
  1573. Desc: Deletes this PPATCH_FIX_LIST and all PPATCH_FIX_LIST in this chain
  1574. Params:
  1575. IN PPATCH_FIX_LIST pPat: The PPATCH_FIX_LIST to delete.
  1576. Note: Caller must NULLify this argument
  1577. Return:
  1578. void
  1579. --*/
  1580. {
  1581. PPATCH_FIX_LIST pPatNext;
  1582. while (pPat) {
  1583. pPatNext = pPat->pNext;
  1584. delete (pPat);
  1585. pPat = pPatNext;
  1586. }
  1587. }
  1588. void
  1589. DeleteLayerFixList(
  1590. IN PLAYER_FIX_LIST pll
  1591. )
  1592. /*++
  1593. DeleteLayerFixList
  1594. Desc: Deletes this PLAYER_FIX_LIST and all PLAYER_FIX_LIST in this chain
  1595. Note: Caller must NULLify this argument
  1596. Params:
  1597. IN PLAYER_FIX_LIST pll: The PLAYER_FIX_LIST to delete.
  1598. Return:
  1599. void
  1600. --*/
  1601. {
  1602. PLAYER_FIX_LIST pllNext;
  1603. while (pll) {
  1604. pllNext = pll->pNext;
  1605. delete (pll);
  1606. pll = pllNext;
  1607. }
  1608. }
  1609. void
  1610. DeleteFlagFixList(
  1611. IN PFLAG_FIX_LIST pfl
  1612. )
  1613. /*++
  1614. DeleteFlagFixList
  1615. Desc: Deletes this PFLAG_FIX_LIST and all PFLAG_FIX_LIST in this chain
  1616. Note: Caller must NULLify this argument
  1617. Params:
  1618. IN PFLAG_FIX_LIST pfl: The PFLAG_FIX_LIST to delete.
  1619. Return:
  1620. void
  1621. --*/
  1622. {
  1623. PFLAG_FIX_LIST pflNext;
  1624. while (pfl) {
  1625. pflNext = pfl->pNext;
  1626. delete (pfl);
  1627. pfl = pflNext;
  1628. }
  1629. }
  1630. void
  1631. DeleteMatchingFiles(
  1632. IN PMATCHINGFILE pMatch
  1633. )
  1634. /*++
  1635. DeleteMatchingFiles
  1636. Desc: Deletes this PMATCHINGFILE and all PMATCHINGFILE in this chain
  1637. Note: Caller must NULLify this argument
  1638. Params:
  1639. IN PMATCHINGFILE pMatch: The PMATCHINGFILE to delete.
  1640. Return:
  1641. void
  1642. --*/
  1643. {
  1644. PMATCHINGFILE pMatchNext;
  1645. while (pMatch) {
  1646. pMatchNext = pMatch->pNext;
  1647. delete (pMatch);
  1648. pMatch = pMatchNext;
  1649. }
  1650. }
  1651. BOOL
  1652. WriteXML(
  1653. IN CSTRING& szFilename,
  1654. IN CSTRINGLIST* pString
  1655. )
  1656. /*++
  1657. WriteXML
  1658. Desc: Writes the XML contained in pString to file szFilename. CSTRINGLIST is a linked
  1659. list of CSTRING, and a node contains one line of XML to be written to the file
  1660. Params:
  1661. IN CSTRING& szFilename: The name of the file
  1662. IN CSTRINGLIST* pString: Linked list of CSTRING containing the XML.
  1663. Each node contains one line of XML to be written to the file
  1664. Return:
  1665. TRUE: Success
  1666. FALSE: There was some error
  1667. --*/
  1668. {
  1669. BOOL bOk = TRUE;
  1670. HANDLE hFile = NULL;
  1671. PSTRLIST pTemp = NULL;
  1672. TCHAR chUnicodeID = 0xFEFF; // Ensure that the file is saved as unicode
  1673. TCHAR szCR[] = {TEXT('\r'), TEXT('\n')};
  1674. DWORD dwBytesWritten;
  1675. CSTRING szTemp;
  1676. if (NULL == pString) {
  1677. bOk = FALSE;
  1678. goto End;
  1679. }
  1680. pTemp = pString->m_pHead;
  1681. hFile = CreateFile((LPCTSTR)szFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1682. if (INVALID_HANDLE_VALUE == hFile) {
  1683. bOk = FALSE;
  1684. goto End;
  1685. }
  1686. if (!WriteFile(hFile, &chUnicodeID, sizeof(chUnicodeID) , &dwBytesWritten, NULL)) {
  1687. assert(FALSE);
  1688. bOk = FALSE;
  1689. goto End;
  1690. }
  1691. while (NULL != pTemp) {
  1692. if (!WriteFile(hFile,
  1693. pTemp->szStr.pszString,
  1694. pTemp->szStr.Length() * sizeof(TCHAR) ,
  1695. &dwBytesWritten,
  1696. NULL)) {
  1697. bOk = FALSE;
  1698. goto End;
  1699. }
  1700. if (!WriteFile(hFile, szCR, sizeof(szCR) , &dwBytesWritten, NULL)) {
  1701. bOk = FALSE;
  1702. goto End;
  1703. }
  1704. pTemp = pTemp->pNext;
  1705. }
  1706. End:
  1707. if (hFile != INVALID_HANDLE_VALUE) {
  1708. CloseHandle(hFile);
  1709. }
  1710. return bOk;
  1711. }
  1712. void
  1713. CleanupDbSupport(
  1714. IN PDATABASE pDataBase
  1715. )
  1716. /*++
  1717. CleanupDbSupport
  1718. Desc: Deletes the data structures associated with a PDATABASE. This should be called
  1719. when we are going to close a database or we are going to delete a database.
  1720. We should call this function before we do a delete PDATABASE
  1721. Params:
  1722. IN PDATABASE pDataBase: The pointer to the database
  1723. Return:
  1724. void
  1725. --*/
  1726. {
  1727. if (pDataBase == NULL) {
  1728. assert(FALSE);
  1729. return;
  1730. }
  1731. //
  1732. // Free the Library section for the local database
  1733. //
  1734. //
  1735. // Free the shims
  1736. //
  1737. PSHIM_FIX pShimFixNext;
  1738. while (pDataBase->pShimFixes) {
  1739. pShimFixNext = pDataBase->pShimFixes->pNext;
  1740. delete (pDataBase->pShimFixes);
  1741. pDataBase->pShimFixes = pShimFixNext;
  1742. }
  1743. //
  1744. // Free the patches
  1745. //
  1746. PPATCH_FIX pPatchFixNext;
  1747. while (pDataBase->pPatchFixes) {
  1748. pPatchFixNext = pDataBase->pPatchFixes->pNext;
  1749. delete (pDataBase->pPatchFixes);
  1750. pDataBase->pPatchFixes = pPatchFixNext;
  1751. }
  1752. //
  1753. // Free the flags
  1754. //
  1755. PFLAG_FIX pFlagFixNext;
  1756. while (pDataBase->pFlagFixes) {
  1757. pFlagFixNext = pDataBase->pFlagFixes->pNext;
  1758. delete(pDataBase->pFlagFixes);
  1759. pDataBase->pFlagFixes = pFlagFixNext;
  1760. }
  1761. //
  1762. // Free the layers.
  1763. //
  1764. PLAYER_FIX pLayerFixNext;
  1765. while (pDataBase->pLayerFixes) {
  1766. pLayerFixNext = pDataBase->pLayerFixes->pNext;
  1767. //
  1768. // Delete the shim list for this layer
  1769. //
  1770. DeleteShimFixList(pDataBase->pLayerFixes->pShimFixList);
  1771. //
  1772. // Delete the flags for this layer
  1773. //
  1774. DeleteFlagFixList(pDataBase->pLayerFixes->pFlagFixList);
  1775. delete (pDataBase->pLayerFixes);
  1776. pDataBase->pLayerFixes = pLayerFixNext;
  1777. }
  1778. //
  1779. // Free the AppHelp
  1780. //
  1781. PAPPHELP pAppHelpNext;
  1782. while (pDataBase->pAppHelp) {
  1783. pAppHelpNext = pDataBase->pAppHelp->pNext;
  1784. delete pDataBase->pAppHelp;
  1785. pDataBase->pAppHelp = pAppHelpNext;
  1786. }
  1787. //
  1788. // Free the exes of the local database.
  1789. //
  1790. PDBENTRY pEntryNext = NULL;
  1791. PDBENTRY pApp = pDataBase->pEntries, pEntry = pDataBase->pEntries;
  1792. while (pApp) {
  1793. pEntry = pApp;
  1794. pApp = pApp->pNext;
  1795. while (pEntry) {
  1796. pEntryNext = pEntry->pSameAppExe;
  1797. delete pEntry;
  1798. pEntry = pEntryNext;
  1799. }
  1800. }
  1801. pDataBase->pEntries = NULL;
  1802. }
  1803. BOOL
  1804. GetDatabaseEntries(
  1805. IN PCTSTR szFullPath,
  1806. IN PDATABASE pDataBase
  1807. )
  1808. /*++
  1809. GetDatabaseEntries
  1810. Desc: Reads in database contents.
  1811. If this is the system database, then we only read in the
  1812. fix entries as the library section has been already read when we started up.
  1813. For other databases reads in both the library section and the entries
  1814. Params:
  1815. IN PCTSTR szFullPath: Full path of the database. If NULL we load the system database
  1816. IN PDATABASE pDataBase: Pointer to the database that we are going to populate
  1817. Return:
  1818. TRUE: Success
  1819. FALSE: Failure
  1820. --*/
  1821. {
  1822. CSTRING strMessage;
  1823. TAGID tiDatabase, tiLibrary, tiExe;
  1824. BOOL bOk = TRUE;
  1825. WCHAR wszShimDB[MAX_PATH * 2] = L"";
  1826. PDB pdb = NULL;
  1827. UINT uResult = 0;
  1828. if (pDataBase == NULL) {
  1829. assert(FALSE);
  1830. return FALSE;
  1831. }
  1832. SetCursor(LoadCursor(NULL, IDC_WAIT));
  1833. if (pDataBase == &GlobalDataBase) {
  1834. uResult = GetSystemWindowsDirectoryW(wszShimDB, MAX_PATH);
  1835. if (uResult == 0 || uResult >= MAX_PATH) {
  1836. bOk = FALSE;
  1837. goto Cleanup;
  1838. }
  1839. ADD_PATH_SEPARATOR(wszShimDB, ARRAYSIZE(wszShimDB));
  1840. StringCchCat(wszShimDB, ARRAYSIZE(wszShimDB), TEXT("AppPatch\\sysmain.sdb"));
  1841. } else {
  1842. if (StringCchPrintf(wszShimDB, ARRAYSIZE(wszShimDB), TEXT("%s"), szFullPath) != S_OK) {
  1843. bOk = FALSE;
  1844. goto Cleanup_Msg;
  1845. }
  1846. pDataBase->strPath = wszShimDB;
  1847. }
  1848. //
  1849. // Open the database.
  1850. //
  1851. pdb = SdbOpenDatabase(wszShimDB, DOS_PATH);
  1852. if (pdb == NULL) {
  1853. Dbg(dlError, "Cannot open shim DB \"%ws\"\n", wszShimDB);
  1854. bOk = FALSE;
  1855. goto Cleanup_Msg;
  1856. }
  1857. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  1858. if (tiDatabase == 0) {
  1859. Dbg(dlError, "Cannot find TAG_DATABASE\n");
  1860. bOk = FALSE;
  1861. goto Cleanup_Msg;
  1862. }
  1863. TAGID tiGuid = SdbFindFirstTag(pdb, tiDatabase, TAG_DATABASE_ID);
  1864. TAGID tName = NULL;
  1865. //
  1866. // Get the guid for the database
  1867. //
  1868. if (0 != tiGuid) {
  1869. GUID* pGuid;
  1870. pGuid = (GUID*)SdbGetBinaryTagData(pdb, tiGuid);
  1871. TCHAR szGuid[128];
  1872. *szGuid = 0;
  1873. if (pGuid != NULL) {
  1874. StringCchPrintf(szGuid,
  1875. ARRAYSIZE(szGuid),
  1876. TEXT ("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  1877. pGuid->Data1,
  1878. pGuid->Data2,
  1879. pGuid->Data3,
  1880. pGuid->Data4[0],
  1881. pGuid->Data4[1],
  1882. pGuid->Data4[2],
  1883. pGuid->Data4[3],
  1884. pGuid->Data4[4],
  1885. pGuid->Data4[5],
  1886. pGuid->Data4[6],
  1887. pGuid->Data4[7]);
  1888. if (pDataBase != &GlobalDataBase &&
  1889. (!lstrcmpi(szGuid, GlobalDataBase.szGUID)
  1890. || !lstrcmpi(szGuid, GUID_APPHELP_SDB)
  1891. || !lstrcmpi(szGuid, GUID_SYSTEST_SDB)
  1892. || !lstrcmpi(szGuid, GUID_MSI_SDB)
  1893. || !lstrcmpi(szGuid, GUID_DRVMAIN_SDB))) {
  1894. MessageBox(g_hDlg,
  1895. CSTRING(IDS_ERROR_SYSDB),
  1896. g_szAppName,
  1897. MB_ICONERROR);
  1898. bOk = FALSE;
  1899. goto Cleanup;
  1900. }
  1901. SafeCpyN(pDataBase->szGUID, szGuid, ARRAYSIZE(pDataBase->szGUID));
  1902. //
  1903. // Get the name of the database
  1904. //
  1905. tName = SdbFindFirstTag(pdb, tiDatabase, TAG_NAME);
  1906. if (0 != tName) {
  1907. pDataBase->strName = ReadDBString(pdb, tName);
  1908. }
  1909. } else {
  1910. bOk = FALSE;
  1911. goto Cleanup_Msg;
  1912. }
  1913. } else {
  1914. bOk = FALSE;
  1915. goto Cleanup_Msg;
  1916. }
  1917. if ((pDataBase->type == DATABASE_TYPE_WORKING) && CheckInstalled(pDataBase->strPath,
  1918. pDataBase->szGUID)) {
  1919. MessageBox(g_hDlg,
  1920. GetString(IDS_TRYOPENINSTALLED),
  1921. g_szAppName,
  1922. MB_ICONWARNING);
  1923. bOk = FALSE;
  1924. goto Cleanup;
  1925. }
  1926. tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
  1927. if (tiLibrary == 0) {
  1928. Dbg(dlError, "Cannot find TAG_LIBRARY\n");
  1929. bOk = FALSE;
  1930. goto Cleanup_Msg;
  1931. }
  1932. if (pDataBase != &GlobalDataBase) {
  1933. //
  1934. // Fixes for the main database have been read when the program started.
  1935. //
  1936. ReadFixes(pdb, tiDatabase, tiLibrary, pDataBase);
  1937. }
  1938. //
  1939. // Loop through the EXEs.
  1940. //
  1941. tiExe = SdbFindFirstTag(pdb, tiDatabase, TAG_EXE);
  1942. while (tiExe != TAGID_NULL) {
  1943. AddEntry(pdb, tiExe, pDataBase);
  1944. tiExe = SdbFindNextTag(pdb, tiDatabase, tiExe);
  1945. }
  1946. //
  1947. // Add the pDataBase to the DATABASELIST
  1948. //
  1949. if (pDataBase->type == DATABASE_TYPE_WORKING) {
  1950. DataBaseList.Add(pDataBase);
  1951. }
  1952. goto Cleanup;
  1953. Cleanup_Msg:
  1954. strMessage.Sprintf(GetString(IDS_ERROROPEN), wszShimDB);
  1955. MessageBox(g_hDlg,
  1956. strMessage,
  1957. g_szAppName,
  1958. MB_ICONERROR);
  1959. Cleanup:
  1960. if (pdb != NULL) {
  1961. SdbCloseDatabase(pdb);
  1962. }
  1963. if (bOk == FALSE) {
  1964. CleanupDbSupport(pDataBase);
  1965. }
  1966. SetCursor(LoadCursor(NULL, IDC_ARROW));
  1967. return bOk;
  1968. }
  1969. BOOL
  1970. ReadMainDataBase(
  1971. void
  1972. )
  1973. /*++
  1974. ReadMainDataBase
  1975. Desc: Read the library section of the main database
  1976. Return:
  1977. TRUE: The library section of the main database was read successfully
  1978. FALSE: Otherwise
  1979. --*/
  1980. {
  1981. PDB pdb;
  1982. TAGID tiDatabase, tiLibrary;
  1983. BOOL bOk = TRUE;
  1984. TCHAR szShimDB[MAX_PATH * 2] = TEXT("");
  1985. TAGID tName, tiGuid;
  1986. UINT uResult = 0;
  1987. tiDatabase = tiLibrary = tName = tiGuid = NULL;
  1988. uResult = GetSystemWindowsDirectory(szShimDB, MAX_PATH);
  1989. if (uResult == 0 || uResult >= MAX_PATH) {
  1990. assert(FALSE);
  1991. return FALSE;
  1992. }
  1993. ADD_PATH_SEPARATOR(szShimDB, ARRAYSIZE(szShimDB));
  1994. StringCchCat(szShimDB, ARRAYSIZE(szShimDB), TEXT("apppatch\\sysmain.sdb"));
  1995. //
  1996. // Open the database.
  1997. //
  1998. pdb = SdbOpenDatabase(szShimDB, DOS_PATH);
  1999. if (pdb == NULL) {
  2000. Dbg(dlError, "Cannot open shim DB \"%ws\"\n", szShimDB);
  2001. bOk = FALSE;
  2002. goto Cleanup;
  2003. }
  2004. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  2005. if (tiDatabase == 0) {
  2006. Dbg(dlError, "Cannot find TAG_DATABASE\n");
  2007. bOk = FALSE;
  2008. goto Cleanup;
  2009. }
  2010. tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
  2011. if (tiLibrary == 0) {
  2012. Dbg(dlError, "Cannot find TAG_LIBRARY\n");
  2013. bOk = FALSE;
  2014. goto Cleanup;
  2015. }
  2016. //
  2017. // Read in the guid and the name of the system database.
  2018. //
  2019. tiGuid = SdbFindFirstTag(pdb, tiDatabase, TAG_DATABASE_ID);
  2020. if (0 != tiGuid) {
  2021. GUID* pGuid;
  2022. TCHAR szGuid[128];
  2023. pGuid = (GUID*)SdbGetBinaryTagData(pdb, tiGuid);
  2024. if (pGuid != NULL) {
  2025. *szGuid = 0;
  2026. StringCchPrintf(szGuid,
  2027. ARRAYSIZE(szGuid),
  2028. TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  2029. pGuid->Data1,
  2030. pGuid->Data2,
  2031. pGuid->Data3,
  2032. pGuid->Data4[0],
  2033. pGuid->Data4[1],
  2034. pGuid->Data4[2],
  2035. pGuid->Data4[3],
  2036. pGuid->Data4[4],
  2037. pGuid->Data4[5],
  2038. pGuid->Data4[6],
  2039. pGuid->Data4[7]);
  2040. SafeCpyN(GlobalDataBase.szGUID, szGuid, ARRAYSIZE(GlobalDataBase.szGUID));
  2041. tName = SdbFindFirstTag(pdb, tiDatabase, TAG_NAME);
  2042. if (0 != tName) {
  2043. GlobalDataBase.strName = ReadDBString(pdb, tName);
  2044. }
  2045. } else {
  2046. assert(FALSE);
  2047. bOk = FALSE;
  2048. goto Cleanup;
  2049. }
  2050. } else {
  2051. assert(FALSE);
  2052. bOk = FALSE;
  2053. goto Cleanup;
  2054. }
  2055. ReadFixes(pdb, tiDatabase, tiLibrary, &GlobalDataBase);
  2056. Cleanup:
  2057. if (pdb != NULL) {
  2058. SdbCloseDatabase(pdb);
  2059. }
  2060. return bOk;
  2061. }
  2062. BOOL
  2063. AttributesToXML(
  2064. IN OUT CSTRING& strStr,
  2065. IN PMATCHINGFILE pMatch
  2066. )
  2067. /*++
  2068. AttributesToXML
  2069. Desc: Appends the XML for the attributes of pMatch to strStr
  2070. Params:
  2071. IN OUT CSTRING& strStr: Appends the XML for the attributes of pMatch to this
  2072. IN PMATCHINGFILE pMatch: The PMATCHINGFILE, whose attributes have to converted
  2073. to XML
  2074. Return:
  2075. TRUE: Success
  2076. FALSE: Otherwise
  2077. --*/
  2078. {
  2079. TCHAR szText[1024];
  2080. CSTRING strTemp;
  2081. PATTRINFO_NEW pAttr = NULL;
  2082. *szText = 0;
  2083. if (pMatch == NULL) {
  2084. Dbg(dlError, "pMatch == NULL in AttributesToXML function");
  2085. return FALSE;
  2086. }
  2087. pAttr = pMatch->attributeList.pAttribute;
  2088. if (pAttr == NULL) {
  2089. assert(FALSE);
  2090. return FALSE;
  2091. }
  2092. //
  2093. // For all the attributes see if it available (ATTRIBUTE_AVAILABLE)
  2094. // and if the user has selected this attribute (use the mask), if yes then
  2095. // we get the formatted string for this attribute value that we can write to XML
  2096. //
  2097. for (DWORD dwIndex = 0; dwIndex < ATTRIBUTE_COUNT; ++dwIndex) {
  2098. DWORD dwPos = TagToIndex(pAttr[dwIndex].tAttrID);
  2099. if ((pAttr[dwIndex].dwFlags & ATTRIBUTE_AVAILABLE)
  2100. && dwPos != -1
  2101. && (pMatch->dwMask & (1 << (dwPos + 1)))) {
  2102. *szText = 0;
  2103. SdbFormatAttribute(&pAttr[dwIndex], szText, ARRAYSIZE(szText));
  2104. strStr.Strcat(TEXT(" "));
  2105. strStr.Strcat(szText);
  2106. }
  2107. }
  2108. return TRUE;
  2109. }
  2110. BOOL
  2111. CreateXMLForLUAAction(
  2112. IN PLUADATA pLuaData,
  2113. IN OUT CSTRINGLIST* strlXML
  2114. )
  2115. /*++
  2116. CreateXMLForLUAAction
  2117. Desc: Appends the action string for PLUADATA to strlXML
  2118. Params:
  2119. IN PLUADATA pLuaData
  2120. IN OUT CSTRINGLIST* strlXML
  2121. Return:
  2122. FALSE: If there is some error
  2123. TRUE: Otherwise
  2124. Notes: Currently only one type of ACTION is supported for the LUA shims.
  2125. --*/
  2126. {
  2127. TCHAR szSpace[64];
  2128. INT iszSpaceSize = 0;
  2129. iszSpaceSize = ARRAYSIZE(szSpace);
  2130. CSTRING strTemp;
  2131. strTemp.Sprintf(TEXT("%s<ACTION NAME = \"REDIRECT\" TYPE=\"ChangeACLs\">"),
  2132. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize));
  2133. if (!strlXML->AddString(strTemp)) {
  2134. return FALSE;
  2135. }
  2136. if (pLuaData == NULL) {
  2137. strTemp.Sprintf(
  2138. TEXT("%s<DATA NAME = \"AllUserDir\" VALUETYPE=\"STRING\" VALUE=\"%%ALLUSERSPROFILE%%\\Application Data\\Redirected\"/>"),
  2139. GetSpace(szSpace, TAB_SIZE * 4, iszSpaceSize));
  2140. } else {
  2141. strTemp.Sprintf(
  2142. TEXT("%s<DATA NAME = \"AllUserDir\" VALUETYPE=\"STRING\" VALUE=\"%s\"/>"),
  2143. GetSpace(szSpace, TAB_SIZE * 4, iszSpaceSize),
  2144. pLuaData->strAllUserDir.SpecialCharToXML().pszString);
  2145. }
  2146. if (!strlXML->AddString(strTemp)) {
  2147. return FALSE;
  2148. }
  2149. strTemp.Sprintf(TEXT("%s</ACTION>"), GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize));
  2150. if (!strlXML->AddString(strTemp)) {
  2151. return FALSE;
  2152. }
  2153. return TRUE;
  2154. }
  2155. BOOL
  2156. CreateXMLForShimFixList(
  2157. IN PSHIM_FIX_LIST pShimFixList,
  2158. IN OUT CSTRINGLIST* strlXML
  2159. )
  2160. /*++
  2161. CreateXMLForShimFixList
  2162. Desc: Creates XML for a pShimFixList chain
  2163. Params:
  2164. IN PSHIM_FIX_LIST pShimFixList: The head of the shim fix list
  2165. IN OUT CSTRINGLIST* strlXML: We should append the XML to this
  2166. Return:
  2167. TRUE: If success
  2168. FALSE: If error
  2169. --*/
  2170. {
  2171. CSTRING strTemp;
  2172. TCHAR szSpace[64];
  2173. INT iszSpaceSize = 0;
  2174. iszSpaceSize = ARRAYSIZE(szSpace);
  2175. while (pShimFixList) {
  2176. if (pShimFixList->pShimFix == NULL) {
  2177. assert(FALSE);
  2178. goto Next_ShimList;
  2179. }
  2180. //
  2181. // Check if we have a specific commandline for this shim. For shims with lua data handled differently
  2182. //
  2183. if (pShimFixList->pLuaData) {
  2184. strTemp.Sprintf(TEXT("%s<SHIM NAME=\"%s\" COMMAND_LINE=\"%%DbInfo%%\">"),
  2185. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2186. pShimFixList->pShimFix->strName.SpecialCharToXML().pszString);
  2187. } else if (pShimFixList->strCommandLine.Length()) {
  2188. strTemp.Sprintf(TEXT("%s<SHIM NAME=\"%s\" COMMAND_LINE= \"%s\">"),
  2189. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2190. pShimFixList->pShimFix->strName.SpecialCharToXML().pszString,
  2191. pShimFixList->strCommandLine.SpecialCharToXML().pszString);
  2192. } else {
  2193. strTemp.Sprintf(TEXT("%s<SHIM NAME=\"%s\">"),
  2194. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2195. pShimFixList->pShimFix->strName.SpecialCharToXML().pszString);
  2196. }
  2197. if (!strlXML->AddString(strTemp)) {
  2198. return FALSE;
  2199. }
  2200. //
  2201. // Look for INCLUSIONS & EXCLUSIONS
  2202. //
  2203. if (!pShimFixList->strlInExclude.IsEmpty()) {
  2204. PSTRLIST pList = pShimFixList->strlInExclude.m_pHead;
  2205. while (pList) {
  2206. if (pList->data == INCLUDE) {
  2207. if (pList->szStr == GetString(IDS_INCLUDEMODULE)) {
  2208. strTemp.Sprintf(TEXT("%s<INCLUDE MODULE = \"%s\" />"),
  2209. GetSpace(szSpace, TAB_SIZE * 4, iszSpaceSize),
  2210. TEXT("$"));
  2211. } else {
  2212. strTemp.Sprintf(TEXT("%s<INCLUDE MODULE = \"%s\" />"),
  2213. GetSpace(szSpace, TAB_SIZE * 4, iszSpaceSize),
  2214. pList->szStr.SpecialCharToXML().pszString);
  2215. }
  2216. } else {
  2217. strTemp.Sprintf(TEXT("%s<EXCLUDE MODULE = \"%s\" />"),
  2218. GetSpace(szSpace, TAB_SIZE * 4, iszSpaceSize),
  2219. pList->szStr.SpecialCharToXML().pszString);
  2220. }
  2221. if (!strlXML->AddString(strTemp)) {
  2222. return FALSE;
  2223. }
  2224. pList = pList->pNext;
  2225. }
  2226. }
  2227. //
  2228. // Get the LUA data.
  2229. //
  2230. if (pShimFixList->pLuaData) {
  2231. LuaGenerateXML(pShimFixList->pLuaData, *strlXML);
  2232. }
  2233. strTemp.Sprintf(TEXT("%s</SHIM>"),
  2234. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2235. pShimFixList->pShimFix->strName.SpecialCharToXML().pszString);
  2236. if (!strlXML->AddString(strTemp)) {
  2237. return FALSE;
  2238. }
  2239. if (pShimFixList->pShimFix->strName == TEXT("LUARedirectFS")) {
  2240. if (pShimFixList->pLuaData){
  2241. //
  2242. // If this entry has been customized we need to check if we should create
  2243. // an ACTION node for it.
  2244. //
  2245. if (!(pShimFixList->pLuaData->strAllUserDir.isNULL())) {
  2246. CreateXMLForLUAAction(pShimFixList->pLuaData, strlXML);
  2247. }
  2248. } else {
  2249. //
  2250. // If we don't have any LUA data it means this hasn't been customized.
  2251. // We always create the default Redirected dir.
  2252. //
  2253. CreateXMLForLUAAction(NULL, strlXML);
  2254. }
  2255. }
  2256. Next_ShimList:
  2257. pShimFixList = pShimFixList->pNext;
  2258. }
  2259. return TRUE;
  2260. }
  2261. BOOL
  2262. GetXML(
  2263. IN PDBENTRY pEntry,
  2264. IN BOOL bComplete,
  2265. OUT CSTRINGLIST* strlXML,
  2266. IN PDATABASE pDataBase
  2267. )
  2268. /*++
  2269. GetXML
  2270. Desc: Gets the XML for a fix entry
  2271. Params:
  2272. IN PDBENTRY pEntry: The app or entry whose XML we want
  2273. IN BOOL bComplete: Save all entries for this app.
  2274. pEntry is the head of the list, i.e an app. Otherwise just get the XML for this
  2275. entry
  2276. OUT CSTRINGLIST* strlXML: The XML has to be written into this
  2277. IN PDATABASE pDataBase: The database for which we want to perform the operation
  2278. Return:
  2279. TRUE: Success
  2280. FALSE: Otherwise
  2281. Notes: Also gets the XML for the entire library section. Will create a guid for the database
  2282. If there is none and we are trying to do a save.
  2283. During test run we do not care and allow the compiler to create a guid, but for
  2284. save since the guid member of the PDATABASE has to be updated if there is no guid,
  2285. we create it ourselves
  2286. --*/
  2287. {
  2288. PSHIM_FIX_LIST pShimFixList;
  2289. CSTRING strTemp;
  2290. TCHAR szSpace[64];
  2291. INT iszSpaceSize = 0;
  2292. iszSpaceSize = ARRAYSIZE(szSpace);
  2293. if (pDataBase == NULL) {
  2294. assert(FALSE);
  2295. return FALSE;
  2296. }
  2297. if (!strlXML->AddString(TEXT("<?xml version=\"1.0\" encoding=\"UTF-16\"?>"))) {
  2298. return FALSE;
  2299. }
  2300. if (bComplete == FALSE) {
  2301. //
  2302. // This is a test-run, guid should be generated automatically
  2303. //
  2304. strTemp.Sprintf(TEXT("<DATABASE NAME=\"%s\">"),
  2305. pDataBase->strName.SpecialCharToXML().pszString);
  2306. } else {
  2307. //
  2308. // We are trying to save the database, create a guid if it is not there
  2309. //
  2310. if (*(pDataBase->szGUID) == 0) {
  2311. GUID Guid;
  2312. CoCreateGuid(&Guid);
  2313. StringCchPrintf(pDataBase->szGUID,
  2314. ARRAYSIZE(pDataBase->szGUID),
  2315. TEXT ("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  2316. Guid.Data1,
  2317. Guid.Data2,
  2318. Guid.Data3,
  2319. Guid.Data4[0],
  2320. Guid.Data4[1],
  2321. Guid.Data4[2],
  2322. Guid.Data4[3],
  2323. Guid.Data4[4],
  2324. Guid.Data4[5],
  2325. Guid.Data4[6],
  2326. Guid.Data4[7]);
  2327. }
  2328. strTemp.Sprintf(TEXT("<DATABASE NAME=\"%s\" ID = \"%s\">"),
  2329. pDataBase->strName.SpecialCharToXML().pszString,
  2330. pDataBase->szGUID);
  2331. }
  2332. strlXML->AddString(strTemp);
  2333. strTemp.Sprintf(TEXT("%s<LIBRARY>"),
  2334. GetSpace(szSpace, TAB_SIZE * 1, iszSpaceSize));
  2335. strlXML->AddString(strTemp);
  2336. //
  2337. // Put the AppHelp messages.
  2338. //
  2339. PAPPHELP pAppHelp = pDataBase->pAppHelp;
  2340. while (pAppHelp) {
  2341. CSTRING strName;
  2342. strName.Sprintf(TEXT("%u"), pAppHelp->HTMLHELPID);
  2343. strTemp.Sprintf(TEXT("%s<MESSAGE NAME = \"%s\" >"),
  2344. GetSpace(szSpace, TAB_SIZE * 2, iszSpaceSize),
  2345. strName.SpecialCharToXML().pszString);
  2346. strlXML->AddString(strTemp);
  2347. strTemp.Sprintf(TEXT("%s<SUMMARY>"), GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize));
  2348. strlXML->AddString(strTemp);
  2349. //
  2350. // We must use SpecialCharToXML() and pass TRUE for the apphelp message as html
  2351. // tags are allowed. When we pass TRUE to SpecialCharToXML(), it understands that this is a AppHelp
  2352. // message and ignores the <, > but handles &, " correctly
  2353. //
  2354. strTemp.Sprintf(TEXT("%s%s"),
  2355. GetSpace(szSpace, TAB_SIZE * 4, iszSpaceSize),
  2356. pAppHelp->strMessage.SpecialCharToXML(TRUE).pszString);
  2357. strlXML->AddString(strTemp);
  2358. strTemp.Sprintf(TEXT("%s</SUMMARY>"), GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize));
  2359. strlXML->AddString(strTemp);
  2360. strTemp.Sprintf(TEXT("%s</MESSAGE>"), GetSpace(szSpace, TAB_SIZE * 2, iszSpaceSize));
  2361. strlXML->AddString(strTemp);
  2362. pAppHelp = pAppHelp->pNext;
  2363. }
  2364. //
  2365. // AppHelp Added to Library
  2366. //
  2367. PLAYER_FIX plf = pDataBase->pLayerFixes;
  2368. while (plf) {
  2369. strTemp.Sprintf(TEXT("%s<LAYER NAME=\"%s\">"),
  2370. GetSpace(szSpace, TAB_SIZE * 2, iszSpaceSize),
  2371. plf->strName.SpecialCharToXML().pszString);
  2372. strlXML->AddString(strTemp);
  2373. pShimFixList = plf->pShimFixList;
  2374. CreateXMLForShimFixList(pShimFixList, strlXML);
  2375. //
  2376. // Now the same story for the flags for this layer.
  2377. //
  2378. PFLAG_FIX_LIST pFlagFixList = plf->pFlagFixList;
  2379. while (pFlagFixList) {
  2380. PFLAG_FIX pff = pFlagFixList->pFlagFix;
  2381. if (pFlagFixList->strCommandLine.Length() == 0) {
  2382. strTemp.Sprintf(TEXT("%s<FLAG NAME = \"%s\"/>"),
  2383. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2384. pff->strName.SpecialCharToXML().pszString);
  2385. } else {
  2386. strTemp.Sprintf(TEXT("%s<FLAG NAME = \"%s\" COMMAND_LINE = \"%s\" />"),
  2387. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2388. pff->strName.SpecialCharToXML().pszString,
  2389. pFlagFixList->strCommandLine.SpecialCharToXML().pszString);
  2390. }
  2391. if (!strlXML->AddString(strTemp)) {
  2392. return FALSE;
  2393. }
  2394. pFlagFixList = pFlagFixList->pNext;
  2395. }
  2396. strTemp.Sprintf(TEXT("%s</LAYER>"), GetSpace(szSpace, TAB_SIZE * 2, iszSpaceSize));
  2397. if (!strlXML->AddString(strTemp)) {
  2398. return FALSE;
  2399. }
  2400. plf = plf->pNext;
  2401. }
  2402. strTemp.Sprintf(TEXT("%s</LIBRARY>"), GetSpace(szSpace, TAB_SIZE * 1, iszSpaceSize));
  2403. if (!strlXML->AddString(strTemp)) {
  2404. return FALSE;
  2405. }
  2406. //
  2407. // Now for the EXE entries
  2408. //
  2409. if (!bComplete) {
  2410. if (!GetEntryXML(strlXML, pEntry)) {
  2411. return FALSE;
  2412. }
  2413. } else {
  2414. //
  2415. // Get the XML for all the entries
  2416. //
  2417. for (PDBENTRY pApps = pEntry; pApps != NULL; pApps = pApps->pNext) {
  2418. for (PDBENTRY pEntryinApp = pApps;
  2419. pEntryinApp;
  2420. pEntryinApp = pEntryinApp->pSameAppExe) {
  2421. if (!GetEntryXML(strlXML, pEntryinApp)) {
  2422. return FALSE;
  2423. }
  2424. }
  2425. }
  2426. }
  2427. if (!strlXML->AddString(TEXT("</DATABASE>"))) {
  2428. return FALSE;
  2429. }
  2430. return TRUE;
  2431. }
  2432. BOOL
  2433. GetEntryXML(
  2434. IN OUT CSTRINGLIST* pstrlXML,
  2435. IN PDBENTRY pEntry
  2436. )
  2437. /*++
  2438. GetEntryXML
  2439. Desc: Gets the XML for an entry
  2440. Params:
  2441. IN OUT CSTRINGLIST* pstrlXML: Append the XML to this
  2442. IN PDBENTRY pEntry: Entry whose XML we want to get
  2443. Return:
  2444. TRUE: Success
  2445. FALSE: Otherwise
  2446. --*/
  2447. {
  2448. PSHIM_FIX_LIST pShimFixList;
  2449. PFLAG_FIX_LIST pFlagFixList;
  2450. PLAYER_FIX_LIST pLayerFixList;
  2451. PPATCH_FIX_LIST pPatchFixList;
  2452. TCHAR szSpace[64];
  2453. INT iszSpaceSize = 0;
  2454. iszSpaceSize = ARRAYSIZE(szSpace);
  2455. //
  2456. // The App Info
  2457. //
  2458. if (pEntry == NULL || pstrlXML == NULL) {
  2459. assert(FALSE);
  2460. return FALSE;
  2461. }
  2462. CSTRING strTemp;
  2463. strTemp.Sprintf(TEXT("%s<APP NAME=\"%s\" VENDOR=\"%s\">"),
  2464. GetSpace(szSpace, TAB_SIZE * 1, iszSpaceSize),
  2465. pEntry->strAppName.SpecialCharToXML().pszString,
  2466. pEntry->strVendor.SpecialCharToXML().pszString);
  2467. if (!pstrlXML->AddString(strTemp)) {
  2468. return FALSE;
  2469. }
  2470. if (pEntry->szGUID[0] == 0) {
  2471. strTemp.Sprintf(TEXT("%s<EXE NAME=\"%s\""),
  2472. GetSpace(szSpace, TAB_SIZE * 2, iszSpaceSize),
  2473. pEntry->strExeName.SpecialCharToXML().pszString);
  2474. } else {
  2475. strTemp.Sprintf(TEXT("%s<EXE NAME=\"%s\" ID=\"%s\""),
  2476. GetSpace(szSpace, TAB_SIZE * 2, iszSpaceSize),
  2477. pEntry->strExeName.SpecialCharToXML().pszString,
  2478. pEntry->szGUID);
  2479. }
  2480. PMATCHINGFILE pMatch = pEntry->pFirstMatchingFile;
  2481. //
  2482. // Resolve for the "*". We need to get the attributes for the program being fixed
  2483. //
  2484. while (pMatch) {
  2485. if (pMatch->strMatchName == TEXT("*")) {
  2486. AttributesToXML(strTemp, pMatch);
  2487. break;
  2488. } else {
  2489. pMatch = pMatch->pNext;
  2490. }
  2491. }
  2492. strTemp.Strcat(TEXT(">"));
  2493. if (!pstrlXML->AddString(strTemp)) {
  2494. return FALSE;
  2495. }
  2496. //
  2497. // Add the matching info
  2498. //
  2499. pMatch = pEntry->pFirstMatchingFile;
  2500. while (pMatch) {
  2501. //
  2502. // We will ignore the program file being fixed(represented by *), because
  2503. // we have already added its xml above
  2504. //
  2505. if (pMatch->strMatchName != TEXT("*")) {
  2506. strTemp.Sprintf(TEXT("%s<MATCHING_FILE NAME=\"%s\""),
  2507. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2508. pMatch->strMatchName.SpecialCharToXML().pszString);
  2509. AttributesToXML(strTemp, pMatch);
  2510. strTemp.Strcat(TEXT("/>"));
  2511. if (!pstrlXML->AddString(strTemp)) {
  2512. return FALSE;
  2513. }
  2514. }
  2515. pMatch = pMatch->pNext;
  2516. }
  2517. //
  2518. // Add the layers
  2519. //
  2520. pLayerFixList = pEntry->pFirstLayer;
  2521. pShimFixList = pEntry->pFirstShim;
  2522. BOOL bCustomLayerFound = FALSE; // Does there exist a layer for this exe entry?
  2523. while (pLayerFixList) {
  2524. if (pLayerFixList->pLayerFix == NULL) {
  2525. assert(FALSE);
  2526. goto Next_Layer;
  2527. }
  2528. if (pLayerFixList->pLayerFix->bCustom) {
  2529. bCustomLayerFound = TRUE;
  2530. }
  2531. strTemp.Sprintf(TEXT("%s<LAYER NAME = \"%s\"/>"),
  2532. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2533. pLayerFixList->pLayerFix->strName.SpecialCharToXML().pszString);
  2534. if (!pstrlXML->AddString(strTemp)) {
  2535. return FALSE;
  2536. }
  2537. Next_Layer:
  2538. pLayerFixList = pLayerFixList->pNext;
  2539. }
  2540. if (g_bWin2K
  2541. && (bCustomLayerFound == TRUE || pShimFixList)
  2542. && !IsShimInEntry(TEXT("Win2kPropagateLayer"), pEntry)) {
  2543. //
  2544. // On Win2K we need to add Win2kPropagateLayer shim to entries that have a shim
  2545. // or a custom layer.
  2546. //
  2547. strTemp.Sprintf(TEXT("%s<SHIM NAME= \"Win2kPropagateLayer\"/>"),
  2548. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize));
  2549. if (!pstrlXML->AddString(strTemp)) {
  2550. return FALSE;
  2551. }
  2552. }
  2553. //
  2554. // Add the Shims for this exe
  2555. //
  2556. if (pShimFixList) {
  2557. if (!CreateXMLForShimFixList(pShimFixList, pstrlXML)) {
  2558. return FALSE;
  2559. }
  2560. }
  2561. //
  2562. // Add the Patches
  2563. //
  2564. pPatchFixList = pEntry->pFirstPatch;
  2565. while (pPatchFixList) {
  2566. if (pPatchFixList->pPatchFix == NULL) {
  2567. assert(FALSE);
  2568. goto Next_Patch;
  2569. }
  2570. strTemp.Sprintf(TEXT("%s<PATCH NAME = \"%s\"/>"),
  2571. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2572. pPatchFixList->pPatchFix->strName.SpecialCharToXML().pszString);
  2573. if (!pstrlXML->AddString(strTemp)) {
  2574. return FALSE;
  2575. }
  2576. Next_Patch:
  2577. pPatchFixList = pPatchFixList->pNext;
  2578. }
  2579. //
  2580. // Add the flags
  2581. //
  2582. pFlagFixList = pEntry->pFirstFlag;
  2583. while (pFlagFixList) {
  2584. if (pFlagFixList->pFlagFix == NULL) {
  2585. assert(FALSE);
  2586. goto Next_Flag;
  2587. }
  2588. if (pFlagFixList->strCommandLine.Length() == 0) {
  2589. strTemp.Sprintf(TEXT("%s<FLAG NAME = \"%s\"/>"),
  2590. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2591. pFlagFixList->pFlagFix->strName.SpecialCharToXML().pszString);
  2592. } else {
  2593. strTemp.Sprintf(TEXT("%s<FLAG NAME = \"%s\" COMMAND_LINE = \"%s\"/>"),
  2594. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2595. pFlagFixList->pFlagFix->strName.SpecialCharToXML().pszString,
  2596. pFlagFixList->strCommandLine.SpecialCharToXML().pszString);
  2597. }
  2598. if (!pstrlXML->AddString(strTemp)) {
  2599. return FALSE;
  2600. }
  2601. Next_Flag:
  2602. pFlagFixList = pFlagFixList->pNext;
  2603. }
  2604. //
  2605. // Add the AppHelp
  2606. //
  2607. PAPPHELP pAppHelp = &(pEntry->appHelp);
  2608. assert(pAppHelp);
  2609. if (pAppHelp->bPresent) {
  2610. CSTRING strBlock;
  2611. if (pAppHelp->bBlock) {
  2612. strBlock = TEXT("YES");
  2613. } else {
  2614. strBlock = TEXT("NO");
  2615. }
  2616. CSTRING strName;
  2617. strName.Sprintf(TEXT("%u"), pAppHelp->HTMLHELPID);
  2618. CSTRING strHelpID;
  2619. strHelpID.Sprintf(TEXT("%u"), pAppHelp->HTMLHELPID);
  2620. //
  2621. // The URL is kept with the apphelp in the Library. Just as in the .SDB
  2622. //
  2623. pAppHelp = pEntry->appHelp.pAppHelpinLib;
  2624. assert(pAppHelp);
  2625. assert(pEntry->appHelp.HTMLHELPID == pAppHelp->HTMLHELPID);
  2626. if (pAppHelp->strURL.Length()) {
  2627. strTemp.Sprintf(TEXT("%s<APPHELP MESSAGE = \"%s\" BLOCK = \"%s\" HTMLHELPID = \"%s\" DETAILS_URL = \"%s\" />"),
  2628. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2629. strName.pszString,
  2630. strBlock.pszString,
  2631. strHelpID.pszString,
  2632. pAppHelp->strURL.SpecialCharToXML().pszString);
  2633. } else {
  2634. strTemp.Sprintf(TEXT("%s<APPHELP MESSAGE = \"%s\" BLOCK = \"%s\" HTMLHELPID = \"%s\" />"),
  2635. GetSpace(szSpace, TAB_SIZE * 3, iszSpaceSize),
  2636. strName.pszString,
  2637. strBlock.pszString,
  2638. strHelpID.pszString);
  2639. }
  2640. if (!pstrlXML->AddString(strTemp)) {
  2641. return FALSE;
  2642. }
  2643. }
  2644. // End of AppHelp
  2645. strTemp.Sprintf(TEXT("%s</EXE>"), GetSpace(szSpace, TAB_SIZE * 2, iszSpaceSize));
  2646. if (!pstrlXML->AddString(strTemp)) {
  2647. return FALSE;
  2648. }
  2649. strTemp.Sprintf(TEXT("%s</APP>"), GetSpace(szSpace, TAB_SIZE * 1, iszSpaceSize));
  2650. if (!pstrlXML->AddString(strTemp)) {
  2651. return FALSE;
  2652. }
  2653. return TRUE;
  2654. }
  2655. BOOL
  2656. CheckForDBName(
  2657. IN PDATABASE pDatabase
  2658. )
  2659. /*++
  2660. CheckForDBName
  2661. Description: Prompts the user if the database name is still the default name
  2662. Params:
  2663. IN PDATABASE pDatabase: The pointer to the database, for which we need to make
  2664. the check.
  2665. Return:
  2666. TRUE: The database name is now not the default name
  2667. FALSE: The databae name is still the default name
  2668. --*/
  2669. {
  2670. BOOL bOkayPressed = TRUE;
  2671. CSTRING strNewDBName;
  2672. //
  2673. // Check if the database name is the default name that we provided. We should not
  2674. // allow that because the database name appears in the "Add and Remove" Programs list
  2675. //
  2676. while (pDatabase->strName.BeginsWith(GetString(IDS_DEF_DBNAME))) {
  2677. //
  2678. // Yes, it does
  2679. //
  2680. bOkayPressed = DialogBoxParam(g_hInstance,
  2681. MAKEINTRESOURCE(IDD_DBRENAME),
  2682. g_hDlg,
  2683. DatabaseRenameDlgProc,
  2684. (LPARAM)&strNewDBName);
  2685. if (bOkayPressed == FALSE) {
  2686. //
  2687. // User pressed cancel, we must not save this database
  2688. //
  2689. goto End;
  2690. } else {
  2691. pDatabase->strName = strNewDBName;
  2692. }
  2693. }
  2694. End:
  2695. return bOkayPressed;
  2696. }
  2697. BOOL
  2698. SaveDataBase(
  2699. IN PDATABASE pDataBase,
  2700. IN CSTRING& strFileName
  2701. )
  2702. /*++
  2703. SaveDataBase
  2704. Desc: Saves the database pDataBase in file strFileName
  2705. Params:
  2706. IN PDATABASE pDataBase: The database that we want to save
  2707. IN CSTRING &strFileName: The file in which to save
  2708. Return:
  2709. TRUE: Success
  2710. FALSE: Otherwise
  2711. --*/
  2712. {
  2713. BOOL bOk = TRUE;
  2714. CSTRINGLIST strlXML;
  2715. CSTRING strTemp;
  2716. CSTRING strCommandLine;
  2717. TCHAR szPath[MAX_PATH * 2];
  2718. TCHAR szXMLFileName[MAX_PATH];
  2719. GUID Guid;
  2720. DWORD dwCount = 0;
  2721. *szPath = 0;
  2722. if (!pDataBase || !strFileName.Length()) {
  2723. assert(FALSE);
  2724. bOk = FALSE;
  2725. goto End;
  2726. }
  2727. //
  2728. // Check if the database name has the default name. This routine will prompt
  2729. // the user and lets the user change the name
  2730. //
  2731. if (!CheckForDBName(pDataBase)) {
  2732. //
  2733. // The user did not change the default database name, we must not save
  2734. // the database
  2735. //
  2736. bOk = FALSE;
  2737. goto End;
  2738. }
  2739. SetCursor(LoadCursor(NULL, IDC_WAIT));
  2740. dwCount = GetTempPath(MAX_PATH, szPath);
  2741. if (dwCount == 0 || dwCount > MAX_PATH) {
  2742. bOk = FALSE;
  2743. goto End;
  2744. }
  2745. ADD_PATH_SEPARATOR(szPath, ARRAYSIZE(szPath));
  2746. if (*(pDataBase->szGUID) == NULL) {
  2747. //
  2748. // We do not have a guid. Get that..
  2749. //
  2750. CoCreateGuid(&Guid);
  2751. StringCchPrintf(pDataBase->szGUID,
  2752. ARRAYSIZE(pDataBase->szGUID),
  2753. TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  2754. Guid.Data1,
  2755. Guid.Data2,
  2756. Guid.Data3,
  2757. Guid.Data4[0],
  2758. Guid.Data4[1],
  2759. Guid.Data4[2],
  2760. Guid.Data4[3],
  2761. Guid.Data4[4],
  2762. Guid.Data4[5],
  2763. Guid.Data4[6],
  2764. Guid.Data4[7]);
  2765. }
  2766. StringCchPrintf(szXMLFileName, ARRAYSIZE(szXMLFileName), TEXT("%s.XML"), pDataBase->szGUID);
  2767. szXMLFileName[ARRAYSIZE(szXMLFileName) - 1] = 0;
  2768. StringCchCat(szPath, ARRAYSIZE(szPath), szXMLFileName);
  2769. if (!GetXML(pDataBase->pEntries, TRUE, &strlXML, pDataBase)) {
  2770. bOk = FALSE;
  2771. goto End;
  2772. }
  2773. strTemp = szPath;
  2774. if (!WriteXML(strTemp , &strlXML)) {
  2775. bOk = FALSE;
  2776. goto End;
  2777. }
  2778. strCommandLine.Sprintf(TEXT("custom \"%s\" \"%s\""),
  2779. (LPCTSTR)strTemp,
  2780. (LPCTSTR)strFileName);
  2781. if (!InvokeCompiler(strCommandLine)) {
  2782. MSGF(g_hDlg,
  2783. g_szAppName,
  2784. MB_ICONERROR,
  2785. GetString(IDS_CANNOTSAVE),
  2786. (LPCTSTR)pDataBase->strName);
  2787. bOk = FALSE;
  2788. goto End;
  2789. }
  2790. pDataBase->strPath = strFileName;
  2791. pDataBase->bChanged = FALSE;
  2792. //
  2793. // Add this name to the MRU list and refresh this MRU menu
  2794. //
  2795. AddToMRU(pDataBase->strPath);
  2796. RefreshMRUMenu();
  2797. End:
  2798. SetCaption();
  2799. SetCursor(LoadCursor(NULL, IDC_ARROW));
  2800. return bOk;
  2801. }
  2802. BOOL
  2803. SaveDataBaseAs(
  2804. IN PDATABASE pDataBase
  2805. )
  2806. /*++
  2807. SaveDataBaseAs
  2808. Desc: Saves the database pDataBase after prompting for a file name
  2809. Params:
  2810. IN PDATABASE pDataBase: The database that we want to save
  2811. Return:
  2812. TRUE: Success
  2813. FALSE: Otherwise
  2814. --*/
  2815. {
  2816. TCHAR szBuffer1[MAX_PATH] = TEXT(""), szBuffer2[MAX_PATH] = TEXT("");
  2817. CSTRING strCaption;
  2818. CSTRING strFileName;
  2819. BOOL bOk = FALSE;
  2820. if (pDataBase == NULL) {
  2821. assert(FALSE);
  2822. return FALSE;
  2823. }
  2824. //
  2825. // Check if the database name has the default name. This routine will prompt
  2826. // the user and lets the user change the name
  2827. //
  2828. if (!CheckForDBName(pDataBase)) {
  2829. //
  2830. // The user did not change the default database name, we must not save
  2831. // the database
  2832. //
  2833. bOk = FALSE;
  2834. goto End;
  2835. }
  2836. strCaption.Sprintf(TEXT("%s: \"%s\""), GetString(IDS_SAVE), pDataBase->strName);
  2837. BOOL bResult = GetFileName(g_hDlg,
  2838. strCaption,
  2839. GetString(IDS_FILTER, szBuffer1, ARRAYSIZE(szBuffer1)),
  2840. TEXT(""),
  2841. GetString(IDS_SDB_EXT, szBuffer2, ARRAYSIZE(szBuffer2)),
  2842. OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT,
  2843. FALSE,
  2844. strFileName);
  2845. //
  2846. // Redraw the controls
  2847. //
  2848. UpdateControls();
  2849. if (bResult) {
  2850. bOk = SaveDataBase(pDataBase, strFileName);
  2851. } else {
  2852. bOk = FALSE;
  2853. }
  2854. End:
  2855. SetCaption();
  2856. return bOk;
  2857. }
  2858. BOOL
  2859. CheckIfConflictingEntry(
  2860. IN PDATABASE pDataBase,
  2861. IN PDBENTRY pEntry,
  2862. IN PDBENTRY pEntryBeingEdited,
  2863. IN PDBENTRY* ppEntryFound, // (NULL)
  2864. IN PDBENTRY* ppAppFound // (NULL)
  2865. )
  2866. /*++
  2867. CheckIfConflictingEntry
  2868. Desc: Checks if some entry that will conflict with pEntry already exists in the database
  2869. Algo: For all the entries in the database that have the same name as this
  2870. entry (we do not care for the application name), let us say an
  2871. existing entry with the same name as pEntry is X, we see if all
  2872. the matching files for the entry being checked (pEntry) are also similar to
  2873. some matching files in X
  2874. If yes then we say that pEntry conflicts with X
  2875. Two matching files are said to be similar if there does not any exist any attribute
  2876. that has different values in these two matching files
  2877. Params:
  2878. IN PDATABASE pDataBase : The database in which to make the check
  2879. IN PDBENTRY pEntry, : The entry to check
  2880. IN PDBENTRY pEntryBeingEdited : This is required because when we check for existing
  2881. entries and we are editing an entry, then the entry being edited
  2882. Will always match (well, not if we modify the matching file)
  2883. IN PDBENTRY* ppEntryFound (NULL) : If not NULL this will hold the conflicting entry
  2884. IN PDBENTRY* ppAppFound (NULL) : If not NULL this will hold the app of the conflicting entry
  2885. Return:
  2886. TRUE: There is a conflict
  2887. FALSE: Otherwise
  2888. --*/
  2889. {
  2890. PDBENTRY pApps = NULL, pEntryExists = NULL;
  2891. if (pDataBase == NULL || pEntry == NULL) {
  2892. assert(FALSE);
  2893. return FALSE;
  2894. }
  2895. for (pApps = pDataBase->pEntries;
  2896. pApps != NULL;
  2897. pApps = pApps->pNext) {
  2898. for (pEntryExists = pApps;
  2899. pEntryExists;
  2900. pEntryExists = pEntryExists->pSameAppExe) {
  2901. if (pEntryExists == pEntryBeingEdited) {
  2902. //
  2903. // Do not compare with self. Also pEntryExists will never be NULL here(see the for loop)
  2904. // So we will not enter here when we are creating a new entry as we pass
  2905. // NULL for pEntryBeingEdited.
  2906. //
  2907. continue;
  2908. }
  2909. if (pEntryExists->strExeName == pEntry->strExeName) {
  2910. for (PMATCHINGFILE pMatchNewEntry = pEntry->pFirstMatchingFile;
  2911. pMatchNewEntry != NULL;
  2912. pMatchNewEntry = pMatchNewEntry->pNext) {
  2913. BOOL bFound = FALSE;
  2914. for (PMATCHINGFILE pMatchOldEntry = pEntryExists->pFirstMatchingFile;
  2915. pMatchOldEntry != NULL;
  2916. pMatchOldEntry = pMatchOldEntry->pNext) {
  2917. if (*pMatchNewEntry == *pMatchOldEntry) {
  2918. bFound = TRUE;
  2919. break;
  2920. }
  2921. }
  2922. if (bFound == FALSE) {
  2923. goto next_entry;
  2924. }
  2925. }
  2926. if (ppAppFound) {
  2927. *ppAppFound = pApps;
  2928. }
  2929. if (ppEntryFound) {
  2930. *ppEntryFound = pEntryExists;
  2931. }
  2932. return TRUE;
  2933. }
  2934. next_entry: ;
  2935. }
  2936. }
  2937. return FALSE;
  2938. }
  2939. BOOL
  2940. CloseDataBase(
  2941. IN PDATABASE pDataBase
  2942. )
  2943. /*++
  2944. CloseDataBase
  2945. Desc: Closes the pDataBase database, prompts for save if not saved already.
  2946. This routine will also remove the item for the database from the db tree.
  2947. Only working databases can be closed.
  2948. This routine first checks if the database is saved, if not prompts the user to save it.
  2949. If the user, says CANCEL then we return FALSE.
  2950. Otherwise we first remove the entry from the tree, then close the database
  2951. and return.
  2952. Params:
  2953. IN PDATABASE pDataBase: Database to close
  2954. Return:
  2955. TRUE: The database entry was removed from the tree and the database was
  2956. removed from the list of working databases.
  2957. FALSE: Otherwise
  2958. Notes: In some bizarre condition if DataBaseList.Remove(pDataBase) fails then we will end up
  2959. removing the item from the tree but not from the database list. This is certainly a
  2960. big error but there is no need to worry as by then we are already totally messed up,
  2961. so as to come to this situation
  2962. Please note that we must remove the entry before removing/deleting the database pointer,
  2963. because in case we get the focus on the db tree item whose database has been deleted
  2964. then the lParam of the database tree item will point to a freed memory location
  2965. --*/
  2966. {
  2967. if (pDataBase == NULL) {
  2968. assert(FALSE);
  2969. return FALSE;
  2970. }
  2971. if (!CheckAndSave(pDataBase)) {
  2972. return FALSE;
  2973. }
  2974. //
  2975. // NOTE: This routine will remove the entry and in the process set the focus
  2976. // on some other entry. This will change the g_pPresentDatabase
  2977. //
  2978. if (!DBTree.RemoveDataBase(pDataBase->hItemDB , DATABASE_TYPE_WORKING)) {
  2979. assert(FALSE);
  2980. return FALSE;
  2981. }
  2982. //
  2983. // Clear the entry tree so that we do not get any selection message there. We have to do this
  2984. // because in the next step we are removing the database and if the tree view stays around and it
  2985. // gets a sel change message somehow we may AV as:
  2986. // 1. CompatAdminDlgProc handles WM_NOTIFY for the entry tree
  2987. // 2. HandleNotifyExeTree
  2988. // 3. OnEntrySelChange
  2989. // 4. GetItemType.
  2990. // In GetItemType the pEntry for the entry tree is now no longer valid
  2991. //
  2992. // We do not get this behavior if the focus is in the contents list
  2993. //
  2994. TreeDeleteAll(g_hwndEntryTree);
  2995. g_pSelEntry = g_pEntrySelApp = NULL;
  2996. //
  2997. // Remove this database from the list of databases
  2998. //
  2999. PDATABASELIST pDataBaseList;
  3000. if (pDataBase->type != DATABASE_TYPE_WORKING) {
  3001. assert(FALSE);
  3002. return FALSE;
  3003. }
  3004. return (DataBaseList.Remove(pDataBase));
  3005. }
  3006. void
  3007. GetNextSDBFileName(
  3008. OUT CSTRING& strFileName,
  3009. OUT CSTRING& strDBName
  3010. )
  3011. /*++
  3012. GetNextSDBFileName
  3013. Desc: Gets the next filename and then database name for a working database
  3014. The file name is not the complete path but just the file name like
  3015. Untitled_X
  3016. The database name will be something like New Database(X)
  3017. Params:
  3018. OUT CSTRING &strFileName: Will contain the filename
  3019. OUT CSTRING &strDBName: Will contain the database name
  3020. Return:
  3021. void
  3022. --*/
  3023. {
  3024. BOOL bRepeat = TRUE;
  3025. //
  3026. // When we close the databases, we decrement g_uNextDataBaseIndex, so that it can become
  3027. // 0, but we want to start from 1
  3028. //
  3029. if (g_uNextDataBaseIndex == 0) {
  3030. g_uNextDataBaseIndex = 1;
  3031. }
  3032. strFileName.Sprintf(TEXT("%s_%u"), GetString(IDS_DEF_FILENAME), g_uNextDataBaseIndex);
  3033. while (bRepeat) {
  3034. PDATABASE pDatabase = DataBaseList.pDataBaseHead;
  3035. strDBName.Sprintf(TEXT("%s(%u)"), GetString(IDS_DEF_DBNAME), g_uNextDataBaseIndex);
  3036. //
  3037. // Try to make sure that we do not have a database with the same name.
  3038. // This is not a strict rule and users can rename it to some existing open database
  3039. //
  3040. while (pDatabase) {
  3041. if (pDatabase->strName == strDBName) {
  3042. ++g_uNextDataBaseIndex;
  3043. break;
  3044. }
  3045. pDatabase = pDatabase->pNext;
  3046. }
  3047. bRepeat = (pDatabase == NULL) ? FALSE : TRUE;
  3048. }
  3049. }
  3050. BOOL
  3051. CompareLayers(
  3052. IN PLAYER_FIX pLayerOne,
  3053. IN PLAYER_FIX pLayerTwo
  3054. )
  3055. /*++
  3056. CompareLayers
  3057. Desc: Checks if two layers have the same stuff
  3058. Algo: Two layers will be said to be same if they have the same shims and fixes and for each
  3059. similar shim and fix, the parameters also tally.
  3060. For shims two include-exclude lists will be said to be similar if they have the same modules
  3061. and module types and the order of occurrence is also same
  3062. Params:
  3063. IN PLAYER_FIX pLayerOne: Layer 1
  3064. IN PLAYER_FIX pLayerTwo: layer 2
  3065. Return:
  3066. TRUE: Both layers have same stuff
  3067. FALSE: Otherwise
  3068. --*/
  3069. {
  3070. BOOL bFound = FALSE;
  3071. if (pLayerOne == NULL || pLayerTwo == NULL) {
  3072. assert(FALSE);
  3073. return FALSE;
  3074. }
  3075. //
  3076. // First compare the flag Lists
  3077. //
  3078. int countOne = 0, countTwo = 0; // Number of elements in pFlag/ShimListOne/Two
  3079. for (PFLAG_FIX_LIST pFlagListOne = pLayerOne->pFlagFixList;
  3080. pFlagListOne;
  3081. pFlagListOne = pFlagListOne->pNext) {
  3082. countOne++;
  3083. bFound = FALSE;
  3084. for (PFLAG_FIX_LIST pFlagListTwo = pLayerTwo->pFlagFixList;
  3085. pFlagListTwo;
  3086. pFlagListTwo = pFlagListTwo->pNext) {
  3087. if (pFlagListOne->pFlagFix == pFlagListTwo->pFlagFix) {
  3088. if (pFlagListOne->strCommandLine != pFlagListTwo->strCommandLine) {
  3089. return FALSE;
  3090. }
  3091. bFound = TRUE;
  3092. break;
  3093. }
  3094. }
  3095. if (bFound == FALSE) {
  3096. return FALSE;
  3097. }
  3098. }
  3099. // TODO: Can optimize
  3100. // Count the number of items in the second list.
  3101. //
  3102. countTwo = 0;
  3103. for (PFLAG_FIX_LIST pFlagListTwo = pLayerTwo->pFlagFixList;
  3104. pFlagListTwo;
  3105. pFlagListTwo = pFlagListTwo->pNext) {
  3106. countTwo++;
  3107. }
  3108. if (countOne != countTwo) {
  3109. return FALSE;
  3110. }
  3111. bFound = FALSE;
  3112. countOne = 0;
  3113. for (PSHIM_FIX_LIST pShimListOne = pLayerOne->pShimFixList;
  3114. pShimListOne;
  3115. pShimListOne = pShimListOne->pNext) {
  3116. bFound = FALSE;
  3117. countOne++;
  3118. for (PSHIM_FIX_LIST pShimListTwo = pLayerTwo->pShimFixList;
  3119. pShimListTwo;
  3120. pShimListTwo = pShimListTwo->pNext) {
  3121. if (pShimListOne->pShimFix == pShimListTwo->pShimFix) {
  3122. //
  3123. // Now check if the command lines are same
  3124. //
  3125. if (pShimListOne->strCommandLine != pShimListTwo->strCommandLine) {
  3126. return FALSE;
  3127. }
  3128. //
  3129. // Now check if the include exclude lists are same. Operator is overloaded
  3130. //
  3131. if (pShimListOne->strlInExclude != pShimListTwo->strlInExclude) {
  3132. return FALSE;
  3133. }
  3134. bFound = TRUE;
  3135. break;
  3136. }
  3137. }
  3138. if (bFound == FALSE) {
  3139. return FALSE;
  3140. }
  3141. }
  3142. countTwo = 0;
  3143. for (PSHIM_FIX_LIST pShimListTwo = pLayerTwo->pShimFixList;
  3144. pShimListTwo;
  3145. pShimListTwo = pShimListTwo->pNext) {
  3146. countTwo++;
  3147. }
  3148. return (countOne == countTwo);
  3149. }
  3150. BOOL
  3151. PasteSystemAppHelp(
  3152. IN PDBENTRY pEntry,
  3153. IN PAPPHELP_DATA pData,
  3154. IN PDATABASE pDataBaseTo,
  3155. OUT PAPPHELP* ppAppHelpInLib
  3156. )
  3157. /*++
  3158. PasteSystemAppHelp
  3159. Desc: This routine, copies the apphelp for the help-id present in apphelp.sdb,
  3160. to the custom database specified by pDataBaseTo
  3161. Params:
  3162. IN PDBENTRY pEntry: The entry to which this apphelp message has been applied
  3163. IN PAPPHELP_DATA pData: Address of a APPHELP_DATA to pass to SdbReadApphelpDetailsData
  3164. This contains among other things the HTMLHELPID of the message to be copied
  3165. IN PDATABASE pDataBaseTo: The database in which we want to copy this message to
  3166. OUT PAPPHELP* ppAppHelpInLib: If not null Will contain a pointer to copied PAPPHELP
  3167. in the library section of pDataBaseTo
  3168. Return:
  3169. TRUE: Successful
  3170. FALSE: Otherwise
  3171. --*/
  3172. {
  3173. PDB pdbAppHelp = NULL;
  3174. BOOL bOk = TRUE;
  3175. if (!pEntry || !pData || !pDataBaseTo) {
  3176. assert (FALSE);
  3177. return FALSE;
  3178. }
  3179. pdbAppHelp = SdbOpenApphelpDetailsDatabase(NULL);
  3180. if (pdbAppHelp == NULL) {
  3181. bOk = FALSE;
  3182. goto end;
  3183. }
  3184. if (!SdbReadApphelpDetailsData(pdbAppHelp, pData)) {
  3185. bOk = FALSE;
  3186. goto end;
  3187. }
  3188. PAPPHELP pAppHelpNew = new APPHELP;
  3189. if (NULL == pAppHelpNew) {
  3190. MEM_ERR;
  3191. bOk = FALSE;
  3192. goto end;
  3193. }
  3194. pAppHelpNew->strURL = pData->szURL;
  3195. pAppHelpNew->strMessage = pData->szDetails;
  3196. pAppHelpNew->HTMLHELPID = ++(pDataBaseTo->m_nMAXHELPID);
  3197. pAppHelpNew->severity = pEntry->appHelp.severity;
  3198. pAppHelpNew->bBlock = pEntry->appHelp.bBlock;
  3199. pAppHelpNew->pNext = pDataBaseTo->pAppHelp;
  3200. pDataBaseTo->pAppHelp = pAppHelpNew;
  3201. if (ppAppHelpInLib) {
  3202. *ppAppHelpInLib = pAppHelpNew;
  3203. }
  3204. end:
  3205. if (pdbAppHelp) {
  3206. SdbCloseDatabase(pdbAppHelp);
  3207. pdbAppHelp = NULL;
  3208. }
  3209. return bOk;
  3210. }
  3211. BOOL
  3212. PasteAppHelpMessage(
  3213. IN PAPPHELP pAppHelp,
  3214. IN PDATABASE pDataBaseTo,
  3215. OUT PAPPHELP* ppAppHelpInLib
  3216. )
  3217. /*++
  3218. PasteAppHelpMessage
  3219. Desc: This routine is used to copy a single apphelp from a custom database
  3220. to some another database. This will be employed when we are copy pasting the
  3221. DBENTRY ies from one database to another. The APPHELP pointed to by the
  3222. DBENTRY, in the library, has to be copied to the library of the second database.
  3223. Notes: This routine is to be used only when we are copying from a custom (working or installed)
  3224. database, because for them we keep the app help data in the library.
  3225. For system aka main or global database the apphelp that is kept in the lib section for
  3226. custom databases is kept in apphelp.sdb so we employ PasteSystemAppHelp() for pasting
  3227. system database apphelp messages
  3228. Important: Win2K SP3 does not have apphelp.sdb and SdbOpenApphelpDetailsDatabase(NULL)
  3229. will fail there, so we cannot copy-paste app help from the system
  3230. database to a custom database in win2k
  3231. --*/
  3232. {
  3233. PAPPHELP pAppHelpNew = NULL;
  3234. if (pAppHelp == NULL || pDataBaseTo == NULL) {
  3235. assert(FALSE);
  3236. return FALSE;
  3237. }
  3238. pAppHelpNew = new APPHELP;
  3239. if (pAppHelpNew == NULL) {
  3240. MEM_ERR;
  3241. return FALSE;
  3242. }
  3243. //
  3244. // Copy all members of pAppHelp to pAppHelpNew
  3245. //
  3246. *pAppHelpNew = *pAppHelp;
  3247. //
  3248. // Now change the members that should change.
  3249. //
  3250. pAppHelpNew->HTMLHELPID = ++(pDataBaseTo->m_nMAXHELPID);
  3251. pAppHelpNew->pNext = pDataBaseTo->pAppHelp;
  3252. pDataBaseTo->pAppHelp = pAppHelpNew;
  3253. if (ppAppHelpInLib) {
  3254. *ppAppHelpInLib = pAppHelpNew;
  3255. }
  3256. return TRUE;
  3257. }
  3258. INT
  3259. PasteLayer(
  3260. IN PLAYER_FIX plf,
  3261. IN PDATABASE pDataBaseTo,
  3262. IN BOOL bForcePaste, // (FALSE)
  3263. OUT PLAYER_FIX* pplfNewInserted, // (NULL)
  3264. IN BOOL bShow // (FALSE)
  3265. )
  3266. /*++
  3267. PasteLayer
  3268. Desc: Pastes single layer plf to pDataBaseTo
  3269. Params:
  3270. IN PLAYER_FIX plf: The layer to paste
  3271. IN PDATABASE pDataBaseTo: The database to paste into
  3272. IN BOOL bForcePaste (FALSE): This means that we do want to
  3273. copy the layer, even if there exists a layer with the same name and shims
  3274. in database
  3275. OUT PLAYER_FIX* pplfNewInserted (NULL): Will contain the pointer to the
  3276. newly pasted layer or existing exactly similar layer
  3277. IN BOOL bShow (FALSE): Should we set the focus to the
  3278. newly created layer in the DBTree
  3279. Return:
  3280. 0: Copied, Note that we will return 0, if a layer already exists in this database
  3281. with the same name and same set of fixes and bForce == FALSE
  3282. -1: There was some error
  3283. Algo:
  3284. We proceed this way, for the modes to be pasted, we check if there exists some layer
  3285. in the target database with the same name. If there does not exist then we just paste it.
  3286. If there exists a layer with the same name then we check if the two layers are exactly
  3287. similar.
  3288. If they are exactly similar and bForcePaste is false then we quit. If they are exactly similar
  3289. and bForcePaste is true then we will paste the layer. It will have a derived name though. e.g
  3290. suppose we want to copy layer foo, then the name of the new layer that will be pasted will
  3291. be foo(1). Both of them will have the same fixes. We will also do this if the names are similar
  3292. but the contents of the two layers are different.
  3293. Under no circumstance will we allow two layers to have the same name in a database
  3294. If there already exists a layer with the same name then we always make a new layer with a derived
  3295. name. e.g suppose we want to copy layer foo, then the name of the new layer that
  3296. will be pasted will be foo(1)
  3297. Notes: This function is used when we copy-paste a layer from one db to another and also when we
  3298. copy an entry from one database that is fixed with a custom layer. bForcePaste will be true
  3299. if we are copying a layer from one database to another, but false if the routine is
  3300. getting called because we are trying to copy-paste an entry.
  3301. --*/
  3302. {
  3303. PLAYER_FIX pLayerFound = NULL;
  3304. INT iReturn = -1;
  3305. CSTRING strName = plf->strName;
  3306. CSTRING strEvent;
  3307. TCHAR szNewLayerName[MAX_PATH];
  3308. //
  3309. // Check if we have a layer with the same name in the target database or in
  3310. // the system database
  3311. //
  3312. pLayerFound = (PLAYER_FIX)FindFix(LPCTSTR(strName), FIX_LAYER, pDataBaseTo);
  3313. if (pLayerFound) {
  3314. //
  3315. // Now we check if *plf is exactly same as *pLayerFound
  3316. //
  3317. if (pplfNewInserted) {
  3318. *pplfNewInserted = pLayerFound;
  3319. }
  3320. if (!bForcePaste && CompareLayers(plf, pLayerFound)) {
  3321. //
  3322. // The layer already exists, do nothing
  3323. //
  3324. return 0;
  3325. } else {
  3326. //
  3327. // Dissimilar or we want to force a paste, Get the unique name
  3328. //
  3329. *szNewLayerName = 0;
  3330. strName = GetUniqueName(pDataBaseTo,
  3331. plf->strName,
  3332. szNewLayerName,
  3333. ARRAYSIZE(szNewLayerName),
  3334. FIX_LAYER);
  3335. }
  3336. }
  3337. //
  3338. // Add this new layer for the second database.
  3339. //
  3340. PLAYER_FIX pLayerNew = new LAYER_FIX(TRUE);
  3341. if (pLayerNew == NULL) {
  3342. MEM_ERR;
  3343. return -1;
  3344. }
  3345. //
  3346. // Overloaded operator. Copy all the fields from plf to pLayerNew. Then we will
  3347. // change the fields that need to be changed
  3348. //
  3349. *pLayerNew = *plf;
  3350. //
  3351. // Set the name of the layer. This might need to be changed, if we already had a layer
  3352. // by the same name in the target database
  3353. //
  3354. pLayerNew->strName = strName;
  3355. pLayerNew->pNext = pDataBaseTo->pLayerFixes;
  3356. pDataBaseTo->pLayerFixes = pLayerNew;
  3357. if (pplfNewInserted) {
  3358. *pplfNewInserted = pLayerNew;
  3359. }
  3360. if (plf->bCustom == FALSE) {
  3361. //
  3362. // System layer. We will have to add the event that a system layer had to be
  3363. // renamed
  3364. //
  3365. strEvent.Sprintf(GetString(IDS_EVENT_SYSTEM_RENAME),
  3366. plf->strName.pszString,
  3367. szNewLayerName,
  3368. pDataBaseTo->strName.pszString);
  3369. AppendEvent(EVENT_SYSTEM_RENAME, NULL, strEvent.pszString);
  3370. } else {
  3371. //
  3372. // We will show the name of the layer as it is shown in the target database.
  3373. // It might have got changed in case there was a conflict
  3374. //
  3375. strEvent.Sprintf(GetString(IDS_EVENT_LAYER_COPYOK),
  3376. plf->strName.pszString,
  3377. pDataBaseTo->strName.pszString,
  3378. pLayerNew->strName.pszString,
  3379. pDataBaseTo->strName.pszString);
  3380. AppendEvent(EVENT_LAYER_COPYOK, NULL, strEvent.pszString);
  3381. }
  3382. DBTree.AddNewLayer(pDataBaseTo, pLayerNew, bShow);
  3383. return 0;
  3384. }
  3385. BOOL
  3386. PasteMultipleLayers(
  3387. IN PDATABASE pDataBaseTo
  3388. )
  3389. /*++
  3390. PasteMultipleLayers
  3391. Desc: Pastes the layers that are copied to the clipboard to another database
  3392. Params:
  3393. IN PDATABASE pDataBaseTo: The database to copy the layers to
  3394. Return:
  3395. TRUE: Success
  3396. FALSE: Error
  3397. Notes: The difference between PasteMultipleLayers and PasteAllLayers is that
  3398. PasteMultipleLayers will only paste layers which are in the clipboard.
  3399. But PasteAllLayers will copy all layers of the "From" database. So
  3400. PasteAllLayers only checks which database is the "From" database.
  3401. PasteMultipleLayers is used when we select multiple items from the contents list
  3402. (RHS). PasteAllLayers is used when we have selected the "Compatibility Modes" node
  3403. in the db tree (LHS) while copying
  3404. --*/
  3405. {
  3406. CopyStruct* pCopyTemp = gClipBoard.pClipBoardHead;
  3407. //
  3408. // Copy all the layers in the clipboard
  3409. //
  3410. while (pCopyTemp) {
  3411. INT iRet = PasteLayer((PLAYER_FIX)pCopyTemp->lpData,
  3412. pDataBaseTo,
  3413. TRUE,
  3414. NULL,
  3415. FALSE);
  3416. if (iRet == -1) {
  3417. return FALSE;
  3418. }
  3419. pCopyTemp = pCopyTemp->pNext;
  3420. }
  3421. if (pDataBaseTo->hItemAllLayers) {
  3422. TreeView_Expand(DBTree.m_hLibraryTree, pDataBaseTo->hItemAllLayers, TVE_EXPAND);
  3423. TreeView_SelectItem(DBTree.m_hLibraryTree, pDataBaseTo->hItemAllLayers);
  3424. }
  3425. return TRUE;
  3426. }
  3427. BOOL
  3428. ShimFlagExistsInLayer(
  3429. IN LPVOID lpData,
  3430. IN PLAYER_FIX plf,
  3431. IN TYPE type
  3432. )
  3433. /*++
  3434. ShimFlagExistsInLayer
  3435. Desc: Checks if the specified shim / flag pData is present in the layer plf.
  3436. We just check if the layer contains this shim or flag, i.e. there is a
  3437. pointer in the PSHIM_FIX_LIST or PFLAG_FIX_LIST of the layer to the
  3438. shim or flag
  3439. Params:
  3440. IN LPVOID lpData: The pointer to shim or flag that we want to look for
  3441. IN PLAYER_FIX plf: The layer in which we should be looking
  3442. IN TYPE type: One of a) FIX_SHIM b) FIX_FLAG
  3443. Return:
  3444. TRUE: The fix exists in the layer
  3445. FALSE: Otherwise
  3446. --*/
  3447. {
  3448. if (lpData == NULL || plf == NULL) {
  3449. assert(FALSE);
  3450. return FALSE;
  3451. }
  3452. //
  3453. // First test for shims
  3454. //
  3455. if (type == FIX_SHIM) {
  3456. PSHIM_FIX_LIST psflInLayer = plf->pShimFixList;
  3457. while (psflInLayer) {
  3458. if (psflInLayer->pShimFix == (PSHIM_FIX)lpData) {
  3459. return TRUE;
  3460. }
  3461. psflInLayer = psflInLayer->pNext;
  3462. }
  3463. } else if (type == FIX_FLAG) {
  3464. //
  3465. // Test for flags
  3466. //
  3467. PFLAG_FIX_LIST pfflInLayer = plf->pFlagFixList;
  3468. while (pfflInLayer) {
  3469. if (pfflInLayer->pFlagFix == (PFLAG_FIX)lpData) {
  3470. return TRUE;
  3471. }
  3472. pfflInLayer = pfflInLayer->pNext;
  3473. }
  3474. } else {
  3475. //
  3476. // Invalid type
  3477. //
  3478. assert(FALSE);
  3479. return FALSE;
  3480. }
  3481. return FALSE;
  3482. }
  3483. BOOL
  3484. PasteShimsFlags(
  3485. IN PDATABASE pDataBaseTo
  3486. )
  3487. /*++
  3488. PasteShimsFlags
  3489. Desc: Copies the shims selected from the global database into the presently selected working
  3490. database's presently selected layer
  3491. If this shim is already present in the layer we do not
  3492. copy the shims, otherwise we copy this shim
  3493. The layer in which we want to copy the shims/flags is the layer associated with the
  3494. presently selected hItem in the db tree
  3495. Params:
  3496. IN PDATABASE pDataBaseTo: The database containing the layer in which we want to paste
  3497. the copied shims to.
  3498. --*/
  3499. {
  3500. CopyStruct* pCopyTemp = gClipBoard.pClipBoardHead;
  3501. HTREEITEM hItemSelected = TreeView_GetSelection(DBTree.m_hLibraryTree);
  3502. LPARAM lParam = NULL;
  3503. PLAYER_FIX plf = NULL;
  3504. TYPE type = TYPE_UNKNOWN;
  3505. LVITEM lvitem = {0};
  3506. //
  3507. // hItemSelected should be a layer, so that we can paste the shims into it
  3508. //
  3509. if (hItemSelected == NULL) {
  3510. assert(FALSE);
  3511. return FALSE;
  3512. }
  3513. if (!DBTree.GetLParam(hItemSelected, &lParam)) {
  3514. assert(FALSE);
  3515. return FALSE;
  3516. }
  3517. type = GetItemType(DBTree.m_hLibraryTree, hItemSelected);
  3518. if (type != FIX_LAYER) {
  3519. //
  3520. // A layer should have been selected if we want to copy-paste shims
  3521. //
  3522. if (type == TYPE_GUI_LAYERS && GetFocus() == g_hwndContentsList) {
  3523. //
  3524. // We had the focus on the contents list view. Now lets us get the
  3525. // item that has the selection mark in the list view pretend that the user
  3526. // wants to paste the fixes in that tree item for the corresponding list view
  3527. // item in the db tree
  3528. //
  3529. lvitem.mask = LVIF_PARAM;
  3530. lvitem.iItem = ListView_GetSelectionMark(g_hwndContentsList);
  3531. lvitem.iSubItem = 0;
  3532. if (ListView_GetItem(g_hwndContentsList, &lvitem)) {
  3533. //
  3534. // Since the focus is at the contents list and type == TYPE_GUI_LAYERS and
  3535. // we are going to paste fixes we must be having the "Compatibility Modes"
  3536. // tree item selected in the db tree
  3537. //
  3538. hItemSelected = DBTree.FindChild(hItemSelected,
  3539. lvitem.lParam);
  3540. if (hItemSelected == NULL) {
  3541. assert(FALSE);
  3542. return FALSE;
  3543. }
  3544. //
  3545. // Must set the lParam local variable to that of the list view item's lParam. The
  3546. // list view item for a layer and the corresponding tree view item
  3547. // in the db tree have the same lParam
  3548. //
  3549. lParam = lvitem.lParam;
  3550. } else {
  3551. //
  3552. // could not get the lparam for the list item
  3553. //
  3554. assert(FALSE);
  3555. return FALSE;
  3556. }
  3557. } else {
  3558. //
  3559. // We cannot paste fixes here
  3560. //
  3561. assert(FALSE);
  3562. return FALSE;
  3563. }
  3564. }
  3565. plf = (PLAYER_FIX)lParam;
  3566. while (pCopyTemp) {
  3567. //
  3568. // First we check if this shim is already present in the layer, if yes then we do not
  3569. // copy this, otherwise we copy this shim
  3570. //
  3571. TYPE typeFix = ConvertLpVoid2Type(pCopyTemp->lpData);
  3572. if (ShimFlagExistsInLayer(pCopyTemp->lpData, plf, typeFix)) {
  3573. goto next_shim;
  3574. }
  3575. //
  3576. // Now copy this shim or flag
  3577. //
  3578. if (typeFix == FIX_SHIM) {
  3579. PSHIM_FIX_LIST psfl = new SHIM_FIX_LIST;
  3580. PSHIM_FIX psfToCopy = (PSHIM_FIX)pCopyTemp->lpData;
  3581. if (psfl == NULL) {
  3582. MEM_ERR;
  3583. return FALSE;
  3584. }
  3585. psfl->pShimFix = psfToCopy;
  3586. psfl->pNext = plf->pShimFixList;
  3587. plf->pShimFixList = psfl;
  3588. //
  3589. // [Note:] We are not copying the parameters for the shim or flag because the shim or flag can be
  3590. // only selected from the system database. We need to change this if we allow copying of
  3591. // shims and layers from anywhere else except the system database.
  3592. //
  3593. } else if (typeFix == FIX_FLAG) {
  3594. PFLAG_FIX_LIST pffl = new FLAG_FIX_LIST;
  3595. if (pffl == NULL) {
  3596. MEM_ERR;
  3597. return FALSE;
  3598. }
  3599. pffl->pFlagFix = (PFLAG_FIX)pCopyTemp->lpData;
  3600. pffl->pNext = plf->pFlagFixList;
  3601. plf->pFlagFixList = pffl;
  3602. }
  3603. next_shim:
  3604. pCopyTemp = pCopyTemp->pNext;
  3605. }
  3606. //
  3607. // Now update this layer
  3608. //
  3609. DBTree.RefreshLayer(pDataBaseTo, plf);
  3610. return TRUE;
  3611. }
  3612. BOOL
  3613. PasteAllLayers(
  3614. IN PDATABASE pDataBaseTo
  3615. )
  3616. /*++
  3617. PasteAllLayers
  3618. Desc: Copies the layers that are in the clipboard to some other database
  3619. Params:
  3620. IN PDATABASE pDataBaseTo: The database in which we want to paste the modes
  3621. Return:
  3622. TRUE: Success
  3623. FALSE: Error
  3624. Notes: The difference between PasteMultipleLayers and PasteAllLayers is that
  3625. PasteMultipleLayers will only paste layers which are in the clipboard. But
  3626. PasteAllLayers will copy all layers of the "From" database. So
  3627. PasteAllLayers only checks which database is the "From" database.
  3628. PasteMultipleLayers is used when we select multiple items from the contents list
  3629. (RHS). PasteAllLayers is used when we have selected the "Compatibility Modes" node
  3630. in the db tree (LHS) while copying
  3631. --*/
  3632. {
  3633. PLAYER_FIX plf = gClipBoard.pDataBase->pLayerFixes;
  3634. while (plf) {
  3635. if (PasteLayer(plf, pDataBaseTo, TRUE, NULL, FALSE) == -1) {
  3636. return FALSE;
  3637. }
  3638. plf = plf->pNext;
  3639. }
  3640. if (pDataBaseTo->hItemAllLayers) {
  3641. TreeView_Expand(DBTree.m_hLibraryTree, pDataBaseTo->hItemAllLayers, TVE_EXPAND);
  3642. TreeView_SelectItem(DBTree.m_hLibraryTree, pDataBaseTo->hItemAllLayers);
  3643. }
  3644. return TRUE;
  3645. }
  3646. void
  3647. FreeAppHelp(
  3648. PAPPHELP_DATA pData
  3649. )
  3650. {
  3651. // bugbug: Do we need to free the strings with PAPPHELP_DATA <TODO>
  3652. }
  3653. INT
  3654. PasteSingleApp(
  3655. IN PDBENTRY pApptoPaste,
  3656. IN PDATABASE pDataBaseTo,
  3657. IN PDATABASE pDataBaseFrom,
  3658. IN BOOL bAllExes,
  3659. IN PCTSTR szNewAppNameIn //def = NULL
  3660. )
  3661. /*++
  3662. Desc: Pastes a single app into the database
  3663. Params:
  3664. IN PDBENTRY pApptoPaste: App to paste
  3665. IN PDATABASE pDataBaseTo: Database in which to paste
  3666. IN PDATABASE pDataBaseFrom: Database from where we obtained the pApptoPaste
  3667. IN BOOL bAllExes: Should we paste all exes for this app or only the entry
  3668. for pApptoPaste
  3669. IN PCTSTR szNewAppNameIn (NULL): If non null then the app name for the entries should be
  3670. changed to this name
  3671. Note: We save the Previous value of the m_nMAXHELPID of the TO database.
  3672. The function PasteAppHelpMessage will modify that while pasting the
  3673. entries, we will again make use of this so that the entries point
  3674. to the correct apphelp messages in the database and also they contain
  3675. the correct HTMLHELPids.
  3676. Return:
  3677. -1: There was some problem
  3678. 1: Successful
  3679. --*/
  3680. {
  3681. HCURSOR hCursor = GetCursor();
  3682. UINT uPrevMaxHtmldIdTo = pDataBaseTo->m_nMAXHELPID;
  3683. CSTRING strAppName = pApptoPaste->strAppName;
  3684. CSTRING strNewname = pApptoPaste->strAppName;
  3685. PDBENTRY pEntryToPaste = pApptoPaste;
  3686. PDBENTRY pApp = NULL;
  3687. PDBENTRY pEntryNew = NULL;
  3688. INT iRet = 0;
  3689. BOOL bConflictFound = FALSE;
  3690. CSTRING strEvent;
  3691. INT iReturn = 1;
  3692. SetCursor(LoadCursor(NULL, IDC_WAIT));
  3693. //
  3694. // Copy the layers
  3695. //
  3696. while (pEntryToPaste) {
  3697. PDBENTRY pEntryMatching = NULL, pAppOfEntry = NULL;
  3698. BOOL bRepaint = FALSE; //ReDraw the entry tree only if the entry to be deleted is in that!
  3699. // The entry that we want to ignore while looking for conflicts. This variable
  3700. // is used when we are doing a cut-paste on the same database, at that time we will like to ignore
  3701. // the entry that has been cut, during checking for conflicts
  3702. //
  3703. PDBENTRY pEntryIgnoreMatching = NULL;
  3704. if (!bAllExes && g_bIsCut && pDataBaseFrom == pDataBaseTo && gClipBoard.SourceType == ENTRY_TREE) {
  3705. pEntryIgnoreMatching = pApptoPaste;
  3706. }
  3707. if (CheckIfConflictingEntry(pDataBaseTo,
  3708. pEntryToPaste,
  3709. pEntryIgnoreMatching,
  3710. &pEntryMatching,
  3711. &pAppOfEntry)) {
  3712. if (g_bEntryConflictDonotShow == FALSE) {
  3713. *g_szData = 0;
  3714. StringCchPrintf(g_szData,
  3715. ARRAYSIZE(g_szData),
  3716. GetString(IDS_ENTRYCONFLICT),
  3717. pEntryMatching->strExeName.pszString,
  3718. pEntryMatching->strAppName.pszString);
  3719. iRet = DialogBoxParam(g_hInstance,
  3720. MAKEINTRESOURCE(IDD_CONFLICTENTRY),
  3721. g_hDlg,
  3722. HandleConflictEntry,
  3723. (LPARAM)g_szData);
  3724. if (iRet == IDNO) {
  3725. goto NextEntry;
  3726. }
  3727. strEvent.Sprintf(GetString(IDS_EVENT_CONFLICT_ENTRY),
  3728. pEntryMatching->strExeName.pszString,
  3729. pEntryMatching->strAppName.pszString,
  3730. pDataBaseTo->strName.pszString);
  3731. AppendEvent(EVENT_CONFLICT_ENTRY, NULL, strEvent.pszString);
  3732. bConflictFound = TRUE;
  3733. }
  3734. //
  3735. // Now copy the entry
  3736. //
  3737. HTREEITEM hItemSelected = DBTree.GetSelection();
  3738. if (GetItemType(DBTree.m_hLibraryTree, hItemSelected) == TYPE_ENTRY) {
  3739. LPARAM lParam;
  3740. if (DBTree.GetLParam(hItemSelected, &lParam) && (PDBENTRY)lParam == pAppOfEntry) {
  3741. //
  3742. // The entry tree for the correct app is already visible. So we can paste directly there
  3743. //
  3744. bRepaint = TRUE;
  3745. }
  3746. }
  3747. }
  3748. pEntryNew = new DBENTRY;
  3749. if (pEntryNew == NULL) {
  3750. iRet = -1;
  3751. goto End;
  3752. }
  3753. *pEntryNew = *pEntryToPaste;
  3754. GUID Guid;
  3755. CoCreateGuid(&Guid);
  3756. StringCchPrintf(pEntryNew->szGUID,
  3757. ARRAYSIZE(pEntryNew->szGUID),
  3758. TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  3759. Guid.Data1,
  3760. Guid.Data2,
  3761. Guid.Data3,
  3762. Guid.Data4[0],
  3763. Guid.Data4[1],
  3764. Guid.Data4[2],
  3765. Guid.Data4[3],
  3766. Guid.Data4[4],
  3767. Guid.Data4[5],
  3768. Guid.Data4[6],
  3769. Guid.Data4[7]);
  3770. //
  3771. // Now set the flags as per the entry being copied.
  3772. //
  3773. SetDisabledStatus(HKEY_LOCAL_MACHINE,
  3774. pEntryNew->szGUID,
  3775. pEntryToPaste->bDisablePerMachine);
  3776. //
  3777. // Unfortunately, now the custom layers in the custom layer list for the entry
  3778. // point to the custom layers in the From database, so correct that !
  3779. //
  3780. DeleteLayerFixList(pEntryNew->pFirstLayer);
  3781. pEntryNew->pFirstLayer = NULL;
  3782. PLAYER_FIX plfNewInserted = NULL; // The layer inserted by PasteLayer
  3783. PLAYER_FIX_LIST plflExisting = pEntryToPaste->pFirstLayer;
  3784. while (plflExisting) {
  3785. assert(plflExisting->pLayerFix);
  3786. PLAYER_FIX_LIST plflNew = new LAYER_FIX_LIST;
  3787. if (plflExisting->pLayerFix->bCustom) {
  3788. INT iRetLayerPaste = PasteLayer(plflExisting->pLayerFix,
  3789. pDataBaseTo,
  3790. FALSE,
  3791. &plfNewInserted,
  3792. FALSE);
  3793. if (iRetLayerPaste == -1) {
  3794. if (plflNew) {
  3795. delete plflNew;
  3796. }
  3797. if (pEntryNew) {
  3798. delete pEntryNew;
  3799. }
  3800. iRet = -1;
  3801. goto End;
  3802. }
  3803. plflNew->pLayerFix = plfNewInserted;
  3804. } else {
  3805. plflNew->pLayerFix = plflExisting->pLayerFix;
  3806. }
  3807. //
  3808. // Add this layer list for the entry.
  3809. //
  3810. plflNew->pNext = pEntryNew->pFirstLayer;
  3811. pEntryNew->pFirstLayer = plflNew;
  3812. plflExisting = plflExisting->pNext;
  3813. }
  3814. //
  3815. // Now get the apphelp message as well.
  3816. //
  3817. PAPPHELP pAppHelpInLib = NULL;
  3818. if (pDataBaseFrom->type != DATABASE_TYPE_GLOBAL && pEntryToPaste->appHelp.bPresent) {
  3819. if (!PasteAppHelpMessage(pEntryToPaste->appHelp.pAppHelpinLib,
  3820. pDataBaseTo,
  3821. &pAppHelpInLib)) {
  3822. iRet = -1;
  3823. goto End;
  3824. }
  3825. pEntryNew->appHelp.HTMLHELPID = ++uPrevMaxHtmldIdTo;
  3826. assert(pAppHelpInLib);
  3827. pEntryNew->appHelp.pAppHelpinLib = pAppHelpInLib;
  3828. } else if (pDataBaseFrom->type == DATABASE_TYPE_GLOBAL && pEntryToPaste->appHelp.bPresent) {
  3829. APPHELP_DATA AppHelpData;
  3830. ZeroMemory(&AppHelpData, sizeof(AppHelpData));
  3831. AppHelpData.dwHTMLHelpID = pEntryToPaste->appHelp.HTMLHELPID;
  3832. if (!PasteSystemAppHelp(pEntryToPaste, &AppHelpData, pDataBaseTo, &pAppHelpInLib)) {
  3833. //
  3834. // We cannot copy apphelp in win2k
  3835. //
  3836. pEntryNew->appHelp.bPresent = FALSE;
  3837. FreeAppHelp(&AppHelpData);
  3838. } else {
  3839. pEntryNew->appHelp.HTMLHELPID = ++uPrevMaxHtmldIdTo;
  3840. assert(pAppHelpInLib);
  3841. pEntryNew->appHelp.pAppHelpinLib = pAppHelpInLib;
  3842. FreeAppHelp(&AppHelpData);
  3843. }
  3844. }
  3845. //
  3846. // If We were passed the app name use that.
  3847. //
  3848. if (szNewAppNameIn != NULL) {
  3849. pEntryNew->strAppName = szNewAppNameIn;
  3850. }
  3851. BOOL bNew;
  3852. pApp = AddExeInApp(pEntryNew, &bNew, pDataBaseTo);
  3853. if (bNew == TRUE) {
  3854. pApp = NULL;
  3855. }
  3856. if (bConflictFound == FALSE) {
  3857. //
  3858. // We have been able to copy entry without any conflicts
  3859. //
  3860. strEvent.Sprintf(GetString(IDS_EVENT_ENTRY_COPYOK),
  3861. pEntryNew->strExeName.pszString,
  3862. pEntryNew->strAppName.pszString,
  3863. pDataBaseFrom->strName.pszString,
  3864. pDataBaseTo->strName.pszString);
  3865. AppendEvent(EVENT_ENTRY_COPYOK, NULL, strEvent.pszString);
  3866. }
  3867. NextEntry:
  3868. //
  3869. // Copy all other entries only if asked.
  3870. //
  3871. pEntryToPaste = (bAllExes) ? pEntryToPaste->pSameAppExe: NULL;
  3872. }
  3873. if (pEntryNew) {
  3874. DBTree.AddApp(pDataBaseTo, pEntryNew, TRUE);
  3875. }
  3876. End:
  3877. SetCursor(hCursor);
  3878. return iRet;
  3879. }
  3880. BOOL
  3881. PasteMultipleApps(
  3882. IN PDATABASE pDataBaseTo
  3883. )
  3884. /*++
  3885. PasteMultipleApps
  3886. Desc: Copies multiple apps that have been copied to the clipboard
  3887. Params:
  3888. IN PDATABASE pDataBaseTo: The database to copy to
  3889. Return:
  3890. TRUE: Success
  3891. FALSE: Error
  3892. --*/
  3893. {
  3894. CopyStruct* pCopyTemp = gClipBoard.pClipBoardHead;
  3895. int iRet = 0;
  3896. while (pCopyTemp ) {
  3897. iRet = PasteSingleApp((PDBENTRY) pCopyTemp->lpData,
  3898. pDataBaseTo,
  3899. gClipBoard.pDataBase,
  3900. TRUE);
  3901. if (iRet == IDCANCEL || iRet == -1) {
  3902. break;
  3903. }
  3904. pCopyTemp = pCopyTemp->pNext;
  3905. }
  3906. SendMessage(g_hwndEntryTree, WM_SETREDRAW, TRUE, 0);
  3907. return iRet != -1 ? TRUE : FALSE;
  3908. }
  3909. BOOL
  3910. PasteAllApps(
  3911. IN PDATABASE pDataBaseTo
  3912. )
  3913. /*++
  3914. PasteAllApps
  3915. Desc: Copies all apps from one database to another. This routine is called when the user
  3916. had pressed copy when the focus was on the "Applications" tree item for a database
  3917. Params:
  3918. IN PDATABASE pDataBaseTo: The database to copy to
  3919. Return:
  3920. TRUE: Success
  3921. FALSE: Error
  3922. --*/
  3923. {
  3924. if (gClipBoard.pDataBase == NULL) {
  3925. assert(FALSE);
  3926. return FALSE;
  3927. }
  3928. PDBENTRY pApp = gClipBoard.pDataBase->pEntries;
  3929. int iRet = 0;
  3930. while (pApp) {
  3931. iRet = PasteSingleApp(pApp, pDataBaseTo, gClipBoard.pDataBase, TRUE);
  3932. if (iRet == IDCANCEL || iRet == -1) {
  3933. break;
  3934. }
  3935. pApp = pApp->pNext;
  3936. }
  3937. SendMessage(g_hwndEntryTree,
  3938. WM_SETREDRAW,
  3939. TRUE,
  3940. 0);
  3941. return (iRet != -1) ? TRUE : FALSE;
  3942. }
  3943. void
  3944. ValidateClipBoard(
  3945. IN PDATABASE pDataBase,
  3946. IN LPVOID lpData
  3947. )
  3948. /*++
  3949. ValidateClipBoard
  3950. Desc: If the database is being closed and we have something from that database in the
  3951. clipboard Then the clipboard should be emptied.
  3952. If we have some other data in the clipboard such as an entry or some layer in
  3953. the clipboard and that is removed we have to remove it from the clipboard as
  3954. well.
  3955. Params:
  3956. IN PDATABASE pDataBase: Database being closed
  3957. IN LPVOID lpData: The entry or layer being removed
  3958. --*/
  3959. {
  3960. if (pDataBase && pDataBase == gClipBoard.pDataBase) {
  3961. gClipBoard.RemoveAll();
  3962. } else if (lpData) {
  3963. gClipBoard.CheckAndRemove(lpData);
  3964. }
  3965. }
  3966. BOOL
  3967. RemoveApp(
  3968. IN PDATABASE pDataBase,
  3969. IN PDBENTRY pApp
  3970. )
  3971. /*++
  3972. RemoveApp
  3973. Desc: Removes the application pApp and all the entries of this app from pDataBase
  3974. Params:
  3975. IN PDATABASE pDataBase: The database in which pApp resides
  3976. IN PDBENTRY pApp: The app to remove
  3977. Return:
  3978. void
  3979. --*/
  3980. {
  3981. if (!pDataBase || !pApp) {
  3982. assert(FALSE);
  3983. return FALSE;
  3984. }
  3985. PDBENTRY pAppInDataBase = pDataBase->pEntries;
  3986. PDBENTRY pAppPrev = NULL;
  3987. //
  3988. // Find the previous pointer of the app, so that we can remove this app
  3989. //
  3990. while (pAppInDataBase) {
  3991. if (pAppInDataBase == pApp) {
  3992. break;
  3993. }
  3994. pAppPrev = pAppInDataBase;
  3995. pAppInDataBase = pAppInDataBase->pNext;
  3996. }
  3997. if (pAppInDataBase) {
  3998. //
  3999. // We found the app
  4000. //
  4001. if (pAppPrev) {
  4002. pAppPrev->pNext = pAppInDataBase->pNext;
  4003. } else {
  4004. //
  4005. // The first app of the database matched
  4006. //
  4007. pDataBase->pEntries = pAppInDataBase->pNext;
  4008. }
  4009. }
  4010. PDBENTRY pEntryTemp = pAppInDataBase;
  4011. PDBENTRY pTempNext = NULL;
  4012. //
  4013. // Delete all the entries of this app.
  4014. //
  4015. while (pEntryTemp) {
  4016. pTempNext = pEntryTemp->pSameAppExe;
  4017. ValidateClipBoard(NULL, pEntryTemp);
  4018. delete pEntryTemp;
  4019. pEntryTemp = pTempNext;
  4020. }
  4021. --pDataBase->uAppCount;
  4022. return TRUE;
  4023. }
  4024. void
  4025. RemoveAllApps(
  4026. IN PDATABASE pDataBase
  4027. )
  4028. /*++
  4029. RemoveAllApps
  4030. Desc: Removes all the applications and all the entries from pDataBase. This will be invoked
  4031. when the user presses delete after when the focus was on the "Applications"
  4032. tree item for a database. Or when we want to cut all the applications
  4033. Params:
  4034. IN PDATABASE pDataBase: The database from which to remove all the entries
  4035. Return:
  4036. void
  4037. --*/
  4038. {
  4039. while (pDataBase->pEntries) {
  4040. //
  4041. // pDataBase->pEntries will get modified in the following function, as it is the first element
  4042. //
  4043. RemoveApp(pDataBase, pDataBase->pEntries);
  4044. }
  4045. }
  4046. BOOL
  4047. CheckForSDB(
  4048. void
  4049. )
  4050. /*++
  4051. CheckForSDB
  4052. Desc: Attempts to locate sysmain.sdb in the apppatch directory.
  4053. --*/
  4054. {
  4055. HANDLE hFile;
  4056. TCHAR szSDBPath[MAX_PATH * 2];
  4057. BOOL fResult = FALSE;
  4058. UINT uResult = 0;
  4059. uResult = GetSystemWindowsDirectory(szSDBPath, MAX_PATH);
  4060. if (uResult == 0 || uResult >= MAX_PATH) {
  4061. assert(FALSE);
  4062. return FALSE;
  4063. }
  4064. ADD_PATH_SEPARATOR(szSDBPath, ARRAYSIZE(szSDBPath));
  4065. StringCchCat(szSDBPath, ARRAYSIZE(szSDBPath), TEXT("apppatch\\sysmain.sdb"));
  4066. hFile = CreateFile(szSDBPath,
  4067. GENERIC_READ,
  4068. FILE_SHARE_READ | FILE_SHARE_WRITE,
  4069. NULL,
  4070. OPEN_EXISTING,
  4071. FILE_ATTRIBUTE_NORMAL,
  4072. NULL);
  4073. if (INVALID_HANDLE_VALUE != hFile) {
  4074. CloseHandle(hFile);
  4075. fResult = TRUE;
  4076. } else {
  4077. fResult = FALSE;
  4078. }
  4079. return (fResult);
  4080. }
  4081. BOOL
  4082. CheckIfInstalledDB(
  4083. IN PCTSTR szGuid
  4084. )
  4085. /*++
  4086. CheckIfInstalledDB
  4087. Desc: Tests whether the szGuid matches with one of an installed database.
  4088. This function assumes that all the installed databases are currently in
  4089. InstalledDataBaseList
  4090. Params:
  4091. IN PCTSTR szGuid: The guid of the database that we want to check
  4092. Return:
  4093. TRUE: If installed
  4094. FALSE: Otherwise
  4095. Warn: Do not do EnterCriticalSection(g_csInstalledList) in CheckIfInstalledDB()
  4096. because CheckIfInstalledDB() is called by Qyery db as well when it tries
  4097. to evaluate expressions and it might already have done a
  4098. EnterCriticalSection(g_csInstalledList)
  4099. and then we will get a deadlock
  4100. --*/
  4101. {
  4102. PDATABASE pDatabase = NULL;
  4103. //
  4104. // Was this a system database ?
  4105. //
  4106. if (!lstrcmpi(szGuid, GlobalDataBase.szGUID)
  4107. || !lstrcmpi(szGuid, GUID_APPHELP_SDB)
  4108. || !lstrcmpi(szGuid, GUID_SYSTEST_SDB)
  4109. || !lstrcmpi(szGuid, GUID_MSI_SDB)
  4110. || !lstrcmpi(szGuid, GUID_DRVMAIN_SDB)) {
  4111. return TRUE;
  4112. }
  4113. pDatabase = InstalledDataBaseList.pDataBaseHead;
  4114. while (pDatabase) {
  4115. if (!lstrcmpi(pDatabase->szGUID, szGuid)) {
  4116. return TRUE;
  4117. }
  4118. pDatabase = pDatabase->pNext;
  4119. }
  4120. return FALSE;
  4121. }
  4122. INT
  4123. GetLayerCount(
  4124. IN LPARAM lp,
  4125. IN TYPE type
  4126. )
  4127. /*++
  4128. GetLayerCount
  4129. Desc: Gets the number of layers applied to a entry or present in a database
  4130. Params:
  4131. IN LPARAM lp: The pointer to an entry or a database
  4132. IN TYPE type: The type, either an entry (TYPE_ENTRY) or one of the DATABASE_TYPE_*
  4133. Return:
  4134. -1: Error
  4135. #Layers: Otherwise
  4136. --*/
  4137. {
  4138. PLAYER_FIX_LIST plfl;
  4139. PLAYER_FIX plf;
  4140. INT iCount = 0;
  4141. PDATABASE pDatabase = NULL;
  4142. PDBENTRY pEntry = NULL;
  4143. if (lp == NULL) {
  4144. assert(FALSE);
  4145. return -1;
  4146. }
  4147. if (type == TYPE_ENTRY) {
  4148. pEntry = (PDBENTRY)lp;
  4149. plfl = pEntry->pFirstLayer;
  4150. while (plfl) {
  4151. ++iCount;
  4152. plfl = plfl->pNext;
  4153. }
  4154. return iCount;
  4155. }
  4156. if (type == DATABASE_TYPE_GLOBAL
  4157. || type == DATABASE_TYPE_INSTALLED
  4158. || type == DATABASE_TYPE_WORKING) {
  4159. pDatabase = (PDATABASE)lp;
  4160. plf = pDatabase->pLayerFixes;
  4161. while (plf) {
  4162. ++iCount;
  4163. plf = plf->pNext;
  4164. }
  4165. }
  4166. return iCount;
  4167. }
  4168. INT
  4169. GetPatchCount(
  4170. IN LPARAM lp,
  4171. IN TYPE type
  4172. )
  4173. /*++
  4174. GetPatchCount
  4175. Desc: Gets the number of patches applied to a entry or present in a database
  4176. Params:
  4177. IN LPARAM lp: The pointer to an entry or a database
  4178. IN TYPE type: The type, either an entry (TYPE_ENTRY) or one of the DATABASE_TYPE_*
  4179. Return:
  4180. -1: Error
  4181. #Patches: Otherwise
  4182. --*/
  4183. {
  4184. PPATCH_FIX_LIST ppfl;
  4185. PPATCH_FIX ppf;
  4186. INT iCount = 0;
  4187. if (lp == NULL) {
  4188. return -1;
  4189. }
  4190. if (type == TYPE_ENTRY) {
  4191. PDBENTRY pEntry = (PDBENTRY)lp;
  4192. ppfl = pEntry->pFirstPatch;
  4193. while (ppfl) {
  4194. ++iCount;
  4195. ppfl = ppfl->pNext;
  4196. }
  4197. return iCount;
  4198. }
  4199. if (type == DATABASE_TYPE_GLOBAL || type == DATABASE_TYPE_INSTALLED || type == DATABASE_TYPE_WORKING) {
  4200. PDATABASE pDatabase = (PDATABASE)lp;
  4201. ppf = pDatabase->pPatchFixes;
  4202. while (ppf) {
  4203. ++iCount;
  4204. ppf = ppf->pNext;
  4205. }
  4206. }
  4207. return iCount;
  4208. }
  4209. INT
  4210. GetShimFlagCount(
  4211. IN LPARAM lp,
  4212. IN TYPE type
  4213. )
  4214. /*++
  4215. GetShimFlagCount
  4216. Desc: Gets the number of shims and flags applied to a entry or present in a database
  4217. Params:
  4218. IN LPARAM lp: The pointer to an entry or a database
  4219. IN TYPE type: The type, either an entry (TYPE_ENTRY) or one of the DATABASE_TYPE_*,
  4220. Or FIX_LAYER
  4221. Return:
  4222. -1: Error
  4223. #shims and flags: Otherwise
  4224. --*/
  4225. {
  4226. PSHIM_FIX_LIST psfl = NULL;
  4227. PSHIM_FIX psf = NULL;
  4228. PFLAG_FIX_LIST pffl = NULL;
  4229. PFLAG_FIX pff = NULL;
  4230. INT iCount = 0;
  4231. if (lp == NULL) {
  4232. assert(FALSE);
  4233. return -1;
  4234. }
  4235. if (type == TYPE_ENTRY) {
  4236. PDBENTRY pEntry = (PDBENTRY)lp;
  4237. psfl = pEntry->pFirstShim;
  4238. while (psfl) {
  4239. ++iCount;
  4240. psfl = psfl->pNext;
  4241. }
  4242. pffl = pEntry->pFirstFlag;
  4243. while (pffl) {
  4244. ++iCount;
  4245. pffl = pffl->pNext;
  4246. }
  4247. return iCount;
  4248. } else if (type == DATABASE_TYPE_GLOBAL || type == DATABASE_TYPE_INSTALLED || type == DATABASE_TYPE_WORKING) {
  4249. PDATABASE pDatabase = (PDATABASE)lp;
  4250. psf = pDatabase->pShimFixes;
  4251. while (psf) {
  4252. ++iCount;
  4253. psf = psf->pNext;
  4254. }
  4255. pff = pDatabase->pFlagFixes;
  4256. while (pff) {
  4257. ++iCount;
  4258. pff = pff->pNext;
  4259. }
  4260. return iCount;
  4261. } else if (type == FIX_LAYER) {
  4262. PLAYER_FIX plf = (PLAYER_FIX)lp;
  4263. psfl = plf->pShimFixList;
  4264. while (psfl) {
  4265. ++iCount;
  4266. psfl = psfl->pNext;
  4267. }
  4268. pffl = plf->pFlagFixList;
  4269. while (pffl) {
  4270. ++iCount;
  4271. pffl = pffl->pNext;
  4272. }
  4273. } else {
  4274. assert(FALSE);
  4275. }
  4276. return iCount;
  4277. }
  4278. INT
  4279. GetMatchCount(
  4280. IN PDBENTRY pEntry
  4281. )
  4282. /*++
  4283. GetMatchCount
  4284. Desc: Returns the number of matching files used by an entry
  4285. Params:
  4286. IN PDBENTRY pEntry: The entry whose number of matching files we want to get
  4287. Return:
  4288. -1: If error
  4289. number of matching files: if success
  4290. --*/
  4291. {
  4292. if (pEntry == NULL) {
  4293. assert(FALSE);
  4294. return -1;
  4295. }
  4296. PMATCHINGFILE pMatch = pEntry->pFirstMatchingFile;
  4297. INT iCount = 0;
  4298. while (pMatch) {
  4299. iCount++;
  4300. pMatch = pMatch->pNext;
  4301. }
  4302. return iCount;
  4303. }
  4304. BOOL
  4305. IsUnique(
  4306. IN PDATABASE pDatabase,
  4307. IN PCTSTR szName,
  4308. IN UINT uType
  4309. )
  4310. /*++
  4311. IsUnique
  4312. Desc: Tests whether the passed string already exists as an appname
  4313. or a layer name in the database pDatabase
  4314. Params:
  4315. IN PDATABASE pDatabase: The database in which to search
  4316. IN PCTSTR szName: The string to search for
  4317. IN UINT uType: One of:
  4318. a) FIX_LAYER: If it is FIX_LAYER, we should check if a
  4319. layer with the name szName already exists in the database.
  4320. b) TYPE_ENTRY: If it is TYPE_ENTRY we should check if an app with the strAppName of szName
  4321. already exists in the database
  4322. --*/
  4323. {
  4324. PLAYER_FIX plf = NULL;
  4325. PDBENTRY pEntry = NULL;
  4326. if (pDatabase == NULL || szName == NULL) {
  4327. assert(FALSE);
  4328. return FALSE;
  4329. }
  4330. if (uType == FIX_LAYER) {
  4331. plf = pDatabase->pLayerFixes;
  4332. while (plf) {
  4333. if (plf->strName == szName) {
  4334. return FALSE;
  4335. }
  4336. plf = plf->pNext;
  4337. }
  4338. return TRUE;
  4339. } else if (uType == TYPE_ENTRY) {
  4340. pEntry = pDatabase->pEntries;
  4341. while (pEntry) {
  4342. if (pEntry->strAppName == szName) {
  4343. return FALSE;
  4344. }
  4345. pEntry = pEntry->pNext;
  4346. }
  4347. return TRUE;
  4348. } else {
  4349. //
  4350. // Invalid TYPE
  4351. //
  4352. assert(FALSE);
  4353. }
  4354. return FALSE;
  4355. }
  4356. PTSTR
  4357. GetUniqueName(
  4358. IN PDATABASE pDatabase,
  4359. IN PCTSTR szExistingName,
  4360. OUT PTSTR szBuffer,
  4361. IN INT cchBufferCount,
  4362. IN TYPE type
  4363. )
  4364. /*++
  4365. GetUniqueName
  4366. Desc: Gets a unique name for a layer or an app
  4367. Params:
  4368. IN PDATABASE pDatabase: The database in which to search
  4369. IN PCTSTR szExistingName: The existing layer or app name
  4370. OUT PTSTR szBuffer: The buffer where we put in the name
  4371. IN INT cchBufferCount: The size of the buffer szBuffer in TCHARs
  4372. IN TYPE type: One of: a) FIX_LAYER b) TYPE_ENTRY:
  4373. Return: Pointer to szBuffer. This will contain the new name
  4374. --*/
  4375. {
  4376. CSTRING strNewname;
  4377. TCHAR szName[MAX_PATH];
  4378. BOOL bValid = FALSE;
  4379. UINT uIndex = 0;
  4380. if (szBuffer == NULL) {
  4381. assert(FALSE);
  4382. return TEXT("X");
  4383. }
  4384. *szBuffer = 0;
  4385. *szName = 0;
  4386. SafeCpyN(szName, szExistingName, ARRAYSIZE(szName));
  4387. //
  4388. // Extract any number that occurs between () in the string, and increment that
  4389. //
  4390. TCHAR *pch = szName + lstrlen(szName);
  4391. while (pch > szName) {
  4392. if (*pch == TEXT(')')) {
  4393. *pch = TEXT('\0');
  4394. } else if (*pch == TEXT('(')) {
  4395. *pch = TEXT('\0');
  4396. uIndex = Atoi(pch + 1, &bValid);
  4397. if (bValid) {
  4398. ++uIndex;
  4399. } else {
  4400. SafeCpyN(szName, szExistingName, ARRAYSIZE(szName));
  4401. }
  4402. break;
  4403. }
  4404. --pch;
  4405. }
  4406. if (uIndex == 0) {
  4407. uIndex = 1;
  4408. }
  4409. while (TRUE) {
  4410. strNewname.Sprintf(TEXT("%s(%u)"), szName, uIndex);
  4411. if (IsUnique(pDatabase, strNewname, type) == TRUE) {
  4412. break;
  4413. }
  4414. uIndex++;
  4415. }
  4416. SafeCpyN(szBuffer, strNewname, cchBufferCount);
  4417. return szBuffer;
  4418. }
  4419. PDBENTRY
  4420. GetAppForEntry(
  4421. IN PDATABASE pDatabase,
  4422. IN PDBENTRY pEntryToCheck
  4423. )
  4424. /*++
  4425. GetAppForEntry
  4426. Desc: Gets the app for the entry.
  4427. Params:
  4428. IN PDATABASE pDatabase: The database in which to look
  4429. IN PDBENTRY pEntryToCheck: The entry whose app we need to find
  4430. Return: The First PDBENTRY in the link list where this entry occurs, if it
  4431. occurs in the database
  4432. NULL otherwise
  4433. --*/
  4434. {
  4435. PDBENTRY pApp = pDatabase->pEntries;
  4436. PDBENTRY pEntry = pApp;
  4437. while (pApp) {
  4438. pEntry = pApp;
  4439. while (pEntry) {
  4440. if (pEntry == pEntryToCheck) {
  4441. goto End;
  4442. }
  4443. pEntry = pEntry->pSameAppExe;
  4444. }
  4445. pApp = pApp->pNext;
  4446. }
  4447. End:
  4448. return pApp;
  4449. }
  4450. BOOL
  4451. GetDbGuid(
  4452. OUT PTSTR pszGuid,
  4453. IN INT cchpszGuid,
  4454. IN PDB pdb
  4455. )
  4456. /*++
  4457. GetDbGuid
  4458. Desc: Gets the guid of the database specified by pdb in pszGuid
  4459. OUT TCHAR* pszGuid: The guid will be stored in this
  4460. IN PDB pdb: The pdb of the database whose guid we want
  4461. Return:
  4462. TRUE: Success
  4463. FALSE: Error
  4464. --*/
  4465. {
  4466. BOOL bOk = FALSE;
  4467. TAGID tiDatabase = NULL;
  4468. TAGID tName = NULL;
  4469. if (pszGuid == NULL || cchpszGuid == 0) {
  4470. assert(FALSE);
  4471. return FALSE;
  4472. }
  4473. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  4474. if (tiDatabase == 0) {
  4475. Dbg(dlError, "Cannot find TAG_DATABASE\n");
  4476. bOk = FALSE;
  4477. goto End;
  4478. }
  4479. tName = SdbFindFirstTag(pdb, tiDatabase, TAG_DATABASE_ID);
  4480. if (0 != tName) {
  4481. GUID* pGuid;
  4482. TAGID tiGuid = SdbFindFirstTag(pdb, tiDatabase, TAG_DATABASE_ID);
  4483. pGuid = (GUID*)SdbGetBinaryTagData(pdb, tiGuid);
  4484. //BUGBUG: What about freeing this ?
  4485. *pszGuid = 0;
  4486. if (pszGuid != NULL) {
  4487. StringCchPrintf(pszGuid,
  4488. cchpszGuid,
  4489. TEXT ("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  4490. pGuid->Data1,
  4491. pGuid->Data2,
  4492. pGuid->Data3,
  4493. pGuid->Data4[0],
  4494. pGuid->Data4[1],
  4495. pGuid->Data4[2],
  4496. pGuid->Data4[3],
  4497. pGuid->Data4[4],
  4498. pGuid->Data4[5],
  4499. pGuid->Data4[6],
  4500. pGuid->Data4[7]);
  4501. bOk = TRUE;
  4502. }
  4503. }
  4504. End:
  4505. return bOk;
  4506. }
  4507. BOOL
  4508. IsShimInEntry(
  4509. IN PCTSTR szShimName,
  4510. IN PDBENTRY pEntry
  4511. )
  4512. /*++
  4513. IsShimInEntry
  4514. Desc: Checks if the entry has the specified shim.
  4515. We only check if the shim name matches, we do not check for parameters
  4516. Params:
  4517. IN PCTSTR szShimName: Name of the shim that we want to check for
  4518. IN PDBENTRY pEntry: Entry that we want to check in
  4519. --*/
  4520. {
  4521. PSHIM_FIX_LIST psfl = NULL;
  4522. if (pEntry == NULL) {
  4523. assert(FALSE);
  4524. return FALSE;
  4525. }
  4526. psfl = pEntry->pFirstShim;
  4527. while (psfl) {
  4528. if (psfl->pShimFix->strName == szShimName) {
  4529. return TRUE;
  4530. }
  4531. psfl = psfl->pNext;
  4532. }
  4533. return FALSE;
  4534. }
  4535. BOOL
  4536. IsShimInlayer(
  4537. IN PLAYER_FIX plf,
  4538. IN PSHIM_FIX psf,
  4539. IN CSTRING* pstrCommandLine,
  4540. IN CSTRINGLIST* pstrlInEx
  4541. )
  4542. /*++
  4543. IsShimInlayer
  4544. Desc: Checks if the shim psf is present in the layer plf
  4545. Params:
  4546. IN PLAYER_FIX plf: The layer to check in
  4547. IN PSHIM_FIX psf: The shim to check for
  4548. IN CSTRING* pstrCommandLine: Any command line for the shim
  4549. IN CSTRINGLIST* pstrlInEx: The pointer to the include-exclude list for the shim
  4550. Return: TRUE if present
  4551. : FALSE if not present
  4552. --*/
  4553. {
  4554. PSHIM_FIX_LIST psflInLayer = plf->pShimFixList;
  4555. while (psflInLayer) {
  4556. if (psflInLayer->pShimFix == psf) {
  4557. if (pstrCommandLine && psflInLayer->strCommandLine != *pstrCommandLine) {
  4558. goto Next_Loop;
  4559. }
  4560. if (pstrlInEx && *pstrlInEx != psflInLayer->strlInExclude) {
  4561. goto Next_Loop;
  4562. }
  4563. return TRUE;
  4564. }
  4565. Next_Loop:
  4566. psflInLayer = psflInLayer->pNext;
  4567. }
  4568. return FALSE;
  4569. }
  4570. BOOL
  4571. IsFlagInlayer(
  4572. PLAYER_FIX plf,
  4573. PFLAG_FIX pff,
  4574. CSTRING* pstrCommandLine
  4575. )
  4576. /*++
  4577. IsFlagInlayer
  4578. Desc: Checks if the flag psf is present in the layer plf
  4579. Params:
  4580. IN PLAYER_FIX plf: The layer to check in
  4581. IN PFLAG_FIX pff: The flag to check for
  4582. IN CSTRING* pstrCommandLine: Any command line for the flag
  4583. Return: TRUE if present
  4584. : FALSE if not present
  4585. --*/
  4586. {
  4587. PFLAG_FIX_LIST pfflInLayer = plf->pFlagFixList;
  4588. while (pfflInLayer) {
  4589. if (pfflInLayer->pFlagFix == pff) {
  4590. if (pstrCommandLine && *pstrCommandLine != pff->strCommandLine) {
  4591. goto Next_Loop;
  4592. } else {
  4593. return TRUE;
  4594. }
  4595. }
  4596. Next_Loop:
  4597. pfflInLayer = pfflInLayer->pNext;
  4598. }
  4599. return FALSE;
  4600. }
  4601. void
  4602. PreprocessForSaveAs(
  4603. IN PDATABASE pDatabase
  4604. )
  4605. /*++
  4606. PreprocessForSaveAs
  4607. Desc: This routine replaces the db guid and the entry guids with fresh guids.
  4608. This routine is called just before we do a save as. This routine,
  4609. also makes sure that if there is a entry that is disabled then the
  4610. new guid for the entry also is set to disabled in the registry.
  4611. Params:
  4612. IN PDATABASE pDatabase: The database that we are going to save
  4613. --*/
  4614. {
  4615. GUID Guid;
  4616. PDBENTRY pEntry = NULL, pApp = NULL;
  4617. if (pDatabase == NULL) {
  4618. assert(FALSE);
  4619. return;
  4620. }
  4621. CoCreateGuid(&Guid);
  4622. StringCchPrintf(pDatabase->szGUID,
  4623. ARRAYSIZE(pDatabase->szGUID),
  4624. TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  4625. Guid.Data1,
  4626. Guid.Data2,
  4627. Guid.Data3,
  4628. Guid.Data4[0],
  4629. Guid.Data4[1],
  4630. Guid.Data4[2],
  4631. Guid.Data4[3],
  4632. Guid.Data4[4],
  4633. Guid.Data4[5],
  4634. Guid.Data4[6],
  4635. Guid.Data4[7]);
  4636. pEntry = pDatabase->pEntries, pApp = pDatabase->pEntries;
  4637. while (pEntry) {
  4638. CoCreateGuid(&Guid);
  4639. StringCchPrintf(pEntry->szGUID,
  4640. ARRAYSIZE(pEntry->szGUID),
  4641. TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  4642. Guid.Data1,
  4643. Guid.Data2,
  4644. Guid.Data3,
  4645. Guid.Data4[0],
  4646. Guid.Data4[1],
  4647. Guid.Data4[2],
  4648. Guid.Data4[3],
  4649. Guid.Data4[4],
  4650. Guid.Data4[5],
  4651. Guid.Data4[6],
  4652. Guid.Data4[7]);
  4653. //
  4654. // Now set the flags as per the entry being copied.
  4655. //
  4656. SetDisabledStatus(HKEY_LOCAL_MACHINE,
  4657. pEntry->szGUID,
  4658. pEntry->bDisablePerMachine);
  4659. if (pEntry->pSameAppExe) {
  4660. pEntry = pEntry->pSameAppExe;
  4661. } else {
  4662. pApp = pApp->pNext;
  4663. pEntry = pApp;
  4664. }
  4665. }
  4666. }
  4667. void
  4668. ShowShimLog(
  4669. void
  4670. )
  4671. /*++
  4672. ShowShimLog
  4673. Desc: Show the shim log file in notepad.
  4674. --*/
  4675. {
  4676. STARTUPINFO si;
  4677. PROCESS_INFORMATION pi;
  4678. TCHAR szLogPath[MAX_PATH * 2];
  4679. CSTRING strCmd;
  4680. CSTRING strNotePadpath;
  4681. UINT uResult = 0;
  4682. *szLogPath = 0;
  4683. uResult = GetSystemWindowsDirectory(szLogPath, MAX_PATH);
  4684. if (uResult == 0 || uResult >= MAX_PATH) {
  4685. assert(FALSE);
  4686. return;
  4687. }
  4688. ADD_PATH_SEPARATOR(szLogPath, ARRAYSIZE(szLogPath));
  4689. StringCchCat(szLogPath, ARRAYSIZE(szLogPath), TEXT("AppPatch\\") SHIM_FILE_LOG_NAME);
  4690. if (GetFileAttributes(szLogPath) == -1) {
  4691. //
  4692. // The log file does not exist
  4693. //
  4694. MessageBox(g_hDlg,
  4695. GetString(IDS_NO_LOGFILE),
  4696. g_szAppName,
  4697. MB_ICONEXCLAMATION | MB_OK);
  4698. return;
  4699. }
  4700. strNotePadpath.GetSystemDirectory();
  4701. strNotePadpath += TEXT("notepad.exe");
  4702. //
  4703. // Note the space at the end
  4704. //
  4705. strCmd.Sprintf(TEXT("\"%s\" "), (LPCTSTR)strNotePadpath, szLogPath);
  4706. strCmd.Strcat(szLogPath);
  4707. ZeroMemory(&si, sizeof(si));
  4708. si.cb = sizeof(si);
  4709. if (!CreateProcess(NULL,
  4710. (LPTSTR)strCmd,
  4711. NULL,
  4712. NULL,
  4713. FALSE,
  4714. NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
  4715. NULL,
  4716. NULL,
  4717. &si,
  4718. &pi)) {
  4719. MessageBox(g_hDlg, GetString(IDS_NO_NOTEPAD), g_szAppName, MB_ICONEXCLAMATION);
  4720. return;
  4721. }
  4722. CloseHandle(pi.hThread);
  4723. CloseHandle(pi.hProcess);
  4724. }
  4725. INT
  4726. CopyShimFixList(
  4727. IN OUT PSHIM_FIX_LIST* ppsflDest,
  4728. IN PSHIM_FIX_LIST* ppsflSrc
  4729. )
  4730. /*++
  4731. Copy
  4732. Desc: Copies the *ppsflSrc to *ppsflDest. Removes any existing
  4733. shims first
  4734. Params:
  4735. IN OUT PSHIM_FIX_LIST* ppsflDest: The pointer to shim fix list in which we want to copy
  4736. IN PSHIM_FIX_LIST* ppsflSrc: The pointer to shim fix list from which we want to copy
  4737. Return: Number of shims copied
  4738. --*/
  4739. {
  4740. PSHIM_FIX_LIST psflDestination = NULL;
  4741. PSHIM_FIX_LIST psflSrc = NULL;
  4742. PSHIM_FIX_LIST psflTemp = NULL;
  4743. INT iCount = 0;
  4744. if (ppsflDest == NULL || ppsflSrc == NULL) {
  4745. assert(FALSE);
  4746. goto End;
  4747. }
  4748. psflDestination = *ppsflDest;
  4749. psflSrc = *ppsflSrc;
  4750. //
  4751. // Remove all the shims for this
  4752. //
  4753. DeleteShimFixList(psflDestination);
  4754. psflDestination = NULL;
  4755. //
  4756. // Now do the copy
  4757. //
  4758. //
  4759. // Loop over the shims for psflSrc and add them to the destination shim fix list
  4760. //
  4761. while (psflSrc) {
  4762. psflTemp = new SHIM_FIX_LIST;
  4763. if (psflTemp == NULL) {
  4764. MEM_ERR;
  4765. goto End;
  4766. }
  4767. //
  4768. // copy all the members for psflSrc
  4769. //
  4770. if (psflSrc->pLuaData) {
  4771. //
  4772. // Source has lua data so we need to get that
  4773. //
  4774. psflTemp->pLuaData = new LUADATA;
  4775. if (psflTemp == NULL) {
  4776. MEM_ERR;
  4777. break;
  4778. }
  4779. psflTemp->pLuaData->Copy(psflSrc->pLuaData);
  4780. }
  4781. psflTemp->pShimFix = psflSrc->pShimFix;
  4782. psflTemp->strCommandLine = psflSrc->strCommandLine;
  4783. psflTemp->strlInExclude = psflSrc->strlInExclude;
  4784. if (psflDestination == NULL) {
  4785. //
  4786. // First item
  4787. //
  4788. psflDestination = psflTemp;
  4789. } else {
  4790. //
  4791. // Insert at the beginning
  4792. //
  4793. psflTemp->pNext = psflDestination;
  4794. psflDestination = psflTemp;
  4795. }
  4796. ++iCount;
  4797. psflSrc = psflSrc->pNext;
  4798. }
  4799. End:
  4800. if (ppsflDest) {
  4801. *ppsflDest = psflDestination;
  4802. }
  4803. return iCount;
  4804. }
  4805. BOOL
  4806. IsValidAppName(
  4807. IN PCTSTR pszAppName
  4808. )
  4809. /*++
  4810. ValidAppName
  4811. Desc: Checks if the name can be used for an app. Since LUA wizard uses the app name
  4812. to create directories, we should not allow the chars that are not allowed in file
  4813. names
  4814. Params:
  4815. IN PCTSTR pszAppName: The name that we want to check
  4816. Return:
  4817. TRUE: The app name is valid
  4818. FDALSE: Otherwise
  4819. --*/
  4820. {
  4821. PCTSTR pszIndex = pszAppName;
  4822. if (pszIndex == NULL) {
  4823. assert(FALSE);
  4824. return FALSE;
  4825. }
  4826. while (*pszIndex) {
  4827. if (_tcschr(TEXT("\\/?:*<>|\""), *pszIndex)) {
  4828. return FALSE;
  4829. }
  4830. ++pszIndex;
  4831. }
  4832. return TRUE;
  4833. }