239 lines
6.7 KiB
C++
239 lines
6.7 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: smashbin.cpp
|
|
//
|
|
// Contents: Smashes two binary files together, with a given offset
|
|
// Between them padded
|
|
//
|
|
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
#include <winlean.h>
|
|
#include <assert.h>
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
typedef signed int INT;
|
|
typedef signed char INT8, *LPINT8;
|
|
typedef signed short INT16, *LPINT16;
|
|
typedef unsigned int UINT;
|
|
typedef unsigned char UINT8, *LPUINT8;
|
|
typedef unsigned short UINT16, *LPUINT16;
|
|
|
|
|
|
BOOL DoPad(HANDLE hOutput, DWORD padSize)
|
|
{
|
|
const DWORD nBufferBytes = 0x10000;
|
|
BYTE bPadBuffer[nBufferBytes];
|
|
DWORD nWritten = 0;
|
|
|
|
memset(&bPadBuffer, 0, nBufferBytes);
|
|
|
|
while (padSize > nBufferBytes) {
|
|
if (0 == WriteFile(hOutput, bPadBuffer, nBufferBytes, &nWritten, NULL)) {
|
|
fprintf(stderr, "Pad file failed.\n");
|
|
return FALSE;
|
|
}
|
|
assert(nWritten == nBufferBytes);
|
|
padSize -= nBufferBytes;
|
|
}
|
|
|
|
if (padSize > 0) {
|
|
if (0 == WriteFile(hOutput, bPadBuffer, padSize, &nWritten, NULL)) {
|
|
fprintf(stderr, "Pad file failed.\n");
|
|
return FALSE;
|
|
}
|
|
assert(nWritten == padSize);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL DoCopy(HANDLE hInput, HANDLE hOutput, DWORD * totalWritten)
|
|
{
|
|
const DWORD nBufferBytes = 0x10000;
|
|
BYTE bBuffer[nBufferBytes];
|
|
|
|
DWORD nRead = 0;
|
|
do {
|
|
if (0 == ReadFile(hInput, bBuffer, nBufferBytes, &nRead, NULL)) {
|
|
fprintf(stderr, "ReadFile failed.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD nWritten = 0;
|
|
if (0 == WriteFile(hOutput, bBuffer, nRead, &nWritten, NULL)) {
|
|
fprintf(stderr, "WriteFile failed.\n");
|
|
return FALSE;
|
|
}
|
|
assert(nWritten == nRead);
|
|
(*totalWritten) += nWritten;
|
|
} while (nRead != 0);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
BOOL SmashBins(DWORD offset, PCWSTR bin1, PCWSTR bin2, PCWSTR dest)
|
|
{
|
|
BOOL bSuccess = TRUE;
|
|
DWORD totalWritten = 0;
|
|
|
|
// open output file
|
|
HANDLE hOutput = CreateFile(dest,
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
0,
|
|
NULL);
|
|
|
|
if (hOutput == INVALID_HANDLE_VALUE) {
|
|
fprintf(stderr, "Could not open output file: %ls\n", dest);
|
|
return false;
|
|
}
|
|
|
|
// open input 1
|
|
HANDLE hInput1 = CreateFile(bin1,
|
|
GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
if (hInput1 == INVALID_HANDLE_VALUE) {
|
|
fprintf(stderr, "Could not open image file: %ls\n", bin1);
|
|
return FALSE;
|
|
}
|
|
|
|
bSuccess = DoCopy(hInput1, hOutput, &totalWritten);
|
|
|
|
CloseHandle(hInput1);
|
|
if (!bSuccess) {
|
|
CloseHandle(hOutput);
|
|
return bSuccess;
|
|
} else if (totalWritten > offset) {
|
|
CloseHandle(hOutput);
|
|
fprintf(stderr, "First image is larger than offset %d > %d\n",
|
|
totalWritten, offset);
|
|
return FALSE;
|
|
}
|
|
|
|
wprintf(L"00000000..%08x: File %s\n", totalWritten, bin1);
|
|
|
|
bSuccess = DoPad(hOutput, offset - totalWritten);
|
|
|
|
if (!bSuccess) {
|
|
CloseHandle(hOutput);
|
|
return bSuccess;
|
|
}
|
|
|
|
wprintf(L"%08x..%08x: Padding\n", totalWritten, offset);
|
|
totalWritten += (offset - totalWritten);
|
|
|
|
// open input 2
|
|
HANDLE hInput2 = CreateFile(bin2,
|
|
GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
if (hInput1 == INVALID_HANDLE_VALUE) {
|
|
fprintf(stderr, "Could not open image file: %ls\n", bin2);
|
|
return FALSE;
|
|
}
|
|
|
|
bSuccess = DoCopy(hInput2, hOutput, &totalWritten);
|
|
|
|
wprintf(L"%08x..%08x: File %s\n", offset, totalWritten, bin2);
|
|
|
|
CloseHandle(hInput2);
|
|
CloseHandle(hOutput);
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
|
|
int __cdecl wmain(int argc, WCHAR **argv)
|
|
{
|
|
BOOL fNeedHelp = FALSE;
|
|
DWORD offset = 0;
|
|
|
|
int arg;
|
|
for (arg = 1; arg < argc && !fNeedHelp; arg++) {
|
|
if (argv[arg][0] != '-' && argv[arg][0] != '/') {
|
|
break;
|
|
|
|
}
|
|
|
|
WCHAR *argn = argv[arg]+1; // Argument name
|
|
WCHAR *argp = argn; // Argument parameter
|
|
|
|
while (*argp && *argp != ':') {
|
|
argp++;
|
|
}
|
|
|
|
if (*argp == ':') {
|
|
*argp++ = '\0';
|
|
}
|
|
|
|
switch (argn[0]) {
|
|
|
|
case 'o': // Offset
|
|
int scanfRet;
|
|
arg++;
|
|
if(argv[arg][0] == '0' && argv[arg][1] == 'x')
|
|
{
|
|
// hex number
|
|
scanfRet = swscanf(argv[arg], L"%x", &offset);
|
|
} else {
|
|
// base 10 number
|
|
scanfRet = swscanf(argv[arg], L"%d", &offset);
|
|
}
|
|
if(EOF == scanfRet)
|
|
{
|
|
fNeedHelp = TRUE;
|
|
}
|
|
break;
|
|
case '?': // Help
|
|
fNeedHelp = TRUE;
|
|
break;
|
|
|
|
default:
|
|
printf("Unknown argument: %ls\n", argv[arg]);
|
|
fNeedHelp = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (fNeedHelp || argc - arg != 3) {
|
|
printf(
|
|
"Usage:\n"
|
|
" mkbin [options] <binary 1> <binary 2> <output>\n"
|
|
"Options:\n"
|
|
" /o <size> -- Offset of second binary file\n"
|
|
" /? -- Display this help screen.\n"
|
|
"Summary:\n"
|
|
" Smashes two binaries together, with padding between binaries to provide given offset.\n"
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
return SmashBins(offset, argv[arg], argv[arg + 1], argv[arg + 2]) ? 0 : 1;
|
|
}
|
|
|
|
//
|
|
///////////////////////////////////////////////////////////////// End of File.
|
|
|