DragonNest/Third/XTToolkitPro/Samples/Utilities/ResourceEditor/ResourceExport.cpp
2024-12-19 09:48:26 +08:00

1200 lines
29 KiB
C++

// ResourceExport.cpp: implementation of the CResourceExport class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ResourceExport.h"
#include "ResourceViewRecord.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
class CBufferFile : public CMemFile
{
public:
CBufferFile(int nFileSize = 120000)
: CMemFile(nFileSize)
{
}
public:
LPBYTE GetBuffer() {
return m_lpBuffer + GetPosition();
}
LPBYTE GetBufferHeader() {
return m_lpBuffer;
}
};
#pragma pack(push, 1)
typedef struct
{
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
} DLLDLGTEMPLATEEX;
typedef struct
{
DWORD helpID;
DWORD exStyle;
DWORD style;
short x;
short y;
short cx;
short cy;
DWORD id;
} DLLDLGITEMTEMPLATEEX;
#pragma pack(pop)
struct DIRECTORY;
typedef CArray<DIRECTORY*, DIRECTORY*> CArrayDirectories;
struct DIRECTORY
{
DIRECTORY()
{
nID = 0;
nResourceOffset = 0;
lpFatEntry = 0;
lpFatDataEntry = 0;
pResource = NULL;
}
~DIRECTORY()
{
for (int i = 0; i < arrDirs.GetSize(); i++)
{
delete arrDirs[i];
}
if (pResource)
delete pResource;
}
int GetNumberOfIdEntries()
{
return (int)arrDirs.GetSize() - GetNumberOfNamedEntries();
}
int GetNumberOfNamedEntries()
{
int nCount = 0;
for (int i = 0; i < arrDirs.GetSize(); i++)
{
if (!arrDirs[i]->strName.IsEmpty())
{
nCount++;
}
}
return nCount;
}
DIRECTORY* AddDirectory(CString strSub);
DIRECTORY* AddDirectory(int nSub);
CString strName;
CString strResource;
int nID;
int nResourceOffset;
CBufferFile* pResource;
PIMAGE_RESOURCE_DIRECTORY_ENTRY lpFatEntry;
PIMAGE_RESOURCE_DATA_ENTRY lpFatDataEntry;
CArrayDirectories arrDirs;
};
DIRECTORY* DIRECTORY::AddDirectory(CString strSub)
{
int i;
for (i = 0; i < arrDirs.GetSize(); i++)
{
if (arrDirs[i]->strName.IsEmpty())
break;
if (arrDirs[i]->strName == strSub)
{
return arrDirs[i];
}
if (arrDirs[i]->strName > strSub)
{
break;
}
}
DIRECTORY* pType = new DIRECTORY();
pType->strName = strSub;
arrDirs.InsertAt(i, pType);
return pType;
}
DIRECTORY* DIRECTORY::AddDirectory(int nSub)
{
int i;
for (i = 0; i <arrDirs.GetSize(); i++)
{
if (arrDirs[i]->nID == nSub)
{
return arrDirs[i];
}
if (arrDirs[i]->nID > nSub)
{
break;
}
}
DIRECTORY* pType = new DIRECTORY();
pType->nID = nSub;
arrDirs.InsertAt(i, pType);
return pType;
}
DIRECTORY* AddDirectory(DIRECTORY* pRootDir, CString strType, CString strResourceName, UINT nLocale = 0x409)
{
DIRECTORY* pType = pRootDir->AddDirectory(strType);
DIRECTORY* pResName = pType->AddDirectory(strResourceName);
DIRECTORY* pEntry = pResName->AddDirectory(nLocale);
return pEntry;
}
DIRECTORY* AddDirectory(DIRECTORY* pRootDir, int nID, CString strResourceName, UINT nLocale = 0x409)
{
DIRECTORY* pType = pRootDir->AddDirectory(nID);
DIRECTORY* pResName = pType->AddDirectory(strResourceName);
DIRECTORY* pEntry = pResName->AddDirectory(nLocale);
return pEntry;
}
DIRECTORY* AddDirectory(DIRECTORY* pRootDir, int nID, int nResourceName, UINT nLocale = 0x409)
{
DIRECTORY* pType = pRootDir->AddDirectory(nID);
DIRECTORY* pResName = pType->AddDirectory(nResourceName);
DIRECTORY* pEntry = pResName->AddDirectory(nLocale);
return pEntry;
}
void WriteFAT(CBufferFile* lpFAT, DIRECTORY* pDirectory, CArrayDirectories* pDataDirs)
{
IMAGE_RESOURCE_DIRECTORY dir;
ZeroMemory(&dir, sizeof(IMAGE_RESOURCE_DIRECTORY));
dir.NumberOfIdEntries = (WORD)pDirectory->GetNumberOfIdEntries();
dir.NumberOfNamedEntries = (WORD)pDirectory->GetNumberOfNamedEntries();
lpFAT->Write(&dir, sizeof(IMAGE_RESOURCE_DIRECTORY));
int i;
for (i = 0; i < pDirectory->arrDirs.GetSize(); i++)
{
IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
ZeroMemory(&entry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
DIRECTORY* pSubDir = pDirectory->arrDirs[i];
if (pSubDir->arrDirs.GetSize() > 0)
{
entry.DataIsDirectory = 1;
}
if (pSubDir->strName.IsEmpty())
{
entry.Id = (WORD)pSubDir->nID;
}
else
{
entry.NameIsString = 1;
}
pSubDir->lpFatEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)lpFAT->GetBuffer();
lpFAT->Write(&entry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
}
for (i = 0; i < pDirectory->arrDirs.GetSize(); i++)
{
DIRECTORY* pSubDir = pDirectory->arrDirs[i];
PIMAGE_RESOURCE_DIRECTORY_ENTRY lpEntry = pSubDir->lpFatEntry;
if (pSubDir->arrDirs.GetSize() > 0)
{
lpEntry->OffsetToDirectory = lpFAT->GetPosition();
WriteFAT(lpFAT, pSubDir, pDataDirs);
}
else
{
lpEntry->OffsetToData = (DWORD)lpFAT->GetPosition();
IMAGE_RESOURCE_DATA_ENTRY data;
ZeroMemory(&data, sizeof(IMAGE_RESOURCE_DATA_ENTRY));
pSubDir->lpFatDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)lpFAT->GetBuffer();
lpFAT->Write(&data, sizeof(IMAGE_RESOURCE_DATA_ENTRY));
pDataDirs->Add(pSubDir);
}
}
}
void WriteFATNames(CBufferFile* lpFAT, DIRECTORY* pDirectory)
{
USES_CONVERSION;
int i;
for (i = 0; i < pDirectory->arrDirs.GetSize(); i++)
{
DIRECTORY* pSubDir = pDirectory->arrDirs[i];
if (!pSubDir->strName.IsEmpty())
{
PIMAGE_RESOURCE_DIRECTORY_ENTRY lpEntry = pSubDir->lpFatEntry;
lpEntry->NameOffset = lpFAT->GetPosition();
WORD Length = (WORD)pSubDir->strName.GetLength();
lpFAT->Write(&Length, sizeof(Length));
LPCWSTR lpw = T2W((LPTSTR)(LPCTSTR)pSubDir->strName);
lpFAT->Write(lpw, (pSubDir->strName.GetLength()) * sizeof(WCHAR));
}
}
for (i = 0; i < pDirectory->arrDirs.GetSize(); i++)
{
DIRECTORY* pSubDir = pDirectory->arrDirs[i];
if (pSubDir->arrDirs.GetSize() > 0)
{
WriteFATNames(lpFAT, pSubDir);
}
}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CResourceExport::CResourceExport()
{
m_pResources = NULL;
m_pLanguageInfo = 0;
}
CResourceExport::~CResourceExport()
{
}
struct STRINGTABLE
{
STRINGTABLE()
{
ZeroMemory(m_bstr, sizeof(m_bstr));
}
~STRINGTABLE()
{
for (int i = 0; i < 16; i++)
{
if (m_bstr[i])
{
SysFreeString(m_bstr[i]);
}
}
}
BSTR m_bstr[16];
};
void CResourceExport::ExportDllMenuItems(CMemFile* pFile, CXTPPropExchange* pResourceMenu)
{
CXTPPropExchangeEnumeratorPtr ptrEnumeratorStrings(pResourceMenu->GetEnumerator(_T("menuitem")));
POSITION pos = ptrEnumeratorStrings->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSectionMenuItem(ptrEnumeratorStrings->GetNext(pos));
DWORD dwId = 0;
PX_DWord(&ptrSectionMenuItem, _T("id"), dwId);
BSTR bstrValue = 0;
PX_Bstr(&ptrSectionMenuItem, _T("caption"), bstrValue, 0);
BOOL bPopup = (((CXTPPropExchangeXMLNode*)&ptrSectionMenuItem)->IsSectionExists(_T("menuitem")));
WORD mtOption = 0, mtID = 0;
if (bPopup)
mtOption |= MF_POPUP;
if (!pos)
mtOption |= MF_END;
if (!bPopup && dwId == 0)
mtOption |= MF_SEPARATOR;
pFile->Write(&mtOption, sizeof(WORD));
mtID = (WORD)dwId;
if (!bPopup)
pFile->Write(&mtID, sizeof(WORD));
LPCWSTR lpDispalyName = (LPCWSTR)bstrValue;
WORD wLength = 0;
if (lpDispalyName)
{
wLength = (WORD)wcslen(lpDispalyName);
pFile->Write(lpDispalyName, (1 + wLength) * sizeof(WCHAR));
}
else
{
pFile->Write(&wLength, sizeof(WCHAR));
}
if (bstrValue)
{
SysFreeString(bstrValue);
}
if (bPopup)
{
ExportDllMenuItems(pFile, &ptrSectionMenuItem);
}
}
}
AFX_INLINE DWORD AlignDWord(DWORD uLong) { return ((uLong + 3) & ~3); }
void CResourceExport::ExportDllMenus(DIRECTORY* pRoot)
{
CXTPPropExchangeEnumeratorPtr ptrEnumeratorMenus(m_pResources->GetEnumerator(_T("menu")));
POSITION pos = ptrEnumeratorMenus->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSection(ptrEnumeratorMenus->GetNext(pos));
DWORD dwId = 0;
PX_DWord(&ptrSection, _T("id"), dwId);
if (dwId == 0)
continue;
DIRECTORY* pDirectory = AddDirectory(pRoot, (WORD)(DWORD_PTR)RT_MENU, dwId, m_pLanguageInfo->wLanguage);
CBufferFile* pFile = pDirectory->pResource = new CBufferFile(10000);
WORD wVerison = 0;
WORD wOffset = 0;
pFile->Write(&wVerison, sizeof(WORD));
pFile->Write(&wOffset, sizeof(WORD));
ExportDllMenuItems(pFile, &ptrSection);
AlignFile(pFile, 0);
}
}
int CResourceExport::GetDialogControlsCount(CXTPPropExchange* pResourceDialog)
{
CXTPPropExchangeEnumeratorPtr ptrEnumerator(pResourceDialog->GetEnumerator(_T("control")));
POSITION pos = ptrEnumerator->GetPosition();
int nCount = 0;
while (pos)
{
CXTPPropExchangeSection ptrSection(ptrEnumerator->GetNext(pos));
nCount++;
}
return nCount;
}
void CResourceExport::AlignFile(CMemFile* pFile, DWORD dwPosition)
{
DWORD dwAlign = 0;
DWORD dwSize = DWORD(pFile->GetPosition() - dwPosition);
DWORD dwBytes = AlignDWord(dwSize) - dwSize;
ASSERT(dwBytes >= 0 && dwBytes < 4);
pFile->Write(&dwAlign, dwBytes);
}
void CResourceExport::ExportDllDialogControls(CMemFile* pFile, CXTPPropExchange* pResourceDialog)
{
USES_CONVERSION;
CXTPPropExchangeEnumeratorPtr ptrEnumerator(pResourceDialog->GetEnumerator(_T("control")));
POSITION pos = ptrEnumerator->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSection(ptrEnumerator->GetNext(pos));
DLLDLGITEMTEMPLATEEX templ;
ZeroMemory(&templ, sizeof(DLLDLGITEMTEMPLATEEX));
WORD dwEmpty = 0;
DWORD dwPosition = (DWORD)pFile->GetPosition();
RECT rcPos = {0, 0, 0, 0};
PX_Rect(&ptrSection, _T("position"), rcPos, rcPos);
templ.x = (short)rcPos.left;
templ.y = (short)rcPos.top;
templ.cx = (short)rcPos.right;
templ.cy = (short)rcPos.bottom;
PX_DWord(&ptrSection, _T("style"), templ.style, WS_CHILD | WS_VISIBLE | WS_GROUP);
PX_DWord(&ptrSection, _T("styleex"), templ.exStyle, 0);
int id = 0;
PX_Int(&ptrSection, _T("id"), id, 0);
templ.id = id == 0 ? (DWORD)IDC_STATIC : (DWORD)id;
pFile->Write(&templ, sizeof(DLLDLGITEMTEMPLATEEX));
CString strClass;
PX_String(&ptrSection, _T("class"), strClass, _T("STATIC"));
WORD nClass = 0;
if (strClass == _T("BUTTON")) nClass = 0x0080;
if (strClass == _T("EDIT")) nClass = 0x0081;
if (strClass == _T("STATIC")) nClass = 0x0082;
if (strClass == _T("LISTBOX")) nClass = 0x0083;
if (strClass == _T("SCROLLBAR")) nClass = 0x0084;
if (strClass == _T("COMBOBOX")) nClass = 0x0085;
if (nClass != 0)
{
WORD dwSignature = 0xFFFF;
pFile->Write(&dwSignature, sizeof(WORD));
pFile->Write(&nClass, sizeof(WORD));
}
else
{
pFile->Write(T2CW(strClass), (strClass.GetLength() + 1) * sizeof(WCHAR));
}
int nResource = 0;
BOOL bExists = PX_Int(&ptrSection, _T("resource"), nResource);
if (bExists)
{
WORD dwSignature = 0xFFFF;
WORD dwResource = (WORD)nResource;
pFile->Write(&dwSignature, sizeof(WORD));
pFile->Write(&dwResource, sizeof(WORD));
}
else
{
BSTR bstrValue = 0;
PX_Bstr(&ptrSection, _T("caption"), bstrValue, 0);
if (bstrValue)
{
pFile->Write(bstrValue, (1 + (int)wcslen(bstrValue)) * sizeof(WCHAR));
}
else
{
pFile->Write(&dwEmpty, sizeof(WORD));
}
if (bstrValue)
SysFreeString(bstrValue);
}
pFile->Write(&dwEmpty, sizeof(WORD)); // extraCount;
AlignFile(pFile, dwPosition);
}
}
void CResourceExport::ExportDllDialogs(DIRECTORY* pRoot)
{
USES_CONVERSION;
CXTPPropExchangeEnumeratorPtr ptrEnumeratorDialog(m_pResources->GetEnumerator(_T("dialog")));
POSITION pos = ptrEnumeratorDialog->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSection(ptrEnumeratorDialog->GetNext(pos));
DWORD dwId = 0;
PX_DWord(&ptrSection, _T("id"), dwId);
if (dwId == 0)
continue;
DIRECTORY* pDirectory = AddDirectory(pRoot, (WORD)(DWORD_PTR)RT_DIALOG, dwId, m_pLanguageInfo->wLanguage);
CBufferFile* pFile = pDirectory->pResource = new CBufferFile(10000);
DLLDLGTEMPLATEEX templ;
ZeroMemory(&templ, sizeof(DLLDLGTEMPLATEEX));
RECT rcPos = {0, 0, 0, 0};
PX_DWord(&ptrSection, _T("style"), templ.style);
PX_DWord(&ptrSection, _T("styleex"), templ.exStyle, 0);
PX_Rect(&ptrSection, _T("position"), rcPos, rcPos);
templ.dlgVer = 1;
templ.signature = 0xFFFF;
templ.cDlgItems = (WORD)GetDialogControlsCount(&ptrSection);
templ.x = (short)rcPos.left;
templ.y = (short)rcPos.top;
templ.cx = (short)rcPos.right;
templ.cy = (short)rcPos.bottom;
templ.style |= DS_SETFONT;
templ.helpID = dwId;
WORD dwEmpty = 0;
pFile->Write(&templ, sizeof(DLLDLGTEMPLATEEX));
pFile->Write(&dwEmpty, sizeof(WORD)); // menu;
pFile->Write(&dwEmpty, sizeof(WORD)); // windowClass;
BSTR bstrValue = 0;
PX_Bstr(&ptrSection, _T("caption"), bstrValue, 0);
if (bstrValue)
{
pFile->Write(bstrValue, (1 + (int)wcslen(bstrValue)) * sizeof(WCHAR));
}
else
{
pFile->Write(&dwEmpty, sizeof(WORD));
}
if (bstrValue)
SysFreeString(bstrValue);
if (templ.style & DS_SETFONT)
{
int nHeight = 8;
PX_Int(&ptrSection, _T("fontsize"), nHeight, 8);
WORD pointsize = (WORD)nHeight, weight = 0;
BYTE bItalic = 0, charset = 0;
pFile->Write(&pointsize, sizeof(WORD));
pFile->Write(&weight, sizeof(WORD));
pFile->Write(&bItalic, sizeof(BYTE));
pFile->Write(&charset, sizeof(BYTE));
CString strFont;
PX_String(&ptrSection, _T("fontface"), strFont, _T("MS Sans Serif"));
if (!strFont.IsEmpty())
{
pFile->Write(T2CW(strFont), (1 + strFont.GetLength()) * sizeof(WCHAR));
}
else
{
pFile->Write(&dwEmpty, sizeof(WORD));
}
}
AlignFile(pFile, 0);
if (templ.cDlgItems > 0)
{
ExportDllDialogControls(pFile, &ptrSection);
}
}
}
void CResourceExport::ExportDllStringTable(DIRECTORY* pRoot)
{
CMap<UINT, UINT, STRINGTABLE*, STRINGTABLE*> mapStrings;
CXTPPropExchangeEnumeratorPtr ptrEnumeratorStrings(m_pResources->GetEnumerator(_T("string")));
POSITION pos = ptrEnumeratorStrings->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSectionString(ptrEnumeratorStrings->GetNext(pos));
BSTR bstrValue = 0;
DWORD dwId = 0;
PX_DWord(&ptrSectionString, _T("id"), dwId);
PX_Bstr(&ptrSectionString, _T("value"), bstrValue, 0);
int IdTable = (dwId >> 4) + 1;
STRINGTABLE* pst = NULL;
if (!mapStrings.Lookup(IdTable, pst))
{
pst = new STRINGTABLE;
mapStrings.SetAt(IdTable, pst);
}
int nIndex = dwId - (((IdTable - 1 ) << 4));
ASSERT(nIndex >= 0 && nIndex < 16);
pst->m_bstr[nIndex] = bstrValue;
}
pos = mapStrings.GetStartPosition();
while (pos)
{
UINT Id;
STRINGTABLE* pst;
mapStrings.GetNextAssoc(pos, Id, pst);
DIRECTORY* pDirectory = AddDirectory(pRoot, (WORD)(DWORD_PTR)RT_STRING, Id, m_pLanguageInfo->wLanguage);
CBufferFile* pFile = pDirectory->pResource = new CBufferFile(10000);
for (int i = 0; i < 16; i++)
{
WORD wLength = 0;
if (pst->m_bstr[i] != 0)
{
LPCWSTR lpDispalyName = (LPCWSTR)pst->m_bstr[i];
wLength = (WORD)wcslen(lpDispalyName);
pFile->Write(&wLength, sizeof(WORD));
pFile->Write(lpDispalyName, wLength * sizeof(WCHAR));
}
else
{
pFile->Write(&wLength, sizeof(WORD));
}
}
AlignFile(pFile, 0);
delete pst;
}
}
void CResourceExport::ExportDll(CXTPPropExchangeXMLNode* pResources, LPCTSTR lpszOutput)
{
m_pResources = pResources;
DWORD nLangId = 0;
PX_DWord(m_pResources, _T("LANGID"), nLangId);
m_pLanguageInfo = CXTPResourceManager::GetLanguageInfo(nLangId);
if (!m_pLanguageInfo)
{
m_pResources = NULL;
return;
}
DIRECTORY* pRoot = new DIRECTORY();
ExportDllStringTable(pRoot);
ExportDllDialogs(pRoot);
ExportDllMenus(pRoot);
CString lpszResourcePath = lpszOutput ? lpszOutput : _T("C:\\out.dll");
CFile file;
file.Open(lpszResourcePath, CFile::modeWrite | CFile::modeCreate);
PIMAGE_DOS_HEADER pDosExeHdr = (PIMAGE_DOS_HEADER)(_alloca(512));
{
HRSRC hResource = ::FindResource(::GetModuleHandle(NULL), _T("DOSHEADER"), _T("BIN"));
if (hResource == NULL)
return;
HGLOBAL hGlobal = LoadResource(::GetModuleHandle(NULL), hResource);
if (hGlobal == NULL)
return;
LPBYTE pHeader = (LPBYTE)::LockResource(hGlobal);
memcpy(pDosExeHdr, pHeader, 512);
UnlockResource(hGlobal);
FreeResource(hGlobal);
}
PIMAGE_NT_HEADERS pNTHeader = PIMAGE_NT_HEADERS((LPBYTE)pDosExeHdr + (DWORD) pDosExeHdr->e_lfanew);
CBufferFile FAT;
CArrayDirectories DataDirs;
WriteFAT(&FAT, pRoot, &DataDirs);
WriteFATNames(&FAT, pRoot);
file.Write(pDosExeHdr, 512);
file.Write(FAT.GetBufferHeader(), (UINT)FAT.GetLength());
int nOffset = (int)FAT.GetLength();
for (int i = 0; i < DataDirs.GetSize(); i++)
{
DIRECTORY* pSubDir = DataDirs[i];
if (pSubDir->pResource)
{
DWORD dwSize = (DWORD)pSubDir->pResource->GetLength();
pSubDir->lpFatDataEntry->OffsetToData = nOffset + 0x00001000;
pSubDir->lpFatDataEntry->Size = dwSize;
file.Write(pSubDir->pResource->GetBufferHeader(), dwSize);
nOffset += dwSize;
}
else
{
CFile filebmp;
filebmp.Open(pSubDir->strResource, CFile::modeRead);
DWORD dwSize = (DWORD)((int)filebmp.GetLength() - pSubDir->nResourceOffset);
LPBYTE pBitmapInfo =(LPBYTE) malloc(dwSize);
if (pSubDir->nResourceOffset > 0) filebmp.Seek(pSubDir->nResourceOffset, CFile::begin);
filebmp.Read(pBitmapInfo, dwSize);
filebmp.Close();
pSubDir->lpFatDataEntry->OffsetToData = nOffset + 0x00001000;
pSubDir->lpFatDataEntry->Size = dwSize;
file.Write(pBitmapInfo, dwSize);
free(pBitmapInfo);
nOffset += dwSize;
}
}
int nAdd = 0x1000 - (nOffset & 0xFFF);
LPBYTE lpAlign = (LPBYTE)_alloca(0x200 + nAdd);
ZeroMemory(lpAlign, 0x200 + nAdd);
lpAlign[nAdd + 4] = 0x8;
file.Write(lpAlign, 0x200 + nAdd);
nOffset += nAdd;
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNTHeader );
pSection->Misc.VirtualSize = nOffset;
pSection->SizeOfRawData = nOffset;
pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = nOffset;
pSection++;
pSection->VirtualAddress = nOffset + 0x1000;
pSection->PointerToRawData = nOffset + 0x200;
pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = nOffset + 0x1000;
pNTHeader->OptionalHeader.SizeOfImage = nOffset + 0x2000;
pNTHeader->OptionalHeader.SizeOfInitializedData = nOffset + 0x200;
file.SeekToBegin();
file.Write(pDosExeHdr, 512);
file.Write(FAT.GetBufferHeader(), (UINT)FAT.GetLength());
file.Close();
delete pRoot;
m_pLanguageInfo= NULL;
m_pResources = NULL;
}
void Replace(LPSTR lpszData, LPCSTR lpszOld, LPCSTR lpszNew)
{
int nSourceLen = (int)strlen(lpszOld);
int nReplacementLen = (int)strlen(lpszNew);
int nOldLength = (int)strlen(lpszData);
LPSTR lpszStart = lpszData;
LPSTR lpszTarget;
while ((lpszTarget = strstr(lpszStart, lpszOld)) != NULL)
{
int nBalance = nOldLength - int(lpszTarget - lpszData + nSourceLen);
memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
nBalance);
memcpy(lpszTarget, lpszNew, nReplacementLen);
lpszStart = lpszTarget + nReplacementLen;
lpszStart[nBalance] = '\0';
nOldLength += (nReplacementLen - nSourceLen);
}
}
void WriteString(CFile& file, const CString& str)
{
USES_CONVERSION;
file.Write(T2CA((LPCTSTR)str), str.GetLength());
}
void WriteString(CFile& file, LPSTR str)
{
file.Write(str, (int)strlen(str));
}
void CResourceExport::ExchangeString(CXTPPropExchange* pPX, LPCTSTR pszPropName, LPSTR lpString)
{
BSTR bstrValue = 0;
PX_Bstr(pPX, pszPropName, bstrValue, 0);
ASSERT(!bstrValue || wcslen(bstrValue) < 500);
lpString[0] = 0;
WideCharToMultiByte(m_pLanguageInfo->nCodePage, 0, bstrValue, -1, lpString, 512, 0, 0);
Replace(lpString, "\\", "\\\\");
Replace(lpString, "\n", "\\n");
Replace(lpString, "\r", "\\r");
Replace(lpString, "\t", "\\t");
Replace(lpString, "\"", "\"\"");
SysFreeString(bstrValue);
}
void CResourceExport::ExportRcStringTable(CFile& file)
{
LPCSTR lpszHeader =
"/////////////////////////////////////////////////////////////////////////////\r\n"
"//\r\n"
"// String Table\r\n"
"//\r\n\r\n"
"STRINGTABLE\r\n"
"BEGIN\r\n";
WriteString(file, lpszHeader);
CXTPPropExchangeEnumeratorPtr ptrEnumeratorStrings(m_pResources->GetEnumerator(_T("string")));
POSITION pos = ptrEnumeratorStrings->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSectionString(ptrEnumeratorStrings->GetNext(pos));
DWORD dwId = 0;
char lpString[512];
PX_DWord(&ptrSectionString, _T("id"), dwId);
ExchangeString(&ptrSectionString, _T("value"), lpString);
WriteString(file, " ");
CString strResourceName = GetResourceName(dwId);
WriteString(file, strResourceName);
file.Write(" ", max(1, 34 - strResourceName.GetLength()));
WriteString(file, "\"");
WriteString(file, lpString);
WriteString(file, "\"\r\n");
}
WriteString(file, "END\r\n\r\n");
};
void CResourceExport::ExportRcMenuItems(CFile& file, DWORD dwParent, CXTPPropExchange* pResourceMenu, const CString& strIndent)
{
CXTPPropExchangeEnumeratorPtr ptrEnumeratorStrings(pResourceMenu->GetEnumerator(_T("menuitem")));
POSITION pos = ptrEnumeratorStrings->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSectionMenuItem(ptrEnumeratorStrings->GetNext(pos));
DWORD dwId = 0;
PX_DWord(&ptrSectionMenuItem, _T("id"), dwId);
char lpString[512];
ExchangeString(&ptrSectionMenuItem, _T("caption"), lpString);
if (((CXTPPropExchangeXMLNode*)&ptrSectionMenuItem)->IsSectionExists(_T("menuitem")))
{
WriteString(file, strIndent);
WriteString(file, "POPUP \"");
WriteString(file, lpString);
WriteString(file, "\"\r\n");
WriteString(file, strIndent);
WriteString(file, "BEGIN\r\n");
ExportRcMenuItems(file, dwParent, &ptrSectionMenuItem, strIndent + _T(" "));
WriteString(file, strIndent);
WriteString(file, "END\r\n");
}
else if (dwId != 0)
{
WriteString(file, strIndent);
WriteString(file, "MENUITEM \"");
WriteString(file, lpString);
WriteString(file, "\", ");
CString strResourceName = GetResourceName(dwId, dwParent);
WriteString(file, strResourceName);
WriteString(file, "\r\n");
}
else
{
WriteString(file, strIndent);
WriteString(file, "MENUITEM SEPARATOR\r\n");
}
}
}
void CResourceExport::ExportRcMenus(CFile& file)
{
LPCSTR lpszHeader =
"/////////////////////////////////////////////////////////////////////////////\r\n"
"//\r\n"
"// Menu\r\n"
"//\r\n\r\n";
WriteString(file, lpszHeader);
CXTPPropExchangeEnumeratorPtr ptrEnumeratorStrings(m_pResources->GetEnumerator(_T("menu")));
POSITION pos = ptrEnumeratorStrings->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSectionMenu(ptrEnumeratorStrings->GetNext(pos));
DWORD dwId = 0;
PX_DWord(&ptrSectionMenu, _T("id"), dwId);
if (dwId == 0)
continue;
CString strResourceName = GetResourceName(dwId);
CString strMenuHeader;
strMenuHeader.Format(_T("%s MENU DISCARDABLE\r\nBEGIN\r\n"), (LPCTSTR)strResourceName);
WriteString(file, strMenuHeader);
ExportRcMenuItems(file, dwId, &ptrSectionMenu, _T(" "));
WriteString(file, "END\r\n\r\n");
}
}
void CResourceExport::ExportRcDialogControls(CFile& file, DWORD dwParent, CXTPPropExchange* pResourceDialog)
{
CXTPPropExchangeEnumeratorPtr ptrEnumeratorStrings(pResourceDialog->GetEnumerator(_T("control")));
POSITION pos = ptrEnumeratorStrings->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSectionControl(ptrEnumeratorStrings->GetNext(pos));
DWORD dwId = 0;
DWORD dwStyle = 0, styleex = 0;
RECT rc = {0, 0, 0, 0};
CString strClass;
PX_DWord(&ptrSectionControl, _T("id"), dwId);
PX_DWord(&ptrSectionControl, _T("style"), dwStyle, WS_CHILD | WS_VISIBLE | WS_GROUP);
PX_DWord(&ptrSectionControl, _T("styleex"), styleex, 0);
PX_Rect(&ptrSectionControl, _T("position"), rc, rc);
PX_String(&ptrSectionControl, _T("class"), strClass, _T("STATIC"));
CString strResourceName = dwId == 0 ? _T("IDC_STATIC") :
dwId == 1 ? _T("IDOK") : dwId == 2 ? _T("IDCANCEL") : GetResourceName(dwId, dwParent);
char lpCaption[512];
ExchangeString(&ptrSectionControl, _T("caption"), lpCaption);
LPCSTR strType = NULL;
DWORD dwStyleDefault = (WS_CHILD | WS_VISIBLE | WS_TABSTOP);
DWORD bsStyle = dwStyle & 0xF;
BOOL bAddCaption = TRUE;
if (strClass.CompareNoCase(_T("BUTTON")) == 0)
{
if (bsStyle == BS_DEFPUSHBUTTON) strType = " DEFPUSHBUTTON \"";
if (bsStyle == BS_PUSHBUTTON) strType = " PUSHBUTTON \"";
if (bsStyle == BS_RADIOBUTTON) strType = " RADIOBUTTON \"";
if (bsStyle == BS_GROUPBOX)
{
strType = " GROUPBOX \"";
dwStyleDefault = (WS_CHILD | WS_VISIBLE);
}
dwStyleDefault += bsStyle;
}
else if (strClass.CompareNoCase(_T("STATIC")) == 0)
{
if (bsStyle == SS_LEFT) strType = " LTEXT \"";
if (bsStyle == SS_RIGHT)strType = " RTEXT \"";
dwStyleDefault = (WS_CHILD | WS_VISIBLE | WS_GROUP) + bsStyle;
}
else if (strClass.CompareNoCase(_T("COMBOBOX")) == 0)
{
strType = " COMBOBOX ";
bAddCaption = FALSE;
}
else if (strClass.CompareNoCase(_T("LISTBOX")) == 0)
{
strType = " LISTBOX ";
bAddCaption = FALSE;
}
else if (strClass.CompareNoCase(_T("EDIT")) == 0)
{
strType = " EDITTEXT ";
bAddCaption = FALSE;
}
CString str;
if (strType == NULL)
{
WriteString(file, " CONTROL \"");
WriteString(file, lpCaption);
str.Format(_T("\",%s,\"%s\",0x%x,%i,%i,%i,%i"), (LPCTSTR)strResourceName,
(LPCTSTR)strClass, dwStyle,
rc.left, rc.top, rc.right, rc.bottom);
WriteString(file, str);
}
else
{
WriteString(file, strType);
if (bAddCaption)
{
WriteString(file, lpCaption);
WriteString(file, "\",");
}
str.Format(_T("%s,%i,%i,%i,%i"), (LPCTSTR)strResourceName,
rc.left, rc.top, rc.right, rc.bottom);
WriteString(file, str);
if (dwStyle != dwStyleDefault || styleex != 0)
{
str.Format(_T(",0x%x"), dwStyle);
WriteString(file, str);
}
}
if (styleex != 0)
{
str.Format(_T(",0x%x"), styleex);
WriteString(file,str);
}
WriteString(file, "\r\n");
}
}
void CResourceExport::ExportRcDialogs(CFile& file)
{
LPCSTR lpszHeader =
"/////////////////////////////////////////////////////////////////////////////\r\n"
"//\r\n"
"// Dialog\r\n"
"//\r\n\r\n";
WriteString(file, lpszHeader);
CXTPPropExchangeEnumeratorPtr ptrEnumeratorStrings(m_pResources->GetEnumerator(_T("dialog")));
POSITION pos = ptrEnumeratorStrings->GetPosition();
while (pos)
{
CXTPPropExchangeSection ptrSectionDailog(ptrEnumeratorStrings->GetNext(pos));
DWORD dwId = 0;
DWORD dwStyle = 0, dwExStyle = 0;
RECT rc = {0, 0, 0, 0};
CString strFace;
PX_DWord(&ptrSectionDailog, _T("id"), dwId);
PX_DWord(&ptrSectionDailog, _T("style"), dwStyle);
PX_DWord(&ptrSectionDailog, _T("styleex"), dwExStyle, 0);
PX_Rect(&ptrSectionDailog, _T("position"), rc, rc);
PX_String(&ptrSectionDailog, _T("fontface"), strFace, _T("MS Sans Serif"));
char lpCaption[512];
ExchangeString(&ptrSectionDailog, _T("caption"), lpCaption);
if (dwId == 0)
continue;
CString strResourceName = GetResourceName(dwId);
CString strHeader;
strHeader.Format(_T("%s DIALOGEX DISCARDABLE %i, %i, %i, %i\r\n"),
(LPCTSTR)strResourceName, rc.left, rc.top, rc.right, rc.bottom);
WriteString(file, strHeader);
if (dwExStyle != 0)
{
strHeader.Format(_T("EXSTYLE 0x%x\r\n"), dwExStyle);
WriteString(file, strHeader);
}
strHeader.Format(_T("STYLE 0x%x\r\n"), dwStyle);
WriteString(file, strHeader);
WriteString(file, "CAPTION \""); WriteString(file, lpCaption); WriteString(file, "\"\r\n");
WriteString(file, "FONT 8, \""); WriteString(file, strFace); WriteString(file, "\"\r\n");
WriteString(file, "BEGIN\r\n");
ExportRcDialogControls(file, dwId, &ptrSectionDailog);
WriteString(file, "END\r\n\r\n");
}
}
void CResourceExport::ExportRc(CXTPPropExchangeXMLNode* pResources, LPCTSTR lpszOutput)
{
m_pResources = pResources;
CString lpszResourcePath = lpszOutput ? lpszOutput : _T("C:\\out.rc");
CFile file;
file.Open(lpszResourcePath, CFile::modeWrite | CFile::modeCreate);
DWORD nLangId = 0;
PX_DWord(m_pResources, _T("LANGID"), nLangId);
m_pLanguageInfo = CXTPResourceManager::GetLanguageInfo(nLangId);
if (!m_pLanguageInfo)
{
WriteString(file, "Not found");
m_pResources = NULL;
return;
}
CString strHeader;
strHeader.Format(
_T("// Codejock ResourceEditor generated resource script.\r\n")
_T("//\r\n\r\n#include \"afxres.h\"\r\n\r\n")
_T("/////////////////////////////////////////////////////////////////////////////\r\n")
_T("// %s resources\r\n\r\n")
_T("#if !defined(AFX_RESOURCE_DLL)\r\n")
_T("#ifdef _WIN32\r\n")
_T("LANGUAGE %s, %s\r\n")
_T("#pragma code_page(%i)\r\n")
_T("#endif //_WIN32\r\n\r\n"), m_pLanguageInfo->lpszCaption,
m_pLanguageInfo->lpszLang, m_pLanguageInfo->lpszSubLang, m_pLanguageInfo->nCodePage);
WriteString(file, strHeader);
ExportRcDialogs(file);
ExportRcMenus(file);
ExportRcStringTable(file);
WriteString(file, "#endif\r\n");
file.Close();
m_pLanguageInfo = NULL;
m_pResources = NULL;
}