📄 cbinmod.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
#include "cbinmod.h"
#include "..\compress\compress.h"
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CBinMod::CBinMod(bool log2file)
{
hFile = INVALID_HANDLE_VALUE;
fpLog = NULL;
pTOC = 0;
dwImageStart = 0;
dwImageLength = 0;
dwNumRecords = 0;
dwROMOffset = 0;
memset(Records, 0, sizeof(Records));
if(log2file){
char path[MAX_PATH];
char tmp[MAX_PATH];
if(GetTempPath(sizeof(path), path) == ERROR_PATH_NOT_FOUND)
{
printf("Error: GetTempPath() failed\n");
goto exit;
}
if(GetTempFileName(path, "binmod", 0, tmp) == 0)
{
printf("Error: GetTempFileName() failed\n");
goto exit;
}
printf("Logging to %s\n", tmp);
fpLog = fopen(tmp, "w");
if(!fpLog)
{
printf("Error: fopen() failed\n");
goto exit;
}
}
exit:
return;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CBinMod::~CBinMod()
{
if(hFile != INVALID_HANDLE_VALUE)
{
my_CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
if(fpLog){
fclose(fpLog);
fpLog = NULL;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool CBinMod::Init(string _image)
{
image = _image;
if(my_GetFileAttributes(image.c_str()) == INVALID_FILE_ATTRIBUTES){
dprintf("Error: Could not find image '%s'\n", image.c_str());
return false;
}
hFile = my_CreateFile(image.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
0);
if(hFile == INVALID_HANDLE_VALUE) {
dprintf("Error opening %s\n", image.c_str());
goto Error;
}
DWORD cb;
INT fRet;
fRet = my_ReadFile(hFile, pBuffer, 7, &cb, NULL);
if (!fRet || cb != 7) {
dprintf("ERROR: Reading %s (%d)\n", image.c_str(), __LINE__);
goto Error;
}
if(memcmp(pBuffer, "B000FF\x0A", 7 )) {
dprintf("Missing initial signature (BOOOFF\x0A). Not a BIN file\n");
goto Error;
}
//
// Read the image header
//
fRet = my_ReadFile(hFile, &dwImageStart, sizeof(DWORD), &cb, NULL);
if (!fRet || cb != sizeof(DWORD)) {
dprintf("ERROR: Can't find Image start\n");
goto Error;
}
fRet = my_ReadFile(hFile, &dwImageLength, sizeof(DWORD), &cb, NULL);
if (!fRet || cb != sizeof(DWORD)) {
dprintf("ERROR: Can't find Image length\n");
goto Error;
}
//
// Now read the records.
//
DWORD dwRecAddr, dwRecLen, dwRecChk;
while (1) {
//
// Record address
//
fRet = my_ReadFile(hFile, &dwRecAddr, sizeof(DWORD), &cb, NULL);
if (!fRet || cb != sizeof(DWORD)) {
break;
}
//
// Record length
//
fRet = my_ReadFile(hFile, &dwRecLen, sizeof(DWORD), &cb, NULL);
if (!fRet || cb != sizeof(DWORD)) {
break;
}
//
// Record checksum
//
fRet = my_ReadFile(hFile, &dwRecChk, sizeof(DWORD), &cb, NULL);
if (!fRet || cb != sizeof(DWORD)) {
break;
}
Records[dwNumRecords].dwStartAddress = dwRecAddr;
Records[dwNumRecords].dwLength = dwRecLen;
Records[dwNumRecords].dwChecksum = dwRecChk;
Records[dwNumRecords].dwFilePointer = my_SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
dwNumRecords++;
if (dwRecAddr == 0) {
break;
}
my_SetFilePointer(hFile, dwRecLen, NULL, FILE_CURRENT);
}
//
// Find pTOC
//
fRet = AccessBinFile(pBuffer, dwImageStart + 0x40, 8, 0, false);
if (fRet) {
pTOC = *((PDWORD)(pBuffer + 4));
} else {
dprintf("ERROR: Couldn't find pTOC\n");
goto Error;
}
return true;
Error:
image.erase();
return false;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool CBinMod::Replace(string _file)
{
if(my_GetFileAttributes(_file.c_str()) == INVALID_FILE_ATTRIBUTES){
dprintf("Could not find file '%s'\n", _file.c_str());
return false;
}
bool ret = false;
ROMHDR Toc = {0};
DWORD state = 0;
string name;
NextRegion:
if (!ComputeRomOffset(state)) {
goto EndOfRegions;
}
string::size_type idx = _file.rfind('\\');
if(idx == string::npos)
name = _file;
else
name = _file.substr(idx+1); // start just after the \
// read toc
if(!AccessBinFile((PBYTE)&Toc, pTOC, sizeof(ROMHDR), dwROMOffset, false)){
dprintf("Couldn't read TOC data\n");
goto exit;
}
FILESentry *pFileList = new FILESentry[Toc.numfiles];
if(!pFileList){
dprintf("Error allocated space for files list containing %d files\n", Toc.numfiles);
goto exit;
}
DWORD files_section_offset = pTOC + sizeof(ROMHDR) + sizeof(TOCentry) * Toc.nummods;
// read FILESEntry list
if(!AccessBinFile((BYTE*)pFileList,
files_section_offset,
sizeof(FILESentry) * Toc.numfiles,
dwROMOffset,
false)){
dprintf("Couldn't read file list\n");
goto exit;
}
for(int i = 0; i < (int)Toc.numfiles; i++){
if(!AccessBinFile(pBuffer, (DWORD)pFileList[i].lpszFileName, 0, dwROMOffset, false)){
dprintf("Couldn't read file name for file %d\n", i);
goto exit;
}
if(strcmp((char*)pBuffer, name.c_str()) == 0)
{
bool compressed = false;
if(pFileList[i].nRealFileSize != pFileList[i].nCompFileSize) compressed = true;
DWORD size = 0;
if(compressed)
size = pFileList[i].nCompFileSize;
else
size = pFileList[i].nRealFileSize;
dprintf("Found '%s' in the image! - located at %08x, size %08x %s\n", name.c_str(), pFileList[i].ulLoadOffset, size, compressed ? "compressed" : "uncompressed");
BYTE *new_data = NULL;
DWORD csize = 0;
DWORD rsize = 0;
if(!GetNewFileData(&new_data, &csize, &rsize, _file.c_str(), compressed)){
dprintf("Error: failed processing new file\n");
goto exit;
}
if(compressed)
dprintf("New file compressed = %08x, uncompressed = %08x\n", csize, rsize);
else
dprintf("New file uncompressed = %08x\n", rsize);
// if sizes are the same or smaller just overwrite the data and zero pad
if(size >= csize){
BYTE *buffer = new BYTE[size];
if(!buffer){
dprintf("Error: failed allocating buffer\n");
goto exit;
}
memset(buffer, 0, size);
memcpy(buffer, new_data, csize);
if(!AccessBinFile(buffer, pFileList[i].ulLoadOffset, size, dwROMOffset, true)){
dprintf("Error: failed to write new data to image\n");
goto exit;
}
delete[] buffer;
}
else{ // allocate new location for data?
dprintf("File too large for origional location, searching for new space...\n");
BYTE *buffer = new BYTE[csize];
if(!buffer){
dprintf("Error: failed allocating buffer\n");
goto exit;
}
memcpy(buffer, new_data, csize);
pFileList[i].ulLoadOffset = FindHole(csize, &Toc);
if(!pFileList[i].ulLoadOffset){
dprintf("Error: Couldn't find space in the image for file, replace aborted\n");
dprintf(" The image is in a possibly inconsistent state and should not be used!!!!\n");
goto exit;
}
if(!AccessBinFile(buffer, pFileList[i].ulLoadOffset, csize, dwROMOffset, true)){
dprintf("Error: failed to write new data to image\n");
dprintf(" The image is in a possibly inconsistent state and should not be used!!!!\n");
goto exit;
}
delete[] buffer;
}
dprintf("New data written to image!\n");
pFileList[i].nCompFileSize = csize;
pFileList[i].nRealFileSize = rsize;
if(!AccessBinFile((BYTE*)pFileList, files_section_offset, sizeof(FILESentry) * Toc.numfiles, dwROMOffset, true)){
dprintf("Error: failed updating TOC!\n");
dprintf(" The image is in a possibly inconsistent state and should not be used!!!!\n");
goto exit;
}
dprintf("TOC updated!\n");
delete[] new_data;
ret = true;
goto exit;
}
}
goto NextRegion;
EndOfRegions:
dprintf("Error: File not found in image\n");
exit:
return ret;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool CBinMod::GetNewFileData(BYTE **buffer, DWORD *csize, DWORD *rsize, const char *file_name, bool compressed){
bool ret = false;
HANDLE hInput = INVALID_HANDLE_VALUE;
hInput = my_CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if(hInput == INVALID_HANDLE_VALUE){
dprintf("Error opening %s\n", file_name);
goto exit;
}
*csize = *rsize = my_GetFileSize(hInput, NULL);
if(*rsize == INVALID_FILE_SIZE){
dprintf("Error: failed to get file size information for '%s'\n", file_name);
goto exit;
}
*buffer = new BYTE[*rsize];
if(!*buffer){
dprintf("Error: failed allocating buffer\n");
goto exit;
}
DWORD cb = 0;
if(!my_ReadFile(hInput, *buffer, *rsize, &cb, NULL) || cb != *rsize){
dprintf("Error: failed reading '%s'\n", file_name);
goto exit;
}
if(compressed){
// compress the data
BYTE *compressed_data = new BYTE[*rsize];
DWORD compressed_size;
DWORD page_size = 0x1000;
if(!compressed_data){
dprintf("Error: failed allocating buffer\n");
goto exit;
}
char *m_name = "compress.dll";
HMODULE m_hcomp = LoadLibrary(m_name);
if(!m_hcomp){
dprintf("Error: LoadLibrary() failed to load '%s': %d\n", m_name, GetLastError());
return false;
}
CECOMPRESS cecompress = (CECOMPRESS)GetProcAddress(m_hcomp, "CECompress");
if(!cecompress){
dprintf("Error: GetProcAddress() failed to find 'CECompress' in '%s': %d\n", m_name, GetLastError());
FreeLibrary(m_hcomp);
return false;
}
dprintf("Assuming pagesize of %08x for compression!\n", page_size);
compressed_size = cecompress(*buffer,
*rsize,
compressed_data,
*rsize - 1,
1,
page_size);
FreeLibrary(m_hcomp);
// if success
if(compressed_size != -1){
*csize = compressed_size;
memcpy(*buffer, compressed_data, *csize);
}
}
ret = true;
exit:
return ret;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool CBinMod::Extract(string _file)
{
if(image.empty())
return false;
if(GetFileAttributes(_file.c_str()) != INVALID_FILE_ATTRIBUTES){
dprintf("File already exists '%s', extraction aborted.\n", _file.c_str());
return false;
}
bool ret = false;
ROMHDR TOC = {0};
DWORD state = 0;
string name;
NextRegion:
if (!ComputeRomOffset(state)) {
goto EndOfRegions;
}
string::size_type idx = _file.rfind('\\');
if(idx == string::npos)
name = _file;
else
name = _file.substr(idx+1); // start just after the \
// read toc
if(!AccessBinFile((PBYTE)&TOC, pTOC, sizeof(ROMHDR), dwROMOffset, false)){
dprintf("Couldn't read TOC data\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -