/*++ 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; }