1262 lines
26 KiB
C
1262 lines
26 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ne.c
|
|
|
|
Abstract:
|
|
|
|
New-Executable parsing routines
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 04-May-1998
|
|
|
|
Revision History:
|
|
|
|
jimschm 23-Sep-1998 Named icon ID bug fix, error path fixes
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "migutilp.h"
|
|
|
|
//
|
|
// NE code
|
|
//
|
|
|
|
typedef struct {
|
|
HANDLE File;
|
|
DWORD HeaderOffset;
|
|
NE_INFO_BLOCK Header;
|
|
NE_RESOURCES Resources;
|
|
BOOL ResourcesLoaded;
|
|
POOLHANDLE 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;
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
LoadNeHeader (
|
|
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 (!ReadBinaryBlock (File, &dh, sizeof (DOS_HEADER))) {
|
|
__leave;
|
|
}
|
|
|
|
if (dh.e_magic != ('M' + 'Z' * 256)) {
|
|
__leave;
|
|
}
|
|
|
|
SetFilePointer (File, dh.e_lfanew, NULL, FILE_BEGIN);
|
|
if (!ReadBinaryBlock (File, 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 POOLHANDLE Pool
|
|
)
|
|
{
|
|
WORD Type;
|
|
WORD ResCount;
|
|
NE_RES_TYPEINFO TypeInfo;
|
|
PNE_RES_TYPEINFO ReturnInfo = NULL;
|
|
DWORD Size;
|
|
|
|
if (!ReadBinaryBlock (File, &Type, sizeof (WORD))) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!Type) {
|
|
return NULL;
|
|
}
|
|
|
|
if (!ReadBinaryBlock (File, &ResCount, sizeof (WORD))) {
|
|
return NULL;
|
|
}
|
|
|
|
TypeInfo.TypeId = Type;
|
|
TypeInfo.ResourceCount = ResCount;
|
|
|
|
if (!ReadBinaryBlock (File, &TypeInfo.Reserved, sizeof (DWORD))) {
|
|
return NULL;
|
|
}
|
|
|
|
Size = sizeof (NE_RES_NAMEINFO) * ResCount;
|
|
|
|
ReturnInfo = (PNE_RES_TYPEINFO) PoolMemGetMemory (Pool, Size + sizeof (TypeInfo));
|
|
if (!ReturnInfo) {
|
|
return NULL;
|
|
}
|
|
|
|
CopyMemory (ReturnInfo, &TypeInfo, sizeof (TypeInfo));
|
|
|
|
if (!ReadBinaryBlock (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;
|
|
POOLHANDLE TempPool;
|
|
BOOL b = FALSE;
|
|
|
|
TempPool = PoolMemInitPool();
|
|
if (!TempPool) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
|
|
TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
|
|
while (TypeInfo) {
|
|
Size = pComputeSizeOfTypeInfo (TypeInfo);
|
|
if (!GrowListAppend (TypeInfoList, (PBYTE) TypeInfo, Size)) {
|
|
__leave;
|
|
}
|
|
|
|
TypeInfo = pReadNextTypeInfoStruct (File, TempPool);
|
|
}
|
|
|
|
b = TRUE;
|
|
}
|
|
__finally {
|
|
|
|
PoolMemDestroyPool (TempPool);
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pReadStringArrayA (
|
|
IN HANDLE File,
|
|
IN OUT PGROWLIST GrowList
|
|
)
|
|
{
|
|
BYTE Size;
|
|
CHAR Name[256];
|
|
|
|
if (!ReadBinaryBlock (File, &Size, sizeof (BYTE))) {
|
|
return FALSE;
|
|
}
|
|
|
|
while (Size) {
|
|
|
|
if (!ReadBinaryBlock (File, Name, (DWORD) Size)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Name[Size] = 0;
|
|
|
|
GrowListAppendString (GrowList, Name);
|
|
|
|
if (!ReadBinaryBlock (File, &Size, sizeof (BYTE))) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
LoadNeResources (
|
|
IN HANDLE File,
|
|
OUT PNE_RESOURCES Resources
|
|
)
|
|
{
|
|
NE_INFO_BLOCK Header;
|
|
|
|
ZeroMemory (Resources, sizeof (NE_RESOURCES));
|
|
|
|
if (!LoadNeHeader (File, &Header)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Read in NE_RESOURCES struct
|
|
//
|
|
|
|
SetFilePointer (File, (DWORD) Header.OffsetToResourceTable, NULL, FILE_CURRENT);
|
|
|
|
if (!ReadBinaryBlock (File, &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
|
|
FreeNeResources (
|
|
PNE_RESOURCES Resources
|
|
)
|
|
{
|
|
FreeGrowList (&Resources->TypeInfoArray);
|
|
FreeGrowList (&Resources->ResourceNames);
|
|
|
|
ZeroMemory (Resources, sizeof (NE_RESOURCES));
|
|
}
|
|
|
|
|
|
BOOL
|
|
LoadNeIcon (
|
|
HANDLE File,
|
|
INT IconIndex
|
|
)
|
|
{
|
|
NE_RESOURCES Resources;
|
|
INT Count;
|
|
INT i;
|
|
PNE_RES_TYPEINFO TypeInfo = NULL;
|
|
BOOL b = FALSE;
|
|
DWORD Offset;
|
|
WORD w;
|
|
PNE_RES_NAMEINFO NameInfo;
|
|
DWORD Length;
|
|
|
|
PBYTE Data;
|
|
|
|
if (!LoadNeResources (File, &Resources)) {
|
|
return FALSE;
|
|
}
|
|
|
|
__try {
|
|
//
|
|
// Search resources for RT_GROUPICON
|
|
//
|
|
|
|
Count = GrowListGetSize (&Resources.TypeInfoArray);
|
|
for (i = 0 ; i < Count ; i++) {
|
|
TypeInfo = (PNE_RES_TYPEINFO) GrowListGetItem (&Resources.TypeInfoArray, i);
|
|
|
|
if (TypeInfo->TypeId == (WORD) RT_GROUP_ICON) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == Count) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Identify which group icon
|
|
//
|
|
|
|
NameInfo = TypeInfo->NameInfo;
|
|
|
|
for (w = 0 ; w < TypeInfo->ResourceCount ; w++) {
|
|
|
|
if (IconIndex > 0) {
|
|
IconIndex--;
|
|
} else if (!IconIndex) {
|
|
break;
|
|
} else if (-IconIndex == (INT) NameInfo->Id) {
|
|
break;
|
|
}
|
|
|
|
NameInfo++;
|
|
}
|
|
|
|
if (w == TypeInfo->ResourceCount) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Load the group icon resource
|
|
//
|
|
|
|
Offset = (DWORD) NameInfo->Offset << (DWORD) Resources.AlignShift;
|
|
Length = (DWORD) NameInfo->Length << (DWORD) Resources.AlignShift;
|
|
|
|
Data = MemAlloc (g_hHeap, 0, Length);
|
|
if (!Data) {
|
|
__leave;
|
|
}
|
|
|
|
SetFilePointer (File, Offset, NULL, FILE_BEGIN);
|
|
ReadBinaryBlock (File, Data, Length);
|
|
|
|
MemFree (g_hHeap, 0, Data);
|
|
|
|
b = TRUE;
|
|
}
|
|
__finally {
|
|
FreeNeResources (&Resources);
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
BOOL
|
|
LoadNeIconFromFileA (
|
|
PCSTR FileName,
|
|
INT IconIndex
|
|
)
|
|
{
|
|
HANDLE File;
|
|
BOOL b;
|
|
|
|
File = OpenNeFileA (FileName);
|
|
|
|
if (!File) {
|
|
return FALSE;
|
|
}
|
|
|
|
b = LoadNeIcon (File, IconIndex);
|
|
|
|
CloseNeFile (File);
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
OpenNeFileA (
|
|
PCSTR FileName
|
|
)
|
|
{
|
|
PNE_HANDLE NeHandle;
|
|
BOOL b = FALSE;
|
|
|
|
NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
|
|
|
|
__try {
|
|
|
|
NeHandle->ResourcePool = PoolMemInitPool();
|
|
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 (!LoadNeHeader (NeHandle->File, &NeHandle->Header)) {
|
|
__leave;
|
|
}
|
|
|
|
NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
|
|
|
|
b = TRUE;
|
|
}
|
|
__finally {
|
|
if (!b) {
|
|
PushError();
|
|
|
|
if (NeHandle->ResourcePool) {
|
|
PoolMemDestroyPool (NeHandle->ResourcePool);
|
|
}
|
|
|
|
if (NeHandle->File != INVALID_HANDLE_VALUE) {
|
|
CloseHandle (NeHandle->File);
|
|
}
|
|
|
|
MemFree (g_hHeap, 0, NeHandle);
|
|
NeHandle = NULL;
|
|
|
|
PopError();
|
|
}
|
|
}
|
|
|
|
return (HANDLE) NeHandle;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
OpenNeFileW (
|
|
PCWSTR FileName
|
|
)
|
|
{
|
|
PNE_HANDLE NeHandle;
|
|
BOOL b = FALSE;
|
|
|
|
NeHandle = (PNE_HANDLE) MemAlloc (g_hHeap, HEAP_ZERO_MEMORY, sizeof (NE_HANDLE));
|
|
|
|
__try {
|
|
|
|
NeHandle->ResourcePool = PoolMemInitPool();
|
|
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 (!LoadNeHeader (NeHandle->File, &NeHandle->Header)) {
|
|
__leave;
|
|
}
|
|
|
|
NeHandle->HeaderOffset = SetFilePointer (NeHandle->File, 0, NULL, FILE_CURRENT);
|
|
|
|
b = TRUE;
|
|
}
|
|
__finally {
|
|
if (!b) {
|
|
PushError();
|
|
|
|
if (NeHandle->ResourcePool) {
|
|
PoolMemDestroyPool (NeHandle->ResourcePool);
|
|
}
|
|
|
|
if (NeHandle->File != INVALID_HANDLE_VALUE) {
|
|
CloseHandle (NeHandle->File);
|
|
}
|
|
|
|
MemFree (g_hHeap, 0, NeHandle);
|
|
NeHandle = NULL;
|
|
|
|
PopError();
|
|
}
|
|
}
|
|
|
|
return (HANDLE) NeHandle;
|
|
}
|
|
|
|
|
|
VOID
|
|
CloseNeFile (
|
|
HANDLE Handle
|
|
)
|
|
{
|
|
PNE_HANDLE NeHandle;
|
|
|
|
NeHandle = (PNE_HANDLE) Handle;
|
|
if (!NeHandle) {
|
|
return;
|
|
}
|
|
|
|
if (NeHandle->File != INVALID_HANDLE_VALUE) {
|
|
CloseHandle (NeHandle->File);
|
|
}
|
|
|
|
if (NeHandle->ResourcesLoaded) {
|
|
FreeNeResources (&NeHandle->Resources);
|
|
}
|
|
|
|
PoolMemDestroyPool (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) atoi (&ResName[1]);
|
|
}
|
|
|
|
return ResName;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
pLoadNeResourcesFromHandle (
|
|
IN PNE_HANDLE NeHandle
|
|
)
|
|
{
|
|
if (NeHandle->ResourcesLoaded) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (!LoadNeResources (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 (!ReadBinaryBlock (File, &ResNameSize, 1)) {
|
|
return FALSE;
|
|
}
|
|
|
|
ResName[ResNameSize] = 0;
|
|
|
|
return ReadBinaryBlock (File, ResName, ResNameSize);
|
|
}
|
|
|
|
|
|
BOOL
|
|
pEnumNeResourceTypesEx (
|
|
IN HANDLE Handle,
|
|
IN ENUMRESTYPEPROCEXA EnumFunc,
|
|
IN LONG 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 (!pLoadNeResourcesFromHandle (NeHandle)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Enumerate all resource types
|
|
//
|
|
|
|
Count = GrowListGetSize (&NeHandle->Resources.TypeInfoArray);
|
|
for (i = 0 ; i < Count ; i++) {
|
|
TypeInfo = (PNE_RES_TYPEINFO) GrowListGetItem (&NeHandle->Resources.TypeInfoArray, i);
|
|
|
|
if (TypeInfo->TypeId & 0x8000) {
|
|
if (ExFunctionality) {
|
|
if (UnicodeProc) {
|
|
if (!EnumFuncW (Handle, (PWSTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (!EnumFunc (Handle, (PSTR) (TypeInfo->TypeId & 0x7fff), lParam, TypeInfo)) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if (UnicodeProc) {
|
|
if (!EnumFunc2W (Handle, (PWSTR) (TypeInfo->TypeId & 0x7fff), lParam)) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (!EnumFunc2 (Handle, (PSTR) (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
|
|
EnumNeResourceTypesA (
|
|
IN HANDLE Handle,
|
|
IN ENUMRESTYPEPROCA EnumFunc,
|
|
IN LONG lParam
|
|
)
|
|
{
|
|
return pEnumNeResourceTypesEx (
|
|
Handle,
|
|
(ENUMRESTYPEPROCEXA) EnumFunc,
|
|
lParam,
|
|
FALSE, // no ex functionality
|
|
FALSE // ANSI enum proc
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
EnumNeResourceTypesW (
|
|
IN HANDLE Handle,
|
|
IN ENUMRESTYPEPROCW EnumFunc,
|
|
IN LONG lParam
|
|
)
|
|
{
|
|
return pEnumNeResourceTypesEx (
|
|
Handle,
|
|
(ENUMRESTYPEPROCEXA) EnumFunc,
|
|
lParam,
|
|
FALSE, // no ex functionality
|
|
TRUE // UNICODE enum proc
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
pEnumTypeForNameSearchProcA (
|
|
IN HANDLE Handle,
|
|
IN PCSTR Type,
|
|
IN LONG 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
|
|
pEnumNeResourceNamesEx (
|
|
IN HANDLE Handle,
|
|
IN PCSTR Type,
|
|
IN ENUMRESNAMEPROCEXA EnumFunc,
|
|
IN LONG 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 (!pLoadNeResourcesFromHandle (NeHandle)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Locate type
|
|
//
|
|
|
|
ZeroMemory (&Data, sizeof (Data));
|
|
|
|
Data.TypeToFind = Type;
|
|
|
|
if (!pEnumNeResourceTypesEx (
|
|
Handle,
|
|
pEnumTypeForNameSearchProcA,
|
|
(LONG) &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) (NameInfo->Id & 0x7fff), lParam, TypeInfo, NameInfo)) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (!EnumFunc (Handle, Type, (PSTR) (NameInfo->Id & 0x7fff), lParam, TypeInfo, NameInfo)) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if (UnicodeProc) {
|
|
if (!EnumFunc2W (Handle, UnicodeType, (PWSTR) (NameInfo->Id & 0x7fff), lParam)) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (!EnumFunc2 (Handle, Type, (PSTR) (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
|
|
EnumNeResourceNamesA (
|
|
IN HANDLE Handle,
|
|
IN PCSTR Type,
|
|
IN ENUMRESNAMEPROCA EnumFunc,
|
|
IN LONG lParam
|
|
)
|
|
{
|
|
return pEnumNeResourceNamesEx (
|
|
Handle,
|
|
Type,
|
|
(ENUMRESNAMEPROCEXA) EnumFunc,
|
|
lParam,
|
|
FALSE, // no ex functionality
|
|
FALSE // ANSI enum proc
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
EnumNeResourceNamesW (
|
|
IN HANDLE Handle,
|
|
IN PCWSTR Type,
|
|
IN ENUMRESNAMEPROCW EnumFunc,
|
|
IN LONG lParam
|
|
)
|
|
{
|
|
BOOL b;
|
|
PCSTR AnsiType;
|
|
|
|
AnsiType = pConvertUnicodeResourceId (Type);
|
|
|
|
b = pEnumNeResourceNamesEx (
|
|
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
|
|
FindNeResourceExA (
|
|
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 (!pLoadNeResourcesFromHandle (NeHandle)) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Find resource
|
|
//
|
|
|
|
Data.NameToFind = Name;
|
|
|
|
if (!pEnumNeResourceNamesEx (
|
|
Handle,
|
|
Type,
|
|
pEnumTypeForResSearchProcA,
|
|
(LONG) &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 = PoolMemGetMemory (NeHandle->ResourcePool, Length);
|
|
if (!ReturnData) {
|
|
return NULL;
|
|
}
|
|
|
|
SetFilePointer (NeHandle->File, Offset, NULL, FILE_BEGIN);
|
|
|
|
if (!ReadBinaryBlock (NeHandle->File, ReturnData, Length)) {
|
|
PushError();
|
|
MemFree (g_hHeap, 0, ReturnData);
|
|
PopError();
|
|
return NULL;
|
|
}
|
|
|
|
return ReturnData;
|
|
}
|
|
|
|
|
|
PBYTE
|
|
FindNeResourceExW (
|
|
IN HANDLE Handle,
|
|
IN PCWSTR Type,
|
|
IN PCWSTR Name
|
|
)
|
|
{
|
|
PCSTR AnsiType;
|
|
PCSTR AnsiName;
|
|
PBYTE Resource;
|
|
|
|
AnsiType = pConvertUnicodeResourceId (Type);
|
|
AnsiName = pConvertUnicodeResourceId (Name);
|
|
|
|
Resource = FindNeResourceExA (
|
|
Handle,
|
|
AnsiType,
|
|
AnsiName
|
|
);
|
|
|
|
PushError();
|
|
|
|
DestroyAnsiResourceId (AnsiType);
|
|
DestroyAnsiResourceId (AnsiName);
|
|
|
|
PopError();
|
|
|
|
return Resource;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
SizeofNeResourceA (
|
|
IN HANDLE Handle,
|
|
IN PCSTR Type,
|
|
IN PCSTR Name
|
|
)
|
|
{
|
|
PNE_HANDLE NeHandle;
|
|
NAMESEARCHDATAA Data;
|
|
|
|
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 (!pLoadNeResourcesFromHandle (NeHandle)) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Find resource
|
|
//
|
|
|
|
if (!pEnumNeResourceNamesEx (
|
|
Handle,
|
|
Type,
|
|
pEnumTypeForResSearchProcA,
|
|
(LONG) &Data,
|
|
TRUE,
|
|
FALSE
|
|
)) {
|
|
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
|
|
return 0;
|
|
}
|
|
|
|
if (!Data.Found) {
|
|
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
|
|
return 0;
|
|
}
|
|
|
|
return Data.OutboundNameInfo->Length;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SizeofNeResourceW (
|
|
IN HANDLE Handle,
|
|
IN PCWSTR Type,
|
|
IN PCWSTR Name
|
|
)
|
|
{
|
|
PCSTR AnsiType;
|
|
PCSTR AnsiName;
|
|
DWORD Size;
|
|
|
|
AnsiType = pConvertUnicodeResourceId (Type);
|
|
AnsiName = pConvertUnicodeResourceId (Name);
|
|
|
|
Size = SizeofNeResourceA (Handle, AnsiType, AnsiName);
|
|
|
|
PushError();
|
|
|
|
DestroyAnsiResourceId (AnsiType);
|
|
DestroyAnsiResourceId (AnsiName);
|
|
|
|
PopError();
|
|
|
|
return Size;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|