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

2077 lines
54 KiB

  1. /*
  2. Note
  3. ==============
  4. That when we call Opendatabase(bGlobal = TRUE ) then we remove all the entries for the database.
  5. In the case when we had only one DB object, this meant removing all entries, local as well as global
  6. from the DB, but when we have got two DBs, this will only remove the entries for the present DB
  7. Opendatabase(bGlobal = TRUE ) is called only during WM_CREATE of the CApplication otherwise,
  8. bGlobal = FALSE.
  9. If we want others to view other system dbs, then we might have have to take care of this.
  10. */
  11. #include "compatadmin.h"
  12. #include "psapi.h"
  13. extern UINT g_nMAXHELPID;
  14. CSTRING g_szDBName;
  15. BOOL g_bNew = FALSE;
  16. BOOL
  17. DeleteAppHelp (
  18. UINT nHelpID
  19. );
  20. bool
  21. InstallDatabase(
  22. TCHAR *szPath,
  23. TCHAR *szOptions
  24. );
  25. CSTRING CDatabase::m_DBName;
  26. GUID CDatabase::m_DBGuid;
  27. PDB CDatabase::m_pDB;
  28. CSTRING CDatabase::m_szCurrentDatabase;// Name of the SDB File
  29. UINT CDatabase::m_uStandardImages;
  30. //
  31. //Checks whether the 2 PDBENTRIES have the same mathcign files.
  32. //
  33. int CheckMatch(const PDBENTRY pExistEntry, const PDBENTRY pNewEntry);
  34. BOOL CDatabase::ChangeDatabaseName(void)
  35. {
  36. if ( !g_bNew )
  37. g_szDBName = m_DBName;
  38. if ( g_szDBName.Length() == 0 ) {
  39. MEM_ERR;
  40. return FALSE;
  41. }
  42. if ( FALSE == DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_NEWDATABASE),g_theApp.m_hWnd,(DLGPROC)NewDatabaseProc) )
  43. return FALSE;
  44. if ( !g_bNew )
  45. if ( m_DBName != g_szDBName ) {
  46. m_DBName = g_szDBName;
  47. m_bDirty = TRUE;
  48. g_theApp.UpdateView();
  49. }
  50. m_DBName = g_szDBName;
  51. return TRUE;
  52. }
  53. BOOL CDatabase::NewDatabase(BOOL bShowDialog)
  54. {
  55. g_szDBName = TEXT("No Name");
  56. g_bNew = TRUE;
  57. if ( bShowDialog )
  58. if ( !ChangeDatabaseName() )
  59. return FALSE;
  60. g_bNew = FALSE;
  61. CloseDatabase();
  62. CDatabase::m_DBName = g_szDBName;
  63. m_szCurrentDatabase = TEXT("");
  64. g_theApp.UpdateView();
  65. return TRUE;
  66. }
  67. BOOL CDatabase::CloseDatabase(void)
  68. {
  69. // delete only the local database
  70. PDBRECORD pWalk = m_pRecordHead;
  71. PDBRECORD pPrev = pWalk, pNext;//Not needed, just to satisfy Prefast!
  72. while ( NULL != pWalk ) {
  73. if ( ! pWalk->bGlobal ) {
  74. pNext = pWalk->pNext;
  75. if ( pWalk == m_pRecordHead ) {
  76. m_pRecordHead = pWalk->pNext;
  77. }
  78. else
  79. pPrev->pNext = pWalk->pNext;
  80. delete pWalk;
  81. pWalk = pNext;
  82. } else {
  83. pPrev = pWalk;
  84. pWalk = pWalk->pNext;
  85. }
  86. }
  87. // Remove local layers
  88. PDBLAYER pLayer = m_pLayerList;
  89. PDBLAYER pHold;
  90. while ( NULL != pLayer ) {
  91. if ( !pLayer->bPermanent ) {
  92. PDBLAYER pNext = pLayer->pNext;
  93. if ( pLayer == m_pLayerList )
  94. m_pLayerList = pLayer->pNext;
  95. else
  96. pHold->pNext = pLayer->pNext;
  97. delete pLayer;
  98. pLayer = pNext;
  99. continue;
  100. }
  101. pHold = pLayer;
  102. pLayer = pLayer->pNext;
  103. }
  104. ZeroMemory(&m_DBGuid,sizeof(GUID));
  105. /*
  106. m_DBName = "No Name";
  107. m_szCurrentDatabase = "";
  108. g_theApp.UpdateView();
  109. */
  110. m_bDirty = FALSE;
  111. return TRUE;
  112. }
  113. UINT CDatabase::DeleteRecord(PDBRECORD pRecord)
  114. {
  115. PDBRECORD pWalk;
  116. PDBRECORD pHoldRecord;
  117. pWalk = m_pRecordHead;
  118. while ( NULL != pWalk ) {
  119. if ( pWalk == pRecord ) {
  120. // Remove root level record.
  121. PDBENTRY pEntry = pWalk->pEntries;
  122. while ( NULL != pEntry ) {
  123. PDBENTRY pHoldEntry = pEntry->pNext;
  124. if (pEntry->uType == ENTRY_APPHELP) {
  125. DeleteAppHelp( ((PHELPENTRY)pEntry)->uHelpID );
  126. }
  127. delete pEntry;
  128. pEntry = pHoldEntry;
  129. }
  130. if ( NULL != pWalk->pDup ) {
  131. // Replace with duplicate
  132. pWalk->pDup->pNext = pWalk->pNext;
  133. if ( pWalk == m_pRecordHead )
  134. m_pRecordHead = pWalk->pDup;
  135. else
  136. pHoldRecord->pNext = pWalk->pDup;
  137. } else {
  138. if ( pWalk == m_pRecordHead )
  139. m_pRecordHead = m_pRecordHead->pNext;
  140. else
  141. pHoldRecord->pNext = pWalk->pNext;
  142. }
  143. delete pWalk;
  144. m_bDirty = TRUE;
  145. return DELRES_RECORDREMOVED;
  146. }
  147. if ( NULL != pWalk->pDup ) {
  148. PDBRECORD pWalk2 = pWalk->pDup;
  149. PDBRECORD pHold2;
  150. while ( NULL != pWalk2 ) {
  151. if ( pWalk2 == pRecord )
  152. break;
  153. pHold2 = pWalk2;
  154. pWalk2 = pWalk2->pDup;
  155. }
  156. if ( NULL != pWalk2 ) {
  157. // Remove the duplicate entry.
  158. if ( pWalk2 == pWalk->pDup )
  159. pWalk->pDup = pWalk2->pDup;
  160. else
  161. pHold2->pDup = pWalk2->pDup;
  162. PDBENTRY pEntry = pWalk2->pEntries;
  163. while ( NULL != pEntry ) {
  164. PDBENTRY pHoldEntry = pEntry->pNext;
  165. delete pEntry;
  166. pEntry = pHoldEntry;
  167. }
  168. delete pWalk2;
  169. m_bDirty = TRUE;
  170. return DELRES_DUPREMOVED;
  171. }
  172. }
  173. pHoldRecord = pWalk;
  174. pWalk = pWalk->pNext;
  175. }
  176. return DELRES_FAILED;
  177. }
  178. BOOL CDatabase::OpenDatabase(CSTRING & szFilename, BOOL bGlobal)
  179. {
  180. if ( NULL == g_hSDB ) {
  181. TCHAR szShimDB[MAX_PATH_BUFFSIZE] ;
  182. *szShimDB = 0;
  183. GetSystemWindowsDirectory(szShimDB, MAX_PATH);
  184. lstrcat(szShimDB,TEXT("\\AppPatch"));
  185. CSTRING szStr = szShimDB;
  186. if ( szStr.Length() == 0 ) {
  187. MEM_ERR;
  188. return FALSE;
  189. }
  190. g_hSDB = SdbInitDatabase(HID_DOS_PATHS,(LPCWSTR) szStr);
  191. }
  192. #ifndef UNICODE
  193. WCHAR wszFilename[MAX_PATH_BUFFSIZE];
  194. ZeroMemory(wszFilename,sizeof(wszFilename));
  195. MultiByteToWideChar (CP_ACP,MB_PRECOMPOSED,szFilename,lstrlen(szFilename),wszFilename,MAX_PATH);
  196. m_pDB = SdbOpenDatabase(wszFilename,DOS_PATH);
  197. #else
  198. m_pDB = SdbOpenDatabase(szFilename.pszString,DOS_PATH);
  199. #endif
  200. if ( NULL == m_pDB )
  201. return FALSE;
  202. if ( bGlobal ) {
  203. // Delete the previous database from memory
  204. while ( NULL != m_pRecordHead ) {
  205. PDBRECORD pHold = m_pRecordHead->pNext;
  206. delete m_pRecordHead;
  207. m_pRecordHead = pHold;
  208. }
  209. } else {
  210. CloseDatabase();
  211. }
  212. ReadShims(bGlobal);
  213. ReadAppHelp();
  214. // Load in the contents of the database.
  215. TAGID tiDatabase, tiExe;
  216. UINT uShims=0;
  217. UINT uEntries=0;
  218. UINT uAppHelp=0;
  219. UINT uLayers=0;
  220. tiDatabase = SdbFindFirstTag(CDatabase::m_pDB, TAGID_ROOT, TAG_DATABASE);
  221. if ( 0 != tiDatabase ) {
  222. if ( !bGlobal ) {
  223. TAGID tName;
  224. // Read in the database GUID and name.
  225. tName = SdbFindFirstTag(m_pDB, tiDatabase, TAG_NAME);
  226. if ( 0 != tName )
  227. m_DBName = ReadDBString(tName);
  228. tName = SdbFindFirstTag(m_pDB, tiDatabase, TAG_DATABASE_ID);
  229. if ( 0 != tName )
  230. SdbReadBinaryTag(m_pDB,tName,(PBYTE)&m_DBGuid,sizeof(GUID));
  231. }
  232. tiExe = SdbFindFirstTag(CDatabase::m_pDB, tiDatabase, TAG_EXE);
  233. while ( 0 != tiExe ) {
  234. PDBRECORD pRecord = new DBRECORD;
  235. MSG Msg;
  236. while ( PeekMessage(&Msg,NULL,0,0,PM_REMOVE) ) {
  237. TranslateMessage(&Msg);
  238. DispatchMessage(&Msg);
  239. }
  240. ++uEntries;
  241. if ( NULL != pRecord ) {
  242. if ( ReadRecord(tiExe,pRecord) ) {
  243. pRecord->bGlobal = bGlobal;
  244. InsertRecord(pRecord);
  245. }
  246. }
  247. tiExe = SdbFindNextTag(CDatabase::m_pDB, tiDatabase, tiExe);
  248. }
  249. }
  250. if ( !bGlobal ) {
  251. //
  252. // BUGBUG Consider using shlwapi function to find a filename
  253. //
  254. LPTSTR szFile = _tcsrchr( (LPTSTR)szFilename, TEXT('\\'));
  255. if (szFile == NULL) {
  256. szFile = szFilename;
  257. } else {
  258. ++szFile; // or move to the next char CharNext
  259. }
  260. /*
  261. wsprintf(szWindowTitle,"Application Management Console (%s)",szFile+1);
  262. SetWindowText(g_theApp.m_hWnd,szWindowTitle);
  263. */
  264. m_szCurrentDatabase = szFilename;
  265. }
  266. /*
  267. TCHAR szTemp[80];
  268. wsprintf(szTemp,"Entries: %d (L: %d S: %d AH: %d)",uEntries,uLayers, uShims,uAppHelp);
  269. SendMessage(m_hStatusBar,SB_SETTEXT,1,(LPARAM) szTemp);
  270. */
  271. DWORD dwFlags = GetFileAttributes(szFilename);
  272. if ( 0 != (dwFlags & FILE_ATTRIBUTE_READONLY) )
  273. g_theApp.SetStatusText(2,CSTRING(TEXT("Read Only")));
  274. else
  275. g_theApp.SetStatusText(2,CSTRING(TEXT("")));
  276. g_theApp.UpdateView();
  277. SdbCloseDatabase(m_pDB);
  278. m_pDB = NULL;
  279. return TRUE;
  280. }
  281. BOOL CDatabase::InsertRecord(PDBRECORD pRecord)
  282. {
  283. // Insert into the list.
  284. /***
  285. This routine inserts the passed pRecord into the list pointed by m_pRecordHead.
  286. This routine also checks if there is some other files are already associated with this App. and if
  287. yes it makes the pDup record of that exe to point to pRecord. pRecord->pDup will
  288. point to whatever that entry's pDup pointed to. */
  289. if ( NULL != m_pRecordHead ) {
  290. if (pRecord->bGlobal == FALSE) {
  291. }
  292. PDBRECORD pWalk = m_pRecordHead;
  293. PDBRECORD pHold = NULL;
  294. int nResult;
  295. do {
  296. nResult = lstrcmpi(pWalk->szAppName,pRecord->szAppName);
  297. // If less OR Equal
  298. //CHANGE (-1 != )
  299. if ( 0 <= nResult )
  300. break;
  301. pHold = pWalk;
  302. pWalk = pWalk->pNext;
  303. }
  304. while ( NULL != pWalk );
  305. // Insert it right here.
  306. if ( 0 == nResult ) {
  307. // The strings are equal. Simply add shim/apphelp information
  308. // to this .EXE entry.
  309. PDBRECORD pSameAppExes = pWalk;
  310. PDBRECORD pSameAppExesPrev = NULL;
  311. if (pRecord->bGlobal){
  312. pRecord->pDup = pWalk->pDup;
  313. pWalk->pDup = pRecord;
  314. }else{
  315. //
  316. //We do not want to perform the extra check on system entries.
  317. //
  318. while (pSameAppExes) {
  319. if (pSameAppExes->szEXEName == pRecord->szEXEName ) {
  320. //
  321. //Same exe, must check the matching files and if same then we must add these entries to the present exe.
  322. //
  323. int check = CheckMatch(pSameAppExes->pEntries, pRecord->pEntries);
  324. if (check) {
  325. int result = MessageBox(g_theApp.m_hWnd,
  326. TEXT("An existing file with the same name and similar matching information was found\n")
  327. TEXT("Do you wish to update the previous fix with the modified entries?\n\n"),
  328. TEXT("CompatAdmin"),
  329. MB_ICONWARNING | MB_YESNO|MB_DEFBUTTON1 | MB_APPLMODAL
  330. );
  331. if (result == IDYES) {
  332. //
  333. //Add all the entries, except the Matcbing file to this exe entry
  334. //
  335. if (pSameAppExes->szLayerName.Length() &&
  336. pRecord->szLayerName.Length() &&
  337. ! (pRecord->szLayerName == pSameAppExes->szLayerName)
  338. ) {
  339. //
  340. //The new entry contains a layer as well !
  341. //
  342. CSTRING message;
  343. message.sprintf(TEXT("Do you want to replace the compatibiltu mode for File: \"%s\" in Application \"%s\" \?\nPresent Compatability mode = %s\nNew Compatibility mode = %s"),
  344. (LPCTSTR)pSameAppExes->szEXEName,(LPCTSTR)pSameAppExes->szAppName,
  345. (LPCTSTR)pSameAppExes->szLayerName,(LPCTSTR)pRecord->szLayerName
  346. );
  347. int result = MessageBox(g_theApp.m_hWnd,message,TEXT("CompatAdmin"),MB_ICONWARNING | MB_YESNO);
  348. if (result == IDYES) {
  349. pSameAppExes->szLayerName = pRecord->szLayerName;
  350. }
  351. }
  352. else if(!pSameAppExes->szLayerName.Length() && pRecord->szLayerName.Length()){
  353. //
  354. //Add the layer directly
  355. //
  356. pSameAppExes->szLayerName = pRecord->szLayerName;
  357. }
  358. while ( pRecord->pEntries ) {
  359. PDBENTRY pNext = pRecord->pEntries->pNext;
  360. if ( pRecord->pEntries->uType != ENTRY_MATCH ) {
  361. //
  362. //Take out the first entry.
  363. //
  364. pRecord->pEntries->pNext = pSameAppExes->pEntries;
  365. pSameAppExes->pEntries = pRecord->pEntries;
  366. pRecord->pEntries = pNext;
  367. continue;
  368. }
  369. else break;
  370. }//while ( pRecord->pEntries )
  371. PDBENTRY pPrev = pRecord->pEntries;
  372. PDBENTRY pTemp = pRecord->pEntries;
  373. //
  374. //We are here means the first entry is a match entry or NULL. First loop will do nothing.
  375. //
  376. while( pTemp ){
  377. if (pTemp->uType != ENTRY_MATCH) {
  378. //
  379. //Add this to the list of entries for the exe
  380. //
  381. //1. splice this entry from pRecord->pEntries
  382. pPrev->pNext = pTemp->pNext;
  383. //2. Add it to the front of the entrties of the prev. file
  384. pTemp->pNext = pSameAppExes->pEntries;
  385. //3.
  386. pSameAppExes->pEntries = pTemp;
  387. //4. Move on for the other entries in pRecord
  388. pTemp = pPrev->pNext;
  389. }else{
  390. pPrev = pTemp;
  391. pTemp = pTemp->pNext;
  392. }//if (pTemp->uType != ENTRY_MATCH ELSE
  393. }//while( pTemp )
  394. pRecord->DestroyAll();
  395. }//if reuslt == IDYES
  396. else{ //IDNO
  397. pRecord->DestroyAll();
  398. ;
  399. }
  400. break;
  401. }//if (check)
  402. }//if (pSameAppExes->szEXEName == pRecord->szEXEName
  403. pSameAppExesPrev = pSameAppExes;
  404. pSameAppExes = pSameAppExes->pDup;
  405. }//while (pSameAppExes)
  406. //
  407. //We have not found any exe within this app that has the same matching info as this one.
  408. //So we haev to add this to the end
  409. //
  410. if (pSameAppExes == NULL ) {
  411. if ( NULL != pHold ) {
  412. pRecord->pNext = pWalk->pNext;
  413. pHold->pNext = pRecord;
  414. pWalk->pNext = NULL;
  415. pRecord->pDup = pWalk;
  416. } else { // First element
  417. pRecord->pNext =m_pRecordHead->pNext;
  418. m_pRecordHead = pRecord;
  419. pRecord->pDup = pWalk;
  420. }
  421. }
  422. }//else for the outer loop. above the while
  423. } else {
  424. if ( NULL != pHold ) {
  425. pRecord->pNext = pHold->pNext;
  426. pHold->pNext = pRecord;
  427. } else { // First element
  428. pRecord->pNext = m_pRecordHead;
  429. m_pRecordHead = pRecord;
  430. }
  431. }
  432. } else { //fIRST AND ONLY ELEMENT
  433. pRecord->pNext = NULL;
  434. m_pRecordHead = pRecord;
  435. }
  436. return TRUE;
  437. }
  438. BOOL CDatabase::ReadRecord(TAGID tagParent, PDBRECORD pRecord, PDB pDB)
  439. {
  440. TAGID Info;
  441. PDBENTRY pLast = NULL;
  442. if ( NULL == pDB )
  443. pDB = CDatabase::m_pDB;
  444. // Entries with flags are ignored and not displayed
  445. Info = SdbFindFirstTag(pDB, tagParent, TAG_FLAG); //K Did not find this TAG_FLAG IN THE SDB Database !!!
  446. if ( 0 != Info )
  447. return FALSE;
  448. ZeroMemory(pRecord,sizeof(DBRECORD));
  449. Info = SdbGetFirstChild(pDB,tagParent);
  450. while ( 0 != Info ) {
  451. TAG tag;
  452. tag = SdbGetTagFromTagID(pDB,Info);
  453. switch ( tag ) {
  454. case TAG_NAME:
  455. {
  456. pRecord->szEXEName = ReadDBString(Info,pDB);
  457. }
  458. break;
  459. case TAG_LAYER:
  460. {
  461. TAGID Layer = SdbGetFirstChild(pDB,Info);
  462. while ( 0 != Layer ) {
  463. TAG Tag = SdbGetTagFromTagID(pDB,Layer);
  464. switch ( Tag ) {
  465. case TAG_NAME:
  466. pRecord->szLayerName = ReadDBString(Layer,pDB);
  467. break;
  468. }
  469. Layer = SdbGetNextChild(pDB,Info,Layer);
  470. }
  471. }
  472. break;
  473. case TAG_APP_NAME:
  474. {
  475. pRecord->szAppName = ReadDBString(Info,pDB);
  476. }
  477. break;
  478. case TAG_MATCHING_FILE:
  479. {
  480. TAGID MatchInfo;
  481. TAG Tag;
  482. PMATCHENTRY pEntry = new MATCHENTRY;
  483. if ( NULL != pEntry ) {
  484. ZeroMemory(pEntry,sizeof(MATCHENTRY));
  485. pEntry->Entry.uType = ENTRY_MATCH;
  486. pEntry->Entry.pNext = NULL;
  487. MatchInfo = SdbGetFirstChild(pDB,Info);
  488. while ( 0 != MatchInfo ) {
  489. Tag = SdbGetTagFromTagID(pDB,MatchInfo);
  490. switch ( Tag ) {
  491. case TAG_NAME:
  492. pEntry->szMatchName = ReadDBString(MatchInfo,pDB);
  493. break;
  494. case TAG_SIZE:
  495. pEntry->dwSize = SdbReadDWORDTag(pDB,MatchInfo,0);
  496. break;
  497. case TAG_CHECKSUM:
  498. pEntry->dwChecksum = SdbReadDWORDTag(pDB,MatchInfo,0);
  499. break;
  500. case TAG_BIN_FILE_VERSION:
  501. pEntry->FileVersion.QuadPart = SdbReadQWORDTag(pDB,MatchInfo,0);
  502. break;
  503. case TAG_FILE_VERSION:
  504. pEntry->szFileVersion = ReadDBString(MatchInfo,pDB);
  505. break;
  506. case TAG_BIN_PRODUCT_VERSION:
  507. pEntry->ProductVersion.QuadPart = SdbReadQWORDTag(pDB,MatchInfo,0);
  508. break;
  509. case TAG_PRODUCT_VERSION:
  510. pEntry->szProductVersion = ReadDBString(MatchInfo,pDB);
  511. break;
  512. case TAG_FILE_DESCRIPTION:
  513. pEntry->szDescription = ReadDBString(MatchInfo,pDB);
  514. break;
  515. case TAG_COMPANY_NAME:
  516. pEntry->szCompanyName = ReadDBString(MatchInfo,pDB);
  517. break;
  518. }
  519. MatchInfo = SdbGetNextChild(pDB,Info,MatchInfo);
  520. }
  521. /***
  522. Here's what he probably meant. He has used the pEntry->Entry.pNext
  523. to actually link up the the differnrent match entries for the EXE.
  524. pLast points to the last pEntry. !!!! This is SOMETHING.
  525. */
  526. //Note that pEntry is a variable of type PMATCHENTRY
  527. if ( NULL != pLast )
  528. pLast->pNext = (PDBENTRY) pEntry;
  529. else
  530. pRecord->pEntries = (PDBENTRY) pEntry;
  531. pLast = (PDBENTRY) pEntry;
  532. }
  533. }
  534. break;
  535. case TAG_PATCH_REF:
  536. case TAG_SHIM_REF:
  537. {
  538. PSHIMENTRY pEntry = new SHIMENTRY;
  539. //Note that pEntry is a variable of type PSHIMENTRY
  540. if ( NULL != pEntry ) {
  541. TAGID tiShimName;
  542. ZeroMemory(pEntry,sizeof(SHIMENTRY));
  543. pEntry->Entry.uType = ENTRY_SHIM;
  544. pEntry->Entry.pNext = NULL;
  545. tiShimName = SdbFindFirstTag(pDB,Info,TAG_NAME);
  546. pEntry->szShimName = ReadDBString(tiShimName,pDB);
  547. tiShimName = SdbFindFirstTag(pDB,Info,TAG_COMMAND_LINE);
  548. if ( 0 != tiShimName )
  549. pEntry->szCmdLine = ReadDBString(tiShimName,pDB);
  550. if ( NULL != pLast )
  551. pLast->pNext = (PDBENTRY) pEntry;
  552. else
  553. pRecord->pEntries = (PDBENTRY) pEntry;
  554. // Look up the specific shim this entry is associated with.
  555. PSHIMDESC pWalk = g_theApp.GetDBGlobal().m_pShimList;
  556. while ( NULL != pWalk ) {
  557. // == is overloaded in the CSTRING class
  558. if ( pEntry->szShimName == pWalk->szShimName ) {
  559. pEntry->pDesc = pWalk;
  560. break;
  561. }
  562. pWalk = pWalk->pNext;
  563. }
  564. pLast = (PDBENTRY) pEntry;
  565. }
  566. }
  567. break;
  568. case TAG_APPHELP:
  569. {
  570. PHELPENTRY pHelp = new HELPENTRY;
  571. if ( NULL != pHelp ) {
  572. TAGID tTemp;
  573. pHelp->Entry.uType = ENTRY_APPHELP;
  574. pHelp->Entry.pNext = NULL;
  575. tTemp = SdbFindFirstTag(pDB, Info, TAG_PROBLEMSEVERITY);
  576. pHelp->uSeverity = SdbReadDWORDTag(pDB, tTemp, 0);
  577. tTemp = SdbFindFirstTag(pDB, Info, TAG_HTMLHELPID);
  578. pHelp->uHelpID = SdbReadDWORDTag(pDB, tTemp, 0);
  579. if ( NULL != pLast )
  580. pLast->pNext = (PDBENTRY) pHelp;
  581. else
  582. pRecord->pEntries = (PDBENTRY) pHelp;
  583. pLast = (PDBENTRY) pHelp;
  584. }
  585. pRecord->uLayer = LAYER_APPHELP;
  586. }
  587. break;
  588. case TAG_EXE_ID:
  589. {
  590. LPGUID pGUID = (GUID*)SdbGetBinaryTagData(pDB, Info);
  591. if ( NULL != pGUID )
  592. pRecord->guidID = *pGUID;
  593. }
  594. break;
  595. }
  596. Info = SdbGetNextChild(pDB,tagParent,Info);
  597. }
  598. pRecord->dwUserFlags = GetEntryFlags(HKEY_CURRENT_USER,pRecord->guidID);
  599. pRecord->dwGlobalFlags = GetEntryFlags(HKEY_LOCAL_MACHINE,pRecord->guidID);
  600. return TRUE;
  601. }
  602. CSTRING STDCALL CDatabase::ReadDBString(TAGID tagID, PDB pDB)
  603. {
  604. CSTRING Str;
  605. WCHAR szAppName[1024];
  606. if ( NULL == pDB )
  607. pDB = CDatabase::m_pDB;
  608. ZeroMemory(szAppName,sizeof(szAppName));
  609. if ( !SdbReadStringTag(pDB,tagID,szAppName,sizeof(szAppName)/sizeof(WCHAR)) )
  610. return Str;
  611. #ifndef UNICODE
  612. #define SIZE 1024
  613. TCHAR szString[SIZE];
  614. *szString = TEXT('\0');
  615. WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,szAppName, -1, szString, SIZE, NULL, NULL);
  616. Str = szString;
  617. #else
  618. Str = szAppName;
  619. #endif
  620. return Str;
  621. }
  622. BOOL
  623. CDatabase::AddAppHelp(
  624. TAGID tiAppHelp
  625. )
  626. {
  627. TAGID tiInfo;
  628. PAPPHELP pAppHelp = new APPHELP;
  629. if (pAppHelp == NULL) {
  630. MEM_ERR;
  631. goto error;
  632. }
  633. tiInfo = SdbGetFirstChild(m_pDB,tiAppHelp);
  634. while ( 0 != tiInfo ) {
  635. TAG tag;
  636. tag = SdbGetTagFromTagID(m_pDB,tiInfo);
  637. switch ( tag ) {
  638. case TAG_HTMLHELPID:
  639. pAppHelp->HTMLHELPID = SdbReadDWORDTag(m_pDB, tiInfo, 0);
  640. if (pAppHelp->HTMLHELPID > g_nMAXHELPID ){
  641. g_nMAXHELPID = pAppHelp->HTMLHELPID;
  642. }
  643. break;
  644. case TAG_LINK:
  645. {
  646. TAGID tagLink = SdbFindFirstTag(m_pDB, tiAppHelp,TAG_LINK);
  647. if (tagLink) {
  648. tagLink = SdbFindFirstTag(m_pDB, tagLink, TAG_LINK_URL);
  649. pAppHelp->strURL = ReadDBString(tagLink, m_pDB);
  650. }
  651. }
  652. break;
  653. case TAG_APPHELP_DETAILS:
  654. {
  655. pAppHelp->strMessage = ReadDBString(tiInfo, m_pDB);
  656. }
  657. break;
  658. }
  659. tiInfo = SdbGetNextChild(m_pDB, tiAppHelp, tiInfo);
  660. }//while
  661. //
  662. // Now add this to the database apphelp list
  663. //
  664. pAppHelp->pNext = m_pAppHelp;
  665. m_pAppHelp = pAppHelp;
  666. //
  667. // TODO: Cleanup this as well at end (when opening a new database)
  668. //
  669. return TRUE;
  670. error:
  671. if (pAppHelp) {
  672. delete pAppHelp;
  673. }
  674. return FALSE;
  675. }
  676. void
  677. CDatabase::ReadAppHelp(
  678. void
  679. )
  680. {
  681. TAGID tiInfo;
  682. // Read just the AppHelp
  683. tiInfo = SdbFindFirstTag(m_pDB, TAGID_ROOT, TAG_DATABASE);
  684. if ( 0 != tiInfo ) {
  685. TAGID tiAppHelp = SdbFindFirstTag(m_pDB, tiInfo, TAG_APPHELP);
  686. while (tiAppHelp) {
  687. AddAppHelp(tiAppHelp);
  688. tiAppHelp = SdbFindNextTag(m_pDB, tiInfo, tiAppHelp);
  689. }
  690. }
  691. }
  692. void CDatabase::ReadShims(BOOL bPermanent)
  693. /*
  694. This function reads the shims,layers and patches (but not flags) from the database.
  695. After this funciton returns we will have proper values in the
  696. 1. m_pShimList
  697. 2. m_pLayerList
  698. */
  699. {
  700. TAGID tShim;
  701. // Read just the shims
  702. tShim = SdbFindFirstTag(m_pDB, TAGID_ROOT, TAG_DATABASE);
  703. if ( 0 != tShim ) {
  704. TAGID tLib = SdbFindFirstTag(m_pDB, tShim, TAG_LIBRARY);
  705. TAGID tEntry;
  706. // Read the shims
  707. tEntry = SdbFindFirstTag(m_pDB, tLib, TAG_SHIM);
  708. while ( 0 != tEntry ) {
  709. AddShim(tEntry,TRUE, bPermanent,FALSE);
  710. tEntry = SdbFindNextTag(m_pDB, tLib, tEntry);
  711. }
  712. // Read the patches
  713. tEntry = SdbFindFirstTag(m_pDB, tLib, TAG_PATCH);
  714. while ( 0 != tEntry ) {
  715. AddShim(tEntry,FALSE,bPermanent,FALSE);
  716. tEntry = SdbFindNextTag(m_pDB, tLib, tEntry);
  717. }
  718. // Read Layers
  719. tEntry = SdbFindFirstTag(m_pDB, tShim, TAG_LAYER);
  720. while ( 0 != tEntry ) {
  721. PDBLAYER pLayer = new DBLAYER;
  722. if ( NULL != pLayer ) {
  723. TAGID tShims;
  724. TAGID tName;
  725. ZeroMemory(pLayer,sizeof(DBLAYER));
  726. pLayer->bPermanent = bPermanent;
  727. tName = SdbFindFirstTag(m_pDB, tEntry, TAG_NAME);
  728. if ( 0 != tName )
  729. pLayer->szLayerName = ReadDBString(tName);
  730. pLayer->pNext = m_pLayerList;//add this layer to the list of layers for this database
  731. m_pLayerList = pLayer;
  732. tShims = SdbFindFirstTag(m_pDB, tEntry, TAG_SHIM_REF);
  733. while ( 0 != tShims ) {
  734. AddShim(tShims,FALSE,bPermanent,TRUE);
  735. tShims = SdbFindNextTag(m_pDB, tEntry, tShims);
  736. }
  737. }
  738. tEntry = SdbFindNextTag(m_pDB, tShim, tEntry);
  739. }
  740. }
  741. }
  742. /*
  743. BOOL CDatabase::ReadShim(TAGID tShim, PSHIMDESC pDesc)
  744. {
  745. TAGID tInfo;
  746. TAG tLabel;
  747. tInfo = SdbGetFirstChild(m_pDB,tShim);
  748. if ( 0 == tShim )
  749. return FALSE;
  750. while ( 0 != tInfo ) {
  751. tLabel = SdbGetTagFromTagID(m_pDB, tInfo);
  752. switch ( tLabel ) {
  753. case TAG_GENERAL:
  754. pDesc->bGeneral = TRUE;
  755. break;
  756. case TAG_NAME:
  757. pDesc->szShimName = ReadDBString(tInfo);
  758. break;
  759. case TAG_COMMAND_LINE:
  760. pDesc->szShimCommandLine = ReadDBString(tInfo);
  761. break;
  762. case TAG_DLLFILE:
  763. pDesc->szShimDLLName = ReadDBString(tInfo);
  764. break;
  765. case TAG_DESCRIPTION:
  766. pDesc->szShimDesc = ReadDBString(tInfo);
  767. break;
  768. }
  769. tInfo = SdbGetNextChild(m_pDB, tShim, tInfo);
  770. }
  771. return TRUE;
  772. }
  773. */
  774. void CDatabase::AddShim(TAGID tShim, BOOL bShim, BOOL bPermanent, BOOL bLayer)
  775. {
  776. TAGID tInfo;
  777. TAG tLabel;
  778. PSHIMDESC pDesc = new SHIMDESC;
  779. if ( NULL == pDesc ){
  780. CMemException cmem;
  781. throw cmem;
  782. return;
  783. }
  784. ZeroMemory(pDesc,sizeof(SHIMDESC));
  785. pDesc->bShim = bShim;
  786. //pDesc->bPermanent = bPermanent;
  787. pDesc->bGeneral = FALSE;
  788. tInfo = SdbGetFirstChild(m_pDB,tShim);
  789. while ( 0 != tInfo ) {
  790. tLabel = SdbGetTagFromTagID(m_pDB, tInfo);
  791. switch ( tLabel ) {
  792. case TAG_GENERAL:
  793. pDesc->bGeneral = TRUE;
  794. break;
  795. case TAG_NAME:
  796. pDesc->szShimName = ReadDBString(tInfo);
  797. break;
  798. case TAG_COMMAND_LINE:
  799. pDesc->szShimCommandLine = ReadDBString(tInfo);
  800. break;
  801. case TAG_DLLFILE:
  802. pDesc->szShimDLLName = ReadDBString(tInfo);
  803. break;
  804. case TAG_DESCRIPTION:
  805. pDesc->szShimDesc = ReadDBString(tInfo);
  806. break;
  807. }
  808. tInfo = SdbGetNextChild(m_pDB, tShim, tInfo);
  809. }
  810. if ( !bLayer ) { //This is just a shim,
  811. //
  812. //Add in a a sorted manner
  813. //
  814. if ( (m_pShimList == NULL) || pDesc->szShimName < m_pShimList->szShimName ) {
  815. //
  816. //Add at the beginning
  817. //
  818. pDesc->pNext = m_pShimList;
  819. m_pShimList = pDesc;
  820. }
  821. else{
  822. //
  823. // Add into the LL.
  824. //
  825. PSHIMDESC pPrev = m_pShimList;
  826. PSHIMDESC pTemp = m_pShimList->pNext;
  827. while (pTemp) {
  828. if (pDesc->szShimName <= pTemp->szShimName && pDesc->szShimName > pPrev->szShimName) {
  829. //
  830. //This is the position to insert
  831. //
  832. break;
  833. }
  834. else{
  835. pPrev = pTemp;
  836. pTemp = pTemp->pNext;
  837. }
  838. }//while(pTemp)
  839. pDesc->pNext = pTemp;
  840. pPrev->pNext = pDesc;
  841. }
  842. } else{ //This is a SHIM REF for a layer
  843. /*........................................................................
  844. This is executed in the following scenario. We are actually adding the list of layers for the database.
  845. Now when we find SHIM REFS we want to add them to the particular layer.
  846. OK Now this adds this shim as the first entry of the m_pLayerList.Till now we have already added the new layer into
  847. the Linked list headed by m_pLayerList
  848. The following Code has been executed in the ReadShims() function
  849. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  850. PDBLAYER pLayer = new DBLAYER;
  851. pLayer->pNext = m_pLayerList;//add this layer to the list of layers for this database
  852. m_pLayerList = pLayer;
  853. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  854. So the m_pLayerList now points to the new layer added, obviously the LL headed by m_pLayerList is
  855. NOT arranged lexi wise on the names of the layers. The shims in the the LL m_pLayerList->pShimList are also
  856. NOT arranged lexi wise on the names of the shims.
  857. ........................................................................*/
  858. pDesc->pNext = m_pLayerList->pShimList;
  859. m_pLayerList->pShimList = pDesc;
  860. }
  861. }
  862. BOOL CDatabase::SaveDatabase(CSTRING & szFilename)
  863. {
  864. CSTRINGList * pXML = DisassembleRecord(m_pRecordHead,TRUE,TRUE,TRUE,TRUE,FALSE, FALSE);
  865. BOOL bResult;
  866. CSTRING szTempFilename;
  867. TCHAR szPath[MAX_PATH_BUFFSIZE];
  868. if ( NULL == pXML )
  869. return FALSE;
  870. GetSystemWindowsDirectory(szPath, MAX_PATH);
  871. lstrcat(szPath,TEXT("\\AppPatch\\Temp.XML"));
  872. szTempFilename = szPath;
  873. bResult = WriteXML(szTempFilename,pXML);
  874. if ( pXML != NULL ) {
  875. delete pXML;
  876. }
  877. if ( !bResult ) {
  878. MessageBox(g_theApp.m_hWnd,TEXT("Unable to save temporary file."),TEXT("File save error"),MB_OK);
  879. return FALSE;
  880. }
  881. CSTRING szCommandLine;
  882. szCommandLine.sprintf(TEXT("custom \"%s\" \"%s\""),
  883. (LPCTSTR)szTempFilename,
  884. (LPCTSTR)szFilename);
  885. if ( !InvokeCompiler(szCommandLine) ) {
  886. DeleteFile(szTempFilename);
  887. return FALSE;
  888. }
  889. DeleteFile(szTempFilename);
  890. m_szCurrentDatabase = szFilename;
  891. m_bDirty = FALSE;
  892. g_theApp.UpdateView(TRUE);
  893. return TRUE;
  894. }
  895. void CDatabase::ResolveMatch(CSTRING & szStr, PMATCHENTRY pMatch)
  896. {
  897. if ( 0 != pMatch->dwSize ) {
  898. CSTRING szTemp;
  899. szTemp.sprintf(TEXT(" SIZE=\"%d\""),pMatch->dwSize);
  900. szStr.strcat(szTemp);
  901. }
  902. if ( 0 != pMatch->dwChecksum ) {
  903. CSTRING szTemp;
  904. szTemp.sprintf(TEXT(" CHECKSUM=\"0x%08X\""),pMatch->dwChecksum);
  905. szStr.strcat(szTemp);
  906. }
  907. if ( pMatch->szCompanyName.Length() > 0 ) {
  908. CSTRING szTemp;
  909. szTemp.sprintf(TEXT(" COMPANY_NAME=\"%s\""),(LPCTSTR) pMatch->szCompanyName);
  910. szStr.strcat(szTemp);
  911. }
  912. if ( pMatch->szDescription.Length() > 0 ) {
  913. CSTRING szTemp;
  914. szTemp.sprintf(TEXT(" FILE_DESCRIPTION=\"%s\""),(LPCTSTR) pMatch->szDescription);
  915. szStr.strcat(szTemp);
  916. }
  917. if ( pMatch->szFileVersion.Length() > 0 ) {
  918. CSTRING szTemp;
  919. szTemp.sprintf(TEXT(" FILE_VERSION=\"%s\""),(LPCTSTR) pMatch->szFileVersion);
  920. szStr.strcat(szTemp);
  921. }
  922. if ( pMatch->szProductVersion.Length() > 0 ) {
  923. CSTRING szTemp;
  924. szTemp.sprintf(TEXT(" PRODUCT_VERSION=\"%s\""),(LPCTSTR) pMatch->szProductVersion);
  925. szStr.strcat(szTemp);
  926. }
  927. if ( 0 != pMatch->ProductVersion.QuadPart ) {
  928. CSTRING szTemp;
  929. TCHAR szFormat[80];
  930. FormatVersion(pMatch->ProductVersion,szFormat);
  931. szTemp.sprintf(TEXT(" BIN_PRODUCT_VERSION=\"%s\""),szFormat);
  932. szStr.strcat(szTemp);
  933. }
  934. if ( 0 != pMatch->FileVersion.QuadPart ) {
  935. CSTRING szTemp;
  936. TCHAR szFormat[80];
  937. FormatVersion(pMatch->FileVersion,szFormat);
  938. szTemp.sprintf(TEXT(" BIN_FILE_VERSION=\"%s\""),szFormat);
  939. szStr.strcat(szTemp);
  940. }
  941. }
  942. //
  943. // BUGBUG -- there is code in sdbapi to do something like this
  944. // concerning file attributes (in particular in grabmiapi.c
  945. // perhaps we should use that stuff here to decode
  946. //
  947. CSTRINGList * CDatabase::DisassembleRecord(PDBRECORD pRecordIn, BOOL bChildren, BOOL bSiblings, BOOL bIncludeLocalLayers, BOOL bFullXML, BOOL bAllowGlobal, BOOL bTestRun)
  948. {
  949. //
  950. //Create a new GUID for test run
  951. //
  952. CSTRINGList * pList = new CSTRINGList;
  953. if ( NULL == pList )
  954. return NULL;
  955. if ( bFullXML ) {
  956. CSTRING DB;
  957. CSTRING ID;
  958. pList->AddString(TEXT("<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"));
  959. if ( 0 == m_DBGuid.Data1 )
  960. CoCreateGuid(&m_DBGuid);
  961. ID.GUID(m_DBGuid);
  962. if (bTestRun) {
  963. GUID testGuid;
  964. CoCreateGuid(&testGuid);
  965. ID.GUID(testGuid);
  966. }
  967. DB.sprintf(TEXT("<DATABASE NAME=\"%s\" ID=\"%s\">"),(LPCTSTR)m_DBName,(LPCTSTR)ID);
  968. pList->AddString(DB);
  969. }
  970. if ( bIncludeLocalLayers || g_theApp.GetDBLocal().m_pAppHelp != NULL ) {
  971. PDBLAYER pWalk = g_theApp.GetDBLocal().m_pLayerList;
  972. BOOL bLocalLayerToAdd = FALSE;
  973. while ( NULL != pWalk ) {
  974. if ( !pWalk->bPermanent )
  975. bLocalLayerToAdd = TRUE;
  976. pWalk = pWalk->pNext;
  977. }
  978. if ( bLocalLayerToAdd || g_theApp.GetDBLocal().m_pAppHelp != NULL) {
  979. CSTRING szTemp;
  980. szTemp.sprintf(TEXT("<LIBRARY>"));
  981. pList->AddString(szTemp,(PVOID)1);
  982. pWalk = g_theApp.GetDBLocal().m_pLayerList;
  983. while ( NULL != pWalk ) {
  984. if ( !pWalk->bPermanent ) {
  985. PSHIMDESC pShims = pWalk->pShimList;
  986. szTemp.sprintf(TEXT("<LAYER NAME=\"%s\">"),(LPCTSTR)(pWalk->szLayerName));
  987. pList->AddString(szTemp,(PVOID)2);
  988. while ( NULL != pShims ) {
  989. szTemp.sprintf(TEXT("<SHIM NAME=\"%s\"/>"),(LPCTSTR)(pShims->szShimName));
  990. pList->AddString(szTemp,(PVOID)3);
  991. pShims = pShims->pNext;
  992. }
  993. pList->AddString(TEXT("</LAYER>"),(PVOID)2);
  994. }
  995. pWalk = pWalk->pNext;
  996. }
  997. //
  998. // Add the AppHelp Messages
  999. //
  1000. PAPPHELP pAppHelp = g_theApp.GetDBLocal().m_pAppHelp;
  1001. while (pAppHelp) {
  1002. // TODO: When we get the proper message names, after the change to shimdbc, INLCUDE that one
  1003. CSTRING strName;
  1004. strName.sprintf(TEXT("%u"), pAppHelp->HTMLHELPID);
  1005. szTemp.sprintf(TEXT("<MESSAGE NAME = \"%s\" >"), strName.pszString);
  1006. pList->AddString(szTemp,(PVOID)2);
  1007. pList->AddString(TEXT("<SUMMARY>"),(PVOID)3);
  1008. pList->AddString(pAppHelp->strMessage, (PVOID)4);
  1009. pList->AddString(TEXT("</SUMMARY>"),(PVOID)3);
  1010. pList->AddString(TEXT("</MESSAGE>"),(PVOID)2);
  1011. pAppHelp = pAppHelp->pNext;
  1012. }
  1013. // AppHelp Added to Library
  1014. pList->AddString(TEXT("</LIBRARY>"),(PVOID)1);
  1015. }
  1016. }
  1017. while ( NULL != pRecordIn ) {
  1018. PDBRECORD pRecord = pRecordIn;
  1019. while ( NULL != pRecord ) {
  1020. if ( bAllowGlobal || !pRecord->bGlobal ) {
  1021. CSTRING szTemp;
  1022. PDBENTRY pEntry = pRecord->pEntries;
  1023. szTemp.sprintf(TEXT("<APP NAME=\"%s\" VENDOR=\"Unknown\">"),(LPCTSTR)(pRecord->szAppName));
  1024. pList->AddString(szTemp,(PVOID)1);
  1025. if ( 0 == pRecord->guidID.Data1 )
  1026. szTemp.sprintf(TEXT("<EXE NAME=\"%s\""),(LPCTSTR)pRecord->szEXEName);
  1027. else {
  1028. CSTRING szGUID;
  1029. szGUID.GUID(pRecord->guidID);
  1030. szTemp.sprintf(TEXT("<EXE NAME=\"%s\" ID=\"%s\""),(LPCTSTR)pRecord->szEXEName,(LPCTSTR)szGUID);
  1031. }
  1032. while ( NULL != pEntry ) {
  1033. if ( ENTRY_MATCH == pEntry->uType ) {
  1034. PMATCHENTRY pMatch = (PMATCHENTRY) pEntry;
  1035. if ( pMatch->szMatchName == TEXT("*") )
  1036. ResolveMatch(szTemp,pMatch);
  1037. }
  1038. pEntry = pEntry->pNext;
  1039. }
  1040. szTemp.strcat(TEXT(">"));
  1041. pList->AddString(szTemp,(PVOID) 2);
  1042. // Add matching information
  1043. pEntry = pRecord->pEntries;
  1044. while ( NULL != pEntry ) {
  1045. if ( ENTRY_MATCH == pEntry->uType ) {
  1046. PMATCHENTRY pMatch = (PMATCHENTRY) pEntry;
  1047. if ( pMatch->szMatchName != TEXT("*") ) {
  1048. szTemp.sprintf(TEXT("<MATCHING_FILE NAME=\"%s\""),(LPCTSTR)pMatch->szMatchName);
  1049. ResolveMatch(szTemp,pMatch);
  1050. szTemp.strcat(TEXT("/>"));
  1051. pList->AddString(szTemp,(PVOID) 3);
  1052. }
  1053. }
  1054. pEntry = pEntry->pNext;
  1055. }
  1056. // Add Layer information
  1057. BOOL bLayerFound = FALSE; //There are layers for this thing
  1058. if ( pRecord->szLayerName.Length() > 0 ) {
  1059. szTemp.sprintf(TEXT("<LAYER NAME=\"%s\">"),(LPCTSTR)pRecord->szLayerName);
  1060. pList->AddString(szTemp,(PVOID)3);
  1061. pList->AddString(TEXT("</LAYER>"),(PVOID)3);
  1062. bLayerFound = TRUE;
  1063. }
  1064. if (g_bWin2K && bLayerFound) {
  1065. szTemp = TEXT("<SHIM NAME= \"Win2kPropagateLayer\"/>");
  1066. pList->AddString(szTemp,(PVOID)3);
  1067. }
  1068. // Add shim information
  1069. pEntry = pRecord->pEntries;
  1070. while ( NULL != pEntry ) {
  1071. if ( ENTRY_SHIM == pEntry->uType ) {
  1072. PSHIMENTRY pShim = (PSHIMENTRY) pEntry;
  1073. if ( 0 == pShim->szCmdLine.Length() )
  1074. szTemp.sprintf(TEXT("<SHIM NAME=\"%s\"/>"),(LPCTSTR)pShim->szShimName);
  1075. else
  1076. szTemp.sprintf(TEXT("<SHIM NAME=\"%s\" COMMAND_LINE=\"%s\"/>"),(LPCTSTR)pShim->szShimName,(LPCTSTR)pShim->szCmdLine);
  1077. pList->AddString(szTemp,(PVOID) 3);
  1078. }
  1079. pEntry = pEntry->pNext;
  1080. }
  1081. //
  1082. //Do the AppHelp Part
  1083. //
  1084. pEntry = pRecord->pEntries;
  1085. while ( NULL != pEntry ) {
  1086. if ( ENTRY_APPHELP == pEntry->uType ) {
  1087. PHELPENTRY pHelp = (PHELPENTRY)pEntry;
  1088. CSTRING strBlock;
  1089. if (pHelp->bBlock) {
  1090. strBlock = TEXT("YES");
  1091. }else{
  1092. strBlock = TEXT("NO");
  1093. }
  1094. CSTRING strName;
  1095. strName.sprintf(TEXT("%u"), pHelp->uHelpID);
  1096. CSTRING strHelpID;
  1097. strHelpID.sprintf(TEXT("%u"), pHelp->uHelpID);
  1098. if (pHelp->strURL.Length()) {
  1099. szTemp.sprintf(TEXT("<APPHELP MESSAGE = \"%s\" BLOCK = \"%s\" HTMLHELPID = \"%s\" DETAILS_URL = \"%s\" />"),
  1100. strName.pszString,
  1101. strBlock.pszString,
  1102. strHelpID.pszString,
  1103. pHelp->strURL.pszString);
  1104. }else{
  1105. szTemp.sprintf(TEXT("<APPHELP MESSAGE = \"%s\" BLOCK = \"%s\" HTMLHELPID = \"%s\" />"),
  1106. strName.pszString,
  1107. strBlock.pszString,
  1108. strHelpID.pszString);
  1109. }
  1110. pList->AddString(szTemp,(PVOID) 3);
  1111. }
  1112. pEntry = pEntry->pNext;
  1113. }
  1114. // End of AppHelp Part
  1115. pList->AddString(TEXT("</EXE>"),(PVOID) 2);
  1116. pList->AddString(TEXT("</APP>"),(PVOID) 1);
  1117. }
  1118. if ( !bChildren )
  1119. break;
  1120. pRecord = pRecord->pDup;
  1121. }
  1122. if ( !bSiblings )
  1123. break;
  1124. pRecordIn = pRecordIn->pNext;
  1125. }
  1126. if ( bFullXML )
  1127. pList->AddString(TEXT("</DATABASE>"));
  1128. return pList;
  1129. }
  1130. BOOL CDatabase::WriteString(HANDLE hFile, CSTRING & szString, BOOL bAutoCR)
  1131. {
  1132. DWORD dwBytesWritten;
  1133. if ( !WriteFile(hFile, (LPCSTR)szString, szString.Length() ,&dwBytesWritten,NULL) )
  1134. return FALSE;
  1135. if ( bAutoCR ) {
  1136. CHAR szCR[]={13,10};
  1137. if ( !WriteFile(hFile,szCR,sizeof(szCR) ,&dwBytesWritten,NULL) )
  1138. return FALSE;
  1139. }
  1140. return TRUE;
  1141. }
  1142. BOOL CDatabase::WriteXML(CSTRING & szFilename, CSTRINGList * pString)
  1143. {
  1144. HANDLE hFile;
  1145. if ( NULL == pString )
  1146. return FALSE;
  1147. hFile = CreateFile(szFilename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  1148. if ( INVALID_HANDLE_VALUE == hFile ) {
  1149. return FALSE;
  1150. }
  1151. PSTRLIST pWalk = pString->m_pHead;
  1152. CSTRING szTemp;
  1153. while ( NULL != pWalk ) {
  1154. UINT uTabs = pWalk->uExtraData;
  1155. while ( uTabs > 0 ) {
  1156. szTemp = TEXT(" ");
  1157. WriteString(hFile,szTemp,FALSE);
  1158. --uTabs;
  1159. }
  1160. WriteString(hFile,pWalk->szStr,TRUE);
  1161. pWalk = pWalk->pNext;
  1162. }
  1163. CloseHandle(hFile);
  1164. return TRUE;
  1165. }
  1166. BOOL CDatabase::InvokeCompiler(CSTRING & szInCommandLine)
  1167. {
  1168. CSTRING szCommandLine = szInCommandLine;
  1169. szCommandLine.sprintf(TEXT("shimdbc.exe %s"), (LPCTSTR) szInCommandLine);
  1170. BOOL bReturn = TRUE;
  1171. g_theApp.SetStatusText(
  1172. 1,
  1173. CSTRING(TEXT("Creating fix database..."))
  1174. );
  1175. if (!ShimdbcExecute( szCommandLine ) ) {
  1176. MessageBox(NULL,TEXT("There was a problem in executing the compiler. The database could not be created succesfully\nThe database file might be write-protected."), TEXT("Compiler Error"),MB_ICONERROR);
  1177. bReturn = FALSE;
  1178. }
  1179. g_theApp.SetStatusText(
  1180. 1,
  1181. CSTRING(TEXT(""))
  1182. );
  1183. return bReturn;
  1184. }
  1185. DWORD CDatabase::GetEntryFlags(HKEY hKeyRoot, GUID & Guid)
  1186. {
  1187. LONG status;
  1188. HKEY hkey = NULL;
  1189. DWORD dwFlags;
  1190. DWORD type;
  1191. DWORD cbSize = sizeof(DWORD);
  1192. CSTRING szGUID;
  1193. szGUID.GUID(Guid);
  1194. status = RegOpenKey(hKeyRoot, APPCOMPAT_KEY, &hkey);
  1195. if ( ERROR_SUCCESS != status ) {
  1196. status = RegCreateKey(hKeyRoot,APPCOMPAT_KEY,&hkey);
  1197. if ( ERROR_SUCCESS != status )
  1198. return 0;
  1199. }
  1200. status = RegQueryValueEx(hkey, szGUID, NULL, &type, (LPBYTE)&dwFlags, &cbSize);
  1201. if ( ERROR_SUCCESS != status || REG_DWORD != type )
  1202. dwFlags = 0;
  1203. RegCloseKey(hkey);
  1204. return dwFlags;
  1205. }
  1206. BOOL CDatabase::SetEntryFlags(HKEY hKeyRoot, GUID & Guid, DWORD dwFlags)
  1207. {
  1208. LONG status;
  1209. HKEY hkey = NULL;
  1210. CSTRING szGUID;
  1211. szGUID.GUID(Guid);
  1212. status = RegOpenKey(hKeyRoot, APPCOMPAT_KEY, &hkey);
  1213. if ( ERROR_SUCCESS != status ) {
  1214. status = RegCreateKey(hKeyRoot,APPCOMPAT_KEY,&hkey);
  1215. if ( ERROR_SUCCESS != status )
  1216. return 0;
  1217. }
  1218. status = RegSetValueEx(hkey, szGUID, 0, REG_DWORD, (LPBYTE) &dwFlags, sizeof(DWORD));
  1219. RegCloseKey(hkey);
  1220. return( (ERROR_SUCCESS == status) ? TRUE:FALSE );
  1221. }
  1222. BOOL CALLBACK NewDatabaseProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1223. {
  1224. switch ( uMsg ) {
  1225. case WM_INITDIALOG:
  1226. {
  1227. SendMessage(
  1228. GetDlgItem(hWnd,IDC_NAME), // handle to destination window
  1229. EM_LIMITTEXT, // message to send
  1230. (WPARAM) LIMIT_APP_NAME, // text length
  1231. (LPARAM) 0
  1232. );
  1233. if ( g_bNew )
  1234. SetWindowText(hWnd,TEXT("New database"));
  1235. SetWindowText(GetDlgItem(hWnd,IDC_NAME),(LPCTSTR)g_szDBName);
  1236. SetFocus(GetDlgItem(hWnd,IDC_NAME));
  1237. SendMessage(GetDlgItem(hWnd,IDC_NAME),EM_SETSEL,0,-1);
  1238. SHAutoComplete(GetDlgItem(hWnd,IDC_NAME), AUTOCOMPLETE);
  1239. }
  1240. return TRUE;
  1241. case WM_COMMAND:
  1242. switch ( LOWORD(wParam) ) {
  1243. case IDC_NAME:
  1244. {
  1245. if ( EN_UPDATE == HIWORD(wParam) ) {
  1246. TCHAR szText[MAX_PATH_BUFFSIZE];
  1247. GetWindowText(GetDlgItem(hWnd,IDC_NAME),szText,MAX_PATH);
  1248. EnableWindow(GetDlgItem(hWnd,IDOK),(CSTRING::Trim(szText) == 0) ? FALSE:TRUE);
  1249. }
  1250. }
  1251. break;
  1252. case IDOK:
  1253. {
  1254. TCHAR szText[MAX_PATH_BUFFSIZE];
  1255. GetWindowText(GetDlgItem(hWnd,IDC_NAME),szText,MAX_PATH);
  1256. CSTRING::Trim(szText);
  1257. g_szDBName = szText;
  1258. EndDialog(hWnd,TRUE);
  1259. }
  1260. break;
  1261. case IDCANCEL:
  1262. EndDialog(hWnd,FALSE);
  1263. break;
  1264. }
  1265. }
  1266. return FALSE;
  1267. }
  1268. BOOL CDatabase::CleanUp()
  1269. {
  1270. TCHAR szShimDB[MAX_PATH_BUFFSIZE] = _T("");
  1271. GetSystemWindowsDirectory(szShimDB, MAX_PATH);
  1272. lstrcat(szShimDB, _T("\\AppPatch"));
  1273. lstrcat(szShimDB, TEXT("\\test.sdb"));
  1274. InstallDatabase(szShimDB, TEXT("-q -u"));
  1275. DeleteFile(szShimDB);
  1276. return TRUE;
  1277. }
  1278. int CheckMatch
  1279. ( IN PDBENTRY pExistEntry,
  1280. IN PDBENTRY pNewEntry
  1281. )
  1282. {
  1283. PMATCHENTRY pMatchExist = NULL, pMatchNew = NULL;
  1284. //
  1285. //Populate the list of existing match entries
  1286. //
  1287. while (pExistEntry) {
  1288. if (pExistEntry->uType == ENTRY_MATCH) {
  1289. PMATCHENTRY pMatchTemp = new MATCHENTRY;
  1290. *pMatchTemp = *(PMATCHENTRY)pExistEntry;
  1291. if (pMatchExist == NULL) {
  1292. pMatchExist = pMatchTemp;
  1293. pMatchExist->Entry.pNext = NULL;
  1294. pExistEntry = pExistEntry->pNext;
  1295. continue;
  1296. }
  1297. pMatchTemp->Entry.pNext = (PDBENTRY)pMatchExist;
  1298. pMatchExist = (PMATCHENTRY)pMatchTemp;
  1299. }
  1300. pExistEntry = pExistEntry->pNext;
  1301. }//while (pExistEntry)
  1302. //
  1303. //Populate the match entries for the new record
  1304. //
  1305. while (pNewEntry) {
  1306. if (pNewEntry->uType == ENTRY_MATCH) {
  1307. PMATCHENTRY pMatchTemp = new MATCHENTRY;
  1308. PMATCHENTRY match = (PMATCHENTRY)pNewEntry;
  1309. *pMatchTemp = *match;
  1310. if (pMatchNew == NULL) {
  1311. pMatchNew = pMatchTemp;
  1312. pMatchNew->Entry.pNext = NULL;
  1313. pNewEntry = pNewEntry->pNext;
  1314. continue;
  1315. }
  1316. pMatchTemp->Entry.pNext = (PDBENTRY)pMatchNew;
  1317. pMatchNew = (PMATCHENTRY)pMatchTemp;
  1318. }
  1319. pNewEntry = pNewEntry->pNext;
  1320. }//while (pENewEntry)
  1321. //
  1322. //Now check if each and every entry of the pMatchNew is in the existing match list
  1323. //
  1324. PMATCHENTRY tempNew, tempExist;
  1325. tempNew = pMatchNew;
  1326. BOOL found;
  1327. while (tempNew) {
  1328. tempExist = pMatchExist;
  1329. found = FALSE;
  1330. while (tempExist) {
  1331. if (*tempExist == *tempNew) {
  1332. found = TRUE;
  1333. break;
  1334. }
  1335. else{
  1336. tempExist = (PMATCHENTRY)tempExist->Entry.pNext;
  1337. }
  1338. }
  1339. if ( found == FALSE)
  1340. break;
  1341. tempNew = (PMATCHENTRY)tempNew->Entry.pNext;
  1342. }
  1343. //
  1344. //Do the clean-up
  1345. //
  1346. while(pMatchExist){
  1347. tempExist = pMatchExist;
  1348. pMatchExist = (PMATCHENTRY)pMatchExist->Entry.pNext;
  1349. delete tempExist;
  1350. }
  1351. while(pMatchNew){
  1352. tempExist = pMatchNew;
  1353. pMatchNew = (PMATCHENTRY)pMatchNew->Entry.pNext;
  1354. delete tempExist;
  1355. }
  1356. return ( (tempNew == NULL) || found);
  1357. }
  1358. bool
  1359. InstallDatabase(
  1360. TCHAR *szPath,
  1361. TCHAR *szOptions
  1362. )
  1363. {
  1364. TCHAR szSystemDir[MAX_PATH];
  1365. *szSystemDir = 0;
  1366. GetWindowsDirectory(szSystemDir,MAX_PATH);
  1367. CSTRING strSdbInstCommandLine;
  1368. strSdbInstCommandLine.sprintf(TEXT("%s\\System32\\sdbInst.exe %s \"%s\" "),
  1369. szSystemDir,
  1370. szOptions,
  1371. szPath
  1372. );
  1373. if ( !g_theApp.InvokeEXE(NULL,strSdbInstCommandLine.pszString,true,false,false) ) {
  1374. MessageBox(g_theApp.m_hWnd,
  1375. TEXT("There was a problem In executing the data base installer."),
  1376. TEXT("CompatAdmin"),
  1377. MB_ICONERROR
  1378. );
  1379. return false;
  1380. }
  1381. return true;
  1382. }