windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upg/migapp/modules.c
2020-09-26 16:20:57 +08:00

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;
}