windows-nt/Source/XPSP1/NT/sdktools/restools/rltools/common/exentres.c

946 lines
28 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "windefs.h"
#include "restok.h"
#include "exentres.h"
#include "resread.h"
#include "checksum.h"
#define SAME 0 //... Used in string compares
#define MAXLEVELS 3 //... Max # of levels in resource directory
typedef struct tagResSectData {
ULONG ulVirtualAddress; //... Virtual address of section .rsrc
ULONG ulSizeOfResources; //... Size of resources in section .rsrc
ULONG ulVirtualSize; //... Virtual Size of resources in .rsrc
ULONG ulVirtualAddressX; //... Virtual address of section .rsrc1
ULONG ulSizeOfResourcesX; //... Size of resources in section .rsrc1
ULONG ulVirtualSizeX; //... Virtual Size of resources in .rsrc1
} RESSECTDATA, *PRESSECTDATA;
WORD gwFilter = 0;
int InsertResourcesInExe( FILE *, HANDLE);
LONG GetFileResources( FILE *, FILE *, ULONG);
ULONG MoveFilePos( FILE *, ULONG);
ULONG MyWrite( FILE *, PUCHAR, ULONG);
ULONG MyRead( FILE *, PUCHAR, ULONG);
WCHAR *GetDirNameU( WCHAR *, PIMAGE_RESOURCE_DIR_STRING_U);
ULONG ReadResources( FILE *, ULONG, ULONG, PUCHAR);
DWORD AddToLangIDList( DWORD);
ULONG ProcessDirectory( FILE *,
USHORT,
PRESSECTDATA,
PIMAGE_RESOURCE_DIRECTORY,
PIMAGE_RESOURCE_DIRECTORY);
ULONG ProcessDirEntry( FILE *,
USHORT,
PRESSECTDATA,
PIMAGE_RESOURCE_DIRECTORY,
PIMAGE_RESOURCE_DIRECTORY_ENTRY);
ULONG ProcessSubDir( FILE *,
USHORT,
PRESSECTDATA,
PIMAGE_RESOURCE_DIRECTORY,
PIMAGE_RESOURCE_DIRECTORY_ENTRY);
ULONG ProcessNamedEntry( FILE *,
PRESSECTDATA,
PIMAGE_RESOURCE_DIRECTORY,
PIMAGE_RESOURCE_DIRECTORY_ENTRY);
ULONG ProcessIdEntry( FILE *,
PRESSECTDATA,
PIMAGE_RESOURCE_DIRECTORY,
PIMAGE_RESOURCE_DIRECTORY_ENTRY);
ULONG ProcessDataEntry( FILE *,
PRESSECTDATA,
PIMAGE_RESOURCE_DIRECTORY,
PIMAGE_RESOURCE_DATA_ENTRY);
int FindNewExeHdr( FILE *, ULONG *);
IMAGE_DOS_HEADER ExeDosHdr;//... Exe's DOS header
IMAGE_NT_HEADERS NTHdrs; //... Exe's NT headers
struct tagLevelData //... Holds ID or name for each directory level
{
//... level [0] is for resource type
ULONG dwID; //... level [1] is for resource name
WCHAR wszName[128]; //... level [2] is for resource language
}
LevelData[ MAXLEVELS] = { 0L, TEXT(""), 0L, TEXT(""), 0L, TEXT("")};
BOOL fGetResLangIDs = FALSE;
extern BOOL fInThirdPartyEditer;//.. Are we in a 3rd-party resource editor?
extern MSTRDATA gMstr; //... Data from Master Project file (MPJ)
extern PROJDATA gProj; //... Data from Language Project file (PRJ)
extern UCHAR szDHW[];
PLANGLIST pLangIDList = NULL;
//..........................................................................
void FreeLangIDList( void)
{
PLANGLIST pID = NULL;
while ( pLangIDList ) {
pID = pLangIDList->pNext;
RLFREE( pLangIDList);
pLangIDList = pID;
}
}
//..........................................................................
ULONG GetListOfResLangIDs( char *szExeName)
{
ULONG ulRC = SUCCESS;
ULONG ulOffset = 0;
static RESHEADER ResHeader; // Structure contain Resource Header info.
if ( IsExe( szExeName) ) { //.. open the original exe file
FILE *fpExe = FOPEN( szExeName, "rb");
if ( fpExe != NULL ) {
//... Get list of languages in exe file
ulRC = (ULONG)FindNewExeHdr( fpExe, &ulOffset);
if ( ulRC == SUCCESS ) {
fGetResLangIDs = TRUE;
ulRC = (ULONG)GetFileResources( fpExe, NULL, ulOffset);
fGetResLangIDs = FALSE;
}
FCLOSE( fpExe);
} else {
ulRC = ERROR_OPEN_FAILED;
}
} else if ( IsWin32Res( szExeName) ) {
FILE *fpRes = FOPEN( szExeName, "rb");
if ( fpRes != NULL ) {
LONG lEndOffset = 0L;
//... How large is the res file?
fseek( fpRes, 0L, SEEK_END);
lEndOffset = ftell( fpRes);
rewind( fpRes);
//... Get list of languages in .RES file
while ( ulRC == SUCCESS && ! feof( fpRes) ) {
LONG lCurrOffset = 0L;
lCurrOffset = (LONG)ftell( fpRes);
if ( (lCurrOffset + (LONG)sizeof( RESHEADER)) >= lEndOffset ) {
break;
}
if ( GetResHeader( fpRes, &ResHeader, NULL) == -1 ) {
ulRC = 1L;
break;
}
//... Is this the dummy, res32-identifying, res?
if ( ResHeader.lSize == 0L ) {
continue;
}
ulRC = AddToLangIDList( (DWORD)ResHeader.wLanguageId);
SkipBytes( fpRes, (DWORD *)&ResHeader.lSize);
ClearResHeader( ResHeader);
DWordUpFilePointer( fpRes, MYREAD, ftell( fpRes), NULL);
} // END while ( ! feof( InResFile)
FCLOSE( fpRes);
} else {
ulRC = ERROR_OPEN_FAILED;
}
}
if ( ulRC != SUCCESS ) {
FreeLangIDList();
}
return ( ulRC);
}
//..........................................................................
int ExtractResFromExe32A(
char *szExeName,
char *szResName,
WORD wFilter)
{
FILE *fpExe = NULL; //... Handle of input .EXE file
FILE *fpRes = NULL; //... Handle of output .RES file
ULONG ulRC = 0;
ULONG ulOffset = 0;
int nRC = SUCCESS;
gwFilter = wFilter;
//.. open the original exe file
fpExe = FOPEN( szExeName, "rb");
if ( fpExe == NULL ) {
return ( ERROR_OPEN_FAILED);
}
nRC = FindNewExeHdr( fpExe, &ulOffset);
if ( nRC != SUCCESS ) {
FCLOSE( fpExe);
return ( nRC);
}
fpRes = FOPEN( (CHAR *)szResName, "wb");
if ( fpRes != NULL ) {
//... First, write the dummy 32bit identifier
PutByte( fpRes, 0x00, NULL);
PutByte( fpRes, 0x00, NULL);
PutByte( fpRes, 0x00, NULL);
PutByte( fpRes, 0x00, NULL);
PutByte( fpRes, 0x20, NULL);
PutByte( fpRes, 0x00, NULL);
PutByte( fpRes, 0x00, NULL);
PutByte( fpRes, 0x00, NULL);
PutWord( fpRes, 0xffff, NULL);
PutWord( fpRes, 0x00, NULL);
PutWord( fpRes, 0xffff, NULL);
PutWord( fpRes, 0x00, NULL);
PutdWord( fpRes, 0L, NULL);
PutdWord( fpRes, 0L, NULL);
PutdWord( fpRes, 0L, NULL);
PutdWord( fpRes, 0L, NULL);
ulRC = (ULONG)GetFileResources( fpExe, fpRes, ulOffset);
FCLOSE( fpRes);
} else {
ulRC = GetLastError();
}
FCLOSE( fpExe);
return ( ulRC);
}
//..........................................................................
int BuildExeFromRes32A(
char * szOutExe, //... Output EXE file's name
char * szRes, //... File of replacement resources
char * szInExe ) //... Intput EXE file's name
{
HANDLE hExeFile = NULL;
FILE *fpRes = NULL;
DWORD dwRC = 0;
WORD wRC = 0;
//... Copy Input exe to out put exe
if ( CopyFileA( szInExe, szOutExe, FALSE) == FALSE ) {
QuitA( IDS_COPYFILE_FAILED, szInExe, szOutExe);
}
if ( (fpRes = FOPEN( szRes, "rb")) == NULL ) {
return -2;
}
SetLastError(0);
//if Source file was set attributes READ-ONLY, CopyFile sets temp file also.
//And BeginUpdateResourceA returns ERROR.
SetFileAttributesA(szOutExe, FILE_ATTRIBUTE_NORMAL);
hExeFile = BeginUpdateResourceA( szOutExe, TRUE);
dwRC = GetLastError();
if ( ! hExeFile ) {
FCLOSE( fpRes);
return ( -3);
}
wRC = (WORD)InsertResourcesInExe( fpRes, hExeFile);
FCLOSE( fpRes);
if ( wRC != 1 ) {
return ( wRC);
}
SetLastError(0); // needed only to see if EndUpdateResource
// sets last error value.
dwRC = EndUpdateResource( hExeFile, FALSE);
if ( dwRC == FALSE ) {
return ( -4);
}
MapFileAndFixCheckSumA( szOutExe); //... This func always calls QuitT or returns 0
return (1);
}
//..........................................................................
int FindNewExeHdr( FILE *fpExe, ULONG *ulOffset)
{
ULONG ulRC = 0;
//... read the old format EXE header
ulRC = MyRead( fpExe, (void *)&ExeDosHdr, sizeof( ExeDosHdr));
if ( ulRC != 0L && ulRC != sizeof( ExeDosHdr) ) {
return ( ERROR_READ_FAULT);
}
//... make sure its really an EXE file
if ( ExeDosHdr.e_magic != IMAGE_DOS_SIGNATURE ) {
return ( ERROR_INVALID_EXE_SIGNATURE);
}
//... make sure theres a new EXE header
//... floating around somewhere
if ( ! (*ulOffset = ExeDosHdr.e_lfanew) ) {
return ( ERROR_BAD_EXE_FORMAT);
}
return ( SUCCESS);
}
//..........................................................................
int InsertResourcesInExe(
FILE *fpRes,
HANDLE hExeFile )
{
PVOID pResData = NULL;
LONG lEndOffset = 0L;
BOOL bUpdRC = FALSE;
LANGID wLangID = 0;
int nResCnt = 0;
int nResOut = 0;
static RESHEADER ResHeader;
//... How big is the .RES file?
fseek( fpRes, 0L, SEEK_END);
lEndOffset = ftell( fpRes);
rewind( fpRes);
//... Update all resources, found in the .RES,
//... to the .EXE
while ( ! feof( fpRes) ) {
DWordUpFilePointer( fpRes, MYREAD, ftell( fpRes), NULL);
RLFREE( pResData);
if ( ftell( fpRes) >= lEndOffset ) {
return (1);
}
ZeroMemory( &ResHeader, sizeof( ResHeader));
// Read in the resource header
if ( ( GetResHeader( fpRes, &ResHeader, (DWORD *) NULL) == -1 ) ) {
return ( -1);
}
if ( ResHeader.lSize > 0L ) {
wLangID = ResHeader.wLanguageId;
// Allocate Memory to hold resource data
pResData = (PVOID)FALLOC( ResHeader.lSize);
// Read it into the buffer
if ( ResReadBytes( fpRes,
pResData,
(size_t)ResHeader.lSize,
NULL ) == FALSE ) {
RLFREE( pResData);
return (-1);
}
nResCnt++; // Increment # resources read
DWordUpFilePointer( fpRes, MYREAD, ftell( fpRes), NULL);
} else {
continue;
}
// now write the data
if ( ResHeader.bTypeFlag == IDFLAG ) {
if ( ResHeader.bNameFlag == IDFLAG ) {
SetLastError(0);
bUpdRC = UpdateResource( hExeFile,
MAKEINTRESOURCE( ResHeader.wTypeID),
MAKEINTRESOURCE( ResHeader.wNameID),
wLangID,
pResData,
ResHeader.lSize);
if ( ! bUpdRC ) {
RLFREE( pResData);
return (-1);
}
} else {
SetLastError(0);
bUpdRC = UpdateResource( hExeFile,
MAKEINTRESOURCE( ResHeader.wTypeID),
ResHeader.pszName,
wLangID,
pResData,
ResHeader.lSize);
if ( ! bUpdRC ) {
RLFREE( pResData);
return (-1);
}
}
} else {
if (ResHeader.bNameFlag == IDFLAG) {
SetLastError(0);//BUGUG
bUpdRC = UpdateResource( hExeFile,
ResHeader.pszType,
MAKEINTRESOURCE( ResHeader.wNameID),
wLangID,
pResData,
ResHeader.lSize);
if ( ! bUpdRC ) {
RLFREE( pResData);
return (-1);
}
} else {
SetLastError(0);
bUpdRC = UpdateResource( hExeFile,
ResHeader.pszType,
ResHeader.pszName,
wLangID,
pResData,
ResHeader.lSize);
if ( ! bUpdRC ) {
RLFREE( pResData);
return (-1);
}
}
}
ClearResHeader( ResHeader);
RLFREE( pResData);
} //... END WHILE ( ! feof...
return (1);
}
//............................................................
LONG GetFileResources(
FILE *fpExe,
FILE *fpRes,
ULONG ulHdrOffset)
{
ULONG ulOffsetToResources;
ULONG ulOffsetToResourcesX;
ULONG ulRead;
ULONG ulToRead;
ULONG ulRC = SUCCESS;
PUCHAR pResources = NULL; //... Ptr to start of resource directory table
PIMAGE_SECTION_HEADER pSectTbl = NULL;
PIMAGE_SECTION_HEADER pSectTblLast = NULL;
PIMAGE_SECTION_HEADER pSect = NULL;
PIMAGE_SECTION_HEADER pResSect = NULL;
PIMAGE_SECTION_HEADER pResSectX = NULL;
static RESSECTDATA ResSectData;
//... Read the NT image headers into memory
ulRC = MoveFilePos( fpExe, ulHdrOffset);
if ( ulRC != 0L ) {
return ( -1L);
}
ulRead = MyRead( fpExe, (PUCHAR)&NTHdrs, sizeof( IMAGE_NT_HEADERS));
if ( ulRead != 0L && ulRead != sizeof( IMAGE_NT_HEADERS) ) {
return ( -1L);
}
//... Check for valid exe
if ( *(PUSHORT)&NTHdrs.Signature != IMAGE_NT_SIGNATURE ) {
return ( ERROR_INVALID_EXE_SIGNATURE);
}
if ((NTHdrs.FileHeader.Characteristics&IMAGE_FILE_EXECUTABLE_IMAGE) == 0 &&
(NTHdrs.FileHeader.Characteristics&IMAGE_FILE_DLL) == 0) {
return ( ERROR_EXE_MARKED_INVALID);
}
//... Where is resource section in file
//... and how big is it?
//... First, read section table
ulToRead = NTHdrs.FileHeader.NumberOfSections
* sizeof( IMAGE_SECTION_HEADER);
pSectTbl = (PIMAGE_SECTION_HEADER)FALLOC( ulToRead);
memset( (PVOID)pSectTbl, 0, ulToRead);
ulHdrOffset += sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
NTHdrs.FileHeader.SizeOfOptionalHeader;
MoveFilePos( fpExe, ulHdrOffset);
ulRead = MyRead( fpExe, (PUCHAR)pSectTbl, ulToRead);
if ( ulRead != 0L && ulRead != ulToRead ) {
SetLastError(ERROR_BAD_FORMAT);
RLFREE( pSectTbl);
return ( -1L);
}
pSectTblLast = pSectTbl + NTHdrs.FileHeader.NumberOfSections;
for ( pSect = pSectTbl; pSect < pSectTblLast; ++pSect ) {
if ( lstrcmpA( (CHAR *)pSect->Name, ".rsrc") == SAME && pResSect==NULL ) {
pResSect = pSect;
} else if ( lstrcmpA( (CHAR *)pSect->Name, ".rsrc1") == SAME && pResSectX==NULL ) {
pResSectX = pSect;
}
}
if ( pResSect == NULL ) {
RLFREE( pSectTbl);
QuitA( IDS_NO_RES_SECTION, gMstr.szSrc, NULL);
}
ulOffsetToResources = pResSect->PointerToRawData;
ulOffsetToResourcesX = pResSectX ? pResSectX->PointerToRawData : 0L;
ResSectData.ulVirtualAddress = pResSect->VirtualAddress;
ResSectData.ulSizeOfResources = pResSect->SizeOfRawData;
ResSectData.ulVirtualSize = pResSect->Misc.VirtualSize;
ResSectData.ulVirtualAddressX = pResSectX ? pResSectX->VirtualAddress : 0L;
ResSectData.ulSizeOfResourcesX = pResSectX ? pResSectX->SizeOfRawData : 0L;
ResSectData.ulVirtualSizeX = pResSectX ? pResSectX->Misc.VirtualSize : 0L;
//... Read resource section into memory
pResources = (PUCHAR)FALLOC((ulToRead =
(max(ResSectData.ulVirtualSize, ResSectData.ulSizeOfResources) +
max(ResSectData.ulVirtualSizeX, ResSectData.ulSizeOfResourcesX))));
memset( (PVOID)pResources, 0, ulToRead);
ulRC = ReadResources( fpExe,
ulOffsetToResources,
ResSectData.ulSizeOfResources,
pResources);
if ( ulRC != 0L ) {
RLFREE( pSectTbl);
RLFREE( pResources);
return ( ulRC);
} else if ( ResSectData.ulSizeOfResourcesX > 0L ) {
ulRC = ReadResources( fpExe,
ulOffsetToResourcesX,
ResSectData.ulSizeOfResourcesX,
&pResources[ ResSectData.ulVirtualSize]);
if ( ulRC != 0L ) {
RLFREE( pSectTbl);
RLFREE( pResources);
return ( ulRC);
}
}
//... Now process the resource table
ulRC = ProcessDirectory( fpRes,
0,
&ResSectData,
(PIMAGE_RESOURCE_DIRECTORY)pResources,
(PIMAGE_RESOURCE_DIRECTORY)pResources);
RLFREE( pSectTbl);
RLFREE( pResources);
return ( (LONG)ulRC);
}
//......................................................................
ULONG ProcessDirectory(
FILE *fpRes,
USHORT usLevel,
PRESSECTDATA pResSectData,
PIMAGE_RESOURCE_DIRECTORY pResStart,
PIMAGE_RESOURCE_DIRECTORY pResDir)
{
ULONG ulRC = SUCCESS;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirStart;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEnd;
pResDirStart = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
((PBYTE)pResDir + sizeof( IMAGE_RESOURCE_DIRECTORY));
pResDirEnd = pResDirStart
+ pResDir->NumberOfNamedEntries
+ pResDir->NumberOfIdEntries;
for ( pResDirEntry = pResDirStart, ulRC = 0L;
pResDirEntry < pResDirEnd && ulRC == 0L;
++pResDirEntry ) {
ulRC = ProcessDirEntry( fpRes,
usLevel,
pResSectData,
pResStart,
pResDirEntry);
}
return ( ulRC);
}
//......................................................................
ULONG ProcessDirEntry(
FILE *fpRes,
USHORT usLevel,
PRESSECTDATA pResSectData,
PIMAGE_RESOURCE_DIRECTORY pResStart,
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry)
{
ULONG ulRC = SUCCESS;
if ( pResDirEntry->Name & IMAGE_RESOURCE_NAME_IS_STRING ) {
GetDirNameU( LevelData[ usLevel].wszName,
(PIMAGE_RESOURCE_DIR_STRING_U)((PBYTE)pResStart
+ (pResDirEntry->Name & (~IMAGE_RESOURCE_NAME_IS_STRING))));
LevelData[ usLevel].dwID = IMAGE_RESOURCE_NAME_IS_STRING;
} else {
LevelData[ usLevel].wszName[0] = TEXT('\0');
LevelData[ usLevel].dwID = pResDirEntry->Name;
}
if ( pResDirEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY ) {
ulRC = ProcessSubDir( fpRes,
usLevel,
pResSectData,
pResStart,
pResDirEntry);
} else if ( pResDirEntry->Name & IMAGE_RESOURCE_NAME_IS_STRING ) {
ulRC = ProcessNamedEntry( fpRes, pResSectData, pResStart, pResDirEntry);
} else {
ulRC = ProcessIdEntry( fpRes, pResSectData, pResStart, pResDirEntry);
}
return ( ulRC);
}
//......................................................................
ULONG ProcessSubDir(
FILE *fpRes,
USHORT usLevel,
PRESSECTDATA pResSectData,
PIMAGE_RESOURCE_DIRECTORY pResStart,
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry)
{
PIMAGE_RESOURCE_DIRECTORY pResDir;
pResDir = (PIMAGE_RESOURCE_DIRECTORY)((PBYTE)pResStart
+ (pResDirEntry->OffsetToData & (~IMAGE_RESOURCE_DATA_IS_DIRECTORY)));
return ( ++usLevel < MAXLEVELS ? ProcessDirectory( fpRes,
usLevel,
pResSectData,
pResStart,
pResDir)
: -1L);
}
//......................................................................
ULONG ProcessIdEntry(
FILE *fpRes,
PRESSECTDATA pResSectData,
PIMAGE_RESOURCE_DIRECTORY pResStart,
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry)
{
return ( ProcessDataEntry( fpRes,
pResSectData,
pResStart,
(PIMAGE_RESOURCE_DATA_ENTRY)((PBYTE)pResStart
+ pResDirEntry->OffsetToData)));
}
//......................................................................
ULONG ProcessNamedEntry(
FILE *fpRes,
PRESSECTDATA pResSectData,
PIMAGE_RESOURCE_DIRECTORY pResStart,
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry)
{
return ( ProcessDataEntry( fpRes,
pResSectData,
pResStart,
(PIMAGE_RESOURCE_DATA_ENTRY)((PBYTE)pResStart
+ pResDirEntry->OffsetToData)));
}
//......................................................................
ULONG ProcessDataEntry(
FILE *fpRes,
PRESSECTDATA pResSectData,
PIMAGE_RESOURCE_DIRECTORY pResStart,
PIMAGE_RESOURCE_DATA_ENTRY pResData)
{
ULONG ulOffset;
ULONG ulCopied;
DWORD dwHdrSize = 0L;
fpos_t HdrSizePos;
if ( fGetResLangIDs ) { //... Are we just looking for LANG IDs?
return ( AddToLangIDList( (WORD)(LevelData[2].dwID)));
}
if ( gwFilter != 0 ) { //... Filtering turned on?
//... Yes, is this a resource we want?
if ( LevelData[0].dwID == IMAGE_RESOURCE_NAME_IS_STRING
|| LevelData[0].dwID != (DWORD)gwFilter ) {
return ( 0L); //... Not a resource we want
}
}
//... Are we in the dialog editor?
if ( fInThirdPartyEditer ) { //... Is the language we want?
if ( LevelData[2].dwID != gMstr.wLanguageID ) {
return ( 0L); //... Not the language we want
}
}
ulOffset = pResData->OffsetToData - pResSectData->ulVirtualAddress;
if ( ulOffset >= pResSectData->ulVirtualSize ) {
if ( pResSectData->ulVirtualSizeX > 0L ) {
ulOffset = pResData->OffsetToData
+ pResSectData->ulVirtualSize
- pResSectData->ulVirtualAddressX;
if ( ulOffset >= pResSectData->ulVirtualSize
+ pResSectData->ulSizeOfResourcesX ) {
return ( (ULONG)-1L);
}
} else {
return ( (ULONG)-1L);
}
}
//... write out the resource header info
//... First, write the resource's size
PutdWord( fpRes, pResData->Size, &dwHdrSize);
//... Remember where to write real hdr size and
//... write out bogus hdr size, fix up later
fgetpos( fpRes, &HdrSizePos);
PutdWord( fpRes, 0, &dwHdrSize);
//... Write resource type
if ( LevelData[0].dwID == IMAGE_RESOURCE_NAME_IS_STRING ) {
PutString( fpRes, (TCHAR *)LevelData[0].wszName, &dwHdrSize);
} else {
PutWord( fpRes, IDFLAG, &dwHdrSize);
PutWord( fpRes, LOWORD( LevelData[0].dwID), &dwHdrSize);
}
//... Write resource name
//... dbl-null-terminated if string
if ( LevelData[1].dwID == IMAGE_RESOURCE_NAME_IS_STRING ) {
PutString( fpRes, (TCHAR *)LevelData[1].wszName, &dwHdrSize);
} else {
PutWord( fpRes, IDFLAG, &dwHdrSize);
PutWord( fpRes, LOWORD( LevelData[1].dwID), &dwHdrSize);
}
DWordUpFilePointer( fpRes, MYWRITE, ftell( fpRes), &dwHdrSize);
//... More Win32 header stuff
PutdWord( fpRes, 0, &dwHdrSize); //... Data version
PutWord( fpRes, 0x1030, &dwHdrSize); //... MemoryFlags (WORD)
//... language is always a number (WORD)
PutWord( fpRes, LOWORD( LevelData[2].dwID), &dwHdrSize);
//... More Win32 header stuff
PutdWord( fpRes, 0, &dwHdrSize); //... Version
PutdWord( fpRes, 0, &dwHdrSize); //... Characteristics
//... Now, fix up the resource header size
UpdateResSize( fpRes, &HdrSizePos, dwHdrSize);
//... Copy the resource data to the res file
ulCopied = MyWrite( fpRes, (PUCHAR)pResStart + ulOffset, pResData->Size);
if ( ulCopied != 0L && ulCopied != pResData->Size ) {
return ( (ULONG)-1);
}
DWordUpFilePointer( fpRes, MYWRITE, ftell( fpRes), NULL);
return ( 0L);
}
//......................................................................
/*
* Utility routines
*/
ULONG ReadResources(
FILE *fpExe,
ULONG ulOffsetToResources,
ULONG ulSizeOfResources,
PUCHAR pResources)
{
ULONG ulRC = SUCCESS;
ULONG ulRead;
ulRC = MoveFilePos( fpExe, ulOffsetToResources);
if ( ulRC != 0L ) {
return ( (ULONG)-1L);
}
ulRead = MyRead( fpExe, pResources, ulSizeOfResources);
if ( ulRead != 0L && ulRead != ulSizeOfResources ) {
return ( (ULONG)-1L);
}
return ( 0L);
}
//......................................................................
WCHAR * GetDirNameU(
WCHAR *pszDest,
PIMAGE_RESOURCE_DIR_STRING_U pDirStr)
{
CopyMemory( pszDest, pDirStr->NameString, MEMSIZE( pDirStr->Length));
pszDest[ pDirStr->Length] = L'\0';
return ( pszDest);
}
//......................................................................
ULONG MoveFilePos( FILE *fp, ULONG pos)
{
return ( fseek( fp, pos, SEEK_SET));
}
//......................................................................
ULONG MyWrite( FILE *fp, UCHAR *p, ULONG ulToWrite)
{
size_t cWritten;
cWritten = fwrite( p, 1, (size_t)ulToWrite, fp);
return ( (ULONG)(cWritten == ulToWrite ? 0L : cWritten));
}
//......................................................................
ULONG MyRead( FILE *fp, UCHAR*p, ULONG ulRequested )
{
size_t cRead;
cRead = fread( p, 1, (size_t)ulRequested, fp);
return ( (ULONG)(cRead == ulRequested ? 0L : cRead));
}
//......................................................................
DWORD AddToLangIDList( DWORD dwLangID)
{
WORD wLangID = (WORD)dwLangID;
if ( pLangIDList ) {
PLANGLIST pID;
for ( pID = pLangIDList; pID; pID = pID->pNext ) {
if ( pID->wLang == wLangID ) {
break; //... LANGID already in list
} else if ( pID->pNext == NULL ) {
pID->pNext = (PLANGLIST)FALLOC( sizeof( LANGLIST));
pID = pID->pNext;
pID->pNext = NULL;
pID->wLang = wLangID;
//... LANGID now added to list
}
}
} else {
pLangIDList = (PLANGLIST)FALLOC( sizeof( LANGLIST));
pLangIDList->pNext = NULL;
pLangIDList->wLang = wLangID;
}
return ( SUCCESS);
}