1367 lines
42 KiB
C
1367 lines
42 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1997 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
modules.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implements a function that checkes every module listed in MEMDB_CATEGORY_MODULE_CHECK
|
||
|
trying to see if all modules listed in IMPORT section are going to be available on NT.
|
||
|
|
||
|
The entry point is ProcessModules
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Calin Negreanu (calinn) 27-Nov-1997
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
mvander 26-Map-1999 Moved MODULESTATUS defines to fileops.h
|
||
|
calinn 23-Sep-1998 Added support for NT installed files
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "migdbp.h"
|
||
|
#include "migappp.h"
|
||
|
|
||
|
#define DBG_MODULES "Modules"
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
DWORD g_NumEXEs = 0;
|
||
|
#endif
|
||
|
|
||
|
DWORD g_ModuleRecursionLevel = 0;
|
||
|
#define MAX_MODULE_RECURSION_LEVEL 50
|
||
|
|
||
|
#define WIN32_EXE_SET_BITS (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE)
|
||
|
#define WIN32_EXE_CLEAR_BITS (IMAGE_FILE_DLL)
|
||
|
#define WIN32_DLL_SET_BITS (WIN32_EXE_SET_BITS | IMAGE_FILE_DLL)
|
||
|
#define WIN32_DLL_CLEAR_BITS 0
|
||
|
|
||
|
#define WIN16_LIBRARY 0x8000
|
||
|
|
||
|
//since we are reading from a file we need that sizeof to give us the accurate result
|
||
|
#pragma pack(push,1)
|
||
|
|
||
|
typedef struct _NE_HEADER {
|
||
|
WORD Magic;
|
||
|
BYTE MajorLinkerVersion;
|
||
|
BYTE MinorLinkerVersion;
|
||
|
WORD EntryTableOff;
|
||
|
WORD EntryTableLen;
|
||
|
ULONG Reserved;
|
||
|
WORD Flags;
|
||
|
WORD NumberOfDataSeg;
|
||
|
WORD SizeOfHeap;
|
||
|
WORD SizeOfStack;
|
||
|
ULONG CS_IP;
|
||
|
ULONG SS_SP;
|
||
|
WORD NumEntriesSegTable;
|
||
|
WORD NumEntriesModuleTable;
|
||
|
WORD NonResNameTableSize;
|
||
|
WORD SegTableOffset;
|
||
|
WORD ResTableOffset;
|
||
|
WORD ResNameTableOffset;
|
||
|
WORD ModuleTableOffset;
|
||
|
WORD ImportedTableOffset;
|
||
|
ULONG NonResNameTableOffset;
|
||
|
WORD NumberOfMovableEntryPoints;
|
||
|
WORD ShiftCount;
|
||
|
WORD NumberOfResourceSegments;
|
||
|
BYTE TargetOS;
|
||
|
BYTE AdditionalInfo;
|
||
|
WORD FastLoadOffset;
|
||
|
WORD FastLoadSize;
|
||
|
WORD Reserved1;
|
||
|
WORD WinVersionExpected;
|
||
|
} NE_HEADER, *PNE_HEADER;
|
||
|
|
||
|
typedef struct _NE_SEGMENT_ENTRY {
|
||
|
WORD SegmentOffset;
|
||
|
WORD SegmentLen;
|
||
|
WORD SegmentFlags;
|
||
|
WORD SegMinAlloc;
|
||
|
} NE_SEGMENT_ENTRY, *PNE_SEGMENT_ENTRY;
|
||
|
|
||
|
typedef struct _NE_RELOC_ITEM {
|
||
|
BYTE AddressType;
|
||
|
BYTE RelocType;
|
||
|
WORD RelocOffset;
|
||
|
WORD ModuleOffset;
|
||
|
WORD FunctionOffset;
|
||
|
} NE_RELOC_ITEM, *PNE_RELOC_ITEM;
|
||
|
|
||
|
#define SEG_CODE_MASK 0x0001
|
||
|
#define SEG_CODE 0x0000
|
||
|
#define SEG_PRELOAD_MASK 0x0040
|
||
|
#define SEG_PRELOAD 0x0040
|
||
|
#define SEG_RELOC_MASK 0x0100
|
||
|
#define SEG_RELOC 0x0100
|
||
|
|
||
|
#define RELOC_IMPORTED_ORDINAL 0x01
|
||
|
#define RELOC_IMPORTED_NAME 0x02
|
||
|
#define RELOC_ADDR_TYPE 0x03
|
||
|
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
|
||
|
|
||
|
typedef struct _IMPORT_ENUM32 {
|
||
|
/*user area - BEGIN*/
|
||
|
PCSTR ImportModule;
|
||
|
PCSTR ImportFunction;
|
||
|
ULONG ImportFunctionOrd;
|
||
|
/*user area - END*/
|
||
|
|
||
|
PLOADED_IMAGE Image;
|
||
|
PIMAGE_IMPORT_DESCRIPTOR ImageDescriptor;
|
||
|
DWORD ImportFunctionAddr;
|
||
|
PIMAGE_THUNK_DATA ImageData;
|
||
|
PIMAGE_IMPORT_BY_NAME ImageName;
|
||
|
} IMPORT_ENUM32, *PIMPORT_ENUM32;
|
||
|
|
||
|
typedef struct _IMPORT_ENUM16 {
|
||
|
/*user area - BEGIN*/
|
||
|
CHAR ImportModule[MAX_MBCHAR_PATH];
|
||
|
CHAR ImportFunction[MAX_MBCHAR_PATH];
|
||
|
ULONG ImportFunctionOrd;
|
||
|
/*user area - END*/
|
||
|
|
||
|
PCSTR Image;
|
||
|
PDOS_HEADER DosHeader;
|
||
|
PNE_HEADER NeHeader;
|
||
|
PNE_SEGMENT_ENTRY SegmentEntry;
|
||
|
WORD CurrSegEntry;
|
||
|
PWORD CurrNrReloc;
|
||
|
PNE_RELOC_ITEM RelocItem;
|
||
|
WORD CurrRelocItem;
|
||
|
} IMPORT_ENUM16, *PIMPORT_ENUM16;
|
||
|
|
||
|
typedef struct _MODULE_IMAGE {
|
||
|
UINT ModuleType;
|
||
|
union {
|
||
|
struct {
|
||
|
LOADED_IMAGE Image;
|
||
|
} W32Data;
|
||
|
struct {
|
||
|
PCSTR Image;
|
||
|
HANDLE FileHandle;
|
||
|
HANDLE MapHandle;
|
||
|
NE_HEADER Neh;
|
||
|
} W16Data;
|
||
|
} ModuleData;
|
||
|
} MODULE_IMAGE, *PMODULE_IMAGE;
|
||
|
|
||
|
static CHAR g_TempKey[MEMDB_MAX];
|
||
|
|
||
|
#define CLEARBUFFER() g_TempKey[0] = 0
|
||
|
#define ISBUFFEREMPTY() (g_TempKey[0] == 0)
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
LoadModuleData (
|
||
|
IN PCSTR ModuleName,
|
||
|
IN OUT PMODULE_IMAGE ModuleImage
|
||
|
)
|
||
|
{
|
||
|
HANDLE fileHandle;
|
||
|
DWORD bytesRead;
|
||
|
DOS_HEADER dh;
|
||
|
DWORD sign;
|
||
|
PWORD signNE = (PWORD)&sign;
|
||
|
BOOL result = FALSE;
|
||
|
|
||
|
ZeroMemory (ModuleImage, sizeof (MODULE_IMAGE));
|
||
|
ModuleImage->ModuleType = UNKNOWN_MODULE;
|
||
|
|
||
|
fileHandle = CreateFile (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||
|
if (fileHandle == INVALID_HANDLE_VALUE) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
__try {
|
||
|
__try {
|
||
|
if ((!ReadFile (fileHandle, &dh, sizeof (DOS_HEADER), &bytesRead, NULL)) ||
|
||
|
(bytesRead != sizeof (DOS_HEADER))
|
||
|
) {
|
||
|
__leave;
|
||
|
}
|
||
|
result = TRUE;
|
||
|
if (dh.e_magic != IMAGE_DOS_SIGNATURE) {
|
||
|
ModuleImage->ModuleType = UNKNOWN_MODULE;
|
||
|
__leave;
|
||
|
}
|
||
|
ModuleImage->ModuleType = DOS_MODULE;
|
||
|
|
||
|
if (SetFilePointer (fileHandle, dh.e_lfanew, NULL, FILE_BEGIN) != (DWORD)dh.e_lfanew) {
|
||
|
__leave;
|
||
|
}
|
||
|
if ((!ReadFile (fileHandle, &sign, sizeof (DWORD), &bytesRead, NULL)) ||
|
||
|
(bytesRead != sizeof (DWORD))
|
||
|
) {
|
||
|
__leave;
|
||
|
}
|
||
|
|
||
|
if (sign == IMAGE_PE_SIGNATURE) {
|
||
|
ModuleImage->ModuleType = W32_MODULE;
|
||
|
result = MapAndLoad ((PSTR)ModuleName, NULL, &ModuleImage->ModuleData.W32Data.Image, FALSE, TRUE);
|
||
|
}
|
||
|
if (*signNE == IMAGE_NE_SIGNATURE) {
|
||
|
ModuleImage->ModuleType = W16_MODULE;
|
||
|
ModuleImage->ModuleData.W16Data.Image = MapFileIntoMemory (
|
||
|
ModuleName,
|
||
|
&ModuleImage->ModuleData.W16Data.FileHandle,
|
||
|
&ModuleImage->ModuleData.W16Data.MapHandle
|
||
|
);
|
||
|
if (SetFilePointer (fileHandle, dh.e_lfanew, NULL, FILE_BEGIN) != (DWORD)dh.e_lfanew) {
|
||
|
__leave;
|
||
|
}
|
||
|
if ((!ReadFile (fileHandle, &ModuleImage->ModuleData.W16Data.Neh, sizeof (NE_HEADER), &bytesRead, NULL)) ||
|
||
|
(bytesRead != sizeof (NE_HEADER))
|
||
|
) {
|
||
|
__leave;
|
||
|
}
|
||
|
MYASSERT (ModuleImage->ModuleData.W16Data.Neh.Magic == IMAGE_NE_SIGNATURE);
|
||
|
result = (ModuleImage->ModuleData.W16Data.Image != NULL);
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
if (fileHandle != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle (fileHandle);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
CloseHandle (fileHandle);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
UnloadModuleData (
|
||
|
IN OUT PMODULE_IMAGE ModuleImage
|
||
|
)
|
||
|
{
|
||
|
switch (ModuleImage->ModuleType) {
|
||
|
case W32_MODULE:
|
||
|
UnMapAndLoad (&ModuleImage->ModuleData.W32Data.Image);
|
||
|
break;
|
||
|
case W16_MODULE:
|
||
|
UnmapFile (
|
||
|
(PVOID) ModuleImage->ModuleData.W16Data.Image,
|
||
|
ModuleImage->ModuleData.W16Data.FileHandle,
|
||
|
ModuleImage->ModuleData.W16Data.MapHandle
|
||
|
);
|
||
|
break;
|
||
|
default:;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetExeType (
|
||
|
IN PCTSTR ModuleName
|
||
|
)
|
||
|
{
|
||
|
MODULE_IMAGE moduleImage;
|
||
|
DWORD result = EXE_UNKNOWN;
|
||
|
DWORD d;
|
||
|
|
||
|
__try {
|
||
|
if (!LoadModuleData (ModuleName, &moduleImage)) {
|
||
|
LOG ((LOG_WARNING, DBG_MODULES":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
|
||
|
__leave;
|
||
|
}
|
||
|
if (moduleImage.ModuleType == W32_MODULE) {
|
||
|
d = moduleImage.ModuleData.W32Data.Image.Characteristics;
|
||
|
result = (d & IMAGE_FILE_DLL) ? EXE_WIN32_DLL : EXE_WIN32_APP;
|
||
|
} else if (moduleImage.ModuleType == W16_MODULE) {
|
||
|
result = (moduleImage.ModuleData.W16Data.Neh.Flags & WIN16_LIBRARY) ? EXE_WIN16_DLL : EXE_WIN16_APP;
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
UnloadModuleData (&moduleImage);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsNtCompatibleModule (
|
||
|
IN PCTSTR ModuleName
|
||
|
)
|
||
|
{
|
||
|
if (CheckModule (ModuleName, NULL) == MODULESTATUS_BAD) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// other tests?
|
||
|
//
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
PTSTR
|
||
|
pBuildModulePaths (
|
||
|
IN PCTSTR ModuleName,
|
||
|
IN PCTSTR AppPaths OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
PTSTR currentPaths;
|
||
|
HKEY appPathsKey, currentAppKey;
|
||
|
REGKEY_ENUM appPathsEnum;
|
||
|
PCTSTR appPathsValue;
|
||
|
PTSTR appPathValueExp;
|
||
|
PATH_ENUM pathEnum;
|
||
|
DWORD attrib;
|
||
|
PTSTR pathsPtr;
|
||
|
TCHAR modulePath[MAX_PATH];
|
||
|
BOOL b;
|
||
|
|
||
|
StringCopy (modulePath, ModuleName);
|
||
|
pathsPtr = (PTSTR)GetFileNameFromPath (modulePath);
|
||
|
MYASSERT (pathsPtr && *(pathsPtr - 1) == TEXT('\\'));
|
||
|
*(pathsPtr - 1) = 0;
|
||
|
|
||
|
if (AppPaths) {
|
||
|
currentPaths = DuplicateText (AppPaths);
|
||
|
b = FALSE;
|
||
|
if (EnumFirstPathEx (&pathEnum, currentPaths, NULL, NULL, FALSE)) {
|
||
|
do {
|
||
|
if (StringIMatch (pathEnum.PtrCurrPath, modulePath)) {
|
||
|
b = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
} while (EnumNextPath (&pathEnum));
|
||
|
}
|
||
|
|
||
|
if (!b) {
|
||
|
pathsPtr = JoinTextEx (NULL, modulePath, currentPaths, ";", 0, NULL);
|
||
|
FreeText (currentPaths);
|
||
|
currentPaths = pathsPtr;
|
||
|
}
|
||
|
} else {
|
||
|
currentPaths = DuplicateText (modulePath);
|
||
|
}
|
||
|
|
||
|
appPathsKey = OpenRegKeyStr (S_SKEY_APP_PATHS);
|
||
|
if (appPathsKey != NULL) {
|
||
|
currentAppKey = OpenRegKey (appPathsKey, GetFileNameFromPath (ModuleName));
|
||
|
if (currentAppKey != NULL) {
|
||
|
|
||
|
appPathsValue = GetRegValueString (currentAppKey, TEXT("Path"));
|
||
|
|
||
|
if (appPathsValue) {
|
||
|
|
||
|
if (EnumFirstPathEx (&pathEnum, appPathsValue, NULL, NULL, FALSE)) {
|
||
|
do {
|
||
|
MYASSERT (*pathEnum.PtrCurrPath != 0);
|
||
|
appPathValueExp = ExpandEnvironmentTextA(pathEnum.PtrCurrPath);
|
||
|
|
||
|
_mbsctrim (appPathValueExp, '\\');
|
||
|
|
||
|
attrib = QuietGetFileAttributes (appPathValueExp);
|
||
|
|
||
|
if ((attrib != INVALID_ATTRIBUTES) &&
|
||
|
((attrib & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
|
||
|
) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
pathsPtr = JoinTextEx (NULL, currentPaths, appPathValueExp, ";", 0, NULL);
|
||
|
FreeText (currentPaths);
|
||
|
currentPaths = pathsPtr;
|
||
|
|
||
|
FreeText (appPathValueExp);
|
||
|
}
|
||
|
while (EnumNextPath (&pathEnum));
|
||
|
}
|
||
|
|
||
|
MemFree (g_hHeap, 0, appPathsValue);
|
||
|
}
|
||
|
|
||
|
appPathsValue = GetRegValueString (currentAppKey, TEXT("UpdatesPath"));
|
||
|
|
||
|
if (appPathsValue) {
|
||
|
|
||
|
if (EnumFirstPathEx (&pathEnum, appPathsValue, NULL, NULL, FALSE)) {
|
||
|
do {
|
||
|
MYASSERT (*pathEnum.PtrCurrPath != 0);
|
||
|
appPathValueExp = ExpandEnvironmentTextA(pathEnum.PtrCurrPath);
|
||
|
|
||
|
_mbsctrim (appPathValueExp, '\\');
|
||
|
|
||
|
attrib = QuietGetFileAttributes (appPathValueExp);
|
||
|
|
||
|
if ((attrib != INVALID_ATTRIBUTES) &&
|
||
|
((attrib & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
|
||
|
) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
pathsPtr = JoinTextEx (NULL, currentPaths, appPathValueExp, ";", 0, NULL);
|
||
|
FreeText (currentPaths);
|
||
|
currentPaths = pathsPtr;
|
||
|
|
||
|
FreeText (appPathValueExp);
|
||
|
}
|
||
|
while (EnumNextPath (&pathEnum));
|
||
|
}
|
||
|
|
||
|
MemFree (g_hHeap, 0, appPathsValue);
|
||
|
}
|
||
|
|
||
|
CloseRegKey (currentAppKey);
|
||
|
}
|
||
|
CloseRegKey (appPathsKey);
|
||
|
}
|
||
|
|
||
|
return currentPaths;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EnumNextImport16 (
|
||
|
IN OUT PIMPORT_ENUM16 ModuleImports
|
||
|
)
|
||
|
{
|
||
|
PCSTR currSegmentOffset,importPtr;
|
||
|
PWORD moduleNameOffset;
|
||
|
BOOL itemFound;
|
||
|
|
||
|
ModuleImports->RelocItem ++;
|
||
|
ModuleImports->CurrRelocItem ++;
|
||
|
|
||
|
itemFound = FALSE;
|
||
|
|
||
|
while ((ModuleImports->CurrSegEntry <= ModuleImports->NeHeader->NumEntriesSegTable) && (!itemFound)) {
|
||
|
|
||
|
if (((ModuleImports->SegmentEntry->SegmentFlags & SEG_CODE_MASK ) == SEG_CODE ) &&
|
||
|
((ModuleImports->SegmentEntry->SegmentFlags & SEG_RELOC_MASK ) == SEG_RELOC ) &&
|
||
|
((ModuleImports->SegmentEntry->SegmentFlags & SEG_PRELOAD_MASK) == SEG_PRELOAD)
|
||
|
) {
|
||
|
__try {
|
||
|
|
||
|
while ((ModuleImports->CurrRelocItem <= *(ModuleImports->CurrNrReloc)) && (!itemFound)) {
|
||
|
|
||
|
if (((ModuleImports->RelocItem->AddressType == 0) ||
|
||
|
(ModuleImports->RelocItem->AddressType == 2) ||
|
||
|
(ModuleImports->RelocItem->AddressType == 3) ||
|
||
|
(ModuleImports->RelocItem->AddressType == 5) ||
|
||
|
(ModuleImports->RelocItem->AddressType == 11) ||
|
||
|
(ModuleImports->RelocItem->AddressType == 13)
|
||
|
) &&
|
||
|
((ModuleImports->RelocItem->RelocType == RELOC_IMPORTED_ORDINAL) ||
|
||
|
(ModuleImports->RelocItem->RelocType == RELOC_IMPORTED_NAME )
|
||
|
)
|
||
|
) {
|
||
|
itemFound = TRUE;
|
||
|
moduleNameOffset = (PWORD) (ModuleImports->Image +
|
||
|
ModuleImports->DosHeader->e_lfanew +
|
||
|
ModuleImports->NeHeader->ModuleTableOffset +
|
||
|
(ModuleImports->RelocItem->ModuleOffset - 1) * sizeof (WORD));
|
||
|
importPtr = ModuleImports->Image +
|
||
|
ModuleImports->DosHeader->e_lfanew +
|
||
|
ModuleImports->NeHeader->ImportedTableOffset +
|
||
|
*moduleNameOffset;
|
||
|
strncpy (ModuleImports->ImportModule, importPtr + 1, (BYTE)importPtr[0]);
|
||
|
ModuleImports->ImportModule[(BYTE)importPtr[0]] = 0;
|
||
|
|
||
|
if (ModuleImports->RelocItem->RelocType == RELOC_IMPORTED_ORDINAL) {
|
||
|
ModuleImports->ImportFunction[0] = 0;
|
||
|
ModuleImports->ImportFunctionOrd = ModuleImports->RelocItem->FunctionOffset;
|
||
|
}
|
||
|
else {
|
||
|
importPtr = ModuleImports->Image +
|
||
|
ModuleImports->DosHeader->e_lfanew +
|
||
|
ModuleImports->NeHeader->ImportedTableOffset +
|
||
|
ModuleImports->RelocItem->FunctionOffset;
|
||
|
strncpy (ModuleImports->ImportFunction, importPtr + 1, (BYTE)importPtr[0]);
|
||
|
ModuleImports->ImportFunction[(BYTE)importPtr[0]] = 0;
|
||
|
ModuleImports->ImportFunctionOrd = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!itemFound) {
|
||
|
ModuleImports->RelocItem ++;
|
||
|
ModuleImports->CurrRelocItem ++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__except (1) {
|
||
|
itemFound = FALSE;
|
||
|
}
|
||
|
}
|
||
|
if (!itemFound) {
|
||
|
ModuleImports->SegmentEntry ++;
|
||
|
ModuleImports->CurrSegEntry ++;
|
||
|
|
||
|
currSegmentOffset = ModuleImports->Image +
|
||
|
(ModuleImports->SegmentEntry->SegmentOffset << ModuleImports->NeHeader->ShiftCount);
|
||
|
if (ModuleImports->SegmentEntry->SegmentLen == 0) {
|
||
|
currSegmentOffset += 65535;
|
||
|
}
|
||
|
else {
|
||
|
currSegmentOffset += ModuleImports->SegmentEntry->SegmentLen;
|
||
|
}
|
||
|
ModuleImports->CurrNrReloc = (PWORD) currSegmentOffset;
|
||
|
currSegmentOffset += sizeof(WORD);
|
||
|
|
||
|
ModuleImports->RelocItem = (PNE_RELOC_ITEM) currSegmentOffset;
|
||
|
|
||
|
ModuleImports->CurrRelocItem = 1;
|
||
|
}
|
||
|
}
|
||
|
return itemFound;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
EnumFirstImport16 (
|
||
|
IN PCSTR ModuleImage,
|
||
|
IN OUT PIMPORT_ENUM16 ModuleImports
|
||
|
)
|
||
|
{
|
||
|
PCSTR currSegmentOffset;
|
||
|
|
||
|
ZeroMemory (ModuleImports, sizeof (IMPORT_ENUM16));
|
||
|
|
||
|
ModuleImports->Image = ModuleImage;
|
||
|
|
||
|
ModuleImports->DosHeader = (PDOS_HEADER) (ModuleImports->Image);
|
||
|
ModuleImports->NeHeader = (PNE_HEADER) (ModuleImports->Image + ModuleImports->DosHeader->e_lfanew);
|
||
|
|
||
|
ModuleImports->SegmentEntry = (PNE_SEGMENT_ENTRY) (ModuleImports->Image +
|
||
|
ModuleImports->DosHeader->e_lfanew +
|
||
|
ModuleImports->NeHeader->SegTableOffset
|
||
|
);
|
||
|
ModuleImports->CurrSegEntry = 1;
|
||
|
|
||
|
currSegmentOffset = ModuleImports->Image +
|
||
|
(ModuleImports->SegmentEntry->SegmentOffset << ModuleImports->NeHeader->ShiftCount);
|
||
|
if (ModuleImports->SegmentEntry->SegmentLen == 0) {
|
||
|
currSegmentOffset += 65535;
|
||
|
}
|
||
|
else {
|
||
|
currSegmentOffset += ModuleImports->SegmentEntry->SegmentLen;
|
||
|
}
|
||
|
ModuleImports->CurrNrReloc = (PWORD) currSegmentOffset;
|
||
|
currSegmentOffset += sizeof(WORD);
|
||
|
|
||
|
ModuleImports->RelocItem = (PNE_RELOC_ITEM) currSegmentOffset;
|
||
|
|
||
|
ModuleImports->CurrRelocItem = 1;
|
||
|
|
||
|
ModuleImports->RelocItem --;
|
||
|
ModuleImports->CurrRelocItem --;
|
||
|
|
||
|
return EnumNextImport16 (ModuleImports);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EnumNextImportFunction32 (
|
||
|
IN OUT PIMPORT_ENUM32 ModuleImports
|
||
|
)
|
||
|
{
|
||
|
if (ModuleImports->ImportFunctionAddr == 0) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
ModuleImports->ImageData = (PIMAGE_THUNK_DATA)
|
||
|
ImageRvaToVa (
|
||
|
ModuleImports->Image->FileHeader,
|
||
|
ModuleImports->Image->MappedAddress,
|
||
|
ModuleImports->ImportFunctionAddr,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (ModuleImports->ImageData->u1.AddressOfData) {
|
||
|
ModuleImports->ImageName = (PIMAGE_IMPORT_BY_NAME)
|
||
|
ImageRvaToVa (
|
||
|
ModuleImports->Image->FileHeader,
|
||
|
ModuleImports->Image->MappedAddress,
|
||
|
(DWORD)ModuleImports->ImageData->u1.AddressOfData,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (ModuleImports->ImageName) { //import by name
|
||
|
|
||
|
ModuleImports->ImportFunction = ModuleImports->ImageName->Name;
|
||
|
ModuleImports->ImportFunctionOrd = 0;
|
||
|
}
|
||
|
else { //import by number
|
||
|
|
||
|
ModuleImports->ImportFunction = NULL;
|
||
|
ModuleImports->ImportFunctionOrd = ModuleImports->ImageData->u1.Ordinal & (~0x80000000);
|
||
|
}
|
||
|
ModuleImports->ImportFunctionAddr += 4;
|
||
|
return TRUE;
|
||
|
}
|
||
|
else {
|
||
|
ModuleImports->ImportFunctionAddr = 0;
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EnumFirstImportFunction32 (
|
||
|
IN OUT PIMPORT_ENUM32 ModuleImports
|
||
|
)
|
||
|
{
|
||
|
if ((ModuleImports->ImageDescriptor == NULL) ||
|
||
|
(ModuleImports->ImportModule == NULL)
|
||
|
) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
ModuleImports->ImportFunctionAddr = ModuleImports->ImageDescriptor->OriginalFirstThunk;
|
||
|
|
||
|
return EnumNextImportFunction32 (ModuleImports);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EnumNextImportModule32 (
|
||
|
IN OUT PIMPORT_ENUM32 ModuleImports
|
||
|
)
|
||
|
{
|
||
|
if (ModuleImports->ImageDescriptor == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ModuleImports->ImageDescriptor ++;
|
||
|
|
||
|
if (ModuleImports->ImageDescriptor->Name == 0) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
ModuleImports->ImportModule = (PCSTR) ImageRvaToVa (
|
||
|
ModuleImports->Image->FileHeader,
|
||
|
ModuleImports->Image->MappedAddress,
|
||
|
ModuleImports->ImageDescriptor->Name,
|
||
|
NULL
|
||
|
);
|
||
|
return (ModuleImports->ImportModule != NULL);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
EnumFirstImportModule32 (
|
||
|
IN PLOADED_IMAGE ModuleImage,
|
||
|
IN OUT PIMPORT_ENUM32 ModuleImports
|
||
|
)
|
||
|
{
|
||
|
ULONG imageSize;
|
||
|
|
||
|
ZeroMemory (ModuleImports, sizeof (IMPORT_ENUM32));
|
||
|
|
||
|
ModuleImports->Image = ModuleImage;
|
||
|
|
||
|
ModuleImports->ImageDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)
|
||
|
ImageDirectoryEntryToData (
|
||
|
ModuleImage->MappedAddress,
|
||
|
FALSE,
|
||
|
IMAGE_DIRECTORY_ENTRY_IMPORT,
|
||
|
&imageSize
|
||
|
);
|
||
|
if (!ModuleImports->ImageDescriptor) {
|
||
|
LOG((LOG_WARNING, DBG_MODULES":Cannot load import directory for %s", ModuleImage->ModuleName));
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (ModuleImports->ImageDescriptor->Name == 0) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
ModuleImports->ImportModule = (PCSTR) ImageRvaToVa (
|
||
|
ModuleImports->Image->FileHeader,
|
||
|
ModuleImports->Image->MappedAddress,
|
||
|
ModuleImports->ImageDescriptor->Name,
|
||
|
NULL
|
||
|
);
|
||
|
return (ModuleImports->ImportModule != NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
pCheckDependency (
|
||
|
IN PCSTR CurrentPaths,
|
||
|
IN PCSTR ModuleImported)
|
||
|
{
|
||
|
PSTR tempName = NULL;
|
||
|
DWORD memDbValue = 0;
|
||
|
PATH_ENUM pathEnum;
|
||
|
DWORD result = MODULESTATUS_FILENOTFOUND;
|
||
|
DWORD moduleStatus;
|
||
|
|
||
|
pathEnum.BufferPtr = NULL;
|
||
|
|
||
|
if (EnumFirstPath (&pathEnum, CurrentPaths, g_WinDir, g_SystemDir)) {
|
||
|
__try {
|
||
|
do {
|
||
|
if (*pathEnum.PtrCurrPath == 0) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
tempName = JoinPathsA (pathEnum.PtrCurrPath, ModuleImported);
|
||
|
if (SizeOfStringA (tempName) > MAX_PATH) {
|
||
|
//
|
||
|
// path too long, ignore it
|
||
|
//
|
||
|
FreePathStringA (tempName);
|
||
|
tempName = NULL;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
|
||
|
MemDbBuildKey (g_TempKey, MEMDB_CATEGORY_MODULE_CHECK, tempName, NULL, NULL);
|
||
|
if (MemDbGetValue (g_TempKey, &memDbValue)) {
|
||
|
if ((memDbValue == MODULESTATUS_CHECKED ) ||
|
||
|
(memDbValue == MODULESTATUS_CHECKING)) {
|
||
|
result = MODULESTATUS_CHECKED;
|
||
|
__leave;
|
||
|
}
|
||
|
if (memDbValue == MODULESTATUS_NT_MODULE){
|
||
|
result = MODULESTATUS_NT_MODULE;
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
moduleStatus = GetFileStatusOnNt (tempName);
|
||
|
|
||
|
if ((moduleStatus & FILESTATUS_DELETED) == 0) {
|
||
|
if ((moduleStatus & FILESTATUS_REPLACED) == FILESTATUS_REPLACED) {
|
||
|
result = MODULESTATUS_NT_MODULE;
|
||
|
__leave;
|
||
|
}
|
||
|
if (DoesFileExist (tempName)) {
|
||
|
result = CheckModule (tempName, CurrentPaths);
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
if (moduleStatus & FILESTATUS_NTINSTALLED) {
|
||
|
result = MODULESTATUS_NT_MODULE;
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
while (EnumNextPath (&pathEnum));
|
||
|
}
|
||
|
__finally {
|
||
|
EnumPathAbort (&pathEnum);
|
||
|
if (tempName) {
|
||
|
FreePathStringA (tempName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
pIsWin9xModule (
|
||
|
IN PCTSTR ModuleName
|
||
|
)
|
||
|
{
|
||
|
MEMDB_ENUM me;
|
||
|
MemDbBuildKey (g_TempKey, MEMDB_CATEGORY_WIN9X_APIS, ModuleName, TEXT("*"), NULL);
|
||
|
return MemDbEnumFirstValue (&me, g_TempKey, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
pCheckPEModule (
|
||
|
IN PCSTR CurrentPaths,
|
||
|
IN PLOADED_IMAGE ModuleImage
|
||
|
)
|
||
|
{
|
||
|
IMPORT_ENUM32 e;
|
||
|
DWORD result;
|
||
|
|
||
|
if (EnumFirstImportModule32 (ModuleImage, &e)) {
|
||
|
do {
|
||
|
result = pCheckDependency (CurrentPaths, e.ImportModule);
|
||
|
if (result == MODULESTATUS_BAD) {
|
||
|
LOG((
|
||
|
LOG_WARNING,
|
||
|
"%s will be incompatible because %s is incompatible",
|
||
|
ModuleImage->ModuleName,
|
||
|
e.ImportModule));
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
if (result == MODULESTATUS_NT_MODULE) {
|
||
|
|
||
|
if (pIsWin9xModule (e.ImportModule)) {
|
||
|
|
||
|
if (EnumFirstImportFunction32 (&e)) {
|
||
|
do {
|
||
|
if (e.ImportFunction) {
|
||
|
|
||
|
MemDbBuildKey (g_TempKey, MEMDB_CATEGORY_WIN9X_APIS, e.ImportModule, e.ImportFunction, NULL);
|
||
|
if (MemDbGetValue (g_TempKey, NULL)) {
|
||
|
LOG((
|
||
|
LOG_WARNING,
|
||
|
"%s will be incompatible because %s export will not be available in %s",
|
||
|
ModuleImage->ModuleName,
|
||
|
e.ImportFunction,
|
||
|
e.ImportModule));
|
||
|
return MODULESTATUS_BAD;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
wsprintf (g_TempKey, "%s\\%s\\%lu", MEMDB_CATEGORY_WIN9X_APIS, e.ImportModule, e.ImportFunctionOrd);
|
||
|
if (MemDbGetValue (g_TempKey, NULL)) {
|
||
|
LOG((
|
||
|
LOG_WARNING,
|
||
|
"%s will be incompatible because export index %lu will point to a different export in %s",
|
||
|
ModuleImage->ModuleName,
|
||
|
e.ImportFunctionOrd,
|
||
|
e.ImportModule));
|
||
|
return MODULESTATUS_BAD;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (EnumNextImportFunction32 (&e));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (result == MODULESTATUS_FILENOTFOUND) {
|
||
|
LOG ((
|
||
|
LOG_WARNING,
|
||
|
"Dependency %s of %s not found",
|
||
|
e.ImportModule,
|
||
|
ModuleImage->ModuleName
|
||
|
));
|
||
|
}
|
||
|
}
|
||
|
while (EnumNextImportModule32 (&e));
|
||
|
}
|
||
|
return MODULESTATUS_CHECKED;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
pCheckDependency16 (
|
||
|
IN PCSTR CurrentPaths,
|
||
|
IN OUT PCSTR ModuleImported
|
||
|
)
|
||
|
{
|
||
|
PCTSTR moduleImported;
|
||
|
DWORD result = MODULESTATUS_BAD;
|
||
|
DWORD memDbValue;
|
||
|
|
||
|
MemDbBuildKey (g_TempKey, MEMDB_CATEGORY_MODULE_CHECK, ModuleImported, NULL, NULL);
|
||
|
if (MemDbGetValue (g_TempKey, &memDbValue)) {
|
||
|
if ((memDbValue == MODULESTATUS_CHECKED ) ||
|
||
|
(memDbValue == MODULESTATUS_CHECKING)) {
|
||
|
result = MODULESTATUS_CHECKED;
|
||
|
}
|
||
|
if (memDbValue == MODULESTATUS_NT_MODULE){
|
||
|
result = MODULESTATUS_NT_MODULE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (result != MODULESTATUS_BAD) {
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
moduleImported = JoinText (ModuleImported, ".DLL");
|
||
|
result = pCheckDependency (CurrentPaths, moduleImported);
|
||
|
FreeText (moduleImported);
|
||
|
|
||
|
if (result != MODULESTATUS_BAD) {
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
moduleImported = JoinText (ModuleImported, ".EXE");
|
||
|
result = pCheckDependency (CurrentPaths, moduleImported);
|
||
|
FreeText (moduleImported);
|
||
|
|
||
|
if (result != MODULESTATUS_BAD) {
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
moduleImported = JoinText (ModuleImported, ".DRV");
|
||
|
result = pCheckDependency (CurrentPaths, moduleImported);
|
||
|
FreeText (moduleImported);
|
||
|
|
||
|
if (result != MODULESTATUS_BAD) {
|
||
|
return result;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
pCheckNEModule (
|
||
|
IN PCSTR CurrentPaths,
|
||
|
IN PCSTR ModuleName,
|
||
|
IN PCSTR ModuleImage
|
||
|
)
|
||
|
{
|
||
|
IMPORT_ENUM16 e;
|
||
|
DWORD result;
|
||
|
DWORD memDbValue;
|
||
|
|
||
|
if (EnumFirstImport16 (ModuleImage, &e)) {
|
||
|
do {
|
||
|
if (e.ImportModule [0] != 0) {
|
||
|
result = pCheckDependency16 (CurrentPaths, e.ImportModule);
|
||
|
if (result == MODULESTATUS_BAD) {
|
||
|
LOG((
|
||
|
LOG_WARNING,
|
||
|
"%s will be incompatible because %s is incompatible",
|
||
|
ModuleName,
|
||
|
e.ImportModule));
|
||
|
return result;
|
||
|
}
|
||
|
if (result == MODULESTATUS_NT_MODULE) {
|
||
|
|
||
|
if (e.ImportFunctionOrd) {
|
||
|
//import by ordinal
|
||
|
wsprintf (g_TempKey, "%s\\%s\\%lu", MEMDB_CATEGORY_WIN9X_APIS, e.ImportModule, e.ImportFunctionOrd);
|
||
|
if (MemDbGetValue (g_TempKey, NULL)) {
|
||
|
LOG((
|
||
|
LOG_WARNING,
|
||
|
"%s will be incompatible because export index %lu will point to a different export in %s",
|
||
|
ModuleName,
|
||
|
e.ImportFunctionOrd,
|
||
|
e.ImportModule));
|
||
|
return MODULESTATUS_BAD;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
//import by name
|
||
|
MemDbBuildKey (g_TempKey, MEMDB_CATEGORY_WIN9X_APIS, e.ImportModule, e.ImportFunction, NULL);
|
||
|
if (MemDbGetValue (g_TempKey, &memDbValue)) {
|
||
|
LOG((
|
||
|
LOG_WARNING,
|
||
|
"%s will be incompatible because %s export will not be available in %s",
|
||
|
ModuleName,
|
||
|
e.ImportFunction,
|
||
|
e.ImportModule));
|
||
|
return MODULESTATUS_BAD;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (EnumNextImport16 (&e));
|
||
|
}
|
||
|
return MODULESTATUS_CHECKED;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
pCheckModule (
|
||
|
IN PCSTR ModuleName,
|
||
|
IN PCSTR AppPaths OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
MODULE_IMAGE moduleImage;
|
||
|
DWORD result = MODULESTATUS_CHECKED;
|
||
|
PTSTR CurrentPaths = NULL;
|
||
|
|
||
|
__try {
|
||
|
if (!LoadModuleData (ModuleName, &moduleImage)) {
|
||
|
LOG((LOG_WARNING, DBG_MODULES":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
|
||
|
__leave;
|
||
|
}
|
||
|
__try {
|
||
|
|
||
|
CurrentPaths = pBuildModulePaths (ModuleName, AppPaths);
|
||
|
|
||
|
switch (moduleImage.ModuleType) {
|
||
|
case DOS_MODULE:
|
||
|
DEBUGMSG((DBG_MODULES, "Examining %s : DOS module.", ModuleName));
|
||
|
break;
|
||
|
case W16_MODULE:
|
||
|
DEBUGMSG((DBG_MODULES, "Examining %s : W16 module.", ModuleName));
|
||
|
result = pCheckNEModule (CurrentPaths, ModuleName, moduleImage.ModuleData.W16Data.Image);
|
||
|
break;
|
||
|
case W32_MODULE:
|
||
|
DEBUGMSG((DBG_MODULES, "Examining %s : W32 module.", ModuleName));
|
||
|
result = pCheckPEModule (CurrentPaths, &moduleImage.ModuleData.W32Data.Image);
|
||
|
break;
|
||
|
default:
|
||
|
DEBUGMSG((DBG_MODULES, "Examining %s : Unknown module type.", ModuleName));
|
||
|
}
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
DWORD rc = _exception_code();
|
||
|
DEBUGMSG((DBG_WARNING, DBG_MODULES":Access violation while checking %s (ec=%#x)", ModuleName, rc));
|
||
|
result = MODULESTATUS_CHECKED;
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
UnloadModuleData (&moduleImage);
|
||
|
if (CurrentPaths) {
|
||
|
FreeText (CurrentPaths);
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetModuleType (
|
||
|
IN PCSTR ModuleName
|
||
|
)
|
||
|
{
|
||
|
MODULE_IMAGE moduleImage;
|
||
|
DWORD result = UNKNOWN_MODULE;
|
||
|
|
||
|
__try {
|
||
|
if (!LoadModuleData (ModuleName, &moduleImage)) {
|
||
|
LOG((LOG_WARNING, DBG_MODULES":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
|
||
|
__leave;
|
||
|
}
|
||
|
result = moduleImage.ModuleType;
|
||
|
}
|
||
|
__finally {
|
||
|
UnloadModuleData (&moduleImage);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCSTR
|
||
|
Get16ModuleDescription (
|
||
|
IN PCSTR ModuleName
|
||
|
)
|
||
|
{
|
||
|
MODULE_IMAGE moduleImage;
|
||
|
PSTR result = NULL;
|
||
|
|
||
|
PDOS_HEADER dosHeader;
|
||
|
PNE_HEADER neHeader;
|
||
|
PBYTE size;
|
||
|
|
||
|
__try {
|
||
|
if (!LoadModuleData (ModuleName, &moduleImage)) {
|
||
|
LOG((LOG_WARNING, DBG_MODULES":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
|
||
|
__leave;
|
||
|
}
|
||
|
if (moduleImage.ModuleType != W16_MODULE) {
|
||
|
__leave;
|
||
|
}
|
||
|
__try {
|
||
|
dosHeader = (PDOS_HEADER) (moduleImage.ModuleData.W16Data.Image);
|
||
|
neHeader = (PNE_HEADER) (moduleImage.ModuleData.W16Data.Image + dosHeader->e_lfanew);
|
||
|
size = (PBYTE) (moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset);
|
||
|
if (*size == 0) {
|
||
|
__leave;
|
||
|
}
|
||
|
result = AllocPathString (*size + 1);
|
||
|
strncpy (result, moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset + 1, *size);
|
||
|
result [*size] = 0;
|
||
|
}
|
||
|
__except (1) {
|
||
|
DEBUGMSG((DBG_WARNING, DBG_MODULES":Access violation while examining %s.", ModuleName));
|
||
|
if (result != NULL) {
|
||
|
FreePathString (result);
|
||
|
result = NULL;
|
||
|
}
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
UnloadModuleData (&moduleImage);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
PIMAGE_NT_HEADERS
|
||
|
pGetImageNtHeader (
|
||
|
IN PVOID Base
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function returns the address of the NT Header.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Base - Supplies the base of the image.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Returns the address of the NT Header.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PIMAGE_NT_HEADERS NtHeaders;
|
||
|
|
||
|
if (Base != NULL && Base != (PVOID)-1) {
|
||
|
if (((PIMAGE_DOS_HEADER)Base)->e_magic == IMAGE_DOS_SIGNATURE) {
|
||
|
NtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)Base + ((PIMAGE_DOS_HEADER)Base)->e_lfanew);
|
||
|
if (NtHeaders->Signature == IMAGE_NT_SIGNATURE) {
|
||
|
return NtHeaders;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
GetPECheckSum (
|
||
|
IN PCSTR ModuleName
|
||
|
)
|
||
|
{
|
||
|
MODULE_IMAGE moduleImage;
|
||
|
ULONG result = 0;
|
||
|
PIMAGE_NT_HEADERS NtHeaders;
|
||
|
|
||
|
__try {
|
||
|
if (!LoadModuleData (ModuleName, &moduleImage)) {
|
||
|
LOG((LOG_WARNING, DBG_MODULES":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
|
||
|
__leave;
|
||
|
}
|
||
|
if (moduleImage.ModuleType != W32_MODULE) {
|
||
|
__leave;
|
||
|
}
|
||
|
__try {
|
||
|
NtHeaders = pGetImageNtHeader(moduleImage.ModuleData.W32Data.Image.MappedAddress);
|
||
|
if (NtHeaders) {
|
||
|
if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||
|
result = ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum;
|
||
|
} else
|
||
|
if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||
|
result = ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__except (1) {
|
||
|
DEBUGMSG((DBG_WARNING, DBG_MODULES":Access violation while examining %s.", ModuleName));
|
||
|
result = 0;
|
||
|
__leave;
|
||
|
}
|
||
|
}
|
||
|
__finally {
|
||
|
UnloadModuleData (&moduleImage);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CheckModule (
|
||
|
IN PCSTR ModuleName,
|
||
|
IN PCSTR AppPaths OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
DWORD result;
|
||
|
DWORD moduleStatus;
|
||
|
|
||
|
MemDbSetValueEx (MEMDB_CATEGORY_MODULE_CHECK, ModuleName, NULL, NULL, MODULESTATUS_CHECKING, NULL);
|
||
|
|
||
|
g_ModuleRecursionLevel++;
|
||
|
|
||
|
if (g_ModuleRecursionLevel < MAX_MODULE_RECURSION_LEVEL) {
|
||
|
|
||
|
result = pCheckModule (ModuleName, AppPaths);
|
||
|
|
||
|
if (result == MODULESTATUS_BAD) {
|
||
|
|
||
|
moduleStatus = GetFileStatusOnNt (ModuleName);
|
||
|
|
||
|
if ((moduleStatus & FILESTATUS_NTINSTALLED) == FILESTATUS_NTINSTALLED) {
|
||
|
MarkFileForDelete (ModuleName);
|
||
|
result = MODULESTATUS_NT_MODULE;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
result = MODULESTATUS_CHECKED;
|
||
|
}
|
||
|
|
||
|
g_ModuleRecursionLevel--;
|
||
|
|
||
|
MemDbSetValueEx (MEMDB_CATEGORY_MODULE_CHECK, ModuleName, NULL, NULL, result, NULL);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
pProcessModules (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
MEMDB_ENUM enumItems;
|
||
|
PSTR pathsPtr;
|
||
|
DWORD moduleStatus;
|
||
|
|
||
|
DWORD attrib;
|
||
|
LONG stringId;
|
||
|
DWORD status;
|
||
|
DWORD Count = 0;
|
||
|
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("KERNEL32"),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("KERNEL" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("USER32" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("USER" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("GDI32" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("GDI" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("SHELL32" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("SHELL" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("SOUND32" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("SOUND" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("DISPLAY" ),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
MemDbSetValueEx(MEMDB_CATEGORY_MODULE_CHECK,TEXT("KEYBOARD"),NULL,NULL,MODULESTATUS_NT_MODULE,NULL);
|
||
|
|
||
|
MemDbBuildKey (g_TempKey, MEMDB_CATEGORY_MODULE_CHECK, TEXT("*"), NULL, NULL);
|
||
|
|
||
|
if (MemDbEnumFirstValue (&enumItems, g_TempKey, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
|
||
|
do {
|
||
|
|
||
|
if (CANCELLED()) {
|
||
|
SetLastError (ERROR_CANCELLED);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
{
|
||
|
CHAR DbgBuf[256];
|
||
|
|
||
|
if (GetPrivateProfileString ("MigDb", GetFileNameFromPath (enumItems.szName), "", DbgBuf, 256, g_DebugInfPath)) {
|
||
|
DEBUGMSG((DBG_NAUSEA, "Debug point hit in Modules.c"));
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (enumItems.dwValue == MODULESTATUS_UNCHECKED) {
|
||
|
|
||
|
moduleStatus = GetFileStatusOnNt (enumItems.szName);
|
||
|
|
||
|
if ((moduleStatus & FILESTATUS_DELETED) == FILESTATUS_DELETED) {
|
||
|
continue;
|
||
|
}
|
||
|
if ((moduleStatus & FILESTATUS_REPLACED) == FILESTATUS_REPLACED) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
g_ModuleRecursionLevel = 0;
|
||
|
|
||
|
moduleStatus = CheckModule (enumItems.szName, NULL);
|
||
|
|
||
|
if (moduleStatus == MODULESTATUS_BAD) {
|
||
|
|
||
|
status = GetFileStatusOnNt (enumItems.szName);
|
||
|
|
||
|
if (!(status & FILESTATUS_DELETED)) {
|
||
|
RemoveOperationsFromPath (enumItems.szName, ALL_CHANGE_OPERATIONS);
|
||
|
MarkFileForExternalDelete (enumItems.szName);
|
||
|
}
|
||
|
|
||
|
if (!IsFileMarkedForAnnounce (enumItems.szName)) {
|
||
|
AnnounceFileInReport (enumItems.szName, 0, ACT_INC_NOBADAPPS);
|
||
|
}
|
||
|
LOG ((LOG_INFORMATION, (PCSTR)MSG_MODULE_REQUIRES_EXPORT_LOG, enumItems.szName));
|
||
|
}
|
||
|
}
|
||
|
Count++;
|
||
|
if (!(Count % 4)) {
|
||
|
TickProgressBar ();
|
||
|
}
|
||
|
}
|
||
|
while (MemDbEnumNextValue (&enumItems));
|
||
|
}
|
||
|
|
||
|
DEBUGMSG((DBG_MODULES, "Modules checking : ==========================="));
|
||
|
DEBUGMSG((DBG_MODULES, "Number of executables checked : %ld", g_NumEXEs));
|
||
|
DEBUGMSG((DBG_MODULES, "Number of modules in MEMDB tree: %ld", Count));
|
||
|
|
||
|
MemDbDeleteTree (MEMDB_CATEGORY_MODULE_CHECK);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ProcessModules (
|
||
|
IN DWORD Request
|
||
|
)
|
||
|
{
|
||
|
switch (Request) {
|
||
|
case REQUEST_QUERYTICKS:
|
||
|
return TICKS_PROCESS_MODULES;
|
||
|
case REQUEST_RUN:
|
||
|
if (!pProcessModules ()) {
|
||
|
return GetLastError ();
|
||
|
}
|
||
|
else {
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
default:
|
||
|
DEBUGMSG ((DBG_ERROR, "Bad parameter in ProcessModules"));
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pPrepareProcessModules (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
PCTSTR TempStr;
|
||
|
|
||
|
TempStr = JoinPaths (g_UpgradeSources, S_E95ONLY_DAT);
|
||
|
|
||
|
MemDbImport (TempStr);
|
||
|
|
||
|
FreePathString (TempStr);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
PrepareProcessModules (
|
||
|
IN DWORD Request
|
||
|
)
|
||
|
{
|
||
|
switch (Request) {
|
||
|
case REQUEST_QUERYTICKS:
|
||
|
return TICKS_PREPARE_PROCESS_MODULES;
|
||
|
case REQUEST_RUN:
|
||
|
if (!pPrepareProcessModules ()) {
|
||
|
return GetLastError ();
|
||
|
}
|
||
|
else {
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
default:
|
||
|
DEBUGMSG ((DBG_ERROR, "Bad parameter in PrepareProcessModules"));
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
SaveExeFiles (
|
||
|
IN PFILE_HELPER_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
if (Params->Handled) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// Save EXE and SCR files to MemDB to enumerate later
|
||
|
if ((StringIMatch (Params->Extension, TEXT(".EXE"))) ||
|
||
|
(StringIMatch (Params->Extension, TEXT(".SCR")))
|
||
|
) {
|
||
|
if (!IsFileMarkedAsKnownGood (Params->FullFileSpec)) {
|
||
|
MemDbSetValueEx (
|
||
|
MEMDB_CATEGORY_MODULE_CHECK,
|
||
|
Params->FullFileSpec,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
MODULESTATUS_UNCHECKED,
|
||
|
NULL);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
g_NumEXEs++;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|