windows-nt/Source/XPSP1/NT/windows/winstate/cobra/utils/modimage/modimage.c
2020-09-26 16:20:57 +08:00

2264 lines
58 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
modimage.c
Abstract:
Implements a set of routines for examining EXE modules
Author:
Calin Negreanu (calinn) 27-Nov-1997
Revision History:
calinn 08-Mar-2000 Moved over from Win9xUpg project.
--*/
//
// Includes
//
#include "pch.h"
//
// Debug constants
//
#define DBG_MODIMAGE "ModImage"
//
// Strings
//
// None
//
// Constants
//
#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
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
#define IMAGE_NE_SIGNATURE 0x454E // NE
#define IMAGE_PE_SIGNATURE 0x00004550l // PE00
//
// Macros
//
// None
//
// Types
//
#pragma pack(push,1)
typedef struct _DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} DOS_HEADER, *PDOS_HEADER;
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 {
WORD Signature; // 00h
BYTE LinkerVersion; // 02h
BYTE LinkerRevision; // 03h
WORD OffsetToEntryTable; // 04h
WORD LengthOfEntryTable; // 06h
DWORD Reserved; // 08h
WORD Flags; // 0ch
WORD AutoDataSegment; // 0eh
WORD LocalHeapSize; // 10h
WORD StackSize; // 12h
DWORD EntryAddress; // 14h
DWORD StackAddress; // 18h
WORD SegmentTableEntries; // 1ch
WORD ModuleReferenceTableEntries; // 1eh
WORD NonResidentTableSize; // 20h
WORD OffsetToSegmentTable; // 22h
WORD OffsetToResourceTable; // 24h
WORD OffsetToResidentNameTable; // 26h
WORD OffsetToModuleReferenceTable; // 28h
WORD OffsetToImportedNameTable; // 2ah
WORD OffsetToNonResidentNameTable; // 2ch
WORD Unused; // 2eh
WORD MovableEntryPoints; // 30h
WORD LogicalSectorShiftCount; // 32h
WORD ResourceSegments; // 34h
BYTE TargetOS; // 36h
BYTE AdditionalFlags; // 37h
WORD FastLoadOffset; // 38h
WORD SectorsInFastLoad; // 3ah
WORD Reserved2; // 3ch
WORD WindowsVersion; // 3eh
} NE_INFO_BLOCK, *PNE_INFO_BLOCK;
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;
typedef struct {
WORD Offset;
WORD Length;
WORD Flags;
WORD Id;
WORD Handle;
WORD Usage;
} NE_RES_NAMEINFO, *PNE_RES_NAMEINFO;
typedef struct {
WORD TypeId;
WORD ResourceCount;
DWORD Reserved;
NE_RES_NAMEINFO NameInfo[];
} NE_RES_TYPEINFO, *PNE_RES_TYPEINFO;
#pragma pack(pop)
typedef struct {
WORD AlignShift;
GROWLIST TypeInfoArray;
GROWLIST ResourceNames;
} NE_RESOURCES, *PNE_RESOURCES;
typedef struct {
PLOADED_IMAGE Image;
PIMAGE_IMPORT_DESCRIPTOR ImageDescriptor;
DWORD ImportFunctionAddr;
PIMAGE_THUNK_DATA ImageData;
PIMAGE_IMPORT_BY_NAME ImageName;
} MD_IMPORT_ENUM32_HANDLE, *PMD_IMPORT_ENUM32_HANDLE;
typedef struct {
PBYTE Image;
PDOS_HEADER DosHeader;
PNE_HEADER NeHeader;
PNE_SEGMENT_ENTRY SegmentEntry;
WORD CurrSegEntry;
PWORD CurrNrReloc;
PNE_RELOC_ITEM RelocItem;
WORD CurrRelocItem;
} MD_IMPORT_ENUM16_HANDLE, *PMD_IMPORT_ENUM16_HANDLE;
typedef struct {
HANDLE File;
DWORD HeaderOffset;
NE_INFO_BLOCK Header;
NE_RESOURCES Resources;
BOOL ResourcesLoaded;
PMHANDLE ResourcePool;
} NE_HANDLE, *PNE_HANDLE;
typedef BOOL (CALLBACK* ENUMRESTYPEPROCEXA)(HMODULE hModule, PCSTR lpType, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo);
typedef BOOL (CALLBACK* ENUMRESTYPEPROCEXW)(HMODULE hModule, PCWSTR lpType, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo);
typedef BOOL (CALLBACK* ENUMRESNAMEPROCEXA)(HMODULE hModule, PCSTR lpType,
PSTR lpName, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo, PNE_RES_NAMEINFO NameInfo);
typedef BOOL (CALLBACK* ENUMRESNAMEPROCEXW)(HMODULE hModule, PCWSTR lpType,
PWSTR lpName, LONG_PTR lParam, PNE_RES_TYPEINFO TypeInfo, PNE_RES_NAMEINFO NameInfo);
typedef struct {
PCSTR TypeToFind;
PNE_RES_TYPEINFO OutboundTypeInfo;
BOOL Found;
} TYPESEARCHDATAA, *PTYPESEARCHDATAA;
typedef struct {
PCSTR NameToFind;
PNE_RES_TYPEINFO OutboundTypeInfo;
PNE_RES_NAMEINFO OutboundNameInfo;
BOOL Found;
} NAMESEARCHDATAA, *PNAMESEARCHDATAA;
//
// Globals
//
// None
//
// Macro expansion list
//
// None
//
// Private function prototypes
//
// None
//
// Macro expansion definition
//
// None
//
// Code
//
BOOL
MdLoadModuleDataA (
IN PCSTR ModuleName,
OUT PMD_MODULE_IMAGE ModuleImage
)
{
HANDLE fileHandle;
DWORD bytesRead;
DOS_HEADER dh;
DWORD sign;
PWORD signNE = (PWORD)&sign;
BOOL result = FALSE;
ZeroMemory (ModuleImage, sizeof (MD_MODULE_IMAGE));
fileHandle = CreateFileA (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
ModuleImage->ModuleType = MODULETYPE_UNKNOWN;
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 = MODULETYPE_UNKNOWN;
__leave;
}
ModuleImage->ModuleType = MODULETYPE_DOS;
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;
}
CloseHandle (fileHandle);
fileHandle = INVALID_HANDLE_VALUE;
if (sign == IMAGE_PE_SIGNATURE) {
ModuleImage->ModuleType = MODULETYPE_WIN32;
result = MapAndLoad ((PSTR)ModuleName, NULL, &ModuleImage->ModuleData.W32Data.Image, FALSE, TRUE);
}
if (*signNE == IMAGE_NE_SIGNATURE) {
ModuleImage->ModuleType = MODULETYPE_WIN16;
ModuleImage->ModuleData.W16Data.Image = MapFileIntoMemoryA (
ModuleName,
&ModuleImage->ModuleData.W16Data.FileHandle,
&ModuleImage->ModuleData.W16Data.MapHandle
);
result = (ModuleImage->ModuleData.W16Data.Image != NULL);
}
}
__finally {
if (fileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (fileHandle);
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
CloseHandle (fileHandle);
}
return result;
}
BOOL
MdLoadModuleDataW (
IN PCWSTR ModuleName,
OUT PMD_MODULE_IMAGE ModuleImage
)
{
PCSTR moduleNameA;
HANDLE fileHandle;
DWORD bytesRead;
DOS_HEADER dh;
DWORD sign;
PWORD signNE = (PWORD)&sign;
BOOL result = FALSE;
ZeroMemory (ModuleImage, sizeof (MD_MODULE_IMAGE));
fileHandle = CreateFileW (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
ModuleImage->ModuleType = MODULETYPE_UNKNOWN;
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 = MODULETYPE_UNKNOWN;
__leave;
}
ModuleImage->ModuleType = MODULETYPE_DOS;
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;
}
CloseHandle (fileHandle);
fileHandle = INVALID_HANDLE_VALUE;
if (sign == IMAGE_PE_SIGNATURE) {
ModuleImage->ModuleType = MODULETYPE_WIN32;
moduleNameA = ConvertWtoA (ModuleName);
if (moduleNameA) {
result = MapAndLoad ((PSTR) moduleNameA, NULL, &ModuleImage->ModuleData.W32Data.Image, FALSE, TRUE);
FreeConvertedStr (moduleNameA);
}
}
if (*signNE == IMAGE_NE_SIGNATURE) {
ModuleImage->ModuleType = MODULETYPE_WIN16;
ModuleImage->ModuleData.W16Data.Image = MapFileIntoMemoryW (
ModuleName,
&ModuleImage->ModuleData.W16Data.FileHandle,
&ModuleImage->ModuleData.W16Data.MapHandle
);
result = (ModuleImage->ModuleData.W16Data.Image != NULL);
}
}
__finally {
if (fileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (fileHandle);
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
CloseHandle (fileHandle);
}
return result;
}
BOOL
MdUnloadModuleDataA (
IN OUT PMD_MODULE_IMAGE ModuleImage
)
{
switch (ModuleImage->ModuleType) {
case MODULETYPE_WIN32:
UnMapAndLoad (&ModuleImage->ModuleData.W32Data.Image);
break;
case MODULETYPE_WIN16:
UnmapFile (
(PVOID) ModuleImage->ModuleData.W16Data.Image,
ModuleImage->ModuleData.W16Data.FileHandle,
ModuleImage->ModuleData.W16Data.MapHandle
);
break;
default:;
}
return TRUE;
}
BOOL
MdUnloadModuleDataW (
IN OUT PMD_MODULE_IMAGE ModuleImage
)
{
switch (ModuleImage->ModuleType) {
case MODULETYPE_WIN32:
UnMapAndLoad (&ModuleImage->ModuleData.W32Data.Image);
break;
case MODULETYPE_WIN16:
UnmapFile (
(PVOID) ModuleImage->ModuleData.W16Data.Image,
ModuleImage->ModuleData.W16Data.FileHandle,
ModuleImage->ModuleData.W16Data.MapHandle
);
break;
default:;
}
return TRUE;
}
BOOL
MdEnumNextImport16A (
IN OUT PMD_IMPORT_ENUM16A ImportsEnum
)
{
PBYTE currSegmentOffset,importPtr;
PWORD moduleNameOffset;
BOOL itemFound;
PMD_IMPORT_ENUM16_HANDLE handle;
handle = (PMD_IMPORT_ENUM16_HANDLE) ImportsEnum->Handle;
handle->RelocItem ++;
handle->CurrRelocItem ++;
itemFound = FALSE;
while ((handle->CurrSegEntry <= handle->NeHeader->NumEntriesSegTable) && (!itemFound)) {
if (((handle->SegmentEntry->SegmentFlags & SEG_CODE_MASK ) == SEG_CODE ) &&
((handle->SegmentEntry->SegmentFlags & SEG_RELOC_MASK ) == SEG_RELOC ) &&
((handle->SegmentEntry->SegmentFlags & SEG_PRELOAD_MASK) == SEG_PRELOAD)
) {
__try {
while ((handle->CurrRelocItem <= *(handle->CurrNrReloc)) && (!itemFound)) {
if (((handle->RelocItem->AddressType == 0) ||
(handle->RelocItem->AddressType == 2) ||
(handle->RelocItem->AddressType == 3) ||
(handle->RelocItem->AddressType == 5) ||
(handle->RelocItem->AddressType == 11) ||
(handle->RelocItem->AddressType == 13)
) &&
((handle->RelocItem->RelocType == RELOC_IMPORTED_ORDINAL) ||
(handle->RelocItem->RelocType == RELOC_IMPORTED_NAME )
)
) {
itemFound = TRUE;
moduleNameOffset = (PWORD) (handle->Image +
handle->DosHeader->e_lfanew +
handle->NeHeader->ModuleTableOffset +
(handle->RelocItem->ModuleOffset - 1) * sizeof (WORD));
importPtr = handle->Image +
handle->DosHeader->e_lfanew +
handle->NeHeader->ImportedTableOffset +
*moduleNameOffset;
strncpy (ImportsEnum->ImportModule, importPtr + 1, (BYTE)importPtr[0]);
ImportsEnum->ImportModule[(BYTE)importPtr[0]] = 0;
if (handle->RelocItem->RelocType == RELOC_IMPORTED_ORDINAL) {
ImportsEnum->ImportFunction[0] = 0;
ImportsEnum->ImportFunctionOrd = handle->RelocItem->FunctionOffset;
}
else {
importPtr = handle->Image +
handle->DosHeader->e_lfanew +
handle->NeHeader->ImportedTableOffset +
handle->RelocItem->FunctionOffset;
strncpy (ImportsEnum->ImportFunction, importPtr + 1, (BYTE)importPtr[0]);
ImportsEnum->ImportFunction[(BYTE)importPtr[0]] = 0;
ImportsEnum->ImportFunctionOrd = 0;
}
}
if (!itemFound) {
handle->RelocItem ++;
handle->CurrRelocItem ++;
}
}
}
__except (1) {
itemFound = FALSE;
}
}
if (!itemFound) {
handle->SegmentEntry ++;
handle->CurrSegEntry ++;
currSegmentOffset = handle->Image +
(handle->SegmentEntry->SegmentOffset << handle->NeHeader->ShiftCount);
if (handle->SegmentEntry->SegmentLen == 0) {
currSegmentOffset += 65535;
}
else {
currSegmentOffset += handle->SegmentEntry->SegmentLen;
}
handle->CurrNrReloc = (PWORD) currSegmentOffset;
currSegmentOffset += sizeof(WORD);
handle->RelocItem = (PNE_RELOC_ITEM) currSegmentOffset;
handle->CurrRelocItem = 1;
}
}
return itemFound;
}
BOOL
MdEnumFirstImport16A (
IN PBYTE ModuleImage,
IN OUT PMD_IMPORT_ENUM16A ImportsEnum
)
{
PMD_IMPORT_ENUM16_HANDLE handle;
PBYTE currSegmentOffset;
ZeroMemory (ImportsEnum, sizeof (MD_IMPORT_ENUM16A));
ImportsEnum->Handle = MemAlloc (g_hHeap, 0, sizeof (MD_IMPORT_ENUM16_HANDLE));
handle = (PMD_IMPORT_ENUM16_HANDLE) ImportsEnum->Handle;
handle->Image = ModuleImage;
handle->DosHeader = (PDOS_HEADER) (handle->Image);
handle->NeHeader = (PNE_HEADER) (handle->Image + handle->DosHeader->e_lfanew);
handle->SegmentEntry = (PNE_SEGMENT_ENTRY) (handle->Image +
handle->DosHeader->e_lfanew +
handle->NeHeader->SegTableOffset
);
handle->CurrSegEntry = 1;
currSegmentOffset = handle->Image +
(handle->SegmentEntry->SegmentOffset << handle->NeHeader->ShiftCount);
if (handle->SegmentEntry->SegmentLen == 0) {
currSegmentOffset += 65535;
}
else {
currSegmentOffset += handle->SegmentEntry->SegmentLen;
}
handle->CurrNrReloc = (PWORD) currSegmentOffset;
currSegmentOffset += sizeof(WORD);
handle->RelocItem = (PNE_RELOC_ITEM) currSegmentOffset;
handle->CurrRelocItem = 1;
handle->RelocItem --;
handle->CurrRelocItem --;
return MdEnumNextImport16A (ImportsEnum);
}
BOOL
MdAbortImport16EnumA (
IN PMD_IMPORT_ENUM16A ImportsEnum
)
{
if (ImportsEnum->Handle) {
MemFree (g_hHeap, 0, ImportsEnum->Handle);
ImportsEnum->Handle = NULL;
}
return TRUE;
}
BOOL
MdEnumNextImportFunction32A (
IN OUT PMD_IMPORT_ENUM32A ImportsEnum
)
{
PMD_IMPORT_ENUM32_HANDLE handle;
handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
if (handle->ImportFunctionAddr == 0) {
return FALSE;
}
handle->ImageData = (PIMAGE_THUNK_DATA)
ImageRvaToVa (
handle->Image->FileHeader,
handle->Image->MappedAddress,
handle->ImportFunctionAddr,
NULL
);
if (handle->ImageData->u1.AddressOfData) {
handle->ImageName = (PIMAGE_IMPORT_BY_NAME)
ImageRvaToVa (
handle->Image->FileHeader,
handle->Image->MappedAddress,
(DWORD)handle->ImageData->u1.AddressOfData,
NULL
);
if (handle->ImageName) { //import by name
ImportsEnum->ImportFunction = handle->ImageName->Name;
ImportsEnum->ImportFunctionOrd = 0;
}
else { //import by number
ImportsEnum->ImportFunction = NULL;
ImportsEnum->ImportFunctionOrd = (ULONG) handle->ImageData->u1.Ordinal & (~0x80000000);
}
handle->ImportFunctionAddr += 4;
return TRUE;
}
else {
handle->ImportFunctionAddr = 0;
return FALSE;
}
}
BOOL
MdEnumFirstImportFunction32A (
IN OUT PMD_IMPORT_ENUM32A ImportsEnum
)
{
PMD_IMPORT_ENUM32_HANDLE handle;
handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
if ((handle->ImageDescriptor == NULL) ||
(ImportsEnum->ImportModule == NULL)
) {
return FALSE;
}
handle->ImportFunctionAddr = handle->ImageDescriptor->OriginalFirstThunk;
return MdEnumNextImportFunction32A (ImportsEnum);
}
BOOL
MdEnumNextImportModule32A (
IN OUT PMD_IMPORT_ENUM32A ImportsEnum
)
{
PMD_IMPORT_ENUM32_HANDLE handle;
handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
if (handle->ImageDescriptor == NULL) {
return FALSE;
}
handle->ImageDescriptor ++;
if (handle->ImageDescriptor->Name == 0) {
return FALSE;
}
ImportsEnum->ImportModule = (PCSTR)
ImageRvaToVa (
handle->Image->FileHeader,
handle->Image->MappedAddress,
handle->ImageDescriptor->Name,
NULL
);
return (ImportsEnum->ImportModule != NULL);
}
BOOL
MdEnumFirstImportModule32A (
IN PLOADED_IMAGE ModuleImage,
IN OUT PMD_IMPORT_ENUM32A ImportsEnum
)
{
PMD_IMPORT_ENUM32_HANDLE handle;
ULONG imageSize;
ZeroMemory (ImportsEnum, sizeof (MD_IMPORT_ENUM32A));
ImportsEnum->Handle = MemAlloc (g_hHeap, 0, sizeof (MD_IMPORT_ENUM32_HANDLE));
handle = (PMD_IMPORT_ENUM32_HANDLE) ImportsEnum->Handle;
handle->Image = ModuleImage;
handle->ImageDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData (
ModuleImage->MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&imageSize
);
if (!handle->ImageDescriptor) {
DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load import directory for %s", ModuleImage->ModuleName));
return FALSE;
}
if (handle->ImageDescriptor->Name == 0) {
return FALSE;
}
ImportsEnum->ImportModule = (PCSTR)
ImageRvaToVa (
handle->Image->FileHeader,
handle->Image->MappedAddress,
handle->ImageDescriptor->Name,
NULL
);
return (ImportsEnum->ImportModule != NULL);
}
BOOL
MdAbortImport32EnumA (
IN PMD_IMPORT_ENUM32A ImportsEnum
)
{
if (ImportsEnum->Handle) {
MemFree (g_hHeap, 0, ImportsEnum->Handle);
ImportsEnum->Handle = NULL;
}
return TRUE;
}
DWORD
MdGetModuleTypeA (
IN PCSTR ModuleName
)
{
MD_MODULE_IMAGE moduleImage;
DWORD result = MODULETYPE_UNKNOWN;
__try {
if (!MdLoadModuleDataA (ModuleName, &moduleImage)) {
DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
__leave;
}
result = moduleImage.ModuleType;
}
__finally {
MdUnloadModuleDataA (&moduleImage);
}
return result;
}
DWORD
MdGetModuleTypeW (
IN PCWSTR ModuleName
)
{
MD_MODULE_IMAGE moduleImage;
DWORD result = MODULETYPE_UNKNOWN;
__try {
if (!MdLoadModuleDataW (ModuleName, &moduleImage)) {
DEBUGMSGW((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
__leave;
}
result = moduleImage.ModuleType;
}
__finally {
MdUnloadModuleDataW (&moduleImage);
}
return result;
}
PCSTR
MdGet16ModuleDescriptionA (
IN PCSTR ModuleName
)
{
MD_MODULE_IMAGE moduleImage;
PSTR result = NULL;
PDOS_HEADER dosHeader;
PNE_HEADER neHeader;
PBYTE size;
__try {
if (!MdLoadModuleDataA (ModuleName, &moduleImage)) {
DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
__leave;
}
if (moduleImage.ModuleType != MODULETYPE_WIN16) {
__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 = AllocPathStringA (*size + 1);
strncpy (result, moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset + 1, *size);
result [*size] = 0;
}
__except (1) {
DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Access violation while examining %s.", ModuleName));
if (result != NULL) {
FreePathStringA (result);
result = NULL;
}
__leave;
}
}
__finally {
MdUnloadModuleDataA (&moduleImage);
}
return result;
}
PCWSTR
MdGet16ModuleDescriptionW (
IN PCWSTR ModuleName
)
{
MD_MODULE_IMAGE moduleImage;
PSTR resultA = NULL;
PCWSTR tempResult = NULL;
PCWSTR result = NULL;
PDOS_HEADER dosHeader;
PNE_HEADER neHeader;
PBYTE size;
__try {
if (!MdLoadModuleDataW (ModuleName, &moduleImage)) {
DEBUGMSGW((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
__leave;
}
if (moduleImage.ModuleType != MODULETYPE_WIN16) {
__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;
}
resultA = AllocPathStringA (*size + 1);
if (resultA) {
strncpy (resultA, moduleImage.ModuleData.W16Data.Image + neHeader->NonResNameTableOffset + 1, *size);
resultA [*size] = 0;
tempResult = ConvertAtoW (resultA);
if (tempResult) {
result = DuplicatePathStringW (tempResult, 0);
FreeConvertedStr (tempResult);
tempResult = NULL;
}
FreePathStringA (resultA);
resultA = NULL;
}
}
__except (1) {
DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Access violation while examining %s.", ModuleName));
if (result != NULL) {
FreePathStringW (result);
result = NULL;
}
if (tempResult != NULL) {
FreeConvertedStr (tempResult);
tempResult = NULL;
}
if (resultA != NULL) {
FreePathStringA (resultA);
resultA = NULL;
}
__leave;
}
}
__finally {
MdUnloadModuleDataW (&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
MdGetPECheckSumA (
IN PCSTR ModuleName
)
{
MD_MODULE_IMAGE moduleImage;
ULONG result = 0;
PIMAGE_NT_HEADERS NtHeaders;
__try {
if (!MdLoadModuleDataA (ModuleName, &moduleImage)) {
DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Cannot load image for %s. Error:%ld", ModuleName, GetLastError()));
__leave;
}
if (moduleImage.ModuleType != MODULETYPE_WIN32) {
__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) {
DEBUGMSGA((DBG_WARNING, DBG_MODIMAGE":Access violation while examining %s.", ModuleName));
result = 0;
__leave;
}
}
__finally {
MdUnloadModuleDataA (&moduleImage);
}
return result;
}
DWORD
MdGetCheckSumA (
IN PCSTR ModuleName
)
/*++
Routine Description:
GetCheckSum will compute the check sum for 4096 bytes starting at offset 512. The offset and the size of
the chunk are modified if the file size is too small.
Arguments:
ModuleName - Specifies the file to compute the check sum for.
Return value:
The computed checksum
--*/
{
INT i,size = 4096;
DWORD startAddr = 512;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PCHAR buffer = NULL;
DWORD checkSum = 0;
DWORD dontCare;
WIN32_FIND_DATAA findData;
if (!DoesFileExistExA (ModuleName, &findData)) {
return checkSum;
}
if (findData.nFileSizeLow < (ULONG)size) {
//
// File size is less than 4096. We set the start address to 0 and set the size for the checksum
// to the actual file size.
//
startAddr = 0;
size = findData.nFileSizeLow;
}
else
if (startAddr + size > findData.nFileSizeLow) {
//
// File size is too small. We set the start address so that size of checksum can be 4096 bytes
//
startAddr = findData.nFileSizeLow - size;
}
if (size <= 3) {
//
// we need at least 3 bytes to be able to do something here.
//
return 0;
}
__try {
buffer = HeapAlloc (g_hHeap, 0, size);
if (buffer == NULL) {
__leave;
}
fileHandle = CreateFileA (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
__leave;
}
if (SetFilePointer (fileHandle, startAddr, NULL, FILE_BEGIN) != startAddr) {
__leave;
}
if (!ReadFile (fileHandle, buffer, size, &dontCare, NULL)) {
__leave;
}
for (i = 0; i<(size - 3); i+=4) {
checkSum += *((PDWORD) (buffer + i));
checkSum = _rotr (checkSum ,1);
}
}
__finally {
if (fileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (fileHandle);
}
if (buffer != NULL) {
HeapFree (g_hHeap, 0, buffer);
}
}
return checkSum;
}
DWORD
MdGetCheckSumW (
IN PCWSTR ModuleName
)
/*++
Routine Description:
GetCheckSum will compute the check sum for 4096 bytes starting at offset 512. The offset and the size of
the chunk are modified if the file size is too small.
Arguments:
ModuleName - Specifies the file to compute the check sum for.
Return value:
The computed checksum
--*/
{
INT i,size = 4096;
DWORD startAddr = 512;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PCHAR buffer = NULL;
DWORD checkSum = 0;
DWORD dontCare;
WIN32_FIND_DATAW findData;
if (!DoesFileExistExW (ModuleName, &findData)) {
return checkSum;
}
if (findData.nFileSizeLow < (ULONG)size) {
//
// File size is less than 4096. We set the start address to 0 and set the size for the checksum
// to the actual file size.
//
startAddr = 0;
size = findData.nFileSizeLow;
}
else
if (startAddr + size > findData.nFileSizeLow) {
//
// File size is too small. We set the start address so that size of checksum can be 4096 bytes
//
startAddr = findData.nFileSizeLow - size;
}
if (size <= 3) {
//
// we need at least 3 bytes to be able to do something here.
//
return 0;
}
__try {
buffer = HeapAlloc (g_hHeap, 0, size);
if (buffer == NULL) {
__leave;
}
fileHandle = CreateFileW (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
__leave;
}
if (SetFilePointer (fileHandle, startAddr, NULL, FILE_BEGIN) != startAddr) {
__leave;
}
if (!ReadFile (fileHandle, buffer, size, &dontCare, NULL)) {
__leave;
}
for (i = 0; i<(size - 3); i+=4) {
checkSum += *((PDWORD) (buffer + i));
checkSum = _rotr (checkSum ,1);
}
}
__finally {
if (fileHandle != INVALID_HANDLE_VALUE) {
CloseHandle (fileHandle);
}
if (buffer != NULL) {
HeapFree (g_hHeap, 0, buffer);
}
}
return checkSum;
}
VOID
DestroyAnsiResourceId (
IN PCSTR AnsiId
)
{
if (HIWORD (AnsiId)) {
FreeConvertedStr (AnsiId);
}
}
VOID
DestroyUnicodeResourceId (
IN PCWSTR UnicodeId
)
{
if (HIWORD (UnicodeId)) {
FreeConvertedStr (UnicodeId);
}
}
BOOL
NeLoadHeader (
IN HANDLE File,
OUT PNE_INFO_BLOCK Header
)
{
DOS_HEADER dh;
LONG rc = ERROR_BAD_FORMAT;
BOOL b = FALSE;
__try {
SetFilePointer (File, 0, NULL, FILE_BEGIN);
if (!BfReadFile (File, (PBYTE)(&dh), sizeof (DOS_HEADER))) {
__leave;
}
if (dh.e_magic != ('M' + 'Z' * 256)) {
__leave;
}
SetFilePointer (File, dh.e_lfanew, NULL, FILE_BEGIN);
if (!BfReadFile (File, (PBYTE)Header, sizeof (NE_INFO_BLOCK))) {
__leave;
}
if (Header->Signature != ('N' + 'E' * 256) &&
Header->Signature != ('L' + 'E' * 256)
) {
if (Header->Signature == ('P' + 'E' * 256)) {
rc = ERROR_BAD_EXE_FORMAT;
} else {
rc = ERROR_INVALID_EXE_SIGNATURE;
}
DEBUGMSG ((DBG_NAUSEA, "Header signature is %c%c", Header->Signature & 0xff, Header->Signature >> 8));
__leave;
}
SetFilePointer (File, (DWORD) dh.e_lfanew, NULL, FILE_BEGIN);
b = TRUE;
}
__finally {
if (!b) {
SetLastError (rc);
}
}
return b;
}
DWORD
pComputeSizeOfTypeInfo (
IN PNE_RES_TYPEINFO TypeInfo
)
{
return sizeof (NE_RES_TYPEINFO) + TypeInfo->ResourceCount * sizeof (NE_RES_NAMEINFO);
}
PNE_RES_TYPEINFO
pReadNextTypeInfoStruct (
IN HANDLE File,
IN PMHANDLE Pool
)
{
WORD Type;
WORD ResCount;
NE_RES_TYPEINFO TypeInfo;
PNE_RES_TYPEINFO ReturnInfo = NULL;
DWORD Size;
if (!BfReadFile (File, (PBYTE)(&Type), sizeof (WORD))) {
return NULL;
}
if (!Type) {
return NULL;
}
if (!BfReadFile (File, (PBYTE)(&ResCount), sizeof (WORD))) {
return NULL;
}
TypeInfo.TypeId = Type;
TypeInfo.ResourceCount = ResCount;
if (!BfReadFile (File, (PBYTE)(&TypeInfo.Reserved), sizeof (DWORD))) {
return NULL;
}
Size = sizeof (NE_RES_NAMEINFO) * ResCount;
ReturnInfo = (PNE_RES_TYPEINFO) PmGetMemory (Pool, Size + sizeof (TypeInfo));
if (!ReturnInfo) {
return NULL;
}
CopyMemory (ReturnInfo, &TypeInfo, sizeof (TypeInfo));
if (!BfReadFile (File, (PBYTE) ReturnInfo + sizeof (TypeInfo), Size)) {
return NULL;
}
return ReturnInfo;
}
BOOL
pReadTypeInfoArray (
IN HANDLE File,
IN OUT PGROWLIST TypeInfoList
)
{
PNE_RES_TYPEINFO TypeInfo;
DWORD Size;
PMHANDLE TempPool;
BOOL b = FALSE;
TempPool = PmCreatePool();
if (!TempPool) {
return FALSE;
}
__try {
TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
while (TypeInfo) {
Size = pComputeSizeOfTypeInfo (TypeInfo);
if (!GlAppend (TypeInfoList, (PBYTE) TypeInfo, Size)) {
__leave;
}
TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
}
b = TRUE;
}
__finally {
PmDestroyPool (TempPool);
}
return b;
}
BOOL
pReadStringArrayA (
IN HANDLE File,
IN OUT PGROWLIST GrowList
)
{
BYTE Size;
CHAR Name[256];
if (!BfReadFile (File, (PBYTE)(&Size), sizeof (BYTE))) {
return FALSE;
}
while (Size) {
if (!BfReadFile (File, Name, (DWORD) Size)) {
return FALSE;
}
Name[Size] = 0;
GlAppendStringA (GrowList, Name);
if (!BfReadFile (File, (PBYTE)(&Size), sizeof (BYTE))) {
return FALSE;
}
}
return TRUE;
}
BOOL
NeLoadResources (
IN HANDLE File,
OUT PNE_RESOURCES Resources
)
{
NE_INFO_BLOCK Header;
ZeroMemory (Resources, sizeof (NE_RESOURCES));
if (!NeLoadHeader (File, &Header)) {
return FALSE;
}
//
// Read in NE_RESOURCES struct
//
SetFilePointer (File, (DWORD) Header.OffsetToResourceTable, NULL, FILE_CURRENT);
if (!BfReadFile (File, (PBYTE)(&Resources->AlignShift), sizeof (WORD))) {
return FALSE;
}
// Array of NE_RES_TYPEINFO structs
if (!pReadTypeInfoArray (File, &Resources->TypeInfoArray)) {
return FALSE;
}
// Resource names
if (!pReadStringArrayA (File, &Resources->ResourceNames)) {
return FALSE;
}
return TRUE;
}
VOID
NeFreeResources (
PNE_RESOURCES Resources
)
{
GlFree (&Resources->TypeInfoArray);
GlFree (&Resources->ResourceNames);
ZeroMemory (Resources, sizeof (NE_RESOURCES));
}
HANDLE
NeOpenFileA (
PCSTR FileName
)
{
PNE_HANDLE NeHandle;
BOOL b = FALSE;
NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
__try {
NeHandle->ResourcePool = PmCreatePool();
if (!NeHandle->ResourcePool) {
__leave;
}
NeHandle->File = CreateFileA (
FileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (NeHandle->File == INVALID_HANDLE_VALUE) {
__leave;
}
if (!NeLoadHeader (NeHandle->File, &NeHandle->Header)) {
__leave;
}
NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
b = TRUE;
}
__finally {
if (!b) {
PushError();
if (NeHandle->ResourcePool) {
PmDestroyPool (NeHandle->ResourcePool);
}
if (NeHandle->File != INVALID_HANDLE_VALUE) {
CloseHandle (NeHandle->File);
}
MemFree (g_hHeap, 0, NeHandle);
NeHandle = NULL;
PopError();
}
}
return (HANDLE) NeHandle;
}
HANDLE
NeOpenFileW (
PCWSTR FileName
)
{
PNE_HANDLE NeHandle;
BOOL b = FALSE;
NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
__try {
NeHandle->ResourcePool = PmCreatePool();
if (!NeHandle->ResourcePool) {
__leave;
}
NeHandle->File = CreateFileW (
FileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (NeHandle->File == INVALID_HANDLE_VALUE) {
__leave;
}
if (!NeLoadHeader (NeHandle->File, &NeHandle->Header)) {
__leave;
}
NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
b = TRUE;
}
__finally {
if (!b) {
PushError();
if (NeHandle->ResourcePool) {
PmDestroyPool (NeHandle->ResourcePool);
}
if (NeHandle->File != INVALID_HANDLE_VALUE) {
CloseHandle (NeHandle->File);
}
MemFree (g_hHeap, 0, NeHandle);
NeHandle = NULL;
PopError();
}
}
return (HANDLE) NeHandle;
}
VOID
NeCloseFile (
HANDLE Handle
)
{
PNE_HANDLE NeHandle;
NeHandle = (PNE_HANDLE) Handle;
if (!NeHandle) {
return;
}
if (NeHandle->File != INVALID_HANDLE_VALUE) {
CloseHandle (NeHandle->File);
}
if (NeHandle->ResourcesLoaded) {
NeFreeResources (&NeHandle->Resources);
}
PmDestroyPool (NeHandle->ResourcePool);
MemFree (g_hHeap, 0, NeHandle);
}
PCSTR
pConvertUnicodeResourceId (
IN PCWSTR ResId
)
{
if (HIWORD (ResId)) {
return ConvertWtoA (ResId);
}
return (PCSTR) ResId;
}
PCSTR
pDecodeIdReferenceInString (
IN PCSTR ResName
)
{
if (HIWORD (ResName) && ResName[0] == '#') {
return (PCSTR) (ULONG_PTR) atoi (&ResName[1]);
}
return ResName;
}
BOOL
pNeLoadResourcesFromHandle (
IN PNE_HANDLE NeHandle
)
{
if (NeHandle->ResourcesLoaded) {
return TRUE;
}
if (!NeLoadResources (NeHandle->File, &NeHandle->Resources)) {
return FALSE;
}
NeHandle->ResourcesLoaded = TRUE;
return TRUE;
}
BOOL
pLoadNeResourceName (
OUT PSTR ResName,
IN HANDLE File,
IN DWORD StringOffset
)
{
BYTE ResNameSize;
SetFilePointer (File, StringOffset, NULL, FILE_BEGIN);
if (!BfReadFile (File, (PBYTE)(&ResNameSize), 1)) {
return FALSE;
}
ResName[ResNameSize] = 0;
return BfReadFile (File, ResName, ResNameSize);
}
BOOL
pNeEnumResourceTypesEx (
IN HANDLE Handle,
IN ENUMRESTYPEPROCEXA EnumFunc,
IN LONG_PTR lParam,
IN BOOL ExFunctionality,
IN BOOL UnicodeProc
)
{
PNE_HANDLE NeHandle;
PNE_RES_TYPEINFO TypeInfo;
INT Count;
INT i;
DWORD StringOffset;
CHAR ResName[256];
ENUMRESTYPEPROCA EnumFunc2 = (ENUMRESTYPEPROCA) EnumFunc;
ENUMRESTYPEPROCEXW EnumFuncW = (ENUMRESTYPEPROCEXW) EnumFunc;
ENUMRESTYPEPROCW EnumFunc2W = (ENUMRESTYPEPROCW) EnumFunc;
PWSTR UnicodeResName = NULL;
//
// Make sure resources are loaded
//
NeHandle = (PNE_HANDLE) Handle;
if (!NeHandle || !EnumFunc) {
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!pNeLoadResourcesFromHandle (NeHandle)) {
return FALSE;
}
//
// Enumerate all resource types
//
Count = GlGetSize (&NeHandle->Resources.TypeInfoArray);
for (i = 0 ; i < Count ; i++) {
TypeInfo = (PNE_RES_TYPEINFO) GlGetItem (&NeHandle->Resources.TypeInfoArray, i);
if (TypeInfo->TypeId & 0x8000) {
if (ExFunctionality) {
if (UnicodeProc) {
if (!EnumFuncW (Handle, (PWSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
break;
}
} else {
if (!EnumFunc (Handle, (PSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
break;
}
}
} else {
if (UnicodeProc) {
if (!EnumFunc2W (Handle, (PWSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam)) {
break;
}
} else {
if (!EnumFunc2 (Handle, (PSTR) (ULONG_PTR) (TypeInfo->TypeId & 0x7fff), lParam)) {
break;
}
}
}
} else {
//
// TypeInfo->TypeId gives an offset to the resource string name,
// relative to the start of the resource table
//
StringOffset = NeHandle->HeaderOffset + NeHandle->Header.OffsetToResourceTable + TypeInfo->TypeId;
pLoadNeResourceName (ResName, NeHandle->File, StringOffset);
if (UnicodeProc) {
UnicodeResName = (PWSTR) ConvertAtoW (ResName);
}
if (ExFunctionality) {
if (UnicodeProc) {
if (!EnumFuncW (Handle, UnicodeResName, lParam, TypeInfo)) {
break;
}
} else {
if (!EnumFunc (Handle, ResName, lParam, TypeInfo)) {
break;
}
}
} else {
if (UnicodeProc) {
if (!EnumFunc2W (Handle, UnicodeResName, lParam)) {
break;
}
} else {
if (!EnumFunc2 (Handle, ResName, lParam)) {
break;
}
}
}
}
}
return TRUE;
}
BOOL
NeEnumResourceTypesA (
IN HANDLE Handle,
IN ENUMRESTYPEPROCA EnumFunc,
IN LONG_PTR lParam
)
{
return pNeEnumResourceTypesEx (
Handle,
(ENUMRESTYPEPROCEXA) EnumFunc,
lParam,
FALSE, // no ex functionality
FALSE // ANSI enum proc
);
}
BOOL
NeEnumResourceTypesW (
IN HANDLE Handle,
IN ENUMRESTYPEPROCW EnumFunc,
IN LONG_PTR lParam
)
{
return pNeEnumResourceTypesEx (
Handle,
(ENUMRESTYPEPROCEXA) EnumFunc,
lParam,
FALSE, // no ex functionality
TRUE // UNICODE enum proc
);
}
BOOL
pEnumTypeForNameSearchProcA (
IN HANDLE Handle,
IN PCSTR Type,
IN LONG_PTR lParam,
IN PNE_RES_TYPEINFO TypeInfo
)
{
PTYPESEARCHDATAA Data;
Data = (PTYPESEARCHDATAA) lParam;
//
// Compare type
//
if (HIWORD (Data->TypeToFind) == 0) {
if (Type != Data->TypeToFind) {
return TRUE;
}
} else {
if (HIWORD (Type) == 0) {
return TRUE;
}
if (!StringIMatchA (Type, Data->TypeToFind)) {
return TRUE;
}
}
//
// Type found
//
Data->OutboundTypeInfo = TypeInfo;
Data->Found = TRUE;
return FALSE;
}
BOOL
pNeEnumResourceNamesEx (
IN HANDLE Handle,
IN PCSTR Type,
IN ENUMRESNAMEPROCEXA EnumFunc,
IN LONG_PTR lParam,
IN BOOL ExFunctionality,
IN BOOL UnicodeProc
)
{
PNE_HANDLE NeHandle;
PNE_RES_TYPEINFO TypeInfo;
PNE_RES_NAMEINFO NameInfo;
TYPESEARCHDATAA Data;
WORD w;
DWORD StringOffset;
CHAR ResName[256];
ENUMRESNAMEPROCA EnumFunc2 = (ENUMRESNAMEPROCA) EnumFunc;
ENUMRESNAMEPROCEXW EnumFuncW = (ENUMRESNAMEPROCEXW) EnumFunc;
ENUMRESNAMEPROCW EnumFunc2W = (ENUMRESNAMEPROCW) EnumFunc;
PCWSTR UnicodeType = NULL;
PCWSTR UnicodeResName = NULL;
Type = pDecodeIdReferenceInString (Type);
//
// Make sure resources are loaded
//
NeHandle = (PNE_HANDLE) Handle;
if (!NeHandle || !EnumFunc) {
SetLastError (ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!pNeLoadResourcesFromHandle (NeHandle)) {
return FALSE;
}
//
// Locate type
//
ZeroMemory (&Data, sizeof (Data));
Data.TypeToFind = Type;
if (!pNeEnumResourceTypesEx (
Handle,
pEnumTypeForNameSearchProcA,
(ULONG_PTR) &Data,
TRUE, // ex functionality
FALSE // ANSI enum proc
)) {
SetLastError (ERROR_RESOURCE_TYPE_NOT_FOUND);
return FALSE;
}
if (!Data.Found) {
SetLastError (ERROR_RESOURCE_TYPE_NOT_FOUND);
return FALSE;
}
TypeInfo = Data.OutboundTypeInfo;
if (UnicodeProc) {
if (HIWORD (Type)) {
UnicodeType = ConvertAtoW (Type);
} else {
UnicodeType = (PCWSTR) Type;
}
}
//
// Enumerate the resource names
//
NameInfo = TypeInfo->NameInfo;
for (w = 0 ; w < TypeInfo->ResourceCount ; w++) {
if (NameInfo->Id & 0x8000) {
if (ExFunctionality) {
if (UnicodeProc) {
if (!EnumFuncW (
Handle,
UnicodeType,
(PWSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
lParam,
TypeInfo,
NameInfo
)) {
break;
}
} else {
if (!EnumFunc (
Handle,
Type,
(PSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
lParam,
TypeInfo,
NameInfo
)) {
break;
}
}
} else {
if (UnicodeProc) {
if (!EnumFunc2W (
Handle,
UnicodeType,
(PWSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
lParam
)) {
break;
}
} else {
if (!EnumFunc2 (
Handle,
Type,
(PSTR) (ULONG_PTR) (NameInfo->Id & 0x7fff),
lParam
)) {
break;
}
}
}
} else {
//
// TypeInfo->TypeId gives an offset to the resource string name,
// relative to the start of the resource table
//
StringOffset = NeHandle->HeaderOffset + NeHandle->Header.OffsetToResourceTable + NameInfo->Id;
pLoadNeResourceName (ResName, NeHandle->File, StringOffset);
if (UnicodeProc) {
UnicodeResName = ConvertAtoW (ResName);
}
if (ExFunctionality) {
if (UnicodeProc) {
if (!EnumFuncW (Handle, UnicodeType, (PWSTR) UnicodeResName, lParam, TypeInfo, NameInfo)) {
break;
}
} else {
if (!EnumFunc (Handle, Type, ResName, lParam, TypeInfo, NameInfo)) {
break;
}
}
} else {
if (UnicodeProc) {
if (!EnumFunc2W (Handle, UnicodeType, (PWSTR) UnicodeResName, lParam)) {
break;
}
} else {
if (!EnumFunc2 (Handle, Type, ResName, lParam)) {
break;
}
}
}
if (UnicodeProc) {
FreeConvertedStr (UnicodeResName);
}
}
NameInfo++;
}
if (UnicodeProc) {
DestroyUnicodeResourceId (UnicodeType);
}
return TRUE;
}
BOOL
NeEnumResourceNamesA (
IN HANDLE Handle,
IN PCSTR Type,
IN ENUMRESNAMEPROCA EnumFunc,
IN LONG_PTR lParam
)
{
return pNeEnumResourceNamesEx (
Handle,
Type,
(ENUMRESNAMEPROCEXA) EnumFunc,
lParam,
FALSE, // no ex functionality
FALSE // ANSI enum proc
);
}
BOOL
NeEnumResourceNamesW (
IN HANDLE Handle,
IN PCWSTR Type,
IN ENUMRESNAMEPROCW EnumFunc,
IN LONG_PTR lParam
)
{
BOOL b;
PCSTR AnsiType;
AnsiType = pConvertUnicodeResourceId (Type);
b = pNeEnumResourceNamesEx (
Handle,
AnsiType,
(ENUMRESNAMEPROCEXA) EnumFunc,
lParam,
FALSE, // no ex functionality
TRUE // UNICODE enum proc
);
PushError();
DestroyAnsiResourceId (AnsiType);
PopError();
return b;
}
BOOL
pEnumTypeForResSearchProcA (
IN HANDLE Handle,
IN PCSTR Type,
IN PCSTR Name,
IN LPARAM lParam,
IN PNE_RES_TYPEINFO TypeInfo,
IN PNE_RES_NAMEINFO NameInfo
)
{
PNAMESEARCHDATAA Data;
Data = (PNAMESEARCHDATAA) lParam;
//
// Compare name
//
if (HIWORD (Data->NameToFind) == 0) {
if (Name != Data->NameToFind) {
return TRUE;
}
} else {
if (HIWORD (Name) == 0) {
return TRUE;
}
if (!StringIMatchA (Name, Data->NameToFind)) {
return TRUE;
}
}
//
// Name found
//
Data->OutboundTypeInfo = TypeInfo;
Data->OutboundNameInfo = NameInfo;
Data->Found = TRUE;
return FALSE;
}
PBYTE
NeFindResourceExA (
IN HANDLE Handle,
IN PCSTR Type,
IN PCSTR Name
)
{
PNE_HANDLE NeHandle;
NAMESEARCHDATAA Data;
DWORD Offset;
DWORD Length;
PNE_RES_NAMEINFO NameInfo;
PBYTE ReturnData;
Type = pDecodeIdReferenceInString (Type);
Name = pDecodeIdReferenceInString (Name);
ZeroMemory (&Data, sizeof (Data));
//
// Make sure resources are loaded
//
NeHandle = (PNE_HANDLE) Handle;
if (!NeHandle || !Type || !Name) {
SetLastError (ERROR_INVALID_PARAMETER);
return NULL;
}
if (!pNeLoadResourcesFromHandle (NeHandle)) {
return NULL;
}
//
// Find resource
//
Data.NameToFind = Name;
if (!pNeEnumResourceNamesEx (
Handle,
Type,
pEnumTypeForResSearchProcA,
(LONG_PTR) &Data,
TRUE,
FALSE
)) {
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
return NULL;
}
if (!Data.Found) {
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
return NULL;
}
NameInfo = Data.OutboundNameInfo;
Offset = (DWORD) NameInfo->Offset << (DWORD) NeHandle->Resources.AlignShift;
Length = (DWORD) NameInfo->Length << (DWORD) NeHandle->Resources.AlignShift;
ReturnData = PmGetMemory (NeHandle->ResourcePool, Length);
if (!ReturnData) {
return NULL;
}
SetFilePointer (NeHandle->File, Offset, NULL, FILE_BEGIN);
if (!BfReadFile (NeHandle->File, ReturnData, Length)) {
PushError();
MemFree (g_hHeap, 0, ReturnData);
PopError();
return NULL;
}
return ReturnData;
}
PBYTE
NeFindResourceExW (
IN HANDLE Handle,
IN PCWSTR Type,
IN PCWSTR Name
)
{
PCSTR AnsiType;
PCSTR AnsiName;
PBYTE Resource;
AnsiType = pConvertUnicodeResourceId (Type);
AnsiName = pConvertUnicodeResourceId (Name);
Resource = NeFindResourceExA (
Handle,
AnsiType,
AnsiName
);
PushError();
DestroyAnsiResourceId (AnsiType);
DestroyAnsiResourceId (AnsiName);
PopError();
return Resource;
}
DWORD
NeSizeofResourceA (
IN HANDLE Handle,
IN PCSTR Type,
IN PCSTR Name
)
{
PNE_HANDLE NeHandle;
NAMESEARCHDATAA Data;
DWORD result = 0;
SetLastError (ERROR_SUCCESS);
Type = pDecodeIdReferenceInString (Type);
Name = pDecodeIdReferenceInString (Name);
ZeroMemory (&Data, sizeof (Data));
//
// Make sure resources are loaded
//
NeHandle = (PNE_HANDLE) Handle;
if (!NeHandle || !Type || !Name) {
SetLastError (ERROR_INVALID_PARAMETER);
return 0;
}
if (!pNeLoadResourcesFromHandle (NeHandle)) {
return 0;
}
//
// Find resource
//
Data.NameToFind = Name;
if (!pNeEnumResourceNamesEx (
Handle,
Type,
pEnumTypeForResSearchProcA,
(LONG_PTR) &Data,
TRUE,
FALSE
)) {
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
return 0;
}
if (!Data.Found) {
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
return 0;
}
result = Data.OutboundNameInfo->Length;
result = result<<4;
return result;
}
DWORD
NeSizeofResourceW (
IN HANDLE Handle,
IN PCWSTR Type,
IN PCWSTR Name
)
{
PCSTR AnsiType;
PCSTR AnsiName;
DWORD Size;
AnsiType = pConvertUnicodeResourceId (Type);
AnsiName = pConvertUnicodeResourceId (Name);
Size = NeSizeofResourceA (Handle, AnsiType, AnsiName);
PushError();
DestroyAnsiResourceId (AnsiType);
DestroyAnsiResourceId (AnsiName);
PopError();
return Size;
}