1265 lines
38 KiB
C++
1265 lines
38 KiB
C++
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: mkasm.cpp
|
||
|
//
|
||
|
// Contents: Converts binary files into .asm or .cs files.
|
||
|
//
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stddef.h>
|
||
|
#include <winlean.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
enum {
|
||
|
TARGET_BASE = 0x60000,
|
||
|
TARGET_RANGE = 0x10000,
|
||
|
};
|
||
|
|
||
|
BOOL fAsm = TRUE;
|
||
|
BOOL fCpp = FALSE;
|
||
|
BOOL fManaged = FALSE;
|
||
|
BOOL fCompress = FALSE;
|
||
|
BOOL fList = FALSE;
|
||
|
BOOL fAllow64 = FALSE;
|
||
|
|
||
|
CHAR szByteByteVTable[] = "?_vtable@ClassVector_ClassVector_uint8@@2UClass_System_VTable@@A";
|
||
|
// struct Class_System_VTable ClassVector_ClassVector_uint8::_vtable
|
||
|
|
||
|
CHAR szByteByteSuffix[] = "@@2PAUClassVector_ClassVector_uint8@@A";
|
||
|
// ?c_Content@Class_Microsoft_Singularity_Shell_Slides@@2PAUClassVector_ClassVector_uint8@@A
|
||
|
// struct ClassVector_ClassVector_uint8 * Class_Microsoft_Singularity_Shell_Slides::c_Content
|
||
|
|
||
|
CHAR szByteVTable[] = "?_vtable@ClassVector_uint8@@2UClass_System_VTable@@A";
|
||
|
// struct Class_System_VTable ClassVector_uint8::_vtable
|
||
|
|
||
|
CHAR szByteSuffix[] = "@@2PAUClassVector_uint8@@A";
|
||
|
// ?c_Content@Class_Microsoft_Singularity_Shell_Slides@@2PAUClassVector_ClassVector_uint8@@A
|
||
|
// struct ClassVector_ClassVector_uint8 * Class_Microsoft_Singularity_Shell_Slides::c_Content
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
class CFileInfo
|
||
|
{
|
||
|
public:
|
||
|
CFileInfo()
|
||
|
{
|
||
|
m_pszFile = NULL;
|
||
|
m_pNext = NULL;
|
||
|
m_cbInput = 0;
|
||
|
m_cbOutput = 0;
|
||
|
}
|
||
|
|
||
|
BOOL SetFileName(PCSTR pszFile)
|
||
|
{
|
||
|
m_pszFile = pszFile;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL SetFileAndSize()
|
||
|
{
|
||
|
HANDLE hFile = CreateFile(m_pszFile,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
NULL);
|
||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
m_cbInput = GetFileSize(hFile, NULL);
|
||
|
CloseHandle(hFile);
|
||
|
|
||
|
if (m_cbInput == 0xffffffff) {
|
||
|
m_cbInput = 0;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
m_cbOutput = m_cbInput;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL SetOutputSize(UINT32 cbOutput)
|
||
|
{
|
||
|
m_cbOutput = cbOutput;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
CFileInfo * m_pNext;
|
||
|
PCSTR m_pszFile;
|
||
|
UINT32 m_cbInput;
|
||
|
UINT32 m_cbOutput;
|
||
|
};
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////// CFileMap.
|
||
|
//
|
||
|
class CFileMap
|
||
|
{
|
||
|
public:
|
||
|
CFileMap();
|
||
|
~CFileMap();
|
||
|
|
||
|
public:
|
||
|
BOOL Load(PCSTR pszFile);
|
||
|
PBYTE Seek(UINT32 cbPos);
|
||
|
UINT32 Size();
|
||
|
VOID Close();
|
||
|
|
||
|
protected:
|
||
|
PBYTE m_pbData;
|
||
|
UINT32 m_cbData;
|
||
|
};
|
||
|
|
||
|
CFileMap::CFileMap()
|
||
|
{
|
||
|
m_pbData = NULL;
|
||
|
m_cbData = 0;
|
||
|
}
|
||
|
|
||
|
CFileMap::~CFileMap()
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
VOID CFileMap::Close()
|
||
|
{
|
||
|
if (m_pbData) {
|
||
|
UnmapViewOfFile(m_pbData);
|
||
|
m_pbData = NULL;
|
||
|
}
|
||
|
m_cbData = 0;
|
||
|
}
|
||
|
|
||
|
UINT32 CFileMap::Size()
|
||
|
{
|
||
|
return m_cbData;
|
||
|
}
|
||
|
|
||
|
PBYTE CFileMap::Seek(UINT32 cbPos)
|
||
|
{
|
||
|
if (m_pbData && cbPos <= m_cbData) {
|
||
|
return m_pbData + cbPos;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
BOOL CFileMap::Load(PCSTR pszFile)
|
||
|
{
|
||
|
Close();
|
||
|
|
||
|
HANDLE hFile = CreateFile(pszFile,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
0,
|
||
|
NULL);
|
||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ULONG cbInFileData = GetFileSize(hFile, NULL);
|
||
|
if (cbInFileData == 0xffffffff) {
|
||
|
CloseHandle(hFile);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
HANDLE hInFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||
|
CloseHandle(hFile);
|
||
|
if (hInFileMap == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
m_pbData = (PBYTE)MapViewOfFile(hInFileMap, FILE_MAP_COPY, 0, 0, 0);
|
||
|
CloseHandle(hInFileMap);
|
||
|
if (m_pbData == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
m_cbData = cbInFileData;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////// CFileOut.
|
||
|
//
|
||
|
class CFileOut
|
||
|
{
|
||
|
public:
|
||
|
CFileOut();
|
||
|
~CFileOut();
|
||
|
|
||
|
public:
|
||
|
BOOL Create(PCSTR pszFile);
|
||
|
BOOL IsOpen();
|
||
|
|
||
|
BOOL Write(PBYTE pbData, UINT32 cbData);
|
||
|
BOOL Print(PCSTR pszMsg, ...);
|
||
|
BOOL VPrint(PCSTR pszMsg, va_list args);
|
||
|
BOOL Delete();
|
||
|
|
||
|
VOID Close();
|
||
|
|
||
|
protected:
|
||
|
HANDLE m_hFile;
|
||
|
CHAR m_szFile[MAX_PATH];
|
||
|
CHAR m_szBuffer[4096];
|
||
|
INT m_cbBuffer;
|
||
|
};
|
||
|
|
||
|
CFileOut::CFileOut()
|
||
|
{
|
||
|
m_hFile = INVALID_HANDLE_VALUE;
|
||
|
m_szFile[0] = '\0';
|
||
|
m_cbBuffer = 0;
|
||
|
}
|
||
|
|
||
|
CFileOut::~CFileOut()
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
VOID CFileOut::Close()
|
||
|
{
|
||
|
if (m_hFile != INVALID_HANDLE_VALUE) {
|
||
|
if (m_cbBuffer) {
|
||
|
Write((PBYTE)m_szBuffer, m_cbBuffer);
|
||
|
m_cbBuffer = 0;
|
||
|
}
|
||
|
CloseHandle(m_hFile);
|
||
|
m_hFile = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL CFileOut::IsOpen()
|
||
|
{
|
||
|
return (m_hFile != INVALID_HANDLE_VALUE);
|
||
|
}
|
||
|
|
||
|
BOOL CFileOut::Write(PBYTE pbData, UINT32 cbData)
|
||
|
{
|
||
|
if (m_hFile == INVALID_HANDLE_VALUE) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DWORD dwWrote = 0;
|
||
|
if (!WriteFile(m_hFile, pbData, cbData, &dwWrote, NULL) || dwWrote != cbData) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CFileOut::VPrint(PCSTR pszMsg, va_list args)
|
||
|
{
|
||
|
if (m_hFile == INVALID_HANDLE_VALUE) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
INT cbUsed = m_cbBuffer;
|
||
|
INT cbData;
|
||
|
|
||
|
cbData = _vsnprintf(m_szBuffer + cbUsed, sizeof(m_szBuffer)-cbUsed-1, pszMsg, args);
|
||
|
m_cbBuffer += cbData;
|
||
|
|
||
|
if (m_szBuffer[m_cbBuffer - 1] == '\n' ||
|
||
|
m_szBuffer[m_cbBuffer - 1] == '\r') {
|
||
|
|
||
|
cbData = m_cbBuffer;
|
||
|
m_cbBuffer = 0;
|
||
|
return Write((PBYTE)m_szBuffer, cbData);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CFileOut::Print(PCSTR pszMsg, ...)
|
||
|
{
|
||
|
BOOL f;
|
||
|
|
||
|
va_list args;
|
||
|
va_start(args, pszMsg);
|
||
|
f = VPrint(pszMsg, args);
|
||
|
va_end(args);
|
||
|
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
BOOL CFileOut::Delete()
|
||
|
{
|
||
|
if (m_hFile != INVALID_HANDLE_VALUE) {
|
||
|
Close();
|
||
|
return DeleteFile(m_szFile);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CFileOut::Create(PCSTR pszFile)
|
||
|
{
|
||
|
Close();
|
||
|
m_szFile[0] = '\0';
|
||
|
m_hFile = CreateFile(pszFile,
|
||
|
GENERIC_WRITE,
|
||
|
0, NULL, CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||
|
if (m_hFile == INVALID_HANDLE_VALUE) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
strcpy(m_szFile, pszFile);
|
||
|
m_cbBuffer = 0;
|
||
|
return TRUE;
|
||
|
}
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
class COutput
|
||
|
{
|
||
|
protected:
|
||
|
UINT m_nOffset;
|
||
|
CFileOut *m_pfOutput;
|
||
|
|
||
|
public:
|
||
|
COutput(CFileOut *pfOutput)
|
||
|
{
|
||
|
m_pfOutput = pfOutput;
|
||
|
m_nOffset = 0;
|
||
|
}
|
||
|
|
||
|
BOOL VPrint(PCSTR pszMsg, va_list args)
|
||
|
{
|
||
|
return m_pfOutput->VPrint(pszMsg, args);
|
||
|
}
|
||
|
|
||
|
BOOL Print(PCSTR pszMsg, ...)
|
||
|
{
|
||
|
BOOL f;
|
||
|
|
||
|
va_list args;
|
||
|
va_start(args, pszMsg);
|
||
|
f = m_pfOutput->VPrint(pszMsg, args);
|
||
|
va_end(args);
|
||
|
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
virtual void Dump(PBYTE pbData, UINT cbData) = 0;
|
||
|
|
||
|
virtual void Finish()
|
||
|
{
|
||
|
if ((m_nOffset % 16) != 0) {
|
||
|
m_pfOutput->Print("\n");
|
||
|
}
|
||
|
m_nOffset = 0;
|
||
|
}
|
||
|
|
||
|
UINT Size()
|
||
|
{
|
||
|
return m_nOffset;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CAsmOutput : public COutput
|
||
|
{
|
||
|
public:
|
||
|
CAsmOutput(CFileOut *pfOutput)
|
||
|
: COutput(pfOutput)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void Dump(PBYTE pbData, UINT cbData)
|
||
|
{
|
||
|
PBYTE pbEnd = pbData + cbData;
|
||
|
|
||
|
for (; pbData < pbEnd; pbData++, m_nOffset++) {
|
||
|
switch (m_nOffset % 16) {
|
||
|
case 0:
|
||
|
Print(" uint8 %03xh", *pbData);
|
||
|
break;
|
||
|
default:
|
||
|
Print(",%03xh", *pbData);
|
||
|
break;
|
||
|
case 15:
|
||
|
Print(",%03xh\n", *pbData);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class CSharpOutput : public COutput
|
||
|
{
|
||
|
public:
|
||
|
CSharpOutput(CFileOut *pfOutput)
|
||
|
: COutput(pfOutput)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void Dump(PBYTE pbData, UINT cbData)
|
||
|
{
|
||
|
PBYTE pbEnd = pbData + cbData;
|
||
|
|
||
|
for (; pbData < pbEnd; pbData++, m_nOffset++) {
|
||
|
switch (m_nOffset % 16) {
|
||
|
case 0:
|
||
|
Print(" 0x%02x,", *pbData);
|
||
|
break;
|
||
|
default:
|
||
|
Print("0x%02x,", *pbData);
|
||
|
break;
|
||
|
case 15:
|
||
|
Print("0x%02x,\n", *pbData);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
UINT DumpBmp(COutput *output, PBYTE pbData, UINT cbData)
|
||
|
{
|
||
|
#pragma pack(2)
|
||
|
struct BITMAPFILEHEADER {
|
||
|
UINT16 bfType;
|
||
|
UINT32 bfSize;
|
||
|
UINT16 bfReserved1;
|
||
|
UINT16 bfReserved2;
|
||
|
UINT32 bfOffBits;
|
||
|
};
|
||
|
|
||
|
struct BITMAPINFOHEADER {
|
||
|
UINT32 biSize;
|
||
|
UINT32 biWidth;
|
||
|
UINT32 biHeight;
|
||
|
UINT16 biPlanes;
|
||
|
UINT16 biBitCount;
|
||
|
UINT32 biCompression;
|
||
|
UINT32 biSizeImage;
|
||
|
UINT32 biXPelsPerMeter;
|
||
|
UINT32 biYPelsPerMeter;
|
||
|
UINT32 biClrUsed;
|
||
|
UINT32 biClrImportant;
|
||
|
};
|
||
|
#pragma pack()
|
||
|
|
||
|
BITMAPFILEHEADER *pbmf = (BITMAPFILEHEADER *)pbData;
|
||
|
BITMAPINFOHEADER *pbmi = (BITMAPINFOHEADER *)(pbmf + 1);
|
||
|
|
||
|
if (pbmf->bfType != 'MB') {
|
||
|
fprintf(stderr, "Can't convert non-BMP files to BMP compression.\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
UINT cbDumped = 0;
|
||
|
INT16 nValue;
|
||
|
UINT cbScanLine = (((pbmi->biWidth * pbmi->biBitCount) + 31) & ~31) / 8;
|
||
|
PBYTE pbLine = pbData + pbmf->bfOffBits;
|
||
|
//PBYTE pbOut = pbData + pbmf->bfOffBits;
|
||
|
|
||
|
pbmi->biCompression |= 0xff000000;
|
||
|
if (output != NULL) {
|
||
|
output->Dump(pbData, pbmf->bfOffBits);
|
||
|
}
|
||
|
cbDumped += pbmf->bfOffBits;
|
||
|
|
||
|
for (UINT i = 0; i < pbmi->biHeight; i++) {
|
||
|
PBYTE pbIn = pbLine;
|
||
|
PBYTE pbRaw = pbIn;
|
||
|
PBYTE pbEnd = pbLine + cbScanLine;
|
||
|
|
||
|
while (pbIn < pbEnd) {
|
||
|
if (pbIn + 6 < pbEnd &&
|
||
|
pbIn[3] == pbIn[0] &&
|
||
|
pbIn[4] == pbIn[1] &&
|
||
|
pbIn[5] == pbIn[2]) {
|
||
|
|
||
|
PBYTE pbBase = pbIn;
|
||
|
pbIn += 3;
|
||
|
|
||
|
while (pbIn + 3 <= pbEnd &&
|
||
|
pbIn[0] == pbBase[0] &&
|
||
|
pbIn[1] == pbBase[1] &&
|
||
|
pbIn[2] == pbBase[2]) {
|
||
|
|
||
|
pbIn += 3;
|
||
|
}
|
||
|
|
||
|
if (pbBase > pbRaw) {
|
||
|
nValue = (INT16)(pbBase - pbRaw);
|
||
|
if (output != NULL) {
|
||
|
output->Dump((PBYTE)&nValue, sizeof(nValue));
|
||
|
output->Dump(pbRaw, pbBase - pbRaw);
|
||
|
}
|
||
|
cbDumped += sizeof(nValue);
|
||
|
cbDumped += pbBase - pbRaw;
|
||
|
}
|
||
|
|
||
|
nValue = (INT16)(-((pbIn - pbBase) / 3));
|
||
|
if (output != NULL) {
|
||
|
output->Dump((PBYTE)&nValue, sizeof(nValue));
|
||
|
output->Dump(pbBase, 3);
|
||
|
}
|
||
|
cbDumped += sizeof(nValue);
|
||
|
cbDumped += 3;
|
||
|
|
||
|
pbRaw = pbIn;
|
||
|
}
|
||
|
else {
|
||
|
pbIn++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pbEnd > pbRaw) {
|
||
|
nValue = (INT16)(pbEnd - pbRaw);
|
||
|
if (output != NULL) {
|
||
|
output->Dump((PBYTE)&nValue, sizeof(nValue));
|
||
|
output->Dump(pbRaw, pbEnd - pbRaw);
|
||
|
}
|
||
|
cbDumped += sizeof(nValue);
|
||
|
cbDumped += pbEnd - pbRaw;
|
||
|
}
|
||
|
|
||
|
pbLine += cbScanLine;
|
||
|
}
|
||
|
|
||
|
if (output != NULL) {
|
||
|
printf(" From %8d to %8d bytes\n", cbData, cbDumped);
|
||
|
if (output->Size() != cbDumped) {
|
||
|
fprintf(stderr, "Failure in compression: %d reported, %d written\n",
|
||
|
cbDumped, output->Size());
|
||
|
}
|
||
|
output->Finish();
|
||
|
}
|
||
|
|
||
|
return cbDumped;
|
||
|
}
|
||
|
|
||
|
char *find_contents64(CFileMap *pfFile,
|
||
|
PIMAGE_NT_HEADERS64 ppe,
|
||
|
UINT32 *pcbEntry,
|
||
|
UINT32 *pcbBase,
|
||
|
UINT32 *pcbSize,
|
||
|
PBYTE *ppbData)
|
||
|
{
|
||
|
PIMAGE_SECTION_HEADER psec;
|
||
|
|
||
|
fprintf(stderr,"Processing a 64-bit image.\n");
|
||
|
|
||
|
psec = IMAGE_FIRST_SECTION(ppe);
|
||
|
|
||
|
if (ppe->FileHeader.NumberOfSections != 1) {
|
||
|
fprintf(stderr, "Warning: More than one section (.pdata)\n");
|
||
|
}
|
||
|
|
||
|
if (ppe->OptionalHeader.SizeOfInitializedData != 0) {
|
||
|
fprintf(stderr, "Image has initialized data outside of text section.\n");
|
||
|
}
|
||
|
|
||
|
if (ppe->OptionalHeader.SizeOfUninitializedData != 0) {
|
||
|
return "Image has uninitialized data outside of text section.";
|
||
|
}
|
||
|
|
||
|
if (psec->PointerToRawData == 0) {
|
||
|
return "Image has no text content.";
|
||
|
}
|
||
|
|
||
|
if (pfFile->Seek(psec->PointerToRawData) == NULL) {
|
||
|
return "Image text section is invalid.";
|
||
|
}
|
||
|
|
||
|
*pcbEntry =(UINT32) ppe->OptionalHeader.ImageBase + ppe->OptionalHeader.AddressOfEntryPoint;
|
||
|
*pcbBase = (UINT32) ppe->OptionalHeader.ImageBase;
|
||
|
*pcbSize = ppe->OptionalHeader.SizeOfImage;
|
||
|
*ppbData = pfFile->Seek(0);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
char *find_contents32(CFileMap *pfFile,
|
||
|
PIMAGE_NT_HEADERS ppe,
|
||
|
UINT32 *pcbEntry,
|
||
|
UINT32 *pcbBase,
|
||
|
UINT32 *pcbSize,
|
||
|
PBYTE *ppbData)
|
||
|
{
|
||
|
PIMAGE_SECTION_HEADER psec;
|
||
|
|
||
|
psec = IMAGE_FIRST_SECTION(ppe);
|
||
|
|
||
|
if (ppe->FileHeader.NumberOfSections != 1) {
|
||
|
return "Image has more than one sections.";
|
||
|
}
|
||
|
|
||
|
if (ppe->OptionalHeader.SizeOfInitializedData != 0) {
|
||
|
return "Image has initialized data outside of text section.";
|
||
|
}
|
||
|
|
||
|
if (ppe->OptionalHeader.SizeOfUninitializedData != 0) {
|
||
|
return "Image has uninitialized data outside of text section.";
|
||
|
}
|
||
|
|
||
|
if (psec->PointerToRawData == 0) {
|
||
|
return "Image has no text content.";
|
||
|
}
|
||
|
|
||
|
if (pfFile->Seek(psec->PointerToRawData) == NULL) {
|
||
|
return "Image text section is invalid.";
|
||
|
}
|
||
|
|
||
|
*pcbEntry = ppe->OptionalHeader.ImageBase + ppe->OptionalHeader.AddressOfEntryPoint;
|
||
|
*pcbBase = ppe->OptionalHeader.ImageBase;
|
||
|
*pcbSize = ppe->OptionalHeader.SizeOfImage;
|
||
|
*ppbData = pfFile->Seek(0);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
char *find_contents(CFileMap *pfFile,
|
||
|
UINT32 *pcbEntry,
|
||
|
UINT32 *pcbBase,
|
||
|
UINT32 *pcbSize,
|
||
|
PBYTE *ppbData)
|
||
|
{
|
||
|
PIMAGE_DOS_HEADER pdos;
|
||
|
PIMAGE_NT_HEADERS ppe;
|
||
|
//PIMAGE_NT_HEADERS64 ppe64;
|
||
|
|
||
|
*pcbEntry = 0;
|
||
|
*pcbBase = 0;
|
||
|
*pcbSize = 0;
|
||
|
*ppbData = NULL;
|
||
|
|
||
|
// Read in the PE image header
|
||
|
//
|
||
|
pdos = (PIMAGE_DOS_HEADER)pfFile->Seek(0);
|
||
|
if (pdos == NULL || pdos->e_magic != IMAGE_DOS_SIGNATURE) {
|
||
|
return "Image doesn't have MZ signature.";
|
||
|
}
|
||
|
|
||
|
ppe = (PIMAGE_NT_HEADERS)pfFile->Seek(pdos->e_lfanew);
|
||
|
if (ppe == NULL || ppe->Signature != IMAGE_NT_SIGNATURE) {
|
||
|
return "Image doesn't have PE signature.";
|
||
|
}
|
||
|
|
||
|
if (ppe->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
|
||
|
if (fAllow64) {
|
||
|
return find_contents64(pfFile, (PIMAGE_NT_HEADERS64) ppe, pcbEntry, pcbBase, pcbSize, ppbData);
|
||
|
}
|
||
|
else {
|
||
|
return "Image is 64-bit. Use /64 option";
|
||
|
}
|
||
|
}
|
||
|
else return find_contents32(pfFile, ppe, pcbEntry, pcbBase, pcbSize, ppbData);
|
||
|
}
|
||
|
|
||
|
BOOL dump_pe(COutput *pOutput, CFileMap *pInput, PCSTR pszRoot)
|
||
|
{
|
||
|
UINT32 cbEntry = 0;
|
||
|
UINT32 cbBase = 0;
|
||
|
UINT32 cbSize = 0;
|
||
|
PBYTE pbData = NULL;
|
||
|
|
||
|
char *error = find_contents(pInput, &cbEntry, &cbBase, &cbSize, &pbData);
|
||
|
if (error != NULL) {
|
||
|
fprintf(stderr, "Failed: %s\n", error);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (cbEntry < cbBase || cbEntry >= cbBase + cbSize) {
|
||
|
fprintf(stderr, "Failed: Image entry point is not in text section.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (cbBase < TARGET_BASE || cbBase > TARGET_BASE + TARGET_RANGE) {
|
||
|
fprintf(stderr, "Failed: Image is not based at 0x%x.\n", TARGET_BASE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
printf("Total text section: %d bytes\n", cbSize);
|
||
|
|
||
|
// Write .asm data.
|
||
|
//
|
||
|
pOutput->Print("%s_ent EQU 0%08xh\n", pszRoot, cbEntry);
|
||
|
pOutput->Print("%s_dst EQU 0%08xh\n", pszRoot, cbBase);
|
||
|
pOutput->Print("%s_siz EQU 0%08xh\n", pszRoot, cbSize);
|
||
|
pOutput->Print("%s_dat ", pszRoot);
|
||
|
pOutput->Dump(pbData, cbSize);
|
||
|
pOutput->Finish();
|
||
|
pOutput->Print("\n");
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL blob_to_asm(COutput *pOutput, CFileMap *pInput)
|
||
|
{
|
||
|
// Copy the rest of the image.
|
||
|
//
|
||
|
pOutput->Dump(pInput->Seek(0), pInput->Size());
|
||
|
pOutput->Finish();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
int CompareName(PCSTR psz1, PCSTR psz2)
|
||
|
{
|
||
|
for (;;) {
|
||
|
CHAR c1 = *psz1;
|
||
|
CHAR c2 = *psz2;
|
||
|
if (c1 >= 'A' && c1 <= 'Z') {
|
||
|
c1 = c1 - 'A' + 'a';
|
||
|
}
|
||
|
if (c2 >= 'A' && c2 <= 'Z') {
|
||
|
c2 = c2 - 'A' + 'a';
|
||
|
}
|
||
|
|
||
|
if ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9')) {
|
||
|
for (c1 = 0; *psz1 >= '0' && *psz1 <= '9'; psz1++) {
|
||
|
c1 = c1 * 10 + (*psz1 - '0');
|
||
|
}
|
||
|
psz1--;
|
||
|
for (c2 = 0; *psz2 >= '0' && *psz2 <= '9'; psz2++) {
|
||
|
c2 = c2 * 10 + (*psz2 - '0');
|
||
|
}
|
||
|
psz2--;
|
||
|
|
||
|
}
|
||
|
if (c1 != c2) {
|
||
|
return c1 - c2;
|
||
|
}
|
||
|
if (c1 == 0 && c2 == 0) {
|
||
|
return 0;
|
||
|
}
|
||
|
psz1++;
|
||
|
psz2++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PCHAR AppendToName(PCHAR pszDst, PCSTR pszSrc)
|
||
|
{
|
||
|
while (*pszSrc) {
|
||
|
if (*pszSrc == '.') {
|
||
|
*pszDst++ = '_';
|
||
|
pszSrc++;
|
||
|
}
|
||
|
else {
|
||
|
*pszDst++ = *pszSrc++;
|
||
|
}
|
||
|
}
|
||
|
return pszDst;
|
||
|
}
|
||
|
|
||
|
void AsmName(PCHAR pszAsmName, PCSTR pszNamespace, PCSTR pszClass, PCSTR pszField)
|
||
|
{
|
||
|
pszAsmName = AppendToName(pszAsmName, "?c_");
|
||
|
pszAsmName = AppendToName(pszAsmName, pszField);
|
||
|
pszAsmName = AppendToName(pszAsmName, "@Class_");
|
||
|
pszAsmName = AppendToName(pszAsmName, pszNamespace);
|
||
|
pszAsmName = AppendToName(pszAsmName, "_");
|
||
|
pszAsmName = AppendToName(pszAsmName, pszClass);
|
||
|
*pszAsmName = '\0';
|
||
|
}
|
||
|
|
||
|
void CppClassName(PCHAR pszCppClassName, PCSTR pszNamespace, PCSTR pszClass)
|
||
|
{
|
||
|
pszCppClassName = AppendToName(pszCppClassName, "Class_");
|
||
|
pszCppClassName = AppendToName(pszCppClassName, pszNamespace);
|
||
|
pszCppClassName = AppendToName(pszCppClassName, "_");
|
||
|
pszCppClassName = AppendToName(pszCppClassName, pszClass);
|
||
|
*pszCppClassName = '\0';
|
||
|
}
|
||
|
|
||
|
int __cdecl main(int argc, char **argv)
|
||
|
{
|
||
|
BOOL fNeedHelp = FALSE;
|
||
|
BOOL fFlattenPE = TRUE;
|
||
|
PCSTR pszRoot = "asm";
|
||
|
CFileOut cfOutput;
|
||
|
CFileInfo rFiles[512];
|
||
|
CFileInfo *pFiles = NULL;
|
||
|
UINT cFiles = 0;
|
||
|
CHAR szField[256] = "";
|
||
|
CHAR szClass[512] = "";
|
||
|
CHAR szNamespace[512] = "";
|
||
|
CHAR szAsmName[1024];
|
||
|
CHAR szCppClassName[1024];
|
||
|
|
||
|
for (int arg = 1; arg < argc; arg++) {
|
||
|
if (argv[arg][0] == '-' || argv[arg][0] == '/') {
|
||
|
char *argn = argv[arg]+1; // Argument name
|
||
|
char *argp = argn; // Argument parameter
|
||
|
|
||
|
while (*argp && *argp != ':')
|
||
|
argp++;
|
||
|
if (*argp == ':')
|
||
|
*argp++ = '\0';
|
||
|
|
||
|
switch (argn[0]) {
|
||
|
|
||
|
case 'a': // ASM Format
|
||
|
case 'A':
|
||
|
fAsm = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'b': // Binary Blob
|
||
|
case 'B':
|
||
|
fFlattenPE = FALSE;
|
||
|
fManaged = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'c': // C# Class
|
||
|
case 'C':
|
||
|
strcpy(szClass, argp);
|
||
|
fManaged = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'f': // C# Field
|
||
|
case 'F':
|
||
|
strcpy(szField, argp);
|
||
|
fManaged = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'l': // List of files
|
||
|
case 'L':
|
||
|
fManaged = TRUE;
|
||
|
fList = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'm': // C# Format
|
||
|
case 'M':
|
||
|
fAsm = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'n': // C# Namespace
|
||
|
case 'N':
|
||
|
strcpy(szNamespace, argp);
|
||
|
fManaged = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'o': // Output file.
|
||
|
case 'O':
|
||
|
if (!cfOutput.Create(argp)) {
|
||
|
fprintf(stderr, "Could not open output file: %s\n", argp);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'p': // Cpp Format
|
||
|
case 'P':
|
||
|
fCpp = TRUE;
|
||
|
fAsm = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'r': // Set Label Root
|
||
|
case 'R':
|
||
|
pszRoot = argp;
|
||
|
break;
|
||
|
|
||
|
case 'x': // Compress BMP
|
||
|
case 'X': //
|
||
|
fCompress = TRUE;
|
||
|
fManaged = TRUE;
|
||
|
break;
|
||
|
|
||
|
case '6': // 64-bit PE
|
||
|
fAllow64 = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'h': // Help
|
||
|
case 'H':
|
||
|
case '?':
|
||
|
fNeedHelp = TRUE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("Unknown argument: %s\n", argv[arg]);
|
||
|
fNeedHelp = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
// Save the input files away in sorted linked list.
|
||
|
CFileInfo *pNew = &rFiles[cFiles++];
|
||
|
CFileInfo **ppHead = &pFiles;
|
||
|
|
||
|
pNew->SetFileName(argv[arg]);
|
||
|
while (*ppHead != NULL && CompareName(pNew->m_pszFile, (*ppHead)->m_pszFile) > 0) {
|
||
|
ppHead = &(*ppHead)->m_pNext;
|
||
|
}
|
||
|
pNew->m_pNext = *ppHead;
|
||
|
*ppHead = pNew;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (argc == 1) {
|
||
|
fNeedHelp = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!fNeedHelp && !cfOutput.IsOpen()) {
|
||
|
fprintf(stderr, "No output file specified.\n");
|
||
|
fNeedHelp = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!fNeedHelp && pFiles == NULL) {
|
||
|
fprintf(stderr, "No output file specified.\n");
|
||
|
fNeedHelp = TRUE;
|
||
|
}
|
||
|
|
||
|
if (!fNeedHelp && fManaged &&
|
||
|
(szField[0] == '\0' || szClass[0] == '\0')) {
|
||
|
fprintf(stderr, "No field or class name specified for target.\n");
|
||
|
fNeedHelp = TRUE;
|
||
|
}
|
||
|
|
||
|
if (fNeedHelp) {
|
||
|
printf(
|
||
|
"Usage:\n"
|
||
|
" mkasm /o:output [options] inputs\n"
|
||
|
"Options:\n"
|
||
|
" /o:output -- Specify output file.\n"
|
||
|
" /r:root -- Set root label [defaults to `asm'].\n"
|
||
|
" /b -- Treat file as binary blob (not PE file).\n"
|
||
|
" /a -- Output ASM format (default for PE).\n"
|
||
|
" /m -- Output C# format (default for blob).\n"
|
||
|
" /c:class -- Set C# class.\n"
|
||
|
" /n:namespace -- Set C# namespace.\n"
|
||
|
" /f:field -- Set C# field.\n"
|
||
|
" /x -- Use bizarre compression for BMP files.\n"
|
||
|
" /l -- Output contents in an array (list).\n"
|
||
|
" /64 -- manipulate 64-bit PE files."
|
||
|
" /h or /? -- Display this help screen.\n"
|
||
|
"Summary:\n"
|
||
|
" Copies the contents of the input files into the output file\n"
|
||
|
" in .asm format. Specific conversions exists for PE and BMP files.\n"
|
||
|
);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// At this point, we have input file(s), output file, and set of desired
|
||
|
// conversions. Time to process the output.
|
||
|
//
|
||
|
|
||
|
BOOL fAbort = false;
|
||
|
COutput *pOutput = NULL;
|
||
|
CAsmOutput asmOutput(&cfOutput);
|
||
|
CSharpOutput sharpOutput(&cfOutput);
|
||
|
|
||
|
AsmName(szAsmName, szNamespace, szClass, szField);
|
||
|
CppClassName(szCppClassName, szNamespace, szClass);
|
||
|
|
||
|
if (fAsm) {
|
||
|
pOutput = &asmOutput;
|
||
|
}
|
||
|
else {
|
||
|
pOutput = &sharpOutput;
|
||
|
}
|
||
|
|
||
|
ULONG cbFiles = 0;
|
||
|
UINT cFile = 0;
|
||
|
for (CFileInfo *pFile = pFiles; pFile != NULL; pFile = pFile->m_pNext) {
|
||
|
if (!pFile->SetFileAndSize()) {
|
||
|
fprintf(stderr, "Unable to open %s, error = %d\n",
|
||
|
pFile->m_pszFile,
|
||
|
GetLastError());
|
||
|
goto abort;
|
||
|
}
|
||
|
if (fCompress) {
|
||
|
CFileMap cfInput;
|
||
|
printf(".");
|
||
|
|
||
|
if (!cfInput.Load(pFile->m_pszFile)) {
|
||
|
fprintf(stderr, "Could not open input file: %s\n", pFile->m_pszFile);
|
||
|
goto abort;
|
||
|
}
|
||
|
pFile->SetOutputSize(DumpBmp(NULL, cfInput.Seek(0), cfInput.Size()));
|
||
|
cfInput.Close();
|
||
|
}
|
||
|
|
||
|
cFile++;
|
||
|
cbFiles += pFile->m_cbOutput;
|
||
|
}
|
||
|
|
||
|
//public: static struct ClassVector_ClassVector_uint8 *
|
||
|
// Class_Microsoft_Singularity_Shell_Slides::c_Content;
|
||
|
|
||
|
//" (?c_Content@Class_Microsoft_Singularity_Shell_Slides@@2PAUClassVector_ClassVector_uint8@@A
|
||
|
if (!fFlattenPE) {
|
||
|
if (fAsm) {
|
||
|
cfOutput.Print("externdef %s:NEAR\n", szByteVTable);
|
||
|
|
||
|
if (fList) {
|
||
|
cfOutput.Print("externdef %s:NEAR\n", szByteByteVTable);
|
||
|
}
|
||
|
else {
|
||
|
cfOutput.Print("align 4\n");
|
||
|
cfOutput.Print(" BARTOK_OBJECT_HEADER {} \n");
|
||
|
cfOutput.Print("%s%s_0 UINT32 %s\n",
|
||
|
szAsmName, szByteSuffix, szByteVTable);
|
||
|
cfOutput.Print(" UINT32 %d\n", cbFiles);
|
||
|
}
|
||
|
}
|
||
|
else if (fCpp) {
|
||
|
if (fList) {
|
||
|
cFile = 0;
|
||
|
for (CFileInfo *pFile = pFiles; pFile != NULL; pFile = pFile->m_pNext) {
|
||
|
cfOutput.Print("struct Vector_%s_%s_0_%d {\n",
|
||
|
szCppClassName, szField, cFile);
|
||
|
cfOutput.Print(" uintptr headerwords[HDRWORDCOUNT];\n");
|
||
|
cfOutput.Print(" union {\n");
|
||
|
cfOutput.Print(" struct {\n");
|
||
|
cfOutput.Print(" Class_System_VTable * vtable;\n");
|
||
|
cfOutput.Print(" uint32 length;\n");
|
||
|
cfOutput.Print(" uint8 data[%d];\n",
|
||
|
pFile->m_cbOutput);
|
||
|
cfOutput.Print(" };\n");
|
||
|
cfOutput.Print(" ClassVector_uint8 object;\n");
|
||
|
cfOutput.Print(" };\n");
|
||
|
cfOutput.Print("};\n");
|
||
|
|
||
|
cFile++;
|
||
|
}
|
||
|
|
||
|
cfOutput.Print("struct Vector_%s_%s_0 {\n",
|
||
|
szCppClassName, szField);
|
||
|
cfOutput.Print(" uintptr headerwords[HDRWORDCOUNT];\n");
|
||
|
cfOutput.Print(" union {\n");
|
||
|
cfOutput.Print(" struct {\n");
|
||
|
cfOutput.Print(" Class_System_VTable * vtable;\n");
|
||
|
cfOutput.Print(" uint32 length;\n");
|
||
|
cfOutput.Print(" ClassVector_uint8 * data[%d];\n", cFiles);
|
||
|
cfOutput.Print(" };\n");
|
||
|
cfOutput.Print(" ClassVector_ClassVector_uint8 object;\n");
|
||
|
cfOutput.Print(" };\n");
|
||
|
cfOutput.Print("};\n");
|
||
|
|
||
|
cfOutput.Print("struct %s {\n", szCppClassName);
|
||
|
cfOutput.Print(" private:\n");
|
||
|
for (UINT i = 0; i < cFiles; i++) {
|
||
|
cfOutput.Print(" static Vector_%s_%s_0_%d c_%s_0_%d;\n",
|
||
|
szCppClassName, szField, i,
|
||
|
szField, i);
|
||
|
}
|
||
|
cfOutput.Print(" static Vector_%s_%s_0 c_%s_0;\n",
|
||
|
szCppClassName, szField, szField);
|
||
|
cfOutput.Print(" public:\n");
|
||
|
cfOutput.Print(" static ClassVector_ClassVector_uint8 * c_%s;\n", szField);
|
||
|
cfOutput.Print("};\n");
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("ClassVector_ClassVector_uint8 * %s::c_%s = &%s::c_%s_0.object;\n",
|
||
|
szCppClassName, szField,
|
||
|
szCppClassName, szField);
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("Vector_%s_%s_0 %s::c_%s_0 = {\n",
|
||
|
szCppClassName, szField,
|
||
|
szCppClassName, szField);
|
||
|
cfOutput.Print(" {},\n");
|
||
|
cfOutput.Print(" (Class_System_VTable *)&ClassVector_ClassVector_uint8::_vtable,\n");
|
||
|
cfOutput.Print(" %d,\n", cFiles);
|
||
|
cfOutput.Print(" {\n");
|
||
|
for (UINT i = 0; i < cFiles; i++) {
|
||
|
cfOutput.Print(" &%s::c_%s_0_%d.object,\n",
|
||
|
szCppClassName, szField, i);
|
||
|
}
|
||
|
cfOutput.Print(" },\n");
|
||
|
cfOutput.Print("};\n");
|
||
|
cfOutput.Print("\n");
|
||
|
}
|
||
|
else {
|
||
|
cfOutput.Print("struct Vector_%s_%s_0 {\n",
|
||
|
szCppClassName, szField);
|
||
|
cfOutput.Print(" uintptr headerwords[HDRWORDCOUNT];\n");
|
||
|
cfOutput.Print(" union { \n");
|
||
|
cfOutput.Print(" struct {\n");
|
||
|
cfOutput.Print(" Class_System_VTable * vtable;\n");
|
||
|
cfOutput.Print(" uint32 length;\n");
|
||
|
cfOutput.Print(" uint8 data[%d];\n",
|
||
|
cbFiles);
|
||
|
cfOutput.Print(" };\n");
|
||
|
cfOutput.Print(" ClassVector_uint8 object;\n");
|
||
|
cfOutput.Print(" };\n");
|
||
|
cfOutput.Print("};\n");
|
||
|
|
||
|
cfOutput.Print("struct %s {\n", szCppClassName);
|
||
|
cfOutput.Print(" private:\n");
|
||
|
cfOutput.Print(" static Vector_%s_%s_0 c_%s_0;\n",
|
||
|
szCppClassName, szField, szField);
|
||
|
cfOutput.Print(" public:\n");
|
||
|
cfOutput.Print(" static ClassVector_uint8 * c_%s;\n", szField);
|
||
|
cfOutput.Print("};\n");
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("ClassVector_uint8 * %s::c_%s = &%s::c_%s_0.object;\n",
|
||
|
szCppClassName, szField,
|
||
|
szCppClassName, szField);
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("Vector_%s_%s_0 %s::c_%s_0 = {\n",
|
||
|
szCppClassName, szField,
|
||
|
szCppClassName, szField);
|
||
|
cfOutput.Print(" {},\n");
|
||
|
cfOutput.Print(" (Class_System_VTable *)&ClassVector_uint8::_vtable,\n");
|
||
|
cfOutput.Print(" %d,\n", cbFiles);
|
||
|
cfOutput.Print(" {\n");
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (szNamespace) {
|
||
|
cfOutput.Print("namespace %s {\n", szNamespace);
|
||
|
}
|
||
|
|
||
|
cfOutput.Print(" public class %s {\n", szClass);
|
||
|
if (fList) {
|
||
|
cfOutput.Print(" public static readonly byte[][] %s = {\n", szField);
|
||
|
}
|
||
|
else {
|
||
|
cfOutput.Print(" public static readonly byte[] %s = {\n", szField);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cFile = 0;
|
||
|
for (CFileInfo *pFile = pFiles; pFile != NULL; pFile = pFile->m_pNext) {
|
||
|
CFileMap cfInput;
|
||
|
printf(".");
|
||
|
|
||
|
if (!cfInput.Load(pFile->m_pszFile)) {
|
||
|
fprintf(stderr, "Could not open input file: %s\n", pFile->m_pszFile);
|
||
|
goto abort;
|
||
|
}
|
||
|
|
||
|
if (fFlattenPE) {
|
||
|
// Flatten PE file
|
||
|
if (!dump_pe(pOutput, &cfInput, pszRoot)) {
|
||
|
goto abort;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (fAsm) {
|
||
|
if (fList) {
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("align 4\n");
|
||
|
cfOutput.Print(" BARTOK_OBJECT_HEADER {} \n");
|
||
|
cfOutput.Print("%s%s_0_%d UINT32 %s\n",
|
||
|
szAsmName,
|
||
|
szByteSuffix,
|
||
|
cFile,
|
||
|
szByteVTable);
|
||
|
cfOutput.Print(" UINT32 %d\n", cfInput.Size());
|
||
|
}
|
||
|
}
|
||
|
else if (fCpp) {
|
||
|
if (fList) {
|
||
|
cfOutput.Print("Vector_%s_%s_0_%d %s::c_%s_0_%d = {\n",
|
||
|
szCppClassName, szField, cFile,
|
||
|
szCppClassName, szField, cFile);
|
||
|
cfOutput.Print(" {},\n");
|
||
|
cfOutput.Print(" (Class_System_VTable *)&ClassVector_uint8::_vtable,\n");
|
||
|
cfOutput.Print(" %d,\n", cfInput.Size());
|
||
|
cfOutput.Print(" {\n");
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (fList) {
|
||
|
cfOutput.Print(" new byte[] {\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fCompress) {
|
||
|
if (!DumpBmp(pOutput, cfInput.Seek(0), cfInput.Size())) {
|
||
|
goto abort;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
pOutput->Dump(cfInput.Seek(0), cfInput.Size());
|
||
|
pOutput->Finish();
|
||
|
}
|
||
|
|
||
|
if (fAsm) {
|
||
|
}
|
||
|
else if (fCpp) {
|
||
|
if (fList) {
|
||
|
cfOutput.Print(" },\n");
|
||
|
cfOutput.Print("};\n");
|
||
|
cfOutput.Print("\n");
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (fList) {
|
||
|
cfOutput.Print(" },\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cfInput.Close();
|
||
|
cFile++;
|
||
|
}
|
||
|
|
||
|
if (!fFlattenPE) {
|
||
|
if (fAsm) {
|
||
|
if (fList) {
|
||
|
// create list array at end.
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("align 4\n");
|
||
|
cfOutput.Print(" BARTOK_OBJECT_HEADER {} \n");
|
||
|
cfOutput.Print("public %s%s\n",
|
||
|
szAsmName,
|
||
|
szByteByteSuffix);
|
||
|
cfOutput.Print("%s%s_0 UINT32 %s\n",
|
||
|
szAsmName,
|
||
|
szByteByteSuffix,
|
||
|
szByteByteVTable);
|
||
|
cfOutput.Print(" UINT32 %d\n", cFiles);
|
||
|
for (UINT i = 0; i < cFiles; i++) {
|
||
|
cfOutput.Print(" UINT32 %s%s_0_%d\n",
|
||
|
szAsmName,
|
||
|
szByteSuffix,
|
||
|
i);
|
||
|
}
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("align 4\n");
|
||
|
cfOutput.Print("public %s%s\n",
|
||
|
szAsmName,
|
||
|
szByteByteSuffix);
|
||
|
cfOutput.Print("%s%s UINT32 %s%s_0\n",
|
||
|
szAsmName,
|
||
|
szByteByteSuffix,
|
||
|
szAsmName,
|
||
|
szByteByteSuffix);
|
||
|
}
|
||
|
else {
|
||
|
cfOutput.Print("\n");
|
||
|
cfOutput.Print("align 4\n");
|
||
|
cfOutput.Print("public %s%s\n",
|
||
|
szAsmName,
|
||
|
szByteSuffix);
|
||
|
cfOutput.Print("%s%s UINT32 %s%s_0\n",
|
||
|
szAsmName,
|
||
|
szByteSuffix,
|
||
|
szAsmName,
|
||
|
szByteSuffix);
|
||
|
}
|
||
|
}
|
||
|
else if (fCpp) {
|
||
|
if (!fList) {
|
||
|
cfOutput.Print(" },\n");
|
||
|
cfOutput.Print("};\n");
|
||
|
cfOutput.Print("\n");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cfOutput.Print(" };\n");
|
||
|
cfOutput.Print(" }\n");
|
||
|
cfOutput.Print("}\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fAbort) {
|
||
|
abort:
|
||
|
cfOutput.Delete();
|
||
|
return 1;
|
||
|
}
|
||
|
cfOutput.Close();
|
||
|
return 0;
|
||
|
}
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////// End of File.
|