https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0b948581fc279f262cfef1...
commit 0b948581fc279f262cfef1aa517229bd29ac8736 Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Mon Apr 13 12:20:47 2020 +0200 Commit: Mark Jansen mark.jansen@reactos.org CommitDate: Fri Apr 17 17:47:24 2020 +0200
[SDK][HOST-TOOLS] Add load_config workaround for gcc builds Since binutils can not add this, we re-introduce pefixup. It searches for the exported symbol '_load_config_used', and uses that to fill out the LOAD_CONFIG directory in the PE header --- CMakeLists.txt | 2 +- modules/rostests/apitests/CMakeLists.txt | 6 +- .../rostests/apitests/loadconfig/CMakeLists.txt | 8 +- .../apitests/loadconfig/loadconfig_apitest.spec | 3 + sdk/cmake/gcc.cmake | 8 + sdk/cmake/msvc.cmake | 4 + sdk/tools/CMakeLists.txt | 5 +- sdk/tools/pefixup.c | 543 ++++++--------------- 8 files changed, 185 insertions(+), 394 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt index 777a0335304..50fbf192c4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ if(NOT CMAKE_CROSSCOMPILING)
set(NATIVE_TARGETS bin2c widl gendib cabman fatten hpp isohybrid mkhive mkisofs obj2bin spec2def geninc mkshelllink utf16le xml2sdb) if(NOT MSVC) - list(APPEND NATIVE_TARGETS rsym) + list(APPEND NATIVE_TARGETS rsym pefixup) endif()
export(TARGETS ${NATIVE_TARGETS} FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake NAMESPACE native- ) diff --git a/modules/rostests/apitests/CMakeLists.txt b/modules/rostests/apitests/CMakeLists.txt index abb0fb8209b..2662835eeeb 100644 --- a/modules/rostests/apitests/CMakeLists.txt +++ b/modules/rostests/apitests/CMakeLists.txt @@ -22,11 +22,7 @@ add_subdirectory(gdi32) add_subdirectory(gditools) add_subdirectory(iphlpapi) add_subdirectory(kernel32) -if(NOT GCC) - # gcc / binutils are unable to add an IMAGE_LOAD_CONFIG_DIRECTORY - # So maybe we should resuscitate sdk/tools/pefixup.c - add_subdirectory(loadconfig) -endif() +add_subdirectory(loadconfig) add_subdirectory(localspl) add_subdirectory(mountmgr) add_subdirectory(msgina) diff --git a/modules/rostests/apitests/loadconfig/CMakeLists.txt b/modules/rostests/apitests/loadconfig/CMakeLists.txt index a09e73e90b1..8c0860b7c13 100644 --- a/modules/rostests/apitests/loadconfig/CMakeLists.txt +++ b/modules/rostests/apitests/loadconfig/CMakeLists.txt @@ -1,12 +1,16 @@
+spec2def(loadconfig_apitest.exe loadconfig_apitest.spec) + list(APPEND SOURCE common.c stacktrace.c loadconfig.h)
-add_executable(loadconfig_apitest ${SOURCE} testlist.c) +add_executable(loadconfig_apitest ${SOURCE} testlist.c ${CMAKE_CURRENT_BINARY_DIR}/loadconfig_apitest.def) target_link_libraries(loadconfig_apitest wine ${PSEH_LIB}) set_module_type(loadconfig_apitest win32cui) add_importlibs(loadconfig_apitest msvcrt kernel32 ntdll) -add_pch(loadconfig_apitest loadconfig.h SOURCE) +#add_pch(loadconfig_apitest loadconfig.h SOURCE) add_rostests_file(TARGET loadconfig_apitest) + +fixup_load_config(loadconfig_apitest) diff --git a/modules/rostests/apitests/loadconfig/loadconfig_apitest.spec b/modules/rostests/apitests/loadconfig/loadconfig_apitest.spec new file mode 100644 index 00000000000..8eb80758252 --- /dev/null +++ b/modules/rostests/apitests/loadconfig/loadconfig_apitest.spec @@ -0,0 +1,3 @@ + +# Export this symbol so we can do binutils job +@ extern _load_config_used diff --git a/sdk/cmake/gcc.cmake b/sdk/cmake/gcc.cmake index 5f0ea13b23a..7d42f327ecf 100644 --- a/sdk/cmake/gcc.cmake +++ b/sdk/cmake/gcc.cmake @@ -345,6 +345,14 @@ if(NOT ARCH STREQUAL "i386") set(DECO_OPTION "-@") endif()
+function(fixup_load_config _target) + get_target_property(PEFIXUP native-pefixup IMPORTED_LOCATION_NOCONFIG) + add_custom_command(TARGET ${_target} POST_BUILD + COMMAND "${PEFIXUP}" + "$<TARGET_FILE:${_target}>" + COMMENT "Patching in LOAD_CONFIG") +endfunction() + function(generate_import_lib _libname _dllname _spec_file) # Generate the def for the import lib add_custom_command( diff --git a/sdk/cmake/msvc.cmake b/sdk/cmake/msvc.cmake index 0662fd24692..ce526ed979f 100644 --- a/sdk/cmake/msvc.cmake +++ b/sdk/cmake/msvc.cmake @@ -371,6 +371,10 @@ function(add_delay_importlibs _module) target_link_libraries(${_module} delayimp) endfunction()
+function(fixup_load_config _target) + # msvc knows how to generate a load_config so no hacks here +endfunction() + function(generate_import_lib _libname _dllname _spec_file)
set(_def_file ${CMAKE_CURRENT_BINARY_DIR}/${_libname}_exp.def) diff --git a/sdk/tools/CMakeLists.txt b/sdk/tools/CMakeLists.txt index 7fab47e68ba..f9e0e19f5f4 100644 --- a/sdk/tools/CMakeLists.txt +++ b/sdk/tools/CMakeLists.txt @@ -4,8 +4,6 @@ function(add_host_tool _tool) set_target_properties(${_tool} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TOOLS_FOLDER}) endfunction()
-#add_executable(pefixup pefixup.c) - if(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -DHAVE_IO_H=1) add_compile_flags_language("/EHsc" "CXX") @@ -40,4 +38,7 @@ add_subdirectory(xml2sdb) if(NOT MSVC) add_subdirectory(log2lines) add_subdirectory(rsym) + + add_host_tool(pefixup pefixup.c) + target_link_libraries(pefixup PRIVATE host_includes) endif() diff --git a/sdk/tools/pefixup.c b/sdk/tools/pefixup.c index be25015e48b..97529747ae1 100644 --- a/sdk/tools/pefixup.c +++ b/sdk/tools/pefixup.c @@ -1,421 +1,196 @@ /* * PE Fixup Utility * Copyright (C) 2005 Filip Navara + * Copyright (C) 2020 Mark Jansen * * The purpose of this utility is fix PE binaries generated by binutils and * to manipulate flags that can't be set by binutils. * - * Currently two features are implemented: + * Currently one features is implemented: * - * - Setting flags on PE sections for use by drivers. The sections - * .text, .data, .idata, .bss are marked as non-pageable and - * non-discarable, section PAGE is marked as pageable and section - * INIT is marked as discaradable. - * - * - Sorting of export name table in executables. DLLTOOL has bug - * in sorting algorithm when the --kill-at flag is used. The exports - * are sorted in the decorated form and so the fastcall symbols are - * incorrectly put at the beginning of export table. This option - * allow to correct sort the table, so binary search can be used - * to process them. + * - Updating the PE header to use a LOAD_CONFIG, + * when the struct is exported with the name '_load_config_used' */
#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -/* The following definitions are ripped from MinGW W32API headers. We don't - use these headers directly in order to allow compilation on Linux hosts. */ - -typedef unsigned char BYTE, *PBYTE; -typedef unsigned short WORD; -typedef unsigned int DWORD; -typedef int LONG; -typedef long LONG_PTR; - -#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 -#define IMAGE_SIZEOF_SHORT_NAME 8 -#define IMAGE_DOS_SIGNATURE 0x5A4D -#define IMAGE_NT_SIGNATURE 0x00004550 -#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000 -#define IMAGE_SCN_MEM_NOT_PAGED 0x8000000 -#define FIELD_OFFSET(t,f) ((LONG)(LONG_PTR)&(((t*)0)->f)) -#define IMAGE_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((unsigned long)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader)) -#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 - -#pragma pack(2) -typedef struct _IMAGE_DOS_HEADER { - WORD e_magic; - WORD e_cblp; - WORD e_cp; - WORD e_crlc; - WORD e_cparhdr; - WORD e_minalloc; - WORD e_maxalloc; - WORD e_ss; - WORD e_sp; - WORD e_csum; - WORD e_ip; - WORD e_cs; - WORD e_lfarlc; - WORD e_ovno; - WORD e_res[4]; - WORD e_oemid; - WORD e_oeminfo; - WORD e_res2[10]; - LONG e_lfanew; -} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; -#pragma pack(4) -#pragma pack(4) -typedef struct _IMAGE_EXPORT_DIRECTORY { - DWORD Characteristics; - DWORD TimeDateStamp; - WORD MajorVersion; - WORD MinorVersion; - DWORD Name; - DWORD Base; - DWORD NumberOfFunctions; - DWORD NumberOfNames; - DWORD AddressOfFunctions; - DWORD AddressOfNames; - DWORD AddressOfNameOrdinals; -} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; -typedef struct _IMAGE_FILE_HEADER { - WORD Machine; - WORD NumberOfSections; - DWORD TimeDateStamp; - DWORD PointerToSymbolTable; - DWORD NumberOfSymbols; - WORD SizeOfOptionalHeader; - WORD Characteristics; -} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; -typedef struct _IMAGE_DATA_DIRECTORY { - DWORD VirtualAddress; - DWORD Size; -} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; -typedef struct _IMAGE_OPTIONAL_HEADER { - WORD Magic; - BYTE MajorLinkerVersion; - BYTE MinorLinkerVersion; - DWORD SizeOfCode; - DWORD SizeOfInitializedData; - DWORD SizeOfUninitializedData; - DWORD AddressOfEntryPoint; - DWORD BaseOfCode; - DWORD BaseOfData; - DWORD ImageBase; - DWORD SectionAlignment; - DWORD FileAlignment; - WORD MajorOperatingSystemVersion; - WORD MinorOperatingSystemVersion; - WORD MajorImageVersion; - WORD MinorImageVersion; - WORD MajorSubsystemVersion; - WORD MinorSubsystemVersion; - DWORD Reserved1; - DWORD SizeOfImage; - DWORD SizeOfHeaders; - DWORD CheckSum; - WORD Subsystem; - WORD DllCharacteristics; - DWORD SizeOfStackReserve; - DWORD SizeOfStackCommit; - DWORD SizeOfHeapReserve; - DWORD SizeOfHeapCommit; - DWORD LoaderFlags; - DWORD NumberOfRvaAndSizes; - IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; -} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; -typedef struct _IMAGE_NT_HEADERS { - DWORD Signature; - IMAGE_FILE_HEADER FileHeader; - IMAGE_OPTIONAL_HEADER OptionalHeader; -} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS; -typedef struct _IMAGE_SECTION_HEADER { - BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; - union { - DWORD PhysicalAddress; - DWORD VirtualSize; - } Misc; - DWORD VirtualAddress; - DWORD SizeOfRawData; - DWORD PointerToRawData; - DWORD PointerToRelocations; - DWORD PointerToLinenumbers; - WORD NumberOfRelocations; - WORD NumberOfLinenumbers; - DWORD Characteristics; -} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; -#pragma pack(4)
-/* End of ripped definitions */ - -typedef struct _export_t { - DWORD name; - WORD ordinal; -} export_t; - -unsigned char *buffer; -PIMAGE_DOS_HEADER dos_header; -PIMAGE_NT_HEADERS nt_header; - -static inline WORD dtohs(WORD in) -{ - PBYTE in_ptr = (PBYTE)∈ - return in_ptr[0] | (in_ptr[1] << 8); -} +// host_includes +#include <typedefs.h> +#include <pecoff.h> +#include "../../dll/win32/dbghelp/compat.h"
-static inline WORD htods(WORD in) +void *rva_to_ptr(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header, DWORD rva) { - WORD out; - PBYTE out_ptr = (PBYTE)&out; - out_ptr[0] = in; out_ptr[1] = in >> 8; - return out; + unsigned int i; + PIMAGE_SECTION_HEADER section_header = IMAGE_FIRST_SECTION(nt_header); + + for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++, section_header++) + { + if (rva >= section_header->VirtualAddress && + rva < section_header->VirtualAddress + section_header->Misc.VirtualSize) + { + return buffer + rva - section_header->VirtualAddress + section_header->PointerToRawData; + } + } + + return NULL; }
-static inline DWORD dtohl(DWORD in) -{ - PBYTE in_ptr = (PBYTE)∈ - return in_ptr[0] | (in_ptr[1] << 8) | (in_ptr[2] << 16) | (in_ptr[3] << 24); -}
-static inline DWORD htodl(DWORD in) +static void fix_checksum(unsigned char *buffer, long len, PIMAGE_NT_HEADERS nt_header) { - DWORD out; - PBYTE out_ptr = (PBYTE)&out; - out_ptr[0] = in ; out_ptr[1] = in >> 8; - out_ptr[2] = in >> 16; out_ptr[3] = in >> 24; - return out; -} + unsigned int checksum = 0; + long n;
-void *rva_to_ptr(DWORD rva) -{ - PIMAGE_SECTION_HEADER section_header; - unsigned int i; + nt_header->OptionalHeader.CheckSum = 0;
- for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header); - i < dtohl(nt_header->FileHeader.NumberOfSections); - i++, section_header++) - { - if (rva >= dtohl(section_header->VirtualAddress) && - rva < dtohl(section_header->VirtualAddress) + - dtohl(section_header->Misc.VirtualSize)) - { - return buffer + rva - dtohl(section_header->VirtualAddress) + - dtohl(section_header->PointerToRawData); - } - } + for (n = 0; n < len; n += 2) + { + checksum += *(unsigned short *)(buffer + n); + checksum = (checksum + (checksum >> 16)) & 0xffff; + }
- return NULL; + checksum += len; + nt_header->OptionalHeader.CheckSum = checksum; }
-int export_compare_func(const void *a, const void *b) +static int add_loadconfig(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header) { - const export_t *ap = a; - const export_t *bp = b; - char *an = rva_to_ptr(ap->name); - char *bn = rva_to_ptr(bp->name); - return strcmp(an, bn); + PIMAGE_DATA_DIRECTORY export_dir; + PIMAGE_EXPORT_DIRECTORY export_directory; + + export_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + if (export_dir->Size != 0) + { + export_directory = rva_to_ptr(buffer, nt_header, export_dir->VirtualAddress); + if (export_directory != NULL) + { + DWORD *name_ptr, *function_ptr, n; + WORD *ordinal_ptr; + + name_ptr = rva_to_ptr(buffer, nt_header, export_directory->AddressOfNames); + ordinal_ptr = rva_to_ptr(buffer, nt_header, export_directory->AddressOfNameOrdinals); + function_ptr = rva_to_ptr(buffer, nt_header, export_directory->AddressOfFunctions); + + for (n = 0; n < export_directory->NumberOfNames; n++) + { + const char* name = rva_to_ptr(buffer, nt_header, name_ptr[n]); + if (!strcmp(name, "_load_config_used")) + { + PIMAGE_DATA_DIRECTORY load_config_dir; + DWORD load_config_rva = function_ptr[ordinal_ptr[n]]; + DWORD* load_config_ptr = rva_to_ptr(buffer, nt_header, load_config_rva); + + /* Update the DataDirectory pointer / size + The first entry of the LOAD_CONFIG struct is the size, use that as DataDirectory.Size */ + load_config_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]; + load_config_dir->VirtualAddress = load_config_rva; + load_config_dir->Size = *load_config_ptr; + + return 0; + } + } + + fprintf(stderr, "Export '_load_config_used' not found\n"); + } + else + { + fprintf(stderr, "Invalid rva for export directory\n"); + } + } + else + { + fprintf(stderr, "No export directory\n"); + } + + return 1; }
int main(int argc, char **argv) { - int fd_in, fd_out; - long len; - char hdrbuf[4] = { }, elfhdr[4] = { '\177', 'E', 'L', 'F' }; - PIMAGE_SECTION_HEADER section_header; - PIMAGE_DATA_DIRECTORY data_dir; - unsigned int i; - unsigned long checksum; - int fixup_exports = 0; - int fixup_sections = 0; - - /* - * Process parameters. - */ - - if (argc < 2) - { - printf("Usage: %s <filename> <options>\n" - "Options:\n" - " -sections Sets section flags for PE image.\n" - " -exports Sort the names in export table.\n", - argv[0]); - return 1; - } - - for (i = 2; i < argc; i++) - { - if (!strcmp(argv[i], "-sections")) - fixup_sections = 1; - else if (!strcmp(argv[i], "-exports")) - fixup_exports = 1; - else - { fprintf(stderr, "Invalid option: %s\n", argv[i]); return 1; } - } - - /* - * Nothing to do. - */ - if (fixup_sections == 0 && fixup_exports == 0) - return 0; - - /* - * Read the whole file to memory. - */ - - fd_in = open(argv[1], O_RDONLY | O_BINARY); - if (fd_in == 0) - { - fprintf(stderr, "Can't open input file.\n"); - return 1; - } - - /* - * PowerPC ReactOS uses elf, so doesn't need pefixup - */ - len = read(fd_in, hdrbuf, sizeof(elfhdr)); - if (!memcmp(hdrbuf, elfhdr, sizeof(elfhdr))) - { - close(fd_in); - return 0; - } - - len = lseek(fd_in, 0, SEEK_END); - if (len < sizeof(IMAGE_DOS_HEADER)) - { - close(fd_in); - fprintf(stderr, "'%s' isn't a PE image (too short)\n", argv[1]); - return 1; - } - - /* Lower down we overwrite the byte at len, so here, we need at least - * one more byte than len. We'll be guaranteed one or two now. */ - buffer = malloc((len + 2) & ~1); - if (buffer == NULL) - { - close(fd_in); - fprintf(stderr, "Not enough memory available.\n"); - return 1; - } - - /* Read the whole input file into a buffer */ - lseek(fd_in, 0, SEEK_SET); - read(fd_in, buffer, len); - /* Here is where the block end overwrite was */ - if (len & 1) - buffer[len] = 0; - - close(fd_in); - - /* - * Check the headers and save pointers to them. - */ - - dos_header = (PIMAGE_DOS_HEADER)buffer; - nt_header = (PIMAGE_NT_HEADERS)(buffer + dtohl(dos_header->e_lfanew)); - - if (dtohs(dos_header->e_magic) != IMAGE_DOS_SIGNATURE || - dtohl(nt_header->Signature) != IMAGE_NT_SIGNATURE) - { - fprintf(stderr, "'%s' isn't a PE image (bad headers)\n", argv[1]); - free(buffer); - return 1; - } - - if (fixup_exports) - { - /* Sort export directory */ - data_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; - if (dtohl(data_dir->Size) != 0) - { - PIMAGE_EXPORT_DIRECTORY export_directory; - DWORD *name_ptr; - WORD *ordinal_ptr; - export_t *exports; - - export_directory = (PIMAGE_EXPORT_DIRECTORY)rva_to_ptr(dtohl(data_dir->VirtualAddress)); - if (export_directory != NULL) - { - exports = malloc(sizeof(export_t) * dtohl(export_directory->NumberOfNames)); - if (exports == NULL) + FILE* file; + long len; + unsigned char *buffer; + PIMAGE_DOS_HEADER dos_header; + int result = 1; + + if (argc < 2) + { + printf("Usage: %s <filename>\n", argv[0]); + return 1; + } + + /* Read the whole file to memory. */ + file = fopen(argv[1], "r+b"); + if (!file) + { + fprintf(stderr, "Can't open '%s'.\n", argv[1]); + return 1; + } + + fseek(file, 0, SEEK_END); + len = ftell(file); + if (len < sizeof(IMAGE_DOS_HEADER)) + { + fclose(file); + fprintf(stderr, "'%s' isn't a PE image (too short)\n", argv[1]); + return 1; + } + + /* Add one byte extra for the case where the input file size is odd. + We rely on this in our crc calculation */ + buffer = calloc(len + 1, 1); + if (buffer == NULL) + { + fclose(file); + fprintf(stderr, "Not enough memory available.\n"); + return 1; + } + + /* Read the whole input file into a buffer */ + fseek(file, 0, SEEK_SET); + fread(buffer, 1, len, file); + + /* Check the headers and save pointers to them. */ + dos_header = (PIMAGE_DOS_HEADER)buffer; + if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) + { + PIMAGE_NT_HEADERS nt_header; + + nt_header = (PIMAGE_NT_HEADERS)(buffer + dos_header->e_lfanew); + + if (nt_header->Signature == IMAGE_NT_SIGNATURE) + { + if (!add_loadconfig(buffer, nt_header)) { - fprintf(stderr, "Not enough memory.\n"); - free(buffer); - return 1; - } + fix_checksum(buffer, len, nt_header);
- name_ptr = (DWORD *)rva_to_ptr(dtohl(export_directory->AddressOfNames)); - ordinal_ptr = (WORD *)rva_to_ptr(dtohl(export_directory->AddressOfNameOrdinals)); + /* We could 'optimize by only writing the changed parts, but keep it simple for now */ + fseek(file, 0, SEEK_SET); + fwrite(buffer, 1, len, file);
- for (i = 0; i < dtohl(export_directory->NumberOfNames); i++) - { - exports[i].name = dtohl(name_ptr[i]); - exports[i].ordinal = dtohl(ordinal_ptr[i]); + /* Success */ + result = 0; } - - qsort(exports, dtohl(export_directory->NumberOfNames), sizeof(export_t), - export_compare_func); - - for (i = 0; i < dtohl(export_directory->NumberOfNames); i++) + else { - name_ptr[i] = htodl(exports[i].name); - ordinal_ptr[i] = htodl(exports[i].ordinal); + /* Error already printed inside add_loadconfig */ } - - free(exports); - } - } - } - - if (fixup_sections) - { - /* Update section flags */ - for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header); - i < dtohl(nt_header->FileHeader.NumberOfSections); - i++, section_header++) - { - if (!strcmp((char*)section_header->Name, ".text") || - !strcmp((char*)section_header->Name, ".data") || - !strcmp((char*)section_header->Name, ".idata") || - !strcmp((char*)section_header->Name, ".rdata") || - !strcmp((char*)section_header->Name, ".bss")) - { - section_header->Characteristics |= htodl(IMAGE_SCN_MEM_NOT_PAGED); - section_header->Characteristics &= htodl(~IMAGE_SCN_MEM_DISCARDABLE); - } - else if (!strcmp((char*)section_header->Name, "INIT")) - { - section_header->Characteristics |= htodl(IMAGE_SCN_MEM_DISCARDABLE); - } - else if (!strcmp((char*)section_header->Name, "PAGE")) - { - section_header->Characteristics |= htodl(IMAGE_SCN_MEM_NOT_PAGED); - } - } - } - - /* Recalculate checksum */ - nt_header->OptionalHeader.CheckSum = 0; - checksum = 0; - for (i = 0; i < len; i += 2) - { - checksum += *(unsigned short *)(buffer + i); - checksum = (checksum + (checksum >> 16)) & 0xffff; - } - checksum += len; - nt_header->OptionalHeader.CheckSum = htods(checksum); - - /* Write the output file */ - fd_out = open(argv[1], O_WRONLY | O_BINARY); - write(fd_out, buffer, len); - close(fd_out); - - return 0; + } + else + { + fprintf(stderr, "'%s' Invalid PE signature: %x\n", argv[1], nt_header->Signature); + } + } + else + { + fprintf(stderr, "'%s' Invalid DOS signature: %x\n", argv[1], dos_header->e_magic); + } + + free(buffer); + fclose(file); + + return result; }