⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cbinmod.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -