windows-nt/Source/XPSP1/NT/shell/lib/badapps/badapps.c
2020-09-26 16:20:57 +08:00

839 lines
20 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
badapps.c
Abstract:
Implements a library for CheckBadApps key.
Author:
Calin Negreanu (calinn) 20-Jan-1999
Revision History:
<alias> <date> <comments>
--*/
#include <windows.h>
#include <winnt.h>
#include <shlwapi.h>
#include <badapps.h>
#include "utils.h"
#include "version.h"
#include "modules.h"
typedef struct {
PCTSTR FileName;
BOOL FindDataLoaded;
WIN32_FIND_DATA FindData;
PBYTE MappedImage;
HANDLE FileHandle;
HANDLE MapHandle;
VERSION_STRUCT VersionData;
HKEY PrevOsKey;
} FILE_DATA, *PFILE_DATA;
typedef BOOL (VERSION_CHECK_PROTOTYPE) (PFILE_DATA FileData, DWORD DataSize, PBYTE Data);
typedef VERSION_CHECK_PROTOTYPE * PVERSION_CHECK_PROTOTYPE;
typedef struct {
DWORD VersionId;
PVERSION_CHECK_PROTOTYPE VersionCheck;
} VERSION_DATA, *PVERSION_DATA;
#define LIBARGS(id, fn) VERSION_CHECK_PROTOTYPE fn;
#define TOOLARGS(name, dispName, allowance, edit, query, output)
VERSION_STAMPS
#undef TOOLARGS
#undef LIBARGS
#define LIBARGS(id, fn) {id, fn},
#define TOOLARGS(name, dispName, allowance, edit, query, output)
VERSION_DATA g_VersionData [] = {
VERSION_STAMPS
{0, NULL}
};
#undef TOOLARGS
#undef LIBARGS
#define FD_FINDDATA 0x00000001
#define FD_MAPPINGDATA 0x00000002
#define FD_VERSIONDATA 0x00000003
#define FD_PREVOSDATA 0x00000004
BOOL
ShLoadFileData (
IN OUT PFILE_DATA FileData,
IN DWORD FileDataType
)
{
LONG status;
HANDLE findHandle;
UINT oldMode;
switch (FileDataType) {
case FD_FINDDATA:
if (!FileData->FindDataLoaded) {
oldMode = SetErrorMode (SEM_FAILCRITICALERRORS);
findHandle = FindFirstFile (FileData->FileName, &FileData->FindData);
SetErrorMode(oldMode);
if (findHandle == INVALID_HANDLE_VALUE) {
return FALSE;
} else {
FindClose (findHandle);
FileData->FindDataLoaded = TRUE;
}
}
break;
case FD_MAPPINGDATA:
if (!FileData->MappedImage) {
FileData->MappedImage = ShMapFileIntoMemory (
FileData->FileName,
&FileData->FileHandle,
&FileData->MapHandle
);
if (!FileData->MappedImage) {
return FALSE;
}
}
break;
case FD_VERSIONDATA:
if (!FileData->VersionData.VersionBuffer) {
if (!ShCreateVersionStruct (&FileData->VersionData, FileData->FileName)) {
FileData->VersionData.VersionBuffer = NULL;
return FALSE;
}
}
break;
case FD_PREVOSDATA:
if (!FileData->PrevOsKey) {
status = RegOpenKey (
HKEY_LOCAL_MACHINE,
S_KEY_PREVOSVERSION,
&FileData->PrevOsKey
);
if (status != ERROR_SUCCESS) {
return FALSE;
}
}
default:
return FALSE;
}
return TRUE;
}
BOOL
ShFreeFileData (
IN OUT PFILE_DATA FileData
)
{
FileData->FindDataLoaded = FALSE;
if (FileData->MappedImage) {
ShUnmapFile (
FileData->MappedImage,
FileData->FileHandle,
FileData->MapHandle
);
FileData->MappedImage = NULL;
FileData->FileHandle = NULL;
FileData->MapHandle = NULL;
}
if (FileData->VersionData.VersionBuffer) {
ShDestroyVersionStruct (&FileData->VersionData);
FileData->VersionData.VersionBuffer = NULL;
}
if (FileData->PrevOsKey) {
RegCloseKey (FileData->PrevOsKey);
FileData->PrevOsKey = NULL;
}
return TRUE;
}
BOOL
ShCheckFileSize (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
if (!ShLoadFileData (FileData, FD_FINDDATA)) {
return FALSE;
}
return (*((UNALIGNED DWORD*)Data) == FileData->FindData.nFileSizeLow);
}
BOOL
ShCheckModuleType (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
if (!ShLoadFileData (FileData, FD_MAPPINGDATA)) {
return FALSE;
}
return (*((UNALIGNED DWORD*) Data) == ShGetModuleType (FileData->MappedImage));
}
BOOL
ShCheckBinFileVer (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONGLONG value;
ULONGLONG mask;
ULONGLONG currVer;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
currVer = 0;
} else {
currVer = ShVerGetFileVer (&FileData->VersionData);
}
value = *(UNALIGNED ULONGLONG*) Data;
mask = *((UNALIGNED ULONGLONG*) (Data + sizeof (ULONGLONG)));
return ((value & mask) == currVer);
}
BOOL
ShCheckBinProductVer (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONGLONG value;
ULONGLONG mask;
ULONGLONG currVer;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
currVer = 0;
} else {
currVer = ShVerGetProductVer (&FileData->VersionData);
}
value = *(UNALIGNED ULONGLONG*)Data;
mask = *((UNALIGNED ULONGLONG*)(Data + sizeof (ULONGLONG)));
return ((value & mask) == currVer);
}
BOOL
ShCheckUpToBinProductVer (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONGLONG ProdVerMS;
ULONGLONG BadProdVer;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
ProdVerMS = 0;
} else {
ProdVerMS = ShVerGetProductVer (&FileData->VersionData);
}
BadProdVer = *(UNALIGNED ULONGLONG*)Data;
return (ProdVerMS <= BadProdVer);
}
BOOL
ShCheckFileDateHi (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONGLONG value;
ULONGLONG currVer;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
currVer = 0;
} else {
currVer = ShVerGetFileDateHi (&FileData->VersionData);
}
value = *(UNALIGNED ULONGLONG*)Data;
return (value == currVer);
}
BOOL
ShCheckFileDateLo (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONGLONG value;
ULONGLONG currVer;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
currVer = 0;
} else {
currVer = ShVerGetFileDateLo (&FileData->VersionData);
}
value = *(UNALIGNED ULONGLONG*)Data;
return (value == currVer);
}
BOOL
ShCheckFileVerOs (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONG value;
ULONG currVer;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
currVer = 0;
} else {
currVer = ShVerGetFileVerOs (&FileData->VersionData);
}
value = *(UNALIGNED ULONG*)Data;
return (value == currVer);
}
BOOL
ShCheckFileVerType (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONG value;
ULONG currVer;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
currVer = 0;
} else {
currVer = ShVerGetFileVerType (&FileData->VersionData);
}
value = *(UNALIGNED ULONG*)Data;
return (value == currVer);
}
BOOL
ShCheckFileCheckSum (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONG value;
if (!ShLoadFileData (FileData, FD_FINDDATA)) {
return FALSE;
}
if (!ShLoadFileData (FileData, FD_MAPPINGDATA)) {
return FALSE;
}
value = *(UNALIGNED ULONG*)Data;
return (value == ShGetCheckSum (FileData->FindData.nFileSizeLow, FileData->MappedImage));
}
BOOL
ShCheckFilePECheckSum (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
ULONG value;
if (!ShLoadFileData (FileData, FD_MAPPINGDATA)) {
return FALSE;
}
value = *(UNALIGNED ULONG*)Data;
return (value == ShGetPECheckSum (FileData->MappedImage));
}
BOOL
ShCheckStrVersion (
IN PFILE_DATA FileData,
IN PCTSTR ValueToCheck,
IN DWORD DataSize,
IN PBYTE Data
)
{
BOOL result = FALSE;
if (!ShLoadFileData (FileData, FD_VERSIONDATA)) {
return FALSE;
}
{
#ifndef UNICODE
PSTR convStr = NULL;
INT converted = 0;
#endif
LPCWSTR localData;
WSTR_ALIGNED_STACK_COPY(&localData,(UNALIGNED TCHAR*)Data);
#ifndef UNICODE
convStr = HeapAlloc (GetProcessHeap (), 0, DataSize);
if (convStr)
{
converted = WideCharToMultiByte (
CP_ACP,
0,
localData,
-1,
convStr,
DataSize,
NULL,
NULL
);
}
if (!converted)
{
if (convStr)
HeapFree (GetProcessHeap (), 0, convStr);
return FALSE;
}
result = ShGlobalVersionCheck (&FileData->VersionData, ValueToCheck, convStr);
HeapFree (GetProcessHeap (), 0, convStr);
#else
result = ShGlobalVersionCheck (&FileData->VersionData, ValueToCheck, localData);
#endif
}
return result;
}
BOOL
ShCheckCompanyName (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_COMPANYNAME, DataSize, Data));
}
BOOL
ShCheckProductVersion (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_PRODUCTVERSION, DataSize, Data));
}
BOOL
ShCheckProductName (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_PRODUCTNAME, DataSize, Data));
}
BOOL
ShCheckFileDescription (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_FILEDESCRIPTION, DataSize, Data));
}
BOOL
ShCheckFileVersion (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_FILEVERSION, DataSize, Data));
}
BOOL
ShCheckOriginalFileName (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_ORIGINALFILENAME, DataSize, Data));
}
BOOL
ShCheckInternalName (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_INTERNALNAME, DataSize, Data));
}
BOOL
ShCheckLegalCopyright (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
return (ShCheckStrVersion (FileData, S_VER_LEGALCOPYRIGHT, DataSize, Data));
}
BOOL
ShCheck16BitDescription (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
PTSTR value;
BOOL result = FALSE;
value = ShGet16ModuleDescription (FileData->MappedImage);
if (!value) {
return FALSE;
}
{
#ifndef UNICODE
PSTR convStr = NULL;
INT converted = 0;
#endif
LPCWSTR localData;
WSTR_ALIGNED_STACK_COPY(&localData,(UNALIGNED TCHAR*)Data);
#ifndef UNICODE
convStr = HeapAlloc (GetProcessHeap (), 0, DataSize);
if (convStr)
{
converted = WideCharToMultiByte (
CP_ACP,
0,
localData,
-1,
convStr,
DataSize,
NULL,
NULL
);
}
if (!converted)
{
if (convStr)
HeapFree (GetProcessHeap (), 0, convStr);
HeapFree (GetProcessHeap (), 0, value);
return FALSE;
}
result = ShIsPatternMatch (convStr, value);
HeapFree (GetProcessHeap (), 0, convStr);
#else
result = ShIsPatternMatch (localData, value);
#endif
}
HeapFree (GetProcessHeap (), 0, value);
return result;
}
BOOL
pShLoadPrevOsData (
IN PFILE_DATA FileData,
IN PCTSTR ValueName,
OUT PDWORD Value
)
{
LONG status;
BOOL result = FALSE;
DWORD type;
DWORD valueSize = sizeof (DWORD);
if (ShLoadFileData (FileData, FD_PREVOSDATA)) {
status = RegQueryValueEx (FileData->PrevOsKey, ValueName, NULL, &type, (PBYTE)Value, &valueSize);
if ((status == ERROR_SUCCESS) &&
(type == REG_DWORD)
) {
result = TRUE;
}
}
return result;
}
BOOL
ShCheckPrevOsMajorVersion (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
BOOL result = FALSE;
DWORD value = 0;
if (pShLoadPrevOsData (FileData, S_VAL_MAJORVERSION, &value)) {
result = (value == *(UNALIGNED DWORD*)(Data));
}
return result;
}
BOOL
ShCheckPrevOsMinorVersion (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
BOOL result = FALSE;
DWORD value = 0;
if (pShLoadPrevOsData (FileData, S_VAL_MINORVERSION, &value)) {
result = (value == *(UNALIGNED DWORD*)(Data));
}
return result;
}
BOOL
ShCheckPrevOsPlatformId (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
BOOL result = FALSE;
DWORD value = 0;
if (pShLoadPrevOsData (FileData, S_VAL_PLATFORMID, &value)) {
result = (value == *(UNALIGNED DWORD*)(Data));
}
return result;
}
BOOL
ShCheckPrevOsBuildNo (
IN PFILE_DATA FileData,
IN DWORD DataSize,
IN PBYTE Data
)
{
BOOL result = FALSE;
DWORD value = 0;
if (pShLoadPrevOsData (FileData, S_VAL_BUILDNO, &value)) {
result = (value == *(UNALIGNED DWORD*)(Data));
}
return result;
}
BOOL
DoesPathExist (
IN PCTSTR Path
)
{
BOOL result = FALSE;
DWORD errMode;
if (Path)
{
errMode = SetErrorMode (SEM_FAILCRITICALERRORS);
result = (GetFileAttributes (Path) != 0xFFFFFFFF);
SetErrorMode(errMode);
}
return result;
}
BOOL
pShCheckBlob (
IN PCTSTR FileName,
IN PBYTE Blob,
IN BOOL QuickMode
)
{
FILE_DATA fileData;
PVERSION_DATA p;
DWORD dataId;
DWORD dataSize;
BOOL result = TRUE;
PTSTR reqFile = NULL;
PTSTR oldReqFile = NULL;
PCTSTR filePtr = NULL;
UINT prefixPathChars;
ZeroMemory (&fileData, sizeof (FILE_DATA));
fileData.FileName = FileName;
if (!DoesPathExist (fileData.FileName)) {
return FALSE;
}
filePtr = ShGetFileNameFromPath (FileName);
if (!filePtr) {
return FALSE;
}
prefixPathChars = (UINT)(filePtr - FileName);
__try {
dataId = *((UNALIGNED DWORD*) Blob);
while (dataId) {
if (dataId == VTID_REQFILE) {
Blob += sizeof (DWORD);
dataSize = *((UNALIGNED DWORD*) Blob);
if (!dataSize) {
// should never happen
dataSize = 1;
}
Blob += sizeof (DWORD);
// if this is the first additional file, reqFile is NULL
oldReqFile = reqFile;
// dataSize includes terminating nul character
reqFile = HeapAlloc (GetProcessHeap (), 0, prefixPathChars * sizeof (TCHAR) + dataSize);
if (!reqFile) {
result = FALSE;
__leave;
}
lstrcpyn (reqFile, fileData.FileName, prefixPathChars + 1);
// if this is the first additional file, oldReqFile is NULL
if (oldReqFile) {
HeapFree (GetProcessHeap (), 0, oldReqFile);
}
{
#ifndef UNICODE
PSTR convStr = NULL;
INT converted = 0;
#endif
LPCWSTR localData;
WSTR_ALIGNED_STACK_COPY(&localData,(UNALIGNED TCHAR*)Blob);
#ifndef UNICODE
convStr = HeapAlloc (GetProcessHeap (), 0, dataSize);
if (convStr)
{
converted = WideCharToMultiByte (
CP_ACP,
0,
localData,
-1,
convStr,
dataSize,
NULL,
NULL
);
}
if (!converted)
{
if (convStr)
HeapFree (GetProcessHeap (), 0, convStr);
result = FALSE;
__leave;
}
lstrcpyn (reqFile + prefixPathChars, convStr, dataSize / sizeof (TCHAR));
HeapFree (GetProcessHeap (), 0, convStr);
#else
lstrcpyn (reqFile + prefixPathChars, localData, dataSize / sizeof (TCHAR));
#endif
}
reqFile [prefixPathChars + (dataSize / sizeof (TCHAR)) - 1] = 0;
ShFreeFileData (&fileData);
fileData.FileName = reqFile;
if (!DoesPathExist (fileData.FileName)) {
result = FALSE;
__leave;
}
Blob += dataSize;
} else {
if (dataId >= VTID_LASTID) {
result = FALSE;
__leave;
}
p = g_VersionData + (dataId - VTID_REQFILE - 1);
if (p->VersionId != dataId) {
result = FALSE;
__leave;
}
Blob += sizeof (DWORD);
dataSize = *((UNALIGNED DWORD*) Blob);
Blob += sizeof (DWORD);
if (!QuickMode) {
if (!p->VersionCheck (&fileData, dataSize, Blob)) {
result = FALSE;
__leave;
}
}
Blob += dataSize;
}
dataId = *((UNALIGNED DWORD*) Blob);
}
}
__finally {
if (reqFile) {
HeapFree (GetProcessHeap (), 0, reqFile);
}
ShFreeFileData (&fileData);
}
return result;
}
BOOL
SHIsBadApp (
IN PBADAPP_DATA Data,
OUT PBADAPP_PROP Prop
)
{
BOOL result = FALSE;
PBADAPP_PROP appProp;
__try {
if (Data->Size != sizeof (BADAPP_DATA)) {
return FALSE;
}
if (Prop->Size != sizeof (BADAPP_PROP)) {
return FALSE;
}
if (*(PDWORD)(Data->Blob) != sizeof (BADAPP_PROP)) {
return FALSE;
}
if (pShCheckBlob (Data->FilePath, Data->Blob + sizeof (BADAPP_PROP), TRUE)) {
result = pShCheckBlob (Data->FilePath, Data->Blob + sizeof (BADAPP_PROP), FALSE);
}
if (result) {
appProp = (PBADAPP_PROP) Data->Blob;
Prop->MsgId = appProp->MsgId;
Prop->AppType = appProp->AppType;
}
}
__except (1) {
result = FALSE;
}
return result;
}