Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1176 lines
34 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
cvtres
Abstract:
This module reads in .res files from OS/2 and writes the resources
in the COFF format for NT. Resources are aligned as necessary
for NT.
Author:
Sanford A. Staab (sanfords) 23-Apr-1990
Revision History:
04-Oct-1990 mikeke
Make it work with named resources
29-May-1990 Steve Wood (stevewo)
Re-wrote the entire thing to sort the resources by type and
id within type before converting.
23-Apr-1990 sanfords
Created
--*/
#include <windows.h>
#include <io.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "cvtres.h"
#include "rc.h"
#include "getmsg.h"
#include "msg.h"
//
// Resources are DWORD aligned and may be in any order.
//
PUCHAR ResTable;
#define TABLE_ALIGN 4
#define DATA_ALIGN 4L
CHAR padding[] = "\0\0\0\0";
const char * const rgszTypeName[] = {
NULL, /* 0 */
"CURSOR", /* 1 */
"BITMAP", /* 2 */
"ICON", /* 3 */
"MENU", /* 4 */
"DIALOG", /* 5 */
"STRING", /* 6 */
"FONTDIR", /* 7 */
"FONT", /* 8 */
"ACCELERATOR", /* 9 */
"RCDATA", /* 10 */
"MESSAGETABLE", /* 11 */
"GROUP_CURSOR", /* 12 */
NULL, /* 13 */
"GROUP_ICON", /* 14 */
NULL, /* 15 */
"VERSION", /* 16 */
"DLGINCLUDE", /* 17 */
NULL, /* 18 */
"PLUGPLAY", /* 19 */
"VXD", /* 20 */
};
typedef struct _RESOURCE_STRING {
ULONG discriminant; // long to make the rest of the struct aligned
union u {
struct {
struct _RESOURCE_STRING *pnext;
ULONG ulOffsetToString;
USHORT cbD;
USHORT cb;
WCHAR sz[1];
};
WORD Ordinal;
};
} RESOURCE_STRING, *PRESOURCE_STRING, **PPRESOURCE_STRING;
#define IS_STRING 1
#define IS_ID 2
// defines to make deferencing easier
#define OffsetToString ulOffsetToString
#define cbData cbD
#define cbsz cb
#define szStr sz
#define pn pnext
typedef struct _RESNAME {
struct _RESNAME *pnext; // The first three fields should be the
PRESOURCE_STRING Name; // same in both res structures
ULONG OffsetToData; //
PRESOURCE_STRING Type;
struct _RESNAME *pnextRes;
RESADDITIONAL *pAdditional;
ULONG OffsetToDataEntry;
USHORT ResourceNumber;
USHORT NumberOfLanguages;
} RESNAME, *PRESNAME, **PPRESNAME;
typedef struct _RESTYPE {
struct _RESTYPE *pnext; // The first three fields should be the
PRESOURCE_STRING Type; // same in both res structures
ULONG OffsetToData; //
struct _RESNAME *NameHeadID;
struct _RESNAME *NameHeadName;
USHORT NumberOfNamesID;
USHORT NumberOfNamesName;
} RESTYPE, *PRESTYPE, **PPRESTYPE;
//
// Globals
//
USHORT cbStringTable = 0L;
PRESOURCE_STRING StringHead = NULL;
PRESNAME ResHead = NULL;
PRESTYPE ResTypeHeadID = NULL;
PRESTYPE ResTypeHeadName = NULL;
USHORT NumberOfNames = 0;
USHORT NumberOfLangDirs = 0;
USHORT NumberOfTypes = 0;
USHORT NumberOfTypesID = 0;
USHORT NumberOfTypesName = 0;
USHORT NumberOfResources = 0;
USHORT NumberOfLanguages = 0;
//
// Default headers
//
IMAGE_FILE_HEADER fhdr = { // main coff file header
IMAGE_FILE_MACHINE_UNKNOWN, // TargetMachine
3, // NumberOfSections
0, // TimeDateStamp
0, // PointerToSymbolTable
2, // NumberOfSymbols;
0, // SizeOfOptionHeader
IMAGE_FILE_32BIT_MACHINE // Characteristics
};
IMAGE_SECTION_HEADER shdr1 = { // CodeView symbols
".debug$S", // Name
0, // PhysicalAddress
0, // VirtualAddress
0, // SizeOfRawData
0, // PointerToRawData
0, // PointerToRelocations
0, // PointerToLinenumbers
0, // NumberOfRelocations
0, // NumberOfLinenumbers
IMAGE_SCN_CNT_INITIALIZED_DATA // Characteristics
| IMAGE_SCN_MEM_READ
| IMAGE_SCN_MEM_DISCARDABLE
| IMAGE_SCN_ALIGN_1BYTES
};
IMAGE_SYMBOL sym1 = {
{ ".debug$S" }, // N.ShortName
0, // Value
1, // SectionNumber
IMAGE_SYM_TYPE_NULL, // Type
IMAGE_SYM_CLASS_STATIC, // StorageClass
0, // NumberOfAuxiliarySymbols
};
IMAGE_SECTION_HEADER shdr2 = { // Resource section
".rsrc$01", // Name (Group table header at beginning)
0, // PhysicalAddress
0, // VirtualAddress
0, // SizeOfRawData
0, // PointerToRawData
0, // PointerToRelocations
0, // PointerToLinenumbers
0, // NumberOfRelocations
0, // NumberOfLinenumbers
IMAGE_SCN_CNT_INITIALIZED_DATA // Characteristics
| IMAGE_SCN_MEM_READ
};
IMAGE_RELOCATION reloc = {
0, // VirtualAddress
1, // SymbolTableIndex
IMAGE_REL_I386_DIR32 // Type
};
IMAGE_SECTION_HEADER shdr3 = { // Resource section
".rsrc$02", // Name (Resource Data after table)
0, // PhysicalAddress
0, // VirtualAddress
0, // SizeOfRawData
0, // PointerToRawData
0, // PointerToRelocations
0, // PointerToLinenumbers
0, // NumberOfRelocations
0, // NumberOfLinenumbers
IMAGE_SCN_CNT_INITIALIZED_DATA // Characteristics
| IMAGE_SCN_MEM_READ
};
IMAGE_SYMBOL sym2 = {
{ ".rsrc$02" }, // N.ShortName
0, // Value
3, // SectionNumber
IMAGE_SYM_TYPE_NULL, // Type
IMAGE_SYM_CLASS_STATIC, // StorageClass
0, // NumberOfAuxiliarySymbols
};
typedef struct CVSIG
{
DWORD dwSignature;
} CVSIG;
static const CVSIG CvSig =
{
1
};
typedef struct CVOBJNAME
{
WORD wLen;
WORD wRecType;
DWORD dwPchSignature;
// Length prefixed object filename is here
} CVOBJNAME;
static CVOBJNAME CvObjName =
{
0, // Filled in at run time
0x0009, // S_OBJNAME
0
};
static const char szCvtresVer[] = "Microsoft CVTRES " VER_PRODUCTVERSION_STR;
typedef struct CVCOMPILE
{
WORD wLen;
WORD wRecType;
BYTE bMachine;
BYTE bLanguage;
BYTE bFlags1;
BYTE bFlags2;
// Length prefixed linker version is here
} CVCOMPILE;
static CVCOMPILE CvCompile =
{
0, // Filled in at run time
0x0001, // S_COMPILE
0, // Filled in at run time
8, // UNDONE: CV_CFL_CVTRES
0x00,
0x08
};
//
// ProtoTypes
//
PRESNAME AddResource(
IN PRESOURCE_STRING Type,
IN PRESOURCE_STRING Name,
IN RESADDITIONAL *pAdditional
);
VOID InitializeDir(
IN PIMAGE_RESOURCE_DIRECTORY pResDir,
IN ULONG characteristics,
IN ULONG version,
IN ULONG timeDate,
IN USHORT cNames,
IN USHORT cID
);
VOID InitializeData(
IN PIMAGE_RESOURCE_DATA_ENTRY pResData,
IN ULONG offset,
IN ULONG size,
IN ULONG codepage,
IN ULONG reserved
);
//
// Reads a String structure from fhIn
// If the first byte is 0xff then this is an ID
// return the ID instead
//
PRESOURCE_STRING ReadStringOrID(
IN FILE *fhIn
)
{
WCHAR ach[256], *s;
USHORT cb;
PRESOURCE_STRING pstring;
PPRESOURCE_STRING ppstring;
s = ach;
MyRead(fhIn, (PUCHAR)s, sizeof(WORD));
if (*s == ID_WORD) {
//
// an ID
//
pstring=(PRESOURCE_STRING)MyAlloc(sizeof(RESOURCE_STRING));
pstring->discriminant = IS_ID;
MyRead(fhIn, ((PUCHAR)&pstring->Ordinal), sizeof(WORD));
}
else {
//
// a string
//
while (*s) {
s++;
MyRead(fhIn, (PUCHAR)s, sizeof(WCHAR));
}
*(s+1) = 0;
cb = s - ach;
//
// see if the string already exists
//
ppstring = &StringHead;
while ((pstring = *ppstring) != NULL) {
if (!wcscmp(pstring->szStr, ach))
break;
ppstring = &(pstring->pn);
}
if (!pstring) {
//
// allocate a new one
//
pstring=(PRESOURCE_STRING)MyAlloc(sizeof(RESOURCE_STRING)+cb*sizeof(WCHAR));
pstring->discriminant = IS_STRING;
pstring->OffsetToString = cbStringTable;
pstring->cbData = sizeof(pstring->cbsz) + cb * sizeof(WCHAR);
pstring->cbsz = cb;
memcpy(pstring->szStr, ach, cb*sizeof(WCHAR));
cbStringTable += pstring->cbData;
pstring->pn=NULL;
*ppstring=pstring;
}
}
return(pstring);
}
//
// add a resource into the resource directory hiearchy
//
PRESNAME
AddResource(
IN PRESOURCE_STRING Type,
IN PRESOURCE_STRING Name,
IN RESADDITIONAL *pAdditional
)
{
PRESTYPE pType;
PPRESTYPE ppType;
PRESNAME pName;
PPRESNAME ppName = NULL;
PRESNAME pNameMatch=NULL;
BOOL fTypeID=(Type->discriminant == IS_ID);
BOOL fNameID=(Name->discriminant == IS_ID);
//
// figure out which list to store it in
//
ppType = fTypeID ? &ResTypeHeadID : &ResTypeHeadName;
//
// Try to find the Type in the list
//
while ((pType=*ppType) != NULL) {
if (pType->Type->Ordinal == Type->Ordinal) {
ppName = fNameID ? &pType->NameHeadID : &pType->NameHeadName;
break;
}
if (fTypeID) {
if (Type->Ordinal < pType->Type->Ordinal)
break;
}
else {
if (wcscmp(Type->szStr, pType->Type->szStr) < 0)
break;
}
ppType = &(pType->pnext);
}
//
// Create a new type if needed
//
if (ppName == NULL) {
NumberOfTypes++;
if (fTypeID) {
NumberOfTypesID++;
}
else {
NumberOfTypesName++;
}
pType = (PRESTYPE)MyAlloc(sizeof(RESTYPE));
pType->pnext = *ppType;
*ppType = pType;
pType->Type = Type;
ppName = fNameID ? &pType->NameHeadID : &pType->NameHeadName;
}
//
// Find proper place for name
//
while ((pName = *ppName) != NULL) {
if (fNameID) {
if (Name->Ordinal == pName->Name->Ordinal &&
pNameMatch == NULL) {
pNameMatch = pName;
break;
}
if (Name->Ordinal < pName->Name->Ordinal)
break;
}
else {
if (wcscmp(Name->szStr, pName->Name->szStr) == 0 &&
pNameMatch == NULL) {
pNameMatch = pName;
break;
}
if (wcscmp(Name->szStr, pName->Name->szStr) < 0)
break;
}
ppName = &(pName->pnext);
}
//
// Add name to list
//
if (pNameMatch != NULL) {
while ((pName = *ppName) != NULL) {
if (pAdditional->LanguageId == pName->pAdditional->LanguageId) {
printf(get_err(MSG_ERROR), 1100, ' ');
if (Type->discriminant == IS_STRING) {
printf(get_err(ERR_DUPRES1), Type->szStr, ' ');
} else if ((Type->Ordinal <= 20) && (rgszTypeName[Type->Ordinal] != NULL)) {
printf(get_err(ERR_DUPRES2), rgszTypeName[Type->Ordinal], ' ');
} else {
printf(get_err(ERR_DUPRESID), Type->Ordinal, ' ');
}
if (Name->discriminant == IS_STRING) {
printf(get_err(ERR_NAMESTR), Name->szStr, pAdditional->LanguageId);
} else {
printf(get_err(ERR_NAMEID), Name->Ordinal, pAdditional->LanguageId);
}
exit(1);
break;
}
if (pAdditional->LanguageId < pName->pAdditional->LanguageId)
break;
if (pName != pNameMatch && pName->NumberOfLanguages != 0)
break;
ppName = &(pName->pnext);
}
}
pName = (PRESNAME)MyAlloc(sizeof(RESNAME));
pName->pnext = *ppName;
*ppName = pName;
pName->Name = Name;
pName->Type = Type;
pName->pAdditional = pAdditional;
//
// keep track of language information
//
if (pNameMatch != NULL) { /* did we add another language? */
NumberOfLanguages++; /* yes, increase list size */
if (pNameMatch == pName->pnext) { /* is new now first in list? */
pName->NumberOfLanguages = pNameMatch->NumberOfLanguages + 1;
/* increment count for head */
pNameMatch->NumberOfLanguages = 0; /* mark not first */
}
else { /* not first in list */
pNameMatch->NumberOfLanguages++; /* increment count for head */
pName->NumberOfLanguages = 0; /* mark not first */
}
}
else { /* just adding an id */
NumberOfNames++; /* one more name */
NumberOfLanguages++; /* one more language */
NumberOfLangDirs++; /* one more language directory */
pName->NumberOfLanguages = 1; /* one language */
if (fNameID) {
pType->NumberOfNamesID += 1; /* add a name id to type */
}
else {
pType->NumberOfNamesName += 1; /* add a name name to type */
}
}
return pName;
}
BOOL
CvtRes(
IN FILE *fhIn,
IN FILE *fhOut,
IN ULONG cbInFile,
IN BOOL fWritable,
IN ULONG timeDate
)
/*++
Routine Description:
Does actual res to coff conversion
1) read resource types and IDs and build up RSRC1 and RSRC2 tables
in memory.
2) Write coff headers
3) Write RSRC1
4) leave space for RSRC2 and transform-copy resource data
to RSRC3 section while finalizing RSRC2 data size fields.
4) Write RSRC2 section.
Arguments:
fhIn - Supplies input file handle.
fhOut - Supplies output file handle.
cbInFile - Supplies size of input file.
Return Value:
fSuccess
--*/
{
LONG cbPad;
ULONG offHere; // input file offset
PRESTYPE pType;
PRESNAME pName;
PRESNAME pNextName;
PRESOURCE_STRING Type;
PRESOURCE_STRING Name;
PRESOURCE_STRING pstring;
ULONG hdrSize;
ULONG dataSize;
ULONG offTypeDir;
ULONG offNameDirs;
ULONG offLangDirs;
ULONG offDataEntries;
ULONG offStringTable;
ULONG cbRes;
ULONG cLanguages;
ULONG cbResTable;
RESADDITIONAL *pAdditional;
PIMAGE_RESOURCE_DIRECTORY ResourceTypeDirectory;
PIMAGE_RESOURCE_DIRECTORY ResourceNameDirectory;
PIMAGE_RESOURCE_DIRECTORY ResourceLangDirectory;
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
PIMAGE_RESOURCE_DIRECTORY_STRING ResourceStringEntry;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceTypeDirectoryEntry;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceNameDirectoryEntry;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResourceLangDirectoryEntry;
BYTE cchObjName;
BYTE cchCvtresVer;
//
// Build up Type and Name directories
//
offHere = 0;
pNextName = NULL;
while (offHere < cbInFile) {
//
// Get the sizes from the file
//
MyRead(fhIn, (PUCHAR)&dataSize, sizeof(ULONG));
MyRead(fhIn, (PUCHAR)&hdrSize, sizeof(ULONG));
if (hdrSize < 2*sizeof(ULONG)) {
ErrorPrint(ERR_FILECORRUPT, szInFile);
return(FALSE);
}
//
// discard null resource
//
if (dataSize == 0) {
offHere = MySeek(fhIn, hdrSize-2*sizeof(ULONG), SEEK_CUR);
continue;
}
pAdditional = (RESADDITIONAL*)MyAlloc(sizeof(RESADDITIONAL));
pAdditional->HeaderSize = hdrSize;
pAdditional->DataSize = dataSize;
//
// Read the TYPE and NAME
//
Type=ReadStringOrID(fhIn);
Name=ReadStringOrID(fhIn);
offHere = MySeek(fhIn, 0, SEEK_CUR);
while (offHere & 3)
offHere = MySeek(fhIn, 1, SEEK_CUR);
//
// Read the rest of the header
//
MyRead(fhIn, (PUCHAR)&pAdditional->DataVersion,
sizeof(RESADDITIONAL)-2*sizeof(ULONG));
//
// if name table then discard it
//
if (Type->discriminant == IS_STRING ||
!(Type->Ordinal == (INT)RT_DLGINCLUDE)) {
if (fVerbose) {
if (Type->discriminant == IS_STRING) {
printf(get_err(INFO_ADDRESOURCE1), Type->szStr, ' ');
} else if ((Type->Ordinal <= 20) && (rgszTypeName[Type->Ordinal] != NULL)) {
printf(get_err(INFO_ADDRESOURCE2), rgszTypeName[Type->Ordinal], ' ');
} else {
printf(get_err(INFO_ADDRESOURCE3), Type->Ordinal, ' ');
}
if (Name->discriminant == IS_STRING) {
printf(get_err(INFO_NAME1), Name->szStr, ' ');
} else {
printf(get_err(INFO_NAME2), Name->Ordinal, ' ');
}
printf(get_err(INFO_LANGUAGE),
pAdditional->LanguageId,
pAdditional->MemoryFlags,
pAdditional->DataSize);
}
pName = AddResource(Type, Name, pAdditional);
pName->OffsetToData = MySeek(fhIn, 0, SEEK_CUR);
pName->ResourceNumber = NumberOfResources++;
//
// put resource into the overall resource list
//
if (!pNextName)
ResHead=pName;
else
pNextName->pnextRes = pName;
pNextName = pName;
}
offHere = MySeek(fhIn, pAdditional->DataSize, SEEK_CUR);
while (offHere & 3)
offHere = MySeek(fhIn, 1, SEEK_CUR);
}
//
// Allocate space for an in-memory copy of the resource table. The
// format of the table will be:
//
// RootDirectory of Types
// SubDirectories of Names
// Array of Data Entry records
// Array of string records
//
offTypeDir = sizeof(IMAGE_RESOURCE_DIRECTORY);
offNameDirs = offTypeDir +
(sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) * NumberOfTypes);
offLangDirs = offNameDirs +
(sizeof(IMAGE_RESOURCE_DIRECTORY) * NumberOfTypes) +
(sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) * NumberOfNames);
offDataEntries = offLangDirs +
(sizeof(IMAGE_RESOURCE_DIRECTORY) * NumberOfLangDirs) +
(sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) * NumberOfLanguages);
offStringTable = offDataEntries +
(sizeof(IMAGE_RESOURCE_DATA_ENTRY) * NumberOfResources);
#if DBG
if (fDebug) {
printf("Offsets\tTypeDir\tNameDir\tLangDir\tData\tString\n");
printf("\t0x%lx\t0x%lx\t0x%lx\t0x%lx\t0x%lx\n",
offTypeDir,
offNameDirs,
offLangDirs,
offDataEntries,
offStringTable);
}
#endif /* DBG */
cbRes = offStringTable + cbStringTable;
cbResTable = ((cbRes + TABLE_ALIGN-1) / TABLE_ALIGN) * TABLE_ALIGN;
ResTable = (PUCHAR)MyAlloc(cbResTable+4);
while ((ULONG)ResTable & 3)
ResTable++;
ResourceTypeDirectory = (PIMAGE_RESOURCE_DIRECTORY)ResTable;
#if DBG
if (fDebug) {
printf("Main directory - ");
}
#endif /* DBG */
InitializeDir(ResourceTypeDirectory, 0, 0, timeDate,
NumberOfTypesName, NumberOfTypesID);
ResourceTypeDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResTable + offTypeDir);
ResourceNameDirectory = (PIMAGE_RESOURCE_DIRECTORY)(ResTable + offNameDirs);
ResourceLangDirectory = (PIMAGE_RESOURCE_DIRECTORY)(ResTable + offLangDirs);
ResourceDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)(ResTable + offDataEntries);
ResourceStringEntry = (PIMAGE_RESOURCE_DIRECTORY_STRING)(ResTable + offStringTable);
pType = ResTypeHeadName;
while (pType) {
ResourceTypeDirectoryEntry->Name = IMAGE_RESOURCE_NAME_IS_STRING |
(offStringTable + pType->Type->OffsetToString);
ResourceTypeDirectoryEntry->OffsetToData = IMAGE_RESOURCE_DATA_IS_DIRECTORY |
(ULONG)((PUCHAR)ResourceNameDirectory - ResTable);
ResourceTypeDirectoryEntry++;
#if DBG
if (fDebug) {
printf("\tName directory - ");
}
#endif /* DBG */
InitializeDir(ResourceNameDirectory, 0, 0, timeDate,
pType->NumberOfNamesName, pType->NumberOfNamesID);
ResourceNameDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
(ResourceNameDirectory + 1);
pName = pType->NameHeadName;
while (pName) {
#if DBG
if (fDebug) {
printf("\t\tLanguage directory - ");
}
#endif /* DBG */
InitializeDir(ResourceLangDirectory, 0, 0, timeDate,
0, pName->NumberOfLanguages);
ResourceLangDirectoryEntry =
(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceLangDirectory+1);
ResourceNameDirectoryEntry->Name =
IMAGE_RESOURCE_NAME_IS_STRING |
(offStringTable + pName->Name->OffsetToString);
ResourceNameDirectoryEntry->OffsetToData =
IMAGE_RESOURCE_DATA_IS_DIRECTORY |
(ULONG)((PUCHAR)ResourceLangDirectory - ResTable);
cLanguages = pName->NumberOfLanguages;
while (cLanguages--) {
ResourceLangDirectoryEntry->Name =
(ULONG)pName->pAdditional->LanguageId;
ResourceLangDirectoryEntry->OffsetToData =
(ULONG)((PUCHAR)ResourceDataEntry - ResTable);
pName->OffsetToDataEntry =
ResourceLangDirectoryEntry->OffsetToData;
InitializeData(ResourceDataEntry, 0, 0, 0, 0);
ResourceDataEntry++;
ResourceLangDirectoryEntry++;
pName = pName->pnext;
}
ResourceLangDirectory = (PIMAGE_RESOURCE_DIRECTORY)
ResourceLangDirectoryEntry;
ResourceNameDirectoryEntry++;
}
pName = pType->NameHeadID;
while (pName) {
#if DBG
if (fDebug) {
printf("\t\tLanguage directory - ");
}
#endif /* DBG */
InitializeDir(ResourceLangDirectory, 0, 0, timeDate,
0, pName->NumberOfLanguages);
ResourceLangDirectoryEntry =
(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceLangDirectory+1);
ResourceNameDirectoryEntry->Name = pName->Name->Ordinal;
ResourceNameDirectoryEntry->OffsetToData =
IMAGE_RESOURCE_DATA_IS_DIRECTORY |
(ULONG)((PUCHAR)ResourceLangDirectory - ResTable);
cLanguages = pName->NumberOfLanguages;
while (cLanguages--) {
ResourceLangDirectoryEntry->Name =
(ULONG)pName->pAdditional->LanguageId;
ResourceLangDirectoryEntry->OffsetToData =
(ULONG)((PUCHAR)ResourceDataEntry - ResTable);
pName->OffsetToDataEntry =
ResourceLangDirectoryEntry->OffsetToData;
InitializeData(ResourceDataEntry, 0, 0, 0, 0);
ResourceDataEntry++;
ResourceLangDirectoryEntry++;
pName = pName->pnext;
}
ResourceLangDirectory = (PIMAGE_RESOURCE_DIRECTORY)
ResourceLangDirectoryEntry;
ResourceNameDirectoryEntry++;
}
ResourceNameDirectory = (PIMAGE_RESOURCE_DIRECTORY)ResourceNameDirectoryEntry;
pType = pType->pnext;
}
pType = ResTypeHeadID;
while (pType) {
ResourceTypeDirectoryEntry->Name = pType->Type->Ordinal;
ResourceTypeDirectoryEntry->OffsetToData = IMAGE_RESOURCE_DATA_IS_DIRECTORY | (ULONG)
((PUCHAR)ResourceNameDirectory - ResTable);
ResourceTypeDirectoryEntry++;
#if DBG
if (fDebug) {
printf("\tName directory - ");
}
#endif /* DBG */
InitializeDir(ResourceNameDirectory, 0, 0, timeDate,
pType->NumberOfNamesName, pType->NumberOfNamesID);
ResourceNameDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
(ResourceNameDirectory + 1);
pName = pType->NameHeadName;
while (pName) {
#if DBG
if (fDebug) {
printf("\t\tLanguage directory - ");
}
#endif /* DBG */
InitializeDir(ResourceLangDirectory, 0, 0, timeDate,
0, pName->NumberOfLanguages);
ResourceLangDirectoryEntry =
(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceLangDirectory+1);
ResourceNameDirectoryEntry->Name =
IMAGE_RESOURCE_NAME_IS_STRING |
(offStringTable + pName->Name->OffsetToString);
ResourceNameDirectoryEntry->OffsetToData =
IMAGE_RESOURCE_DATA_IS_DIRECTORY |
(ULONG)((PUCHAR)ResourceLangDirectory - ResTable);
cLanguages = pName->NumberOfLanguages;
while (cLanguages--) {
ResourceLangDirectoryEntry->Name =
(ULONG)pName->pAdditional->LanguageId;
ResourceLangDirectoryEntry->OffsetToData =
(ULONG)((PUCHAR)ResourceDataEntry - ResTable);
pName->OffsetToDataEntry =
ResourceLangDirectoryEntry->OffsetToData;
InitializeData(ResourceDataEntry, 0, 0, 0, 0);
ResourceDataEntry++;
ResourceLangDirectoryEntry++;
pName = pName->pnext;
}
ResourceLangDirectory = (PIMAGE_RESOURCE_DIRECTORY)
ResourceLangDirectoryEntry;
ResourceNameDirectoryEntry++;
}
pName = pType->NameHeadID;
while (pName) {
#if DBG
if (fDebug) {
printf("\t\tLanguage directory - ");
}
#endif /* DBG */
InitializeDir(ResourceLangDirectory, 0, 0, timeDate,
0, pName->NumberOfLanguages);
ResourceLangDirectoryEntry =
(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceLangDirectory+1);
ResourceNameDirectoryEntry->Name = pName->Name->Ordinal;
ResourceNameDirectoryEntry->OffsetToData =
IMAGE_RESOURCE_DATA_IS_DIRECTORY |
(ULONG)((PUCHAR)ResourceLangDirectory - ResTable);
cLanguages = pName->NumberOfLanguages;
while (cLanguages--) {
ResourceLangDirectoryEntry->Name =
(ULONG)pName->pAdditional->LanguageId;
ResourceLangDirectoryEntry->OffsetToData =
(ULONG)((PUCHAR)ResourceDataEntry - ResTable);
pName->OffsetToDataEntry =
ResourceLangDirectoryEntry->OffsetToData;
InitializeData(ResourceDataEntry, 0, 0, 0, 0);
ResourceDataEntry++;
ResourceLangDirectoryEntry++;
pName = pName->pnext;
}
ResourceLangDirectory = (PIMAGE_RESOURCE_DIRECTORY)
ResourceLangDirectoryEntry;
ResourceNameDirectoryEntry++;
}
ResourceNameDirectory = (PIMAGE_RESOURCE_DIRECTORY)ResourceNameDirectoryEntry;
pType = pType->pnext;
}
//
// Fill in the string table
//
pstring = StringHead;
while (pstring) {
// Copy the string and include the length preceding the string
ResourceStringEntry->Length = pstring->cbsz;
memcpy(ResourceStringEntry, &pstring->cbsz, pstring->cbData);
ResourceStringEntry = (PIMAGE_RESOURCE_DIRECTORY_STRING)
((PUCHAR)ResourceStringEntry + pstring->cbData);
while ((ULONG)ResourceStringEntry & 1)
((PUCHAR)ResourceStringEntry) ++;
pstring = pstring->pn;
}
//
// Fill in the file header
//
fhdr.TimeDateStamp = timeDate;
fhdr.Machine = targetMachine;
if (fWritable) {
shdr2.Characteristics |= IMAGE_SCN_MEM_WRITE;
shdr3.Characteristics |= IMAGE_SCN_MEM_WRITE;
}
//
// Fill in the section header values that we know so far
//
shdr1.PointerToRawData = sizeof(fhdr) + sizeof(shdr1) + sizeof(shdr2) + sizeof(shdr3);
//
// Write the CodeView symbols
//
MySeek(fhOut, shdr1.PointerToRawData, SEEK_SET);
MyWrite(fhOut, (PUCHAR) &CvSig, sizeof(CvSig));
cchObjName = (BYTE) strlen(szOutFile);
CvObjName.wLen = (WORD) (sizeof(CvObjName) + sizeof(BYTE) + cchObjName - sizeof(WORD));
MyWrite(fhOut, (PUCHAR) &CvObjName, sizeof(CvObjName));
MyWrite(fhOut, (PUCHAR) &cchObjName, sizeof(BYTE));
MyWrite(fhOut, (PUCHAR) szOutFile, (DWORD) cchObjName);
cchCvtresVer = (BYTE) strlen(szCvtresVer);
CvCompile.wLen = (WORD) (sizeof(CvCompile) + sizeof(BYTE) + cchCvtresVer - sizeof(WORD));
MyWrite(fhOut, (PUCHAR) &CvCompile, sizeof(CvCompile));
MyWrite(fhOut, (PUCHAR) &cchCvtresVer, sizeof(BYTE));
MyWrite(fhOut, (PUCHAR) szCvtresVer, (DWORD) cchCvtresVer);
shdr1.SizeOfRawData = MySeek(fhOut, 0L, SEEK_CUR) - shdr1.PointerToRawData;
if (shdr1.SizeOfRawData & 1) {
// Pad section to even byte boundary
MyWrite(fhOut, padding, 1);
}
//
// Build header for resource table
//
shdr2.PointerToRawData = MySeek(fhOut, 0L, SEEK_CUR);
shdr2.NumberOfRelocations = NumberOfResources;
shdr2.SizeOfRawData = cbResTable;
shdr2.PointerToRelocations = shdr2.PointerToRawData + cbResTable;
//
// Write resource data
//
shdr3.PointerToRawData = shdr2.PointerToRelocations +
shdr2.NumberOfRelocations * sizeof(IMAGE_RELOCATION);
MySeek(fhOut, shdr3.PointerToRawData, SEEK_SET);
pName = ResHead;
while (pName) {
offHere = MySeek(fhIn, pName->OffsetToData, SEEK_SET);
while (offHere & 3)
offHere = MySeek(fhIn, 1, SEEK_CUR);
pName->OffsetToData = MySeek(fhOut, 0L, SEEK_CUR) -
shdr3.PointerToRawData;
MyCopy(fhIn, fhOut, pName->pAdditional->DataSize);
if ((cbPad = ((DATA_ALIGN-pName->pAdditional->DataSize%DATA_ALIGN)
% DATA_ALIGN)) != 0) {
MyWrite(fhOut, padding, cbPad);
}
ResourceDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)
(ResTable + pName->OffsetToDataEntry);
ResourceDataEntry->Size = pName->pAdditional->DataSize;
ResourceDataEntry->OffsetToData = pName->OffsetToData;
pName = pName->pnextRes;
}
shdr3.SizeOfRawData = MySeek(fhOut, 0L, SEEK_CUR) - shdr3.PointerToRawData;
if (shdr3.SizeOfRawData & 1) {
// Pad section to even byte boundary
MyWrite(fhOut, padding, 1);
}
//
// Output the symbol table
//
fhdr.PointerToSymbolTable = MySeek(fhOut, 0L, SEEK_CUR);
MyWrite(fhOut, (PUCHAR) &sym1, sizeof(IMAGE_SYMBOL));
MyWrite(fhOut, (PUCHAR) &sym2, sizeof(IMAGE_SYMBOL));
//
// Output the string table
//
MyWrite(fhOut, padding, sizeof(ULONG));
//
// Truncate the output file.
//
_chsize(_fileno(fhOut), MySeek(fhOut, 0L, SEEK_CUR));
//
// write completed file and section headers
//
MySeek(fhOut, 0L, SEEK_SET);
MyWrite(fhOut, (PUCHAR) &fhdr, sizeof(fhdr));
MyWrite(fhOut, (PUCHAR) &shdr1, sizeof(shdr1));
MyWrite(fhOut, (PUCHAR) &shdr2, sizeof(shdr2));
MyWrite(fhOut, (PUCHAR) &shdr3, sizeof(shdr3));
//
// write the resource table
//
MySeek(fhOut, shdr2.PointerToRawData, SEEK_SET);
MyWrite(fhOut, ResTable, cbResTable);
//
// write out the relocation records for the resource data entries
//
MySeek(fhOut, shdr2.PointerToRelocations, SEEK_SET);
reloc.Type = targetRelocType;
pName = ResHead;
while (pName) {
reloc.VirtualAddress = pName->OffsetToDataEntry;
MyWrite(fhOut, (PUCHAR) &reloc, sizeof(IMAGE_RELOCATION));
pName = pName->pnextRes;
}
return(TRUE);
}
VOID InitializeDir(
IN PIMAGE_RESOURCE_DIRECTORY pResDir,
IN ULONG characteristics,
IN ULONG version,
IN ULONG timeDate,
IN USHORT cNames,
IN USHORT cID
)
{
#if DBG
if (fDebug) {
printf("@ 0x%lx - %d names, %d ordinals\n", (ULONG)pResDir-(ULONG)ResTable, (LONG)cNames, (LONG)cID);
}
#endif /* DBG */
pResDir->Characteristics = characteristics;
pResDir->TimeDateStamp = timeDate;
pResDir->MajorVersion = HIWORD(version);
pResDir->MinorVersion = LOWORD(version);
pResDir->NumberOfNamedEntries = cNames;
pResDir->NumberOfIdEntries = cID;
}
VOID InitializeData(
IN PIMAGE_RESOURCE_DATA_ENTRY pResData,
IN ULONG offset,
IN ULONG size,
IN ULONG codepage,
IN ULONG reserved
)
{
#if DBG
if (fDebug) {
printf("\t\t\tData at 0x%lx\n", (ULONG)pResData-(ULONG)ResTable);
}
#endif /* DBG */
pResData->OffsetToData = offset;
pResData->Size = size;
pResData->CodePage = codepage;
pResData->Reserved = reserved;
}