singrdk/base/Windows/smashbin/smashbin.cpp

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.