mirror of https://github.com/tongzx/nt5src
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
2077 lines
54 KiB
/*
|
|
|
|
Note
|
|
==============
|
|
|
|
That when we call Opendatabase(bGlobal = TRUE ) then we remove all the entries for the database.
|
|
In the case when we had only one DB object, this meant removing all entries, local as well as global
|
|
from the DB, but when we have got two DBs, this will only remove the entries for the present DB
|
|
|
|
|
|
Opendatabase(bGlobal = TRUE ) is called only during WM_CREATE of the CApplication otherwise,
|
|
bGlobal = FALSE.
|
|
|
|
If we want others to view other system dbs, then we might have have to take care of this.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "compatadmin.h"
|
|
#include "psapi.h"
|
|
extern UINT g_nMAXHELPID;
|
|
|
|
CSTRING g_szDBName;
|
|
BOOL g_bNew = FALSE;
|
|
|
|
BOOL
|
|
DeleteAppHelp (
|
|
UINT nHelpID
|
|
);
|
|
|
|
bool
|
|
InstallDatabase(
|
|
TCHAR *szPath,
|
|
TCHAR *szOptions
|
|
);
|
|
|
|
|
|
|
|
|
|
CSTRING CDatabase::m_DBName;
|
|
GUID CDatabase::m_DBGuid;
|
|
PDB CDatabase::m_pDB;
|
|
CSTRING CDatabase::m_szCurrentDatabase;// Name of the SDB File
|
|
UINT CDatabase::m_uStandardImages;
|
|
|
|
|
|
//
|
|
//Checks whether the 2 PDBENTRIES have the same mathcign files.
|
|
//
|
|
int CheckMatch(const PDBENTRY pExistEntry, const PDBENTRY pNewEntry);
|
|
|
|
|
|
BOOL CDatabase::ChangeDatabaseName(void)
|
|
{
|
|
if ( !g_bNew )
|
|
g_szDBName = m_DBName;
|
|
|
|
if ( g_szDBName.Length() == 0 ) {
|
|
MEM_ERR;
|
|
return FALSE;
|
|
}
|
|
|
|
if ( FALSE == DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_NEWDATABASE),g_theApp.m_hWnd,(DLGPROC)NewDatabaseProc) )
|
|
return FALSE;
|
|
|
|
if ( !g_bNew )
|
|
if ( m_DBName != g_szDBName ) {
|
|
m_DBName = g_szDBName;
|
|
|
|
m_bDirty = TRUE;
|
|
|
|
g_theApp.UpdateView();
|
|
}
|
|
|
|
m_DBName = g_szDBName;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDatabase::NewDatabase(BOOL bShowDialog)
|
|
{
|
|
g_szDBName = TEXT("No Name");
|
|
|
|
g_bNew = TRUE;
|
|
|
|
if ( bShowDialog )
|
|
if ( !ChangeDatabaseName() )
|
|
return FALSE;
|
|
|
|
g_bNew = FALSE;
|
|
|
|
CloseDatabase();
|
|
|
|
CDatabase::m_DBName = g_szDBName;
|
|
|
|
m_szCurrentDatabase = TEXT("");
|
|
|
|
g_theApp.UpdateView();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDatabase::CloseDatabase(void)
|
|
{
|
|
// delete only the local database
|
|
|
|
PDBRECORD pWalk = m_pRecordHead;
|
|
PDBRECORD pPrev = pWalk, pNext;//Not needed, just to satisfy Prefast!
|
|
|
|
while ( NULL != pWalk ) {
|
|
if ( ! pWalk->bGlobal ) {
|
|
pNext = pWalk->pNext;
|
|
|
|
if ( pWalk == m_pRecordHead ) {
|
|
m_pRecordHead = pWalk->pNext;
|
|
}
|
|
|
|
else
|
|
pPrev->pNext = pWalk->pNext;
|
|
|
|
delete pWalk;
|
|
pWalk = pNext;
|
|
|
|
|
|
|
|
} else {
|
|
pPrev = pWalk;
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
}
|
|
|
|
// Remove local layers
|
|
|
|
PDBLAYER pLayer = m_pLayerList;
|
|
PDBLAYER pHold;
|
|
|
|
while ( NULL != pLayer ) {
|
|
if ( !pLayer->bPermanent ) {
|
|
PDBLAYER pNext = pLayer->pNext;
|
|
|
|
if ( pLayer == m_pLayerList )
|
|
m_pLayerList = pLayer->pNext;
|
|
else
|
|
pHold->pNext = pLayer->pNext;
|
|
|
|
delete pLayer;
|
|
|
|
pLayer = pNext;
|
|
|
|
continue;
|
|
}
|
|
|
|
pHold = pLayer;
|
|
pLayer = pLayer->pNext;
|
|
}
|
|
|
|
ZeroMemory(&m_DBGuid,sizeof(GUID));
|
|
|
|
/*
|
|
m_DBName = "No Name";
|
|
|
|
m_szCurrentDatabase = "";
|
|
|
|
g_theApp.UpdateView();
|
|
*/
|
|
m_bDirty = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
UINT CDatabase::DeleteRecord(PDBRECORD pRecord)
|
|
{
|
|
PDBRECORD pWalk;
|
|
PDBRECORD pHoldRecord;
|
|
|
|
pWalk = m_pRecordHead;
|
|
|
|
while ( NULL != pWalk ) {
|
|
if ( pWalk == pRecord ) {
|
|
// Remove root level record.
|
|
|
|
PDBENTRY pEntry = pWalk->pEntries;
|
|
|
|
while ( NULL != pEntry ) {
|
|
PDBENTRY pHoldEntry = pEntry->pNext;
|
|
|
|
if (pEntry->uType == ENTRY_APPHELP) {
|
|
|
|
DeleteAppHelp( ((PHELPENTRY)pEntry)->uHelpID );
|
|
}
|
|
|
|
delete pEntry;
|
|
|
|
pEntry = pHoldEntry;
|
|
}
|
|
|
|
if ( NULL != pWalk->pDup ) {
|
|
// Replace with duplicate
|
|
|
|
pWalk->pDup->pNext = pWalk->pNext;
|
|
|
|
if ( pWalk == m_pRecordHead )
|
|
m_pRecordHead = pWalk->pDup;
|
|
else
|
|
pHoldRecord->pNext = pWalk->pDup;
|
|
} else {
|
|
if ( pWalk == m_pRecordHead )
|
|
m_pRecordHead = m_pRecordHead->pNext;
|
|
else
|
|
pHoldRecord->pNext = pWalk->pNext;
|
|
}
|
|
|
|
delete pWalk;
|
|
|
|
m_bDirty = TRUE;
|
|
|
|
return DELRES_RECORDREMOVED;
|
|
}
|
|
|
|
if ( NULL != pWalk->pDup ) {
|
|
PDBRECORD pWalk2 = pWalk->pDup;
|
|
PDBRECORD pHold2;
|
|
|
|
while ( NULL != pWalk2 ) {
|
|
if ( pWalk2 == pRecord )
|
|
break;
|
|
|
|
pHold2 = pWalk2;
|
|
pWalk2 = pWalk2->pDup;
|
|
}
|
|
|
|
if ( NULL != pWalk2 ) {
|
|
// Remove the duplicate entry.
|
|
|
|
if ( pWalk2 == pWalk->pDup )
|
|
pWalk->pDup = pWalk2->pDup;
|
|
else
|
|
pHold2->pDup = pWalk2->pDup;
|
|
|
|
PDBENTRY pEntry = pWalk2->pEntries;
|
|
|
|
while ( NULL != pEntry ) {
|
|
PDBENTRY pHoldEntry = pEntry->pNext;
|
|
|
|
delete pEntry;
|
|
|
|
pEntry = pHoldEntry;
|
|
}
|
|
|
|
delete pWalk2;
|
|
|
|
m_bDirty = TRUE;
|
|
|
|
return DELRES_DUPREMOVED;
|
|
}
|
|
}
|
|
|
|
pHoldRecord = pWalk;
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
return DELRES_FAILED;
|
|
}
|
|
|
|
BOOL CDatabase::OpenDatabase(CSTRING & szFilename, BOOL bGlobal)
|
|
{
|
|
if ( NULL == g_hSDB ) {
|
|
TCHAR szShimDB[MAX_PATH_BUFFSIZE] ;
|
|
|
|
*szShimDB = 0;
|
|
|
|
|
|
GetSystemWindowsDirectory(szShimDB, MAX_PATH);
|
|
lstrcat(szShimDB,TEXT("\\AppPatch"));
|
|
|
|
CSTRING szStr = szShimDB;
|
|
|
|
if ( szStr.Length() == 0 ) {
|
|
MEM_ERR;
|
|
return FALSE;
|
|
}
|
|
|
|
g_hSDB = SdbInitDatabase(HID_DOS_PATHS,(LPCWSTR) szStr);
|
|
}
|
|
|
|
#ifndef UNICODE
|
|
|
|
WCHAR wszFilename[MAX_PATH_BUFFSIZE];
|
|
|
|
ZeroMemory(wszFilename,sizeof(wszFilename));
|
|
|
|
MultiByteToWideChar (CP_ACP,MB_PRECOMPOSED,szFilename,lstrlen(szFilename),wszFilename,MAX_PATH);
|
|
|
|
m_pDB = SdbOpenDatabase(wszFilename,DOS_PATH);
|
|
#else
|
|
m_pDB = SdbOpenDatabase(szFilename.pszString,DOS_PATH);
|
|
|
|
#endif
|
|
|
|
|
|
if ( NULL == m_pDB )
|
|
return FALSE;
|
|
|
|
if ( bGlobal ) {
|
|
// Delete the previous database from memory
|
|
|
|
|
|
while ( NULL != m_pRecordHead ) {
|
|
PDBRECORD pHold = m_pRecordHead->pNext;
|
|
|
|
delete m_pRecordHead;
|
|
|
|
m_pRecordHead = pHold;
|
|
}
|
|
} else {
|
|
CloseDatabase();
|
|
}
|
|
|
|
ReadShims(bGlobal);
|
|
|
|
ReadAppHelp();
|
|
|
|
// Load in the contents of the database.
|
|
|
|
TAGID tiDatabase, tiExe;
|
|
UINT uShims=0;
|
|
UINT uEntries=0;
|
|
UINT uAppHelp=0;
|
|
UINT uLayers=0;
|
|
|
|
tiDatabase = SdbFindFirstTag(CDatabase::m_pDB, TAGID_ROOT, TAG_DATABASE);
|
|
|
|
if ( 0 != tiDatabase ) {
|
|
if ( !bGlobal ) {
|
|
TAGID tName;
|
|
|
|
// Read in the database GUID and name.
|
|
|
|
tName = SdbFindFirstTag(m_pDB, tiDatabase, TAG_NAME);
|
|
|
|
if ( 0 != tName )
|
|
m_DBName = ReadDBString(tName);
|
|
|
|
tName = SdbFindFirstTag(m_pDB, tiDatabase, TAG_DATABASE_ID);
|
|
|
|
if ( 0 != tName )
|
|
SdbReadBinaryTag(m_pDB,tName,(PBYTE)&m_DBGuid,sizeof(GUID));
|
|
}
|
|
|
|
tiExe = SdbFindFirstTag(CDatabase::m_pDB, tiDatabase, TAG_EXE);
|
|
|
|
|
|
|
|
while ( 0 != tiExe ) {
|
|
PDBRECORD pRecord = new DBRECORD;
|
|
MSG Msg;
|
|
|
|
while ( PeekMessage(&Msg,NULL,0,0,PM_REMOVE) ) {
|
|
TranslateMessage(&Msg);
|
|
DispatchMessage(&Msg);
|
|
}
|
|
|
|
++uEntries;
|
|
|
|
if ( NULL != pRecord ) {
|
|
if ( ReadRecord(tiExe,pRecord) ) {
|
|
pRecord->bGlobal = bGlobal;
|
|
|
|
InsertRecord(pRecord);
|
|
}
|
|
}
|
|
|
|
tiExe = SdbFindNextTag(CDatabase::m_pDB, tiDatabase, tiExe);
|
|
}
|
|
}
|
|
|
|
if ( !bGlobal ) {
|
|
//
|
|
// BUGBUG Consider using shlwapi function to find a filename
|
|
//
|
|
LPTSTR szFile = _tcsrchr( (LPTSTR)szFilename, TEXT('\\'));
|
|
if (szFile == NULL) {
|
|
szFile = szFilename;
|
|
} else {
|
|
++szFile; // or move to the next char CharNext
|
|
}
|
|
|
|
/*
|
|
wsprintf(szWindowTitle,"Application Management Console (%s)",szFile+1);
|
|
|
|
SetWindowText(g_theApp.m_hWnd,szWindowTitle);
|
|
*/
|
|
m_szCurrentDatabase = szFilename;
|
|
}
|
|
/*
|
|
TCHAR szTemp[80];
|
|
|
|
wsprintf(szTemp,"Entries: %d (L: %d S: %d AH: %d)",uEntries,uLayers, uShims,uAppHelp);
|
|
|
|
SendMessage(m_hStatusBar,SB_SETTEXT,1,(LPARAM) szTemp);
|
|
*/
|
|
DWORD dwFlags = GetFileAttributes(szFilename);
|
|
|
|
if ( 0 != (dwFlags & FILE_ATTRIBUTE_READONLY) )
|
|
g_theApp.SetStatusText(2,CSTRING(TEXT("Read Only")));
|
|
else
|
|
g_theApp.SetStatusText(2,CSTRING(TEXT("")));
|
|
|
|
g_theApp.UpdateView();
|
|
|
|
SdbCloseDatabase(m_pDB);
|
|
|
|
m_pDB = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDatabase::InsertRecord(PDBRECORD pRecord)
|
|
{
|
|
// Insert into the list.
|
|
|
|
/***
|
|
This routine inserts the passed pRecord into the list pointed by m_pRecordHead.
|
|
This routine also checks if there is some other files are already associated with this App. and if
|
|
yes it makes the pDup record of that exe to point to pRecord. pRecord->pDup will
|
|
point to whatever that entry's pDup pointed to. */
|
|
|
|
|
|
|
|
if ( NULL != m_pRecordHead ) {
|
|
|
|
if (pRecord->bGlobal == FALSE) {
|
|
|
|
}
|
|
|
|
|
|
|
|
PDBRECORD pWalk = m_pRecordHead;
|
|
PDBRECORD pHold = NULL;
|
|
int nResult;
|
|
|
|
do {
|
|
nResult = lstrcmpi(pWalk->szAppName,pRecord->szAppName);
|
|
|
|
// If less OR Equal
|
|
|
|
//CHANGE (-1 != )
|
|
if ( 0 <= nResult )
|
|
break;
|
|
|
|
pHold = pWalk;
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
while ( NULL != pWalk );
|
|
|
|
// Insert it right here.
|
|
|
|
if ( 0 == nResult ) {
|
|
// The strings are equal. Simply add shim/apphelp information
|
|
// to this .EXE entry.
|
|
|
|
|
|
PDBRECORD pSameAppExes = pWalk;
|
|
PDBRECORD pSameAppExesPrev = NULL;
|
|
|
|
|
|
if (pRecord->bGlobal){
|
|
|
|
pRecord->pDup = pWalk->pDup;
|
|
pWalk->pDup = pRecord;
|
|
|
|
}else{
|
|
//
|
|
//We do not want to perform the extra check on system entries.
|
|
//
|
|
|
|
|
|
while (pSameAppExes) {
|
|
|
|
if (pSameAppExes->szEXEName == pRecord->szEXEName ) {
|
|
|
|
//
|
|
//Same exe, must check the matching files and if same then we must add these entries to the present exe.
|
|
//
|
|
|
|
|
|
|
|
|
|
int check = CheckMatch(pSameAppExes->pEntries, pRecord->pEntries);
|
|
if (check) {
|
|
|
|
|
|
int result = MessageBox(g_theApp.m_hWnd,
|
|
TEXT("An existing file with the same name and similar matching information was found\n")
|
|
TEXT("Do you wish to update the previous fix with the modified entries?\n\n"),
|
|
TEXT("CompatAdmin"),
|
|
MB_ICONWARNING | MB_YESNO|MB_DEFBUTTON1 | MB_APPLMODAL
|
|
);
|
|
|
|
if (result == IDYES) {
|
|
//
|
|
//Add all the entries, except the Matcbing file to this exe entry
|
|
//
|
|
|
|
if (pSameAppExes->szLayerName.Length() &&
|
|
pRecord->szLayerName.Length() &&
|
|
! (pRecord->szLayerName == pSameAppExes->szLayerName)
|
|
) {
|
|
|
|
//
|
|
//The new entry contains a layer as well !
|
|
//
|
|
|
|
|
|
CSTRING message;
|
|
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"),
|
|
(LPCTSTR)pSameAppExes->szEXEName,(LPCTSTR)pSameAppExes->szAppName,
|
|
(LPCTSTR)pSameAppExes->szLayerName,(LPCTSTR)pRecord->szLayerName
|
|
);
|
|
|
|
|
|
int result = MessageBox(g_theApp.m_hWnd,message,TEXT("CompatAdmin"),MB_ICONWARNING | MB_YESNO);
|
|
|
|
if (result == IDYES) {
|
|
pSameAppExes->szLayerName = pRecord->szLayerName;
|
|
}
|
|
}
|
|
else if(!pSameAppExes->szLayerName.Length() && pRecord->szLayerName.Length()){
|
|
//
|
|
//Add the layer directly
|
|
//
|
|
|
|
pSameAppExes->szLayerName = pRecord->szLayerName;
|
|
|
|
|
|
}
|
|
|
|
while ( pRecord->pEntries ) {
|
|
|
|
|
|
PDBENTRY pNext = pRecord->pEntries->pNext;
|
|
|
|
|
|
if ( pRecord->pEntries->uType != ENTRY_MATCH ) {
|
|
|
|
//
|
|
//Take out the first entry.
|
|
//
|
|
|
|
pRecord->pEntries->pNext = pSameAppExes->pEntries;
|
|
pSameAppExes->pEntries = pRecord->pEntries;
|
|
pRecord->pEntries = pNext;
|
|
continue;
|
|
}
|
|
else break;
|
|
|
|
}//while ( pRecord->pEntries )
|
|
|
|
|
|
|
|
PDBENTRY pPrev = pRecord->pEntries;
|
|
PDBENTRY pTemp = pRecord->pEntries;
|
|
|
|
//
|
|
//We are here means the first entry is a match entry or NULL. First loop will do nothing.
|
|
//
|
|
|
|
while( pTemp ){
|
|
|
|
|
|
if (pTemp->uType != ENTRY_MATCH) {
|
|
//
|
|
//Add this to the list of entries for the exe
|
|
//
|
|
|
|
//1. splice this entry from pRecord->pEntries
|
|
pPrev->pNext = pTemp->pNext;
|
|
|
|
//2. Add it to the front of the entrties of the prev. file
|
|
pTemp->pNext = pSameAppExes->pEntries;
|
|
|
|
//3.
|
|
|
|
pSameAppExes->pEntries = pTemp;
|
|
|
|
//4. Move on for the other entries in pRecord
|
|
|
|
pTemp = pPrev->pNext;
|
|
}else{
|
|
pPrev = pTemp;
|
|
pTemp = pTemp->pNext;
|
|
|
|
}//if (pTemp->uType != ENTRY_MATCH ELSE
|
|
}//while( pTemp )
|
|
|
|
pRecord->DestroyAll();
|
|
|
|
}//if reuslt == IDYES
|
|
else{ //IDNO
|
|
pRecord->DestroyAll();
|
|
;
|
|
}
|
|
|
|
break;
|
|
}//if (check)
|
|
|
|
}//if (pSameAppExes->szEXEName == pRecord->szEXEName
|
|
|
|
|
|
pSameAppExesPrev = pSameAppExes;
|
|
pSameAppExes = pSameAppExes->pDup;
|
|
|
|
|
|
|
|
}//while (pSameAppExes)
|
|
|
|
//
|
|
//We have not found any exe within this app that has the same matching info as this one.
|
|
//So we haev to add this to the end
|
|
//
|
|
|
|
if (pSameAppExes == NULL ) {
|
|
|
|
if ( NULL != pHold ) {
|
|
pRecord->pNext = pWalk->pNext;
|
|
pHold->pNext = pRecord;
|
|
pWalk->pNext = NULL;
|
|
pRecord->pDup = pWalk;
|
|
|
|
|
|
|
|
} else { // First element
|
|
pRecord->pNext =m_pRecordHead->pNext;
|
|
m_pRecordHead = pRecord;
|
|
pRecord->pDup = pWalk;
|
|
}
|
|
|
|
}
|
|
|
|
}//else for the outer loop. above the while
|
|
|
|
} else {
|
|
|
|
if ( NULL != pHold ) {
|
|
pRecord->pNext = pHold->pNext;
|
|
pHold->pNext = pRecord;
|
|
} else { // First element
|
|
pRecord->pNext = m_pRecordHead;
|
|
m_pRecordHead = pRecord;
|
|
}
|
|
}
|
|
} else { //fIRST AND ONLY ELEMENT
|
|
pRecord->pNext = NULL;
|
|
m_pRecordHead = pRecord;
|
|
|
|
}
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDatabase::ReadRecord(TAGID tagParent, PDBRECORD pRecord, PDB pDB)
|
|
{
|
|
TAGID Info;
|
|
PDBENTRY pLast = NULL;
|
|
|
|
if ( NULL == pDB )
|
|
pDB = CDatabase::m_pDB;
|
|
|
|
// Entries with flags are ignored and not displayed
|
|
|
|
Info = SdbFindFirstTag(pDB, tagParent, TAG_FLAG); //K Did not find this TAG_FLAG IN THE SDB Database !!!
|
|
|
|
if ( 0 != Info )
|
|
return FALSE;
|
|
|
|
ZeroMemory(pRecord,sizeof(DBRECORD));
|
|
|
|
Info = SdbGetFirstChild(pDB,tagParent);
|
|
|
|
while ( 0 != Info ) {
|
|
TAG tag;
|
|
|
|
tag = SdbGetTagFromTagID(pDB,Info);
|
|
|
|
switch ( tag ) {
|
|
case TAG_NAME:
|
|
{
|
|
pRecord->szEXEName = ReadDBString(Info,pDB);
|
|
}
|
|
break;
|
|
|
|
case TAG_LAYER:
|
|
{
|
|
TAGID Layer = SdbGetFirstChild(pDB,Info);
|
|
|
|
while ( 0 != Layer ) {
|
|
TAG Tag = SdbGetTagFromTagID(pDB,Layer);
|
|
|
|
switch ( Tag ) {
|
|
case TAG_NAME:
|
|
pRecord->szLayerName = ReadDBString(Layer,pDB);
|
|
break;
|
|
}
|
|
|
|
Layer = SdbGetNextChild(pDB,Info,Layer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TAG_APP_NAME:
|
|
{
|
|
pRecord->szAppName = ReadDBString(Info,pDB);
|
|
}
|
|
break;
|
|
|
|
case TAG_MATCHING_FILE:
|
|
{
|
|
TAGID MatchInfo;
|
|
TAG Tag;
|
|
PMATCHENTRY pEntry = new MATCHENTRY;
|
|
|
|
if ( NULL != pEntry ) {
|
|
ZeroMemory(pEntry,sizeof(MATCHENTRY));
|
|
|
|
pEntry->Entry.uType = ENTRY_MATCH;
|
|
pEntry->Entry.pNext = NULL;
|
|
|
|
MatchInfo = SdbGetFirstChild(pDB,Info);
|
|
|
|
while ( 0 != MatchInfo ) {
|
|
Tag = SdbGetTagFromTagID(pDB,MatchInfo);
|
|
|
|
switch ( Tag ) {
|
|
case TAG_NAME:
|
|
pEntry->szMatchName = ReadDBString(MatchInfo,pDB);
|
|
break;
|
|
case TAG_SIZE:
|
|
pEntry->dwSize = SdbReadDWORDTag(pDB,MatchInfo,0);
|
|
break;
|
|
case TAG_CHECKSUM:
|
|
pEntry->dwChecksum = SdbReadDWORDTag(pDB,MatchInfo,0);
|
|
break;
|
|
case TAG_BIN_FILE_VERSION:
|
|
pEntry->FileVersion.QuadPart = SdbReadQWORDTag(pDB,MatchInfo,0);
|
|
break;
|
|
case TAG_FILE_VERSION:
|
|
pEntry->szFileVersion = ReadDBString(MatchInfo,pDB);
|
|
break;
|
|
case TAG_BIN_PRODUCT_VERSION:
|
|
pEntry->ProductVersion.QuadPart = SdbReadQWORDTag(pDB,MatchInfo,0);
|
|
break;
|
|
case TAG_PRODUCT_VERSION:
|
|
pEntry->szProductVersion = ReadDBString(MatchInfo,pDB);
|
|
break;
|
|
case TAG_FILE_DESCRIPTION:
|
|
pEntry->szDescription = ReadDBString(MatchInfo,pDB);
|
|
break;
|
|
case TAG_COMPANY_NAME:
|
|
pEntry->szCompanyName = ReadDBString(MatchInfo,pDB);
|
|
break;
|
|
}
|
|
|
|
MatchInfo = SdbGetNextChild(pDB,Info,MatchInfo);
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
Here's what he probably meant. He has used the pEntry->Entry.pNext
|
|
to actually link up the the differnrent match entries for the EXE.
|
|
pLast points to the last pEntry. !!!! This is SOMETHING.
|
|
|
|
*/
|
|
|
|
//Note that pEntry is a variable of type PMATCHENTRY
|
|
|
|
if ( NULL != pLast )
|
|
pLast->pNext = (PDBENTRY) pEntry;
|
|
else
|
|
pRecord->pEntries = (PDBENTRY) pEntry;
|
|
|
|
pLast = (PDBENTRY) pEntry;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TAG_PATCH_REF:
|
|
case TAG_SHIM_REF:
|
|
{
|
|
PSHIMENTRY pEntry = new SHIMENTRY;
|
|
|
|
//Note that pEntry is a variable of type PSHIMENTRY
|
|
|
|
if ( NULL != pEntry ) {
|
|
TAGID tiShimName;
|
|
|
|
ZeroMemory(pEntry,sizeof(SHIMENTRY));
|
|
|
|
pEntry->Entry.uType = ENTRY_SHIM;
|
|
pEntry->Entry.pNext = NULL;
|
|
|
|
tiShimName = SdbFindFirstTag(pDB,Info,TAG_NAME);
|
|
|
|
pEntry->szShimName = ReadDBString(tiShimName,pDB);
|
|
|
|
tiShimName = SdbFindFirstTag(pDB,Info,TAG_COMMAND_LINE);
|
|
|
|
if ( 0 != tiShimName )
|
|
pEntry->szCmdLine = ReadDBString(tiShimName,pDB);
|
|
|
|
if ( NULL != pLast )
|
|
pLast->pNext = (PDBENTRY) pEntry;
|
|
else
|
|
pRecord->pEntries = (PDBENTRY) pEntry;
|
|
|
|
// Look up the specific shim this entry is associated with.
|
|
|
|
PSHIMDESC pWalk = g_theApp.GetDBGlobal().m_pShimList;
|
|
|
|
while ( NULL != pWalk ) {
|
|
// == is overloaded in the CSTRING class
|
|
|
|
if ( pEntry->szShimName == pWalk->szShimName ) {
|
|
pEntry->pDesc = pWalk;
|
|
break;
|
|
}
|
|
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
pLast = (PDBENTRY) pEntry;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TAG_APPHELP:
|
|
{
|
|
PHELPENTRY pHelp = new HELPENTRY;
|
|
|
|
if ( NULL != pHelp ) {
|
|
TAGID tTemp;
|
|
|
|
pHelp->Entry.uType = ENTRY_APPHELP;
|
|
pHelp->Entry.pNext = NULL;
|
|
|
|
tTemp = SdbFindFirstTag(pDB, Info, TAG_PROBLEMSEVERITY);
|
|
pHelp->uSeverity = SdbReadDWORDTag(pDB, tTemp, 0);
|
|
|
|
tTemp = SdbFindFirstTag(pDB, Info, TAG_HTMLHELPID);
|
|
pHelp->uHelpID = SdbReadDWORDTag(pDB, tTemp, 0);
|
|
|
|
if ( NULL != pLast )
|
|
pLast->pNext = (PDBENTRY) pHelp;
|
|
else
|
|
pRecord->pEntries = (PDBENTRY) pHelp;
|
|
|
|
pLast = (PDBENTRY) pHelp;
|
|
}
|
|
|
|
pRecord->uLayer = LAYER_APPHELP;
|
|
}
|
|
break;
|
|
|
|
case TAG_EXE_ID:
|
|
{
|
|
LPGUID pGUID = (GUID*)SdbGetBinaryTagData(pDB, Info);
|
|
|
|
if ( NULL != pGUID )
|
|
pRecord->guidID = *pGUID;
|
|
}
|
|
break;
|
|
}
|
|
|
|
Info = SdbGetNextChild(pDB,tagParent,Info);
|
|
}
|
|
|
|
|
|
pRecord->dwUserFlags = GetEntryFlags(HKEY_CURRENT_USER,pRecord->guidID);
|
|
pRecord->dwGlobalFlags = GetEntryFlags(HKEY_LOCAL_MACHINE,pRecord->guidID);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CSTRING STDCALL CDatabase::ReadDBString(TAGID tagID, PDB pDB)
|
|
{
|
|
CSTRING Str;
|
|
WCHAR szAppName[1024];
|
|
|
|
if ( NULL == pDB )
|
|
pDB = CDatabase::m_pDB;
|
|
|
|
ZeroMemory(szAppName,sizeof(szAppName));
|
|
|
|
if ( !SdbReadStringTag(pDB,tagID,szAppName,sizeof(szAppName)/sizeof(WCHAR)) )
|
|
return Str;
|
|
|
|
#ifndef UNICODE
|
|
#define SIZE 1024
|
|
TCHAR szString[SIZE];
|
|
|
|
*szString = TEXT('\0');
|
|
|
|
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,szAppName, -1, szString, SIZE, NULL, NULL);
|
|
|
|
Str = szString;
|
|
#else
|
|
|
|
Str = szAppName;
|
|
|
|
#endif
|
|
|
|
return Str;
|
|
}
|
|
|
|
BOOL
|
|
CDatabase::AddAppHelp(
|
|
TAGID tiAppHelp
|
|
)
|
|
{
|
|
TAGID tiInfo;
|
|
|
|
PAPPHELP pAppHelp = new APPHELP;
|
|
|
|
if (pAppHelp == NULL) {
|
|
MEM_ERR;
|
|
goto error;
|
|
}
|
|
|
|
tiInfo = SdbGetFirstChild(m_pDB,tiAppHelp);
|
|
|
|
while ( 0 != tiInfo ) {
|
|
TAG tag;
|
|
|
|
tag = SdbGetTagFromTagID(m_pDB,tiInfo);
|
|
|
|
switch ( tag ) {
|
|
case TAG_HTMLHELPID:
|
|
pAppHelp->HTMLHELPID = SdbReadDWORDTag(m_pDB, tiInfo, 0);
|
|
|
|
if (pAppHelp->HTMLHELPID > g_nMAXHELPID ){
|
|
|
|
g_nMAXHELPID = pAppHelp->HTMLHELPID;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TAG_LINK:
|
|
{
|
|
TAGID tagLink = SdbFindFirstTag(m_pDB, tiAppHelp,TAG_LINK);
|
|
|
|
if (tagLink) {
|
|
tagLink = SdbFindFirstTag(m_pDB, tagLink, TAG_LINK_URL);
|
|
pAppHelp->strURL = ReadDBString(tagLink, m_pDB);
|
|
}
|
|
|
|
}
|
|
break;
|
|
case TAG_APPHELP_DETAILS:
|
|
{
|
|
pAppHelp->strMessage = ReadDBString(tiInfo, m_pDB);
|
|
}
|
|
break;
|
|
}
|
|
|
|
tiInfo = SdbGetNextChild(m_pDB, tiAppHelp, tiInfo);
|
|
|
|
}//while
|
|
|
|
//
|
|
// Now add this to the database apphelp list
|
|
//
|
|
|
|
pAppHelp->pNext = m_pAppHelp;
|
|
m_pAppHelp = pAppHelp;
|
|
|
|
|
|
//
|
|
// TODO: Cleanup this as well at end (when opening a new database)
|
|
//
|
|
return TRUE;
|
|
|
|
error:
|
|
if (pAppHelp) {
|
|
delete pAppHelp;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
void
|
|
CDatabase::ReadAppHelp(
|
|
void
|
|
)
|
|
{
|
|
|
|
TAGID tiInfo;
|
|
|
|
// Read just the AppHelp
|
|
|
|
tiInfo = SdbFindFirstTag(m_pDB, TAGID_ROOT, TAG_DATABASE);
|
|
|
|
if ( 0 != tiInfo ) {
|
|
|
|
TAGID tiAppHelp = SdbFindFirstTag(m_pDB, tiInfo, TAG_APPHELP);
|
|
|
|
while (tiAppHelp) {
|
|
AddAppHelp(tiAppHelp);
|
|
tiAppHelp = SdbFindNextTag(m_pDB, tiInfo, tiAppHelp);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CDatabase::ReadShims(BOOL bPermanent)
|
|
/*
|
|
This function reads the shims,layers and patches (but not flags) from the database.
|
|
After this funciton returns we will have proper values in the
|
|
1. m_pShimList
|
|
2. m_pLayerList
|
|
*/
|
|
|
|
{
|
|
TAGID tShim;
|
|
|
|
// Read just the shims
|
|
|
|
tShim = SdbFindFirstTag(m_pDB, TAGID_ROOT, TAG_DATABASE);
|
|
|
|
if ( 0 != tShim ) {
|
|
TAGID tLib = SdbFindFirstTag(m_pDB, tShim, TAG_LIBRARY);
|
|
TAGID tEntry;
|
|
|
|
// Read the shims
|
|
|
|
tEntry = SdbFindFirstTag(m_pDB, tLib, TAG_SHIM);
|
|
|
|
while ( 0 != tEntry ) {
|
|
AddShim(tEntry,TRUE, bPermanent,FALSE);
|
|
|
|
tEntry = SdbFindNextTag(m_pDB, tLib, tEntry);
|
|
}
|
|
|
|
// Read the patches
|
|
|
|
tEntry = SdbFindFirstTag(m_pDB, tLib, TAG_PATCH);
|
|
|
|
while ( 0 != tEntry ) {
|
|
AddShim(tEntry,FALSE,bPermanent,FALSE);
|
|
|
|
tEntry = SdbFindNextTag(m_pDB, tLib, tEntry);
|
|
}
|
|
|
|
// Read Layers
|
|
|
|
tEntry = SdbFindFirstTag(m_pDB, tShim, TAG_LAYER);
|
|
|
|
while ( 0 != tEntry ) {
|
|
|
|
PDBLAYER pLayer = new DBLAYER;
|
|
|
|
if ( NULL != pLayer ) {
|
|
TAGID tShims;
|
|
TAGID tName;
|
|
|
|
ZeroMemory(pLayer,sizeof(DBLAYER));
|
|
|
|
pLayer->bPermanent = bPermanent;
|
|
|
|
tName = SdbFindFirstTag(m_pDB, tEntry, TAG_NAME);
|
|
|
|
if ( 0 != tName )
|
|
pLayer->szLayerName = ReadDBString(tName);
|
|
|
|
pLayer->pNext = m_pLayerList;//add this layer to the list of layers for this database
|
|
m_pLayerList = pLayer;
|
|
|
|
tShims = SdbFindFirstTag(m_pDB, tEntry, TAG_SHIM_REF);
|
|
|
|
|
|
|
|
while ( 0 != tShims ) {
|
|
AddShim(tShims,FALSE,bPermanent,TRUE);
|
|
|
|
tShims = SdbFindNextTag(m_pDB, tEntry, tShims);
|
|
}
|
|
}
|
|
|
|
tEntry = SdbFindNextTag(m_pDB, tShim, tEntry);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
BOOL CDatabase::ReadShim(TAGID tShim, PSHIMDESC pDesc)
|
|
{
|
|
TAGID tInfo;
|
|
TAG tLabel;
|
|
|
|
tInfo = SdbGetFirstChild(m_pDB,tShim);
|
|
|
|
if ( 0 == tShim )
|
|
return FALSE;
|
|
|
|
while ( 0 != tInfo ) {
|
|
tLabel = SdbGetTagFromTagID(m_pDB, tInfo);
|
|
|
|
switch ( tLabel ) {
|
|
case TAG_GENERAL:
|
|
pDesc->bGeneral = TRUE;
|
|
break;
|
|
|
|
case TAG_NAME:
|
|
pDesc->szShimName = ReadDBString(tInfo);
|
|
break;
|
|
|
|
case TAG_COMMAND_LINE:
|
|
pDesc->szShimCommandLine = ReadDBString(tInfo);
|
|
break;
|
|
|
|
case TAG_DLLFILE:
|
|
pDesc->szShimDLLName = ReadDBString(tInfo);
|
|
break;
|
|
|
|
case TAG_DESCRIPTION:
|
|
pDesc->szShimDesc = ReadDBString(tInfo);
|
|
break;
|
|
}
|
|
|
|
tInfo = SdbGetNextChild(m_pDB, tShim, tInfo);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
*/
|
|
void CDatabase::AddShim(TAGID tShim, BOOL bShim, BOOL bPermanent, BOOL bLayer)
|
|
{
|
|
TAGID tInfo;
|
|
TAG tLabel;
|
|
PSHIMDESC pDesc = new SHIMDESC;
|
|
|
|
if ( NULL == pDesc ){
|
|
CMemException cmem;
|
|
throw cmem;
|
|
return;
|
|
}
|
|
|
|
|
|
ZeroMemory(pDesc,sizeof(SHIMDESC));
|
|
|
|
pDesc->bShim = bShim;
|
|
//pDesc->bPermanent = bPermanent;
|
|
|
|
|
|
|
|
pDesc->bGeneral = FALSE;
|
|
|
|
tInfo = SdbGetFirstChild(m_pDB,tShim);
|
|
|
|
while ( 0 != tInfo ) {
|
|
tLabel = SdbGetTagFromTagID(m_pDB, tInfo);
|
|
|
|
|
|
|
|
switch ( tLabel ) {
|
|
case TAG_GENERAL:
|
|
pDesc->bGeneral = TRUE;
|
|
break;
|
|
case TAG_NAME:
|
|
pDesc->szShimName = ReadDBString(tInfo);
|
|
break;
|
|
case TAG_COMMAND_LINE:
|
|
pDesc->szShimCommandLine = ReadDBString(tInfo);
|
|
break;
|
|
|
|
case TAG_DLLFILE:
|
|
pDesc->szShimDLLName = ReadDBString(tInfo);
|
|
break;
|
|
case TAG_DESCRIPTION:
|
|
pDesc->szShimDesc = ReadDBString(tInfo);
|
|
break;
|
|
}
|
|
|
|
tInfo = SdbGetNextChild(m_pDB, tShim, tInfo);
|
|
}
|
|
|
|
if ( !bLayer ) { //This is just a shim,
|
|
|
|
//
|
|
//Add in a a sorted manner
|
|
//
|
|
|
|
if ( (m_pShimList == NULL) || pDesc->szShimName < m_pShimList->szShimName ) {
|
|
|
|
//
|
|
//Add at the beginning
|
|
//
|
|
|
|
pDesc->pNext = m_pShimList;
|
|
m_pShimList = pDesc;
|
|
|
|
}
|
|
else{
|
|
|
|
//
|
|
// Add into the LL.
|
|
//
|
|
|
|
PSHIMDESC pPrev = m_pShimList;
|
|
PSHIMDESC pTemp = m_pShimList->pNext;
|
|
while (pTemp) {
|
|
if (pDesc->szShimName <= pTemp->szShimName && pDesc->szShimName > pPrev->szShimName) {
|
|
|
|
//
|
|
//This is the position to insert
|
|
//
|
|
break;
|
|
}
|
|
else{
|
|
|
|
pPrev = pTemp;
|
|
pTemp = pTemp->pNext;
|
|
}
|
|
}//while(pTemp)
|
|
|
|
pDesc->pNext = pTemp;
|
|
pPrev->pNext = pDesc;
|
|
}
|
|
|
|
|
|
|
|
|
|
} else{ //This is a SHIM REF for a layer
|
|
/*........................................................................
|
|
|
|
This is executed in the following scenario. We are actually adding the list of layers for the database.
|
|
Now when we find SHIM REFS we want to add them to the particular layer.
|
|
|
|
OK Now this adds this shim as the first entry of the m_pLayerList.Till now we have already added the new layer into
|
|
the Linked list headed by m_pLayerList
|
|
|
|
The following Code has been executed in the ReadShims() function
|
|
|
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
PDBLAYER pLayer = new DBLAYER;
|
|
pLayer->pNext = m_pLayerList;//add this layer to the list of layers for this database
|
|
m_pLayerList = pLayer;
|
|
|
|
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
|
|
So the m_pLayerList now points to the new layer added, obviously the LL headed by m_pLayerList is
|
|
NOT arranged lexi wise on the names of the layers. The shims in the the LL m_pLayerList->pShimList are also
|
|
NOT arranged lexi wise on the names of the shims.
|
|
|
|
|
|
|
|
........................................................................*/
|
|
|
|
pDesc->pNext = m_pLayerList->pShimList;
|
|
m_pLayerList->pShimList = pDesc;
|
|
}
|
|
}
|
|
|
|
BOOL CDatabase::SaveDatabase(CSTRING & szFilename)
|
|
{
|
|
CSTRINGList * pXML = DisassembleRecord(m_pRecordHead,TRUE,TRUE,TRUE,TRUE,FALSE, FALSE);
|
|
BOOL bResult;
|
|
CSTRING szTempFilename;
|
|
TCHAR szPath[MAX_PATH_BUFFSIZE];
|
|
|
|
if ( NULL == pXML )
|
|
return FALSE;
|
|
|
|
|
|
GetSystemWindowsDirectory(szPath, MAX_PATH);
|
|
lstrcat(szPath,TEXT("\\AppPatch\\Temp.XML"));
|
|
|
|
szTempFilename = szPath;
|
|
|
|
bResult = WriteXML(szTempFilename,pXML);
|
|
|
|
if ( pXML != NULL ) {
|
|
|
|
delete pXML;
|
|
}
|
|
|
|
|
|
if ( !bResult ) {
|
|
MessageBox(g_theApp.m_hWnd,TEXT("Unable to save temporary file."),TEXT("File save error"),MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
CSTRING szCommandLine;
|
|
|
|
szCommandLine.sprintf(TEXT("custom \"%s\" \"%s\""),
|
|
(LPCTSTR)szTempFilename,
|
|
(LPCTSTR)szFilename);
|
|
|
|
if ( !InvokeCompiler(szCommandLine) ) {
|
|
|
|
DeleteFile(szTempFilename);
|
|
return FALSE;
|
|
}
|
|
|
|
DeleteFile(szTempFilename);
|
|
|
|
m_szCurrentDatabase = szFilename;
|
|
|
|
m_bDirty = FALSE;
|
|
|
|
g_theApp.UpdateView(TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CDatabase::ResolveMatch(CSTRING & szStr, PMATCHENTRY pMatch)
|
|
{
|
|
if ( 0 != pMatch->dwSize ) {
|
|
CSTRING szTemp;
|
|
|
|
szTemp.sprintf(TEXT(" SIZE=\"%d\""),pMatch->dwSize);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
|
|
if ( 0 != pMatch->dwChecksum ) {
|
|
CSTRING szTemp;
|
|
|
|
szTemp.sprintf(TEXT(" CHECKSUM=\"0x%08X\""),pMatch->dwChecksum);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
|
|
if ( pMatch->szCompanyName.Length() > 0 ) {
|
|
CSTRING szTemp;
|
|
|
|
szTemp.sprintf(TEXT(" COMPANY_NAME=\"%s\""),(LPCTSTR) pMatch->szCompanyName);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
|
|
if ( pMatch->szDescription.Length() > 0 ) {
|
|
CSTRING szTemp;
|
|
|
|
szTemp.sprintf(TEXT(" FILE_DESCRIPTION=\"%s\""),(LPCTSTR) pMatch->szDescription);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
|
|
if ( pMatch->szFileVersion.Length() > 0 ) {
|
|
CSTRING szTemp;
|
|
|
|
szTemp.sprintf(TEXT(" FILE_VERSION=\"%s\""),(LPCTSTR) pMatch->szFileVersion);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
|
|
if ( pMatch->szProductVersion.Length() > 0 ) {
|
|
CSTRING szTemp;
|
|
|
|
szTemp.sprintf(TEXT(" PRODUCT_VERSION=\"%s\""),(LPCTSTR) pMatch->szProductVersion);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
|
|
if ( 0 != pMatch->ProductVersion.QuadPart ) {
|
|
CSTRING szTemp;
|
|
TCHAR szFormat[80];
|
|
|
|
FormatVersion(pMatch->ProductVersion,szFormat);
|
|
|
|
szTemp.sprintf(TEXT(" BIN_PRODUCT_VERSION=\"%s\""),szFormat);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
|
|
if ( 0 != pMatch->FileVersion.QuadPart ) {
|
|
CSTRING szTemp;
|
|
TCHAR szFormat[80];
|
|
|
|
FormatVersion(pMatch->FileVersion,szFormat);
|
|
|
|
szTemp.sprintf(TEXT(" BIN_FILE_VERSION=\"%s\""),szFormat);
|
|
szStr.strcat(szTemp);
|
|
}
|
|
}
|
|
|
|
//
|
|
// BUGBUG -- there is code in sdbapi to do something like this
|
|
// concerning file attributes (in particular in grabmiapi.c
|
|
// perhaps we should use that stuff here to decode
|
|
//
|
|
|
|
CSTRINGList * CDatabase::DisassembleRecord(PDBRECORD pRecordIn, BOOL bChildren, BOOL bSiblings, BOOL bIncludeLocalLayers, BOOL bFullXML, BOOL bAllowGlobal, BOOL bTestRun)
|
|
{
|
|
|
|
//
|
|
//Create a new GUID for test run
|
|
//
|
|
|
|
CSTRINGList * pList = new CSTRINGList;
|
|
|
|
if ( NULL == pList )
|
|
return NULL;
|
|
|
|
if ( bFullXML ) {
|
|
CSTRING DB;
|
|
CSTRING ID;
|
|
|
|
pList->AddString(TEXT("<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"));
|
|
|
|
if ( 0 == m_DBGuid.Data1 )
|
|
CoCreateGuid(&m_DBGuid);
|
|
|
|
ID.GUID(m_DBGuid);
|
|
|
|
if (bTestRun) {
|
|
|
|
GUID testGuid;
|
|
CoCreateGuid(&testGuid);
|
|
ID.GUID(testGuid);
|
|
}
|
|
|
|
DB.sprintf(TEXT("<DATABASE NAME=\"%s\" ID=\"%s\">"),(LPCTSTR)m_DBName,(LPCTSTR)ID);
|
|
|
|
pList->AddString(DB);
|
|
}
|
|
|
|
if ( bIncludeLocalLayers || g_theApp.GetDBLocal().m_pAppHelp != NULL ) {
|
|
PDBLAYER pWalk = g_theApp.GetDBLocal().m_pLayerList;
|
|
BOOL bLocalLayerToAdd = FALSE;
|
|
|
|
while ( NULL != pWalk ) {
|
|
if ( !pWalk->bPermanent )
|
|
bLocalLayerToAdd = TRUE;
|
|
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
if ( bLocalLayerToAdd || g_theApp.GetDBLocal().m_pAppHelp != NULL) {
|
|
CSTRING szTemp;
|
|
|
|
|
|
szTemp.sprintf(TEXT("<LIBRARY>"));
|
|
pList->AddString(szTemp,(PVOID)1);
|
|
|
|
|
|
pWalk = g_theApp.GetDBLocal().m_pLayerList;
|
|
|
|
while ( NULL != pWalk ) {
|
|
if ( !pWalk->bPermanent ) {
|
|
PSHIMDESC pShims = pWalk->pShimList;
|
|
|
|
szTemp.sprintf(TEXT("<LAYER NAME=\"%s\">"),(LPCTSTR)(pWalk->szLayerName));
|
|
pList->AddString(szTemp,(PVOID)2);
|
|
|
|
|
|
while ( NULL != pShims ) {
|
|
szTemp.sprintf(TEXT("<SHIM NAME=\"%s\"/>"),(LPCTSTR)(pShims->szShimName));
|
|
|
|
pList->AddString(szTemp,(PVOID)3);
|
|
pShims = pShims->pNext;
|
|
}
|
|
|
|
pList->AddString(TEXT("</LAYER>"),(PVOID)2);
|
|
}
|
|
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
|
|
//
|
|
// Add the AppHelp Messages
|
|
//
|
|
|
|
PAPPHELP pAppHelp = g_theApp.GetDBLocal().m_pAppHelp;
|
|
|
|
while (pAppHelp) {
|
|
|
|
// TODO: When we get the proper message names, after the change to shimdbc, INLCUDE that one
|
|
|
|
CSTRING strName;
|
|
|
|
strName.sprintf(TEXT("%u"), pAppHelp->HTMLHELPID);
|
|
szTemp.sprintf(TEXT("<MESSAGE NAME = \"%s\" >"), strName.pszString);
|
|
pList->AddString(szTemp,(PVOID)2);
|
|
|
|
pList->AddString(TEXT("<SUMMARY>"),(PVOID)3);
|
|
|
|
pList->AddString(pAppHelp->strMessage, (PVOID)4);
|
|
|
|
pList->AddString(TEXT("</SUMMARY>"),(PVOID)3);
|
|
|
|
pList->AddString(TEXT("</MESSAGE>"),(PVOID)2);
|
|
|
|
pAppHelp = pAppHelp->pNext;
|
|
|
|
}
|
|
|
|
// AppHelp Added to Library
|
|
|
|
|
|
pList->AddString(TEXT("</LIBRARY>"),(PVOID)1);
|
|
}
|
|
}
|
|
|
|
while ( NULL != pRecordIn ) {
|
|
PDBRECORD pRecord = pRecordIn;
|
|
|
|
while ( NULL != pRecord ) {
|
|
if ( bAllowGlobal || !pRecord->bGlobal ) {
|
|
CSTRING szTemp;
|
|
PDBENTRY pEntry = pRecord->pEntries;
|
|
|
|
szTemp.sprintf(TEXT("<APP NAME=\"%s\" VENDOR=\"Unknown\">"),(LPCTSTR)(pRecord->szAppName));
|
|
|
|
pList->AddString(szTemp,(PVOID)1);
|
|
|
|
if ( 0 == pRecord->guidID.Data1 )
|
|
szTemp.sprintf(TEXT("<EXE NAME=\"%s\""),(LPCTSTR)pRecord->szEXEName);
|
|
else {
|
|
CSTRING szGUID;
|
|
|
|
szGUID.GUID(pRecord->guidID);
|
|
|
|
szTemp.sprintf(TEXT("<EXE NAME=\"%s\" ID=\"%s\""),(LPCTSTR)pRecord->szEXEName,(LPCTSTR)szGUID);
|
|
}
|
|
|
|
while ( NULL != pEntry ) {
|
|
if ( ENTRY_MATCH == pEntry->uType ) {
|
|
PMATCHENTRY pMatch = (PMATCHENTRY) pEntry;
|
|
|
|
if ( pMatch->szMatchName == TEXT("*") )
|
|
ResolveMatch(szTemp,pMatch);
|
|
}
|
|
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
|
|
szTemp.strcat(TEXT(">"));
|
|
|
|
pList->AddString(szTemp,(PVOID) 2);
|
|
|
|
// Add matching information
|
|
|
|
pEntry = pRecord->pEntries;
|
|
|
|
while ( NULL != pEntry ) {
|
|
if ( ENTRY_MATCH == pEntry->uType ) {
|
|
PMATCHENTRY pMatch = (PMATCHENTRY) pEntry;
|
|
|
|
if ( pMatch->szMatchName != TEXT("*") ) {
|
|
szTemp.sprintf(TEXT("<MATCHING_FILE NAME=\"%s\""),(LPCTSTR)pMatch->szMatchName);
|
|
ResolveMatch(szTemp,pMatch);
|
|
szTemp.strcat(TEXT("/>"));
|
|
|
|
pList->AddString(szTemp,(PVOID) 3);
|
|
}
|
|
}
|
|
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
|
|
// Add Layer information
|
|
|
|
BOOL bLayerFound = FALSE; //There are layers for this thing
|
|
|
|
if ( pRecord->szLayerName.Length() > 0 ) {
|
|
szTemp.sprintf(TEXT("<LAYER NAME=\"%s\">"),(LPCTSTR)pRecord->szLayerName);
|
|
pList->AddString(szTemp,(PVOID)3);
|
|
pList->AddString(TEXT("</LAYER>"),(PVOID)3);
|
|
|
|
bLayerFound = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_bWin2K && bLayerFound) {
|
|
|
|
szTemp = TEXT("<SHIM NAME= \"Win2kPropagateLayer\"/>");
|
|
pList->AddString(szTemp,(PVOID)3);
|
|
|
|
}
|
|
|
|
|
|
// Add shim information
|
|
|
|
pEntry = pRecord->pEntries;
|
|
|
|
|
|
|
|
|
|
|
|
while ( NULL != pEntry ) {
|
|
if ( ENTRY_SHIM == pEntry->uType ) {
|
|
PSHIMENTRY pShim = (PSHIMENTRY) pEntry;
|
|
|
|
if ( 0 == pShim->szCmdLine.Length() )
|
|
szTemp.sprintf(TEXT("<SHIM NAME=\"%s\"/>"),(LPCTSTR)pShim->szShimName);
|
|
else
|
|
szTemp.sprintf(TEXT("<SHIM NAME=\"%s\" COMMAND_LINE=\"%s\"/>"),(LPCTSTR)pShim->szShimName,(LPCTSTR)pShim->szCmdLine);
|
|
|
|
pList->AddString(szTemp,(PVOID) 3);
|
|
}
|
|
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
|
|
//
|
|
//Do the AppHelp Part
|
|
//
|
|
|
|
|
|
pEntry = pRecord->pEntries;
|
|
|
|
while ( NULL != pEntry ) {
|
|
if ( ENTRY_APPHELP == pEntry->uType ) {
|
|
|
|
PHELPENTRY pHelp = (PHELPENTRY)pEntry;
|
|
|
|
CSTRING strBlock;
|
|
|
|
if (pHelp->bBlock) {
|
|
strBlock = TEXT("YES");
|
|
}else{
|
|
strBlock = TEXT("NO");
|
|
}
|
|
|
|
CSTRING strName;
|
|
strName.sprintf(TEXT("%u"), pHelp->uHelpID);
|
|
|
|
CSTRING strHelpID;
|
|
strHelpID.sprintf(TEXT("%u"), pHelp->uHelpID);
|
|
|
|
|
|
if (pHelp->strURL.Length()) {
|
|
|
|
szTemp.sprintf(TEXT("<APPHELP MESSAGE = \"%s\" BLOCK = \"%s\" HTMLHELPID = \"%s\" DETAILS_URL = \"%s\" />"),
|
|
strName.pszString,
|
|
strBlock.pszString,
|
|
strHelpID.pszString,
|
|
pHelp->strURL.pszString);
|
|
}else{
|
|
|
|
szTemp.sprintf(TEXT("<APPHELP MESSAGE = \"%s\" BLOCK = \"%s\" HTMLHELPID = \"%s\" />"),
|
|
strName.pszString,
|
|
strBlock.pszString,
|
|
strHelpID.pszString);
|
|
}
|
|
|
|
|
|
|
|
pList->AddString(szTemp,(PVOID) 3);
|
|
|
|
|
|
|
|
}
|
|
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
|
|
// End of AppHelp Part
|
|
|
|
|
|
|
|
pList->AddString(TEXT("</EXE>"),(PVOID) 2);
|
|
|
|
pList->AddString(TEXT("</APP>"),(PVOID) 1);
|
|
}
|
|
|
|
if ( !bChildren )
|
|
break;
|
|
|
|
pRecord = pRecord->pDup;
|
|
}
|
|
|
|
if ( !bSiblings )
|
|
break;
|
|
|
|
pRecordIn = pRecordIn->pNext;
|
|
}
|
|
|
|
if ( bFullXML )
|
|
pList->AddString(TEXT("</DATABASE>"));
|
|
|
|
return pList;
|
|
}
|
|
|
|
BOOL CDatabase::WriteString(HANDLE hFile, CSTRING & szString, BOOL bAutoCR)
|
|
{
|
|
DWORD dwBytesWritten;
|
|
|
|
|
|
if ( !WriteFile(hFile, (LPCSTR)szString, szString.Length() ,&dwBytesWritten,NULL) )
|
|
return FALSE;
|
|
|
|
if ( bAutoCR ) {
|
|
CHAR szCR[]={13,10};
|
|
|
|
if ( !WriteFile(hFile,szCR,sizeof(szCR) ,&dwBytesWritten,NULL) )
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDatabase::WriteXML(CSTRING & szFilename, CSTRINGList * pString)
|
|
{
|
|
HANDLE hFile;
|
|
|
|
if ( NULL == pString )
|
|
return FALSE;
|
|
|
|
hFile = CreateFile(szFilename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
|
|
|
if ( INVALID_HANDLE_VALUE == hFile ) {
|
|
return FALSE;
|
|
}
|
|
|
|
PSTRLIST pWalk = pString->m_pHead;
|
|
CSTRING szTemp;
|
|
|
|
while ( NULL != pWalk ) {
|
|
UINT uTabs = pWalk->uExtraData;
|
|
|
|
while ( uTabs > 0 ) {
|
|
szTemp = TEXT(" ");
|
|
WriteString(hFile,szTemp,FALSE);
|
|
|
|
|
|
--uTabs;
|
|
}
|
|
|
|
WriteString(hFile,pWalk->szStr,TRUE);
|
|
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CDatabase::InvokeCompiler(CSTRING & szInCommandLine)
|
|
{
|
|
|
|
|
|
CSTRING szCommandLine = szInCommandLine;
|
|
szCommandLine.sprintf(TEXT("shimdbc.exe %s"), (LPCTSTR) szInCommandLine);
|
|
BOOL bReturn = TRUE;
|
|
|
|
|
|
|
|
|
|
g_theApp.SetStatusText(
|
|
1,
|
|
CSTRING(TEXT("Creating fix database..."))
|
|
);
|
|
|
|
if (!ShimdbcExecute( szCommandLine ) ) {
|
|
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);
|
|
bReturn = FALSE;
|
|
}
|
|
|
|
g_theApp.SetStatusText(
|
|
1,
|
|
CSTRING(TEXT(""))
|
|
);
|
|
|
|
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
DWORD CDatabase::GetEntryFlags(HKEY hKeyRoot, GUID & Guid)
|
|
{
|
|
LONG status;
|
|
HKEY hkey = NULL;
|
|
DWORD dwFlags;
|
|
DWORD type;
|
|
DWORD cbSize = sizeof(DWORD);
|
|
CSTRING szGUID;
|
|
|
|
szGUID.GUID(Guid);
|
|
|
|
status = RegOpenKey(hKeyRoot, APPCOMPAT_KEY, &hkey);
|
|
|
|
if ( ERROR_SUCCESS != status ) {
|
|
status = RegCreateKey(hKeyRoot,APPCOMPAT_KEY,&hkey);
|
|
|
|
if ( ERROR_SUCCESS != status )
|
|
return 0;
|
|
}
|
|
|
|
status = RegQueryValueEx(hkey, szGUID, NULL, &type, (LPBYTE)&dwFlags, &cbSize);
|
|
|
|
if ( ERROR_SUCCESS != status || REG_DWORD != type )
|
|
dwFlags = 0;
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
return dwFlags;
|
|
}
|
|
|
|
BOOL CDatabase::SetEntryFlags(HKEY hKeyRoot, GUID & Guid, DWORD dwFlags)
|
|
{
|
|
LONG status;
|
|
HKEY hkey = NULL;
|
|
CSTRING szGUID;
|
|
|
|
szGUID.GUID(Guid);
|
|
|
|
status = RegOpenKey(hKeyRoot, APPCOMPAT_KEY, &hkey);
|
|
|
|
if ( ERROR_SUCCESS != status ) {
|
|
status = RegCreateKey(hKeyRoot,APPCOMPAT_KEY,&hkey);
|
|
|
|
if ( ERROR_SUCCESS != status )
|
|
return 0;
|
|
}
|
|
|
|
status = RegSetValueEx(hkey, szGUID, 0, REG_DWORD, (LPBYTE) &dwFlags, sizeof(DWORD));
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
return( (ERROR_SUCCESS == status) ? TRUE:FALSE );
|
|
}
|
|
|
|
BOOL CALLBACK NewDatabaseProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch ( uMsg ) {
|
|
case WM_INITDIALOG:
|
|
{
|
|
|
|
SendMessage(
|
|
GetDlgItem(hWnd,IDC_NAME), // handle to destination window
|
|
EM_LIMITTEXT, // message to send
|
|
(WPARAM) LIMIT_APP_NAME, // text length
|
|
(LPARAM) 0
|
|
);
|
|
|
|
|
|
|
|
if ( g_bNew )
|
|
SetWindowText(hWnd,TEXT("New database"));
|
|
|
|
SetWindowText(GetDlgItem(hWnd,IDC_NAME),(LPCTSTR)g_szDBName);
|
|
SetFocus(GetDlgItem(hWnd,IDC_NAME));
|
|
SendMessage(GetDlgItem(hWnd,IDC_NAME),EM_SETSEL,0,-1);
|
|
|
|
SHAutoComplete(GetDlgItem(hWnd,IDC_NAME), AUTOCOMPLETE);
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch ( LOWORD(wParam) ) {
|
|
case IDC_NAME:
|
|
{
|
|
if ( EN_UPDATE == HIWORD(wParam) ) {
|
|
TCHAR szText[MAX_PATH_BUFFSIZE];
|
|
GetWindowText(GetDlgItem(hWnd,IDC_NAME),szText,MAX_PATH);
|
|
|
|
EnableWindow(GetDlgItem(hWnd,IDOK),(CSTRING::Trim(szText) == 0) ? FALSE:TRUE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
{
|
|
TCHAR szText[MAX_PATH_BUFFSIZE];
|
|
|
|
GetWindowText(GetDlgItem(hWnd,IDC_NAME),szText,MAX_PATH);
|
|
|
|
CSTRING::Trim(szText);
|
|
|
|
g_szDBName = szText;
|
|
|
|
EndDialog(hWnd,TRUE);
|
|
}
|
|
break;
|
|
case IDCANCEL:
|
|
EndDialog(hWnd,FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CDatabase::CleanUp()
|
|
{
|
|
TCHAR szShimDB[MAX_PATH_BUFFSIZE] = _T("");
|
|
|
|
GetSystemWindowsDirectory(szShimDB, MAX_PATH);
|
|
lstrcat(szShimDB, _T("\\AppPatch"));
|
|
lstrcat(szShimDB, TEXT("\\test.sdb"));
|
|
|
|
|
|
InstallDatabase(szShimDB, TEXT("-q -u"));
|
|
|
|
DeleteFile(szShimDB);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
int CheckMatch
|
|
( IN PDBENTRY pExistEntry,
|
|
IN PDBENTRY pNewEntry
|
|
)
|
|
|
|
{
|
|
|
|
PMATCHENTRY pMatchExist = NULL, pMatchNew = NULL;
|
|
|
|
//
|
|
//Populate the list of existing match entries
|
|
//
|
|
|
|
while (pExistEntry) {
|
|
if (pExistEntry->uType == ENTRY_MATCH) {
|
|
|
|
PMATCHENTRY pMatchTemp = new MATCHENTRY;
|
|
*pMatchTemp = *(PMATCHENTRY)pExistEntry;
|
|
|
|
if (pMatchExist == NULL) {
|
|
|
|
pMatchExist = pMatchTemp;
|
|
pMatchExist->Entry.pNext = NULL;
|
|
pExistEntry = pExistEntry->pNext;
|
|
continue;
|
|
|
|
}
|
|
|
|
pMatchTemp->Entry.pNext = (PDBENTRY)pMatchExist;
|
|
pMatchExist = (PMATCHENTRY)pMatchTemp;
|
|
|
|
}
|
|
|
|
pExistEntry = pExistEntry->pNext;
|
|
|
|
}//while (pExistEntry)
|
|
|
|
//
|
|
//Populate the match entries for the new record
|
|
//
|
|
|
|
|
|
|
|
|
|
while (pNewEntry) {
|
|
if (pNewEntry->uType == ENTRY_MATCH) {
|
|
|
|
PMATCHENTRY pMatchTemp = new MATCHENTRY;
|
|
PMATCHENTRY match = (PMATCHENTRY)pNewEntry;
|
|
|
|
*pMatchTemp = *match;
|
|
|
|
|
|
if (pMatchNew == NULL) {
|
|
|
|
pMatchNew = pMatchTemp;
|
|
pMatchNew->Entry.pNext = NULL;
|
|
|
|
pNewEntry = pNewEntry->pNext;
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
pMatchTemp->Entry.pNext = (PDBENTRY)pMatchNew;
|
|
pMatchNew = (PMATCHENTRY)pMatchTemp;
|
|
|
|
|
|
}
|
|
|
|
pNewEntry = pNewEntry->pNext;
|
|
|
|
}//while (pENewEntry)
|
|
|
|
//
|
|
//Now check if each and every entry of the pMatchNew is in the existing match list
|
|
//
|
|
|
|
|
|
PMATCHENTRY tempNew, tempExist;
|
|
|
|
tempNew = pMatchNew;
|
|
|
|
|
|
|
|
BOOL found;
|
|
while (tempNew) {
|
|
|
|
tempExist = pMatchExist;
|
|
found = FALSE;
|
|
|
|
while (tempExist) {
|
|
|
|
|
|
if (*tempExist == *tempNew) {
|
|
found = TRUE;
|
|
|
|
break;
|
|
}
|
|
else{
|
|
|
|
tempExist = (PMATCHENTRY)tempExist->Entry.pNext;
|
|
}
|
|
|
|
|
|
}
|
|
if ( found == FALSE)
|
|
break;
|
|
|
|
tempNew = (PMATCHENTRY)tempNew->Entry.pNext;
|
|
}
|
|
|
|
|
|
//
|
|
//Do the clean-up
|
|
//
|
|
|
|
|
|
|
|
while(pMatchExist){
|
|
tempExist = pMatchExist;
|
|
pMatchExist = (PMATCHENTRY)pMatchExist->Entry.pNext;
|
|
delete tempExist;
|
|
}
|
|
|
|
while(pMatchNew){
|
|
tempExist = pMatchNew;
|
|
pMatchNew = (PMATCHENTRY)pMatchNew->Entry.pNext;
|
|
delete tempExist;
|
|
}
|
|
|
|
return ( (tempNew == NULL) || found);
|
|
|
|
}
|
|
|
|
|
|
bool
|
|
InstallDatabase(
|
|
TCHAR *szPath,
|
|
TCHAR *szOptions
|
|
)
|
|
{
|
|
TCHAR szSystemDir[MAX_PATH];
|
|
|
|
*szSystemDir = 0;
|
|
|
|
GetWindowsDirectory(szSystemDir,MAX_PATH);
|
|
|
|
CSTRING strSdbInstCommandLine;
|
|
|
|
strSdbInstCommandLine.sprintf(TEXT("%s\\System32\\sdbInst.exe %s \"%s\" "),
|
|
szSystemDir,
|
|
szOptions,
|
|
szPath
|
|
);
|
|
|
|
if ( !g_theApp.InvokeEXE(NULL,strSdbInstCommandLine.pszString,true,false,false) ) {
|
|
MessageBox(g_theApp.m_hWnd,
|
|
TEXT("There was a problem In executing the data base installer."),
|
|
TEXT("CompatAdmin"),
|
|
MB_ICONERROR
|
|
);
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|