273 lines
9.2 KiB
C
273 lines
9.2 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1997 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
apcompat.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This source implements checking AppCompatibility key that will come with NT
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Calin Negreanu (calinn) 18-May-1999
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "badapps.h"
|
||
|
|
||
|
// #define _OLDAPPDB
|
||
|
#define DBG_APPCOMPAT "AppCompat"
|
||
|
|
||
|
//
|
||
|
// Globals
|
||
|
//
|
||
|
|
||
|
POOLHANDLE g_AppCompatPool = NULL;
|
||
|
HASHTABLE g_AppCompatTable = NULL;
|
||
|
HINF g_AppCompatInf = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
//
|
||
|
// ISSUE - this will change to appmig.inf - leave it the old way until
|
||
|
// AppCompat team checks in the new file
|
||
|
//
|
||
|
#define S_APP_COMPAT_FILE1 TEXT("APPMIG.INF")
|
||
|
#define S_APP_COMPAT_FILE2 TEXT("APPMIG.IN_")
|
||
|
|
||
|
#define S_BASE_WIN_OPTIONS TEXT("BaseWinOptions")
|
||
|
#define S_ADD_REG TEXT("AddReg")
|
||
|
|
||
|
typedef struct _APPCOMPAT_FILE {
|
||
|
PBYTE Info;
|
||
|
DWORD InfoSize;
|
||
|
struct _APPCOMPAT_FILE *Next;
|
||
|
} APPCOMPAT_FILE, *PAPPCOMPAT_FILE;
|
||
|
|
||
|
BOOL
|
||
|
pInitAppCompat (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
PCSTR AppCompatFile = NULL;
|
||
|
PCSTR AppCompatCompFile = NULL;
|
||
|
DWORD decompResult;
|
||
|
BOOL result = TRUE;
|
||
|
INFCONTEXT baseContext, addContext, regContext;
|
||
|
TCHAR baseSection [MEMDB_MAX];
|
||
|
TCHAR addSection [MEMDB_MAX];
|
||
|
TCHAR regValue [MEMDB_MAX];
|
||
|
TCHAR fieldStr [MEMDB_MAX];
|
||
|
INT fieldVal;
|
||
|
PCTSTR regFile;
|
||
|
PAPPCOMPAT_FILE appCompatFile;
|
||
|
DWORD index;
|
||
|
HASHITEM stringId;
|
||
|
|
||
|
if (CANCELLED()) {
|
||
|
SetLastError (ERROR_CANCELLED);
|
||
|
return FALSE;
|
||
|
}
|
||
|
__try {
|
||
|
AppCompatFile = JoinPaths (SOURCEDIRECTORY(0), S_APP_COMPAT_FILE1);
|
||
|
g_AppCompatInf = InfOpenInfFile (AppCompatFile);
|
||
|
if (g_AppCompatInf == INVALID_HANDLE_VALUE) {
|
||
|
FreePathString (AppCompatFile);
|
||
|
AppCompatFile = JoinPaths (g_TempDir, S_APP_COMPAT_FILE1);
|
||
|
AppCompatCompFile = JoinPaths (SOURCEDIRECTORY(0), S_APP_COMPAT_FILE2);
|
||
|
decompResult = SetupDecompressOrCopyFile (AppCompatCompFile, AppCompatFile, 0);
|
||
|
if ((decompResult != ERROR_SUCCESS) && (decompResult != ERROR_ALREADY_EXISTS)) {
|
||
|
LOG((LOG_ERROR, "Cannot open Application compatibility database : %s", AppCompatCompFile));
|
||
|
result = FALSE;
|
||
|
__leave;
|
||
|
}
|
||
|
g_AppCompatInf = InfOpenInfFile (AppCompatFile);
|
||
|
if (g_AppCompatInf == INVALID_HANDLE_VALUE) {
|
||
|
LOG((LOG_ERROR, "Cannot open Application compatibility database : %s", AppCompatCompFile));
|
||
|
result = FALSE;
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
g_AppCompatPool = PoolMemInitNamedPool ("AppCompat Pool");
|
||
|
g_AppCompatTable = HtAllocWithData (sizeof (PAPPCOMPAT_FILE));
|
||
|
if (g_AppCompatTable == NULL) {
|
||
|
LOG((LOG_ERROR, "Cannot initialize memory for Application compatibility operations"));
|
||
|
result = FALSE;
|
||
|
__leave;
|
||
|
}
|
||
|
//
|
||
|
// finally load the data from ApCompat.inf
|
||
|
//
|
||
|
if (SetupFindFirstLine (g_AppCompatInf, S_BASE_WIN_OPTIONS, NULL, &baseContext)) {
|
||
|
do {
|
||
|
if (SetupGetStringField (&baseContext, 1, baseSection, MEMDB_MAX, NULL)) {
|
||
|
if (SetupFindFirstLine (g_AppCompatInf, baseSection, S_ADD_REG, &addContext)) {
|
||
|
do {
|
||
|
if (SetupGetStringField (&addContext, 1, addSection, MEMDB_MAX, NULL)) {
|
||
|
if (SetupFindFirstLine (g_AppCompatInf, addSection, NULL, ®Context)) {
|
||
|
do {
|
||
|
if (SetupGetStringField (®Context, 2, regValue, MEMDB_MAX, NULL)) {
|
||
|
regFile = GetFileNameFromPath (regValue);
|
||
|
appCompatFile = (PAPPCOMPAT_FILE) PoolMemGetMemory (g_AppCompatPool, sizeof (APPCOMPAT_FILE));
|
||
|
ZeroMemory (appCompatFile, sizeof (APPCOMPAT_FILE));
|
||
|
index = SetupGetFieldCount (®Context);
|
||
|
if (index > 4) {
|
||
|
appCompatFile->Info = (PBYTE) PoolMemGetMemory (g_AppCompatPool, index - 4);
|
||
|
appCompatFile->InfoSize = index - 4;
|
||
|
index = 0;
|
||
|
while (SetupGetStringField (®Context, index+5, fieldStr, MEMDB_MAX, NULL)) {
|
||
|
sscanf (fieldStr, TEXT("%x"), &fieldVal);
|
||
|
appCompatFile->Info [index] = (BYTE) fieldVal;
|
||
|
index ++;
|
||
|
}
|
||
|
if (index) {
|
||
|
stringId = HtFindString (g_AppCompatTable, regFile);
|
||
|
if (stringId) {
|
||
|
HtCopyStringData (g_AppCompatTable, stringId, &(appCompatFile->Next));
|
||
|
HtSetStringData (g_AppCompatTable, stringId, &appCompatFile);
|
||
|
} else {
|
||
|
HtAddStringAndData (g_AppCompatTable, regFile, &appCompatFile);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} while (SetupFindNextLine (®Context, ®Context));
|
||
|
}
|
||
|
}
|
||
|
} while (SetupFindNextLine (&addContext, &addContext));
|
||
|
}
|
||
|
}
|
||
|
} while (SetupFindNextLine (&baseContext, &baseContext));
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
if (AppCompatFile) {
|
||
|
FreePathString (AppCompatFile);
|
||
|
AppCompatFile = NULL;
|
||
|
}
|
||
|
if (AppCompatCompFile) {
|
||
|
FreePathString (AppCompatCompFile);
|
||
|
AppCompatCompFile = NULL;
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
InitAppCompat (
|
||
|
IN DWORD Request
|
||
|
)
|
||
|
{
|
||
|
switch (Request) {
|
||
|
case REQUEST_QUERYTICKS:
|
||
|
return TICKS_INIT_APP_COMPAT;
|
||
|
case REQUEST_RUN:
|
||
|
if (!pInitAppCompat ()) {
|
||
|
return GetLastError ();
|
||
|
}
|
||
|
else {
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
default:
|
||
|
DEBUGMSG ((DBG_ERROR, "Bad parameter in InitAppCompat"));
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
pDoneAppCompat (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
if (g_AppCompatTable) {
|
||
|
HtFree (g_AppCompatTable);
|
||
|
g_AppCompatTable = NULL;
|
||
|
}
|
||
|
if (g_AppCompatPool) {
|
||
|
PoolMemDestroyPool (g_AppCompatPool);
|
||
|
g_AppCompatPool = NULL;
|
||
|
}
|
||
|
if (g_AppCompatInf != INVALID_HANDLE_VALUE) {
|
||
|
InfCloseInfFile (g_AppCompatInf);
|
||
|
g_AppCompatInf = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
DoneAppCompat (
|
||
|
IN DWORD Request
|
||
|
)
|
||
|
{
|
||
|
switch (Request) {
|
||
|
case REQUEST_QUERYTICKS:
|
||
|
return TICKS_DONE_APP_COMPAT;
|
||
|
case REQUEST_RUN:
|
||
|
if (!pDoneAppCompat ()) {
|
||
|
return GetLastError ();
|
||
|
}
|
||
|
else {
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
default:
|
||
|
DEBUGMSG ((DBG_ERROR, "Bad parameter in DoneAppCompat"));
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
AppCompatTestFile (
|
||
|
IN OUT PFILE_HELPER_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
PCTSTR filePtr;
|
||
|
HASHITEM stringId;
|
||
|
PAPPCOMPAT_FILE appCompatFile;
|
||
|
BOOL found = FALSE;
|
||
|
BADAPP_DATA badAppData;
|
||
|
BADAPP_PROP badAppProp;
|
||
|
|
||
|
if (Params->Handled == 0) {
|
||
|
|
||
|
filePtr = GetFileNameFromPath (Params->FullFileSpec);
|
||
|
if (filePtr) {
|
||
|
stringId = HtFindString (g_AppCompatTable, filePtr);
|
||
|
if (stringId) {
|
||
|
HtCopyStringData (g_AppCompatTable, stringId, &appCompatFile);
|
||
|
while (!found && appCompatFile) {
|
||
|
if (appCompatFile->Info) {
|
||
|
|
||
|
badAppProp.Size = sizeof(BADAPP_PROP);
|
||
|
badAppData.Size = sizeof(BADAPP_DATA);
|
||
|
badAppData.FilePath = Params->FullFileSpec;
|
||
|
badAppData.Blob = appCompatFile->Info;
|
||
|
badAppData.BlobSize = appCompatFile->InfoSize;
|
||
|
|
||
|
if (SHIsBadApp(&badAppData, &badAppProp)) {
|
||
|
switch (badAppProp.AppType & APPTYPE_TYPE_MASK)
|
||
|
{
|
||
|
case APPTYPE_INC_HARDBLOCK:
|
||
|
case APPTYPE_INC_NOBLOCK:
|
||
|
found = TRUE;
|
||
|
MarkFileForExternalDelete (Params->FullFileSpec);
|
||
|
if (!IsFileMarkedForAnnounce (Params->FullFileSpec)) {
|
||
|
AnnounceFileInReport (Params->FullFileSpec, 0, ACT_INCOMPATIBLE);
|
||
|
}
|
||
|
Params->Handled = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
appCompatFile = appCompatFile->Next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|