28,102 → 28,147 |
#include <fstream> |
#include <vector> |
|
bool update_pe_timestamp(LPCTSTR filename, time_t timestamp) { |
size_t peoffset; |
FILE* fptr; |
typedef struct _PE32 { |
uint32_t magic; // 0x50450000 |
IMAGE_FILE_HEADER fileHeader; // COFF Header without Signature |
IMAGE_OPTIONAL_HEADER32 optHeader; // Standard COFF fields, Windows Specific Fields, Data Directories |
} PE32; |
|
fptr = _wfopen(filename, L"rb+"); |
if (fptr == NULL) return false; |
#ifdef UNICODE |
typedef std::wstring tstring; |
#else |
typedef std::string tstring; |
#endif |
|
fseek(fptr, 0x3C, SEEK_SET); |
fread(&peoffset, sizeof(peoffset), 1, fptr); |
int binary_file_string_replace(tstring file_name, const char* asearch, const char* areplace) { |
std::ifstream input(file_name, std::ios::binary); |
|
fseek(fptr, (long)peoffset + 8, SEEK_SET); |
fwrite(×tamp, sizeof(time_t), 1, fptr); |
std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>())); |
std::vector<char>::iterator itbegin = buffer.begin(); |
std::vector<char>::iterator itend = buffer.end(); |
|
fclose(fptr); |
if (strlen(asearch) != strlen(areplace)) { |
printf("Replace value length greater than original!\n"); |
return -1; |
} |
int MAX_BUFFER = strlen(asearch); |
|
return true; |
char* needed_str = (char*)malloc(MAX_BUFFER); |
if (needed_str == 0) return -1; |
char* replace_str = (char*)malloc(MAX_BUFFER); |
if (replace_str == 0) return -1; |
|
memcpy(needed_str, asearch, MAX_BUFFER); |
memcpy(replace_str, areplace, MAX_BUFFER); |
|
int ifound = 0; |
|
for (auto it = itbegin; it < itend; it++) { |
if (memcmp(it._Ptr, needed_str, MAX_BUFFER) == 0) { |
strncpy(it._Ptr, replace_str, MAX_BUFFER); |
it += MAX_BUFFER - 1; // -1 because it++ will be set on the next loop |
ifound++; |
} |
} |
|
bool update_pe_stackSizeCommit(LPCTSTR filename, size_t stackReserve, size_t stackCommit) { |
size_t peoffset; |
FILE* fptr; |
if (ifound > 0) { |
std::ofstream ofile(file_name, std::ios::out | std::ios::binary); |
ofile.write((char*)&buffer[0], buffer.size() * sizeof(char)); |
ofile.close(); |
} |
|
fptr = _wfopen(filename, L"rb+"); |
if (fptr == NULL) return false; |
return ifound; |
} |
|
fseek(fptr, 0x3C, SEEK_SET); |
fread(&peoffset, sizeof(peoffset), 1, fptr); |
int binary_file_string_find(tstring file_name, const char* asearch) { |
std::ifstream input(file_name, std::ios::binary); |
|
fseek(fptr, (long)peoffset + 12 * 8, SEEK_SET); |
fwrite(&stackReserve, sizeof(size_t), 1, fptr); |
std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>())); |
std::vector<char>::iterator itbegin = buffer.begin(); |
std::vector<char>::iterator itend = buffer.end(); |
|
fseek(fptr, (long)peoffset + 12 * 8 + 4, SEEK_SET); |
fwrite(&stackCommit, sizeof(size_t), 1, fptr); |
int MAX_BUFFER = strlen(asearch); |
|
fclose(fptr); |
char* needed_str = (char*)malloc(MAX_BUFFER); |
if (needed_str == 0) return -1; |
|
return true; |
memcpy(needed_str, asearch, MAX_BUFFER); |
|
int ifound = 0; |
|
for (auto it = itbegin; it < itend; it++) { |
if (memcmp(it._Ptr, needed_str, MAX_BUFFER) == 0) { |
it += MAX_BUFFER - 1; // -1 because it++ will be set on the next loop |
ifound++; |
} |
} |
|
bool update_pe_heapSizeCommit(LPCTSTR filename, size_t heapReserve, size_t heapCommit) { |
return ifound; |
} |
|
void _set_pe_int32(FILE* fptr, size_t fieldoffset, int32_t val) { |
size_t peoffset; |
FILE* fptr; |
|
fptr = _wfopen(filename, L"rb+"); |
if (fptr == NULL) return false; |
fseek(fptr, 0x3C, SEEK_SET); |
fread(&peoffset, sizeof(peoffset), 1, fptr); |
|
fseek(fptr, (long)peoffset + fieldoffset, SEEK_SET); |
fwrite(&val, sizeof(int32_t), 1, fptr); |
} |
|
int32_t _get_pe_int32(FILE* fptr, size_t fieldoffset) { |
size_t peoffset; |
int32_t res; |
|
fseek(fptr, 0x3C, SEEK_SET); |
fread(&peoffset, sizeof(peoffset), 1, fptr); |
|
fseek(fptr, (long)peoffset + 13 * 8, SEEK_SET); |
fwrite(&heapReserve, sizeof(size_t), 1, fptr); |
fseek(fptr, (long)peoffset + fieldoffset, SEEK_SET); |
fread(&res, sizeof(int32_t), 1, fptr); |
|
fseek(fptr, (long)peoffset + 13 * 8 + 4, SEEK_SET); |
fwrite(&heapCommit, sizeof(size_t), 1, fptr); |
return res; |
} |
|
bool update_pe_timestamp(LPCTSTR filename, __time32_t timestamp) { |
FILE* fptr = _wfopen(filename, L"rb+"); |
if (fptr == NULL) return false; |
|
_set_pe_int32(fptr, /*0x0008*/offsetof(PE32, fileHeader.TimeDateStamp), timestamp); |
|
fclose(fptr); |
|
return true; |
} |
|
bool openWatcomCosmetics(LPCTSTR filename) { |
if (binary_file_string_find(filename, "Open Watcom") > 0) { |
FILE* fptr = _wfopen(filename, L"rb+"); |
if (fptr == NULL) return false; |
|
//DOS .EXE header |
struct image_dos_header |
{ |
uint16_t e_magic; // Magic number |
uint16_t e_cblp; // Bytes on last page of file |
uint16_t e_cp; // Pages in file |
uint16_t e_crlc; // Relocations |
uint16_t e_cparhdr; // Size of header in paragraphs |
uint16_t e_minalloc; // Minimum extra paragraphs needed |
uint16_t e_maxalloc; // Maximum extra paragraphs needed |
uint16_t e_ss; // Initial (relative) SS value |
uint16_t e_sp; // Initial SP value |
uint16_t e_csum; // Checksum |
uint16_t e_ip; // Initial IP value |
uint16_t e_cs; // Initial (relative) CS value |
uint16_t e_lfarlc; // File address of relocation table |
uint16_t e_ovno; // Overlay number |
uint16_t e_res[4]; // Reserved words |
uint16_t e_oemid; // OEM identifier (for e_oeminfo) |
uint16_t e_oeminfo; // OEM information; e_oemid specific |
uint16_t e_res2[10]; // Reserved words |
int32_t e_lfanew; // File address of new exe header |
}; |
// Min OS Version 1.11 ... But the actual minimal Windows version is Windows NT 3.11 |
int32_t minOsVersion = _get_pe_int32(fptr, /*0x0040*/offsetof(PE32, optHeader.MajorOperatingSystemVersion)); |
if (minOsVersion == 0x000B0001) { |
_set_pe_int32(fptr, /*0x0040*/offsetof(PE32, optHeader.MajorOperatingSystemVersion), 0x00000003); // Windows 3.0 |
} |
|
struct image_file_header |
{ |
uint16_t Machine; |
uint16_t NumberOfSections; |
uint32_t TimeDateStamp; |
uint32_t PointerToSymbolTable; |
uint32_t NumberOfSymbols; |
uint16_t SizeOfOptionalHeader; |
uint16_t Characteristics; |
}; |
// Stack reserved cannot be changed with linker option "OPTION STACK=1m" (Rejected https://github.com/open-watcom/open-watcom-v2/issues/780) |
// It is not required for DLLs, but everybody does it, and I think it is cosmetics to fill these fields, even if not required. |
_set_pe_int32(fptr, /*0x0060*/offsetof(PE32, optHeader.SizeOfStackReserve), 0x00100000); |
_set_pe_int32(fptr, /*0x0064*/offsetof(PE32, optHeader.SizeOfStackCommit), 0x00001000); |
// Heap reserved can be changed with linker option "OPTION HEAP=1m" |
_set_pe_int32(fptr, /*0x0068*/offsetof(PE32, optHeader.SizeOfHeapReserve), 0x00100000); |
_set_pe_int32(fptr, /*0x006C*/offsetof(PE32, optHeader.SizeOfHeapCommit), 0x00001000); |
|
fclose(fptr); |
|
// 32 bit (OpenWatcom cosmetics): Export table name "FilterFoundry.dll" => "FilterFoundry.8bf" |
// since OpenWatcom cannot link a 8BF file natively. |
binary_file_string_replace(filename, "FilterFoundry.dll", "FilterFoundry.8bf"); |
} |
|
return true; |
} |
|
uint32_t calculate_checksum(LPCTSTR filename) { |
//Calculate checksum of image |
// Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library |
132,7 → 177,7 |
|
FILE* fptr; |
unsigned long long checksum = 0; |
struct image_dos_header header; |
IMAGE_DOS_HEADER header; |
size_t filesize; |
unsigned long long top; |
unsigned long pe_checksum_pos; |
144,7 → 189,7 |
|
//Read DOS header |
fseek(fptr, 0, SEEK_SET); |
fread(&header, sizeof(struct image_dos_header), 1, fptr); |
fread(&header, sizeof(IMAGE_DOS_HEADER), 1, fptr); |
|
//Calculate PE checksum |
fseek(fptr, 0, SEEK_SET); |
154,7 → 199,7 |
//"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+ |
//Calculate real PE headers "CheckSum" field position |
//Sum is safe here |
pe_checksum_pos = header.e_lfanew + sizeof(struct image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers; |
pe_checksum_pos = header.e_lfanew + sizeof(IMAGE_FILE_HEADER) + sizeof(uint32_t) + checksum_pos_in_optional_headers; |
|
//Calculate checksum for each byte of file |
fseek(fptr, 0L, SEEK_END); |
190,7 → 235,6 |
} |
|
bool repair_pe_checksum(LPCTSTR filename) { |
size_t peoffset; |
FILE* fptr; |
|
uint32_t checksum = calculate_checksum(filename); |
199,12 → 243,8 |
fptr = _wfopen(filename, L"rb+"); |
if (fptr == NULL) return false; |
|
fseek(fptr, 0x3C, SEEK_SET); |
fread(&peoffset, sizeof(peoffset), 1, fptr); |
_set_pe_int32(fptr, /*0x0058*/offsetof(PE32, optHeader.CheckSum), (int32_t)checksum); |
|
fseek(fptr, (long)peoffset + 88, SEEK_SET); |
fwrite(&checksum, sizeof(uint32_t), 1, fptr); |
|
fclose(fptr); |
|
return true; |
272,51 → 312,7 |
return bSuccessful; |
} |
|
#ifdef UNICODE |
int binary_file_string_replace(std::wstring file_name, const char* asearch, const char* areplace) { |
#else |
int binary_file_string_replace(std::string file_name, const char* asearch, const char* areplace) { |
#endif |
std::ifstream input(file_name, std::ios::binary); |
|
std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>())); |
std::vector<char>::iterator itbegin = buffer.begin(); |
std::vector<char>::iterator itend = buffer.end(); |
|
if (strlen(asearch) != strlen(areplace)) { |
printf("Replace value length greater than original!\n"); |
return -1; |
} |
int MAX_BUFFER = strlen(asearch); |
|
char* needed_str = (char*)malloc(MAX_BUFFER); |
if (needed_str == 0) return -1; |
char* replace_str = (char*)malloc(MAX_BUFFER); |
if (replace_str == 0) return -1; |
|
memcpy(needed_str, asearch, MAX_BUFFER); |
memcpy(replace_str, areplace, MAX_BUFFER); |
|
int ifound = 0; |
|
for (auto it = itbegin; it < itend ; it++) { |
if (memcmp(it._Ptr, needed_str, MAX_BUFFER) == 0) { |
strncpy(it._Ptr, replace_str, MAX_BUFFER); |
it += MAX_BUFFER - 1; // -1 because it++ will be set on the next loop |
ifound++; |
} |
} |
|
if (ifound > 0) { |
std::ofstream ofile(file_name, std::ios::out | std::ios::binary); |
ofile.write((char*)&buffer[0], buffer.size() * sizeof(char)); |
ofile.close(); |
} |
|
return ifound; |
} |
|
|
int main() |
{ |
LPCTSTR lpTemplateType = L"TPLT"; |
397,23 → 393,13 |
removeFromFile(file64tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral); |
} |
|
// 32 bit (OpenWatcom cosmetics): Export table name "filterfoundry.dll" => "FilterFoundry.8bf" |
// since OpenWatcom cannot link a 8BF file natively. |
binary_file_string_replace(file32tmp, "filterfoundry.dll", "FilterFoundry.8bf"); |
binary_file_string_replace(file32out, "filterfoundry.dll", "FilterFoundry.8bf"); |
// Do some cosmetics to OpenWatcom binaries |
openWatcomCosmetics(file32tmp); |
openWatcomCosmetics(file32out); |
|
// More OpenWatcom cosmetics! https://github.com/open-watcom/open-watcom-v2/issues/780 (Rejected) |
// Stack reserved cannot be changed with linker option "OPTION STACK=1m" (Rejected) |
// It is not required for DLLs, but everybody does it, and I think it is cosmetics to fill these fields, even if not required. |
update_pe_stackSizeCommit(file32tmp, 1024 * 1024, 4096); |
update_pe_stackSizeCommit(file32out, 1024 * 1024, 4096); |
// Heap reserved can be changed with linker option "OPTION HEAP=1m" |
update_pe_heapSizeCommit(file32tmp, 1024 * 1024, 4096); |
update_pe_heapSizeCommit(file32out, 1024 * 1024, 4096); |
|
// 3. Update timestamp of 32/64 "TMP" |
{ |
if (!update_pe_timestamp(file32tmp, time(0))) { |
if (!update_pe_timestamp(file32tmp, (__time32_t)time(0))) { |
DeleteFile(file32out); |
DeleteFile(file64out); |
printf("Error: Update TMP timestamp 32\n"); |
420,7 → 406,7 |
return 1; |
} |
|
if (!update_pe_timestamp(file64tmp, time(0))) { |
if (!update_pe_timestamp(file64tmp, (__time32_t)time(0))) { |
DeleteFile(file32out); |
DeleteFile(file64out); |
printf("Error: Update TMP timestamp 64\n"); |
566,7 → 552,7 |
|
// 9. Update timestamp of 32/64 "OUT" |
{ |
if (!update_pe_timestamp(file32out, time(0))) { |
if (!update_pe_timestamp(file32out, (__time32_t)time(0))) { |
DeleteFile(file32out); |
DeleteFile(file64out); |
printf("Error: Update OUT timestamp 32\n"); |
573,7 → 559,7 |
return 1; |
} |
|
if (!update_pe_timestamp(file64out, time(0))) { |
if (!update_pe_timestamp(file64out, (__time32_t)time(0))) { |
DeleteFile(file32out); |
DeleteFile(file64out); |
printf("Error: Update OUT timestamp 64\n"); |