Subversion Repositories filter_foundry

Rev

Rev 455 | Rev 529 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 455 Rev 456
Line 26... Line 26...
26
#include <windows.h>
26
#include <windows.h>
27
#include <string>
27
#include <string>
28
#include <fstream>
28
#include <fstream>
29
#include <vector>
29
#include <vector>
30
 
30
 
31
bool update_pe_timestamp(LPCTSTR filename, time_t timestamp) {
31
typedef struct _PE32 {
32
        size_t peoffset;
32
        uint32_t magic; // 0x50450000
-
 
33
        IMAGE_FILE_HEADER fileHeader; // COFF Header without Signature
-
 
34
        IMAGE_OPTIONAL_HEADER32 optHeader; // Standard COFF fields, Windows Specific Fields, Data Directories
33
        FILE* fptr;
35
} PE32;
34
 
36
 
-
 
37
#ifdef UNICODE
35
        fptr = _wfopen(filename, L"rb+");
38
typedef std::wstring tstring;
-
 
39
#else
36
        if (fptr == NULL) return false;
40
typedef std::string tstring;
-
 
41
#endif
37
 
42
 
38
        fseek(fptr, 0x3C, SEEK_SET);
43
int binary_file_string_replace(tstring file_name, const char* asearch, const char* areplace) {
39
        fread(&peoffset, sizeof(peoffset), 1, fptr);
44
        std::ifstream input(file_name, std::ios::binary);
40
 
45
 
-
 
46
        std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>()));
41
        fseek(fptr, (long)peoffset + 8, SEEK_SET);
47
        std::vector<char>::iterator itbegin = buffer.begin();
42
        fwrite(&timestamp, sizeof(time_t), 1, fptr);
48
        std::vector<char>::iterator itend = buffer.end();
43
 
49
 
-
 
50
        if (strlen(asearch) != strlen(areplace)) {
-
 
51
                printf("Replace value length greater than original!\n");
44
        fclose(fptr);
52
                return -1;
-
 
53
        }
-
 
54
        int MAX_BUFFER = strlen(asearch);
45
 
55
 
-
 
56
        char* needed_str = (char*)malloc(MAX_BUFFER);
-
 
57
        if (needed_str == 0) return -1;
-
 
58
        char* replace_str = (char*)malloc(MAX_BUFFER);
-
 
59
        if (replace_str == 0) return -1;
-
 
60
 
-
 
61
        memcpy(needed_str, asearch, MAX_BUFFER);
-
 
62
        memcpy(replace_str, areplace, MAX_BUFFER);
-
 
63
 
46
        return true;
64
        int ifound = 0;
-
 
65
 
-
 
66
        for (auto it = itbegin; it < itend; it++) {
-
 
67
                if (memcmp(it._Ptr, needed_str, MAX_BUFFER) == 0) {
-
 
68
                        strncpy(it._Ptr, replace_str, MAX_BUFFER);
-
 
69
                        it += MAX_BUFFER - 1; // -1 because it++ will be set on the next loop
-
 
70
                        ifound++;
-
 
71
                }
47
}
72
        }
48
 
73
 
-
 
74
        if (ifound > 0) {
49
bool update_pe_stackSizeCommit(LPCTSTR filename, size_t stackReserve, size_t stackCommit) {
75
                std::ofstream ofile(file_name, std::ios::out | std::ios::binary);
-
 
76
                ofile.write((char*)&buffer[0], buffer.size() * sizeof(char));
50
        size_t peoffset;
77
                ofile.close();
51
        FILE* fptr;
78
        }
52
 
79
 
53
        fptr = _wfopen(filename, L"rb+");
-
 
54
        if (fptr == NULL) return false;
80
        return ifound;
-
 
81
}
55
 
82
 
56
        fseek(fptr, 0x3C, SEEK_SET);
83
int binary_file_string_find(tstring file_name, const char* asearch) {
57
        fread(&peoffset, sizeof(peoffset), 1, fptr);
84
        std::ifstream input(file_name, std::ios::binary);
58
 
85
 
-
 
86
        std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>()));
59
        fseek(fptr, (long)peoffset + 12 * 8, SEEK_SET);
87
        std::vector<char>::iterator itbegin = buffer.begin();
60
        fwrite(&stackReserve, sizeof(size_t), 1, fptr);
88
        std::vector<char>::iterator itend = buffer.end();
61
 
89
 
62
        fseek(fptr, (long)peoffset + 12 * 8 + 4, SEEK_SET);
-
 
63
        fwrite(&stackCommit, sizeof(size_t), 1, fptr);
90
        int MAX_BUFFER = strlen(asearch);
64
 
91
 
-
 
92
        char* needed_str = (char*)malloc(MAX_BUFFER);
65
        fclose(fptr);
93
        if (needed_str == 0) return -1;
66
 
94
 
-
 
95
        memcpy(needed_str, asearch, MAX_BUFFER);
-
 
96
 
-
 
97
        int ifound = 0;
-
 
98
 
-
 
99
        for (auto it = itbegin; it < itend; it++) {
-
 
100
                if (memcmp(it._Ptr, needed_str, MAX_BUFFER) == 0) {
-
 
101
                        it += MAX_BUFFER - 1; // -1 because it++ will be set on the next loop
-
 
102
                        ifound++;
-
 
103
                }
-
 
104
        }
-
 
105
 
67
        return true;
106
        return ifound;
68
}
107
}
69
 
108
 
70
bool update_pe_heapSizeCommit(LPCTSTR filename, size_t heapReserve, size_t heapCommit) {
109
void _set_pe_int32(FILE* fptr, size_t fieldoffset, int32_t val) {
71
        size_t peoffset;
110
        size_t peoffset;
72
        FILE* fptr;
-
 
73
 
111
 
-
 
112
        fseek(fptr, 0x3C, SEEK_SET);
-
 
113
        fread(&peoffset, sizeof(peoffset), 1, fptr);
-
 
114
 
74
        fptr = _wfopen(filename, L"rb+");
115
        fseek(fptr, (long)peoffset + fieldoffset, SEEK_SET);
75
        if (fptr == NULL) return false;
116
        fwrite(&val, sizeof(int32_t), 1, fptr);
-
 
117
}
-
 
118
 
-
 
119
int32_t _get_pe_int32(FILE* fptr, size_t fieldoffset) {
-
 
120
        size_t peoffset;
-
 
121
        int32_t res;
76
 
122
 
77
        fseek(fptr, 0x3C, SEEK_SET);
123
        fseek(fptr, 0x3C, SEEK_SET);
78
        fread(&peoffset, sizeof(peoffset), 1, fptr);
124
        fread(&peoffset, sizeof(peoffset), 1, fptr);
79
 
125
 
80
        fseek(fptr, (long)peoffset + 13 * 8, SEEK_SET);
126
        fseek(fptr, (long)peoffset + fieldoffset, SEEK_SET);
81
        fwrite(&heapReserve, sizeof(size_t), 1, fptr);
127
        fread(&res, sizeof(int32_t), 1, fptr);
82
 
128
 
-
 
129
        return res;
-
 
130
}
-
 
131
 
-
 
132
bool update_pe_timestamp(LPCTSTR filename, __time32_t timestamp) {
83
        fseek(fptr, (long)peoffset + 13 * 8 + 4, SEEK_SET);
133
        FILE* fptr = _wfopen(filename, L"rb+");
84
        fwrite(&heapCommit, sizeof(size_t), 1, fptr);
134
        if (fptr == NULL) return false;
-
 
135
 
-
 
136
        _set_pe_int32(fptr, /*0x0008*/offsetof(PE32, fileHeader.TimeDateStamp), timestamp);
85
 
137
 
86
        fclose(fptr);
138
        fclose(fptr);
87
 
139
 
88
        return true;
140
        return true;
89
}
141
}
90
 
142
 
-
 
143
bool openWatcomCosmetics(LPCTSTR filename) {
-
 
144
        if (binary_file_string_find(filename, "Open Watcom") > 0) {
-
 
145
                FILE* fptr = _wfopen(filename, L"rb+");
-
 
146
                if (fptr == NULL) return false;
91
 
147
 
92
//DOS .EXE header
-
 
93
struct image_dos_header
-
 
94
{
-
 
95
        uint16_t e_magic;                     // Magic number
-
 
96
        uint16_t e_cblp;                      // Bytes on last page of file
148
                // Min OS Version 1.11 ... But the actual minimal Windows version is Windows NT 3.11
97
        uint16_t e_cp;                        // Pages in file
149
                int32_t minOsVersion = _get_pe_int32(fptr, /*0x0040*/offsetof(PE32, optHeader.MajorOperatingSystemVersion));
98
        uint16_t e_crlc;                      // Relocations
150
                if (minOsVersion == 0x000B0001) {
99
        uint16_t e_cparhdr;                   // Size of header in paragraphs
151
                        _set_pe_int32(fptr, /*0x0040*/offsetof(PE32, optHeader.MajorOperatingSystemVersion), 0x00000003); // Windows 3.0
-
 
152
                }
-
 
153
 
100
        uint16_t e_minalloc;                  // Minimum extra paragraphs needed
154
                // Stack reserved cannot be changed with linker option "OPTION STACK=1m" (Rejected https://github.com/open-watcom/open-watcom-v2/issues/780)
101
        uint16_t e_maxalloc;                  // Maximum extra paragraphs needed
155
                // It is not required for DLLs, but everybody does it, and I think it is cosmetics to fill these fields, even if not required.
102
        uint16_t e_ss;                        // Initial (relative) SS value
156
                _set_pe_int32(fptr, /*0x0060*/offsetof(PE32, optHeader.SizeOfStackReserve), 0x00100000);
103
        uint16_t e_sp;                        // Initial SP value
157
                _set_pe_int32(fptr, /*0x0064*/offsetof(PE32, optHeader.SizeOfStackCommit),  0x00001000);
104
        uint16_t e_csum;                      // Checksum
-
 
105
        uint16_t e_ip;                        // Initial IP value
158
                // Heap reserved can be changed with linker option "OPTION HEAP=1m"
106
        uint16_t e_cs;                        // Initial (relative) CS value
159
                _set_pe_int32(fptr, /*0x0068*/offsetof(PE32, optHeader.SizeOfHeapReserve),  0x00100000);
107
        uint16_t e_lfarlc;                    // File address of relocation table
160
                _set_pe_int32(fptr, /*0x006C*/offsetof(PE32, optHeader.SizeOfHeapCommit),   0x00001000);
108
        uint16_t e_ovno;                      // Overlay number
-
 
-
 
161
 
109
        uint16_t e_res[4];                    // Reserved words
162
                fclose(fptr);
110
        uint16_t e_oemid;                     // OEM identifier (for e_oeminfo)
-
 
-
 
163
 
111
        uint16_t e_oeminfo;                   // OEM information; e_oemid specific
164
                // 32 bit (OpenWatcom cosmetics): Export table name "FilterFoundry.dll" => "FilterFoundry.8bf"
112
        uint16_t e_res2[10];                  // Reserved words
165
                // since OpenWatcom cannot link a 8BF file natively.
113
        int32_t  e_lfanew;                    // File address of new exe header
166
                binary_file_string_replace(filename, "FilterFoundry.dll", "FilterFoundry.8bf");
114
};
167
        }
115
 
168
 
116
struct image_file_header
-
 
117
{
-
 
118
        uint16_t Machine;
169
        return true;
119
        uint16_t NumberOfSections;
-
 
120
        uint32_t TimeDateStamp;
-
 
121
        uint32_t PointerToSymbolTable;
-
 
122
        uint32_t NumberOfSymbols;
-
 
123
        uint16_t SizeOfOptionalHeader;
-
 
124
        uint16_t Characteristics;
-
 
125
};
170
}
126
 
171
 
127
uint32_t calculate_checksum(LPCTSTR filename) {
172
uint32_t calculate_checksum(LPCTSTR filename) {
128
        //Calculate checksum of image
173
        //Calculate checksum of image
129
        // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
174
        // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
130
        // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
175
        // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
131
        // Converted from C++ to C by Daniel Marschall
176
        // Converted from C++ to C by Daniel Marschall
132
 
177
 
133
        FILE* fptr;
178
        FILE* fptr;
134
        unsigned long long checksum = 0;
179
        unsigned long long checksum = 0;
135
        struct image_dos_header header;
180
        IMAGE_DOS_HEADER header;
136
        size_t filesize;
181
        size_t filesize;
137
        unsigned long long top;
182
        unsigned long long top;
138
        unsigned long pe_checksum_pos;
183
        unsigned long pe_checksum_pos;
139
        static const unsigned long checksum_pos_in_optional_headers = 64;
184
        static const unsigned long checksum_pos_in_optional_headers = 64;
140
        size_t i;
185
        size_t i;
Line 142... Line 187...
142
        fptr = _wfopen(filename, L"rb");
187
        fptr = _wfopen(filename, L"rb");
143
        if (fptr == NULL) return 0x00000000;
188
        if (fptr == NULL) return 0x00000000;
144
 
189
 
145
        //Read DOS header
190
        //Read DOS header
146
        fseek(fptr, 0, SEEK_SET);
191
        fseek(fptr, 0, SEEK_SET);
147
        fread(&header, sizeof(struct image_dos_header), 1, fptr);
192
        fread(&header, sizeof(IMAGE_DOS_HEADER), 1, fptr);
148
 
193
 
149
        //Calculate PE checksum
194
        //Calculate PE checksum
150
        fseek(fptr, 0, SEEK_SET);
195
        fseek(fptr, 0, SEEK_SET);
151
        top = 0xFFFFFFFF;
196
        top = 0xFFFFFFFF;
152
        top++;
197
        top++;
153
 
198
 
154
        //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
199
        //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
155
        //Calculate real PE headers "CheckSum" field position
200
        //Calculate real PE headers "CheckSum" field position
156
        //Sum is safe here
201
        //Sum is safe here
157
        pe_checksum_pos = header.e_lfanew + sizeof(struct image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
202
        pe_checksum_pos = header.e_lfanew + sizeof(IMAGE_FILE_HEADER) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
158
 
203
 
159
        //Calculate checksum for each byte of file
204
        //Calculate checksum for each byte of file
160
        fseek(fptr, 0L, SEEK_END);
205
        fseek(fptr, 0L, SEEK_END);
161
        filesize = ftell(fptr);
206
        filesize = ftell(fptr);
162
        fseek(fptr, 0L, SEEK_SET);
207
        fseek(fptr, 0L, SEEK_SET);
Line 188... Line 233...
188
        //Return checksum
233
        //Return checksum
189
        return (uint32_t)checksum;
234
        return (uint32_t)checksum;
190
}
235
}
191
 
236
 
192
bool repair_pe_checksum(LPCTSTR filename) {
237
bool repair_pe_checksum(LPCTSTR filename) {
193
        size_t peoffset;
-
 
194
        FILE* fptr;
238
        FILE* fptr;
195
 
239
 
196
        uint32_t checksum = calculate_checksum(filename);
240
        uint32_t checksum = calculate_checksum(filename);
197
        //if (checksum == 0x00000000) return false;
241
        //if (checksum == 0x00000000) return false;
198
 
242
 
199
        fptr = _wfopen(filename, L"rb+");
243
        fptr = _wfopen(filename, L"rb+");
200
        if (fptr == NULL) return false;
244
        if (fptr == NULL) return false;
201
 
245
 
202
        fseek(fptr, 0x3C, SEEK_SET);
-
 
203
        fread(&peoffset, sizeof(peoffset), 1, fptr);
-
 
204
 
-
 
205
        fseek(fptr, (long)peoffset + 88, SEEK_SET);
246
        _set_pe_int32(fptr, /*0x0058*/offsetof(PE32, optHeader.CheckSum), (int32_t)checksum);
206
        fwrite(&checksum, sizeof(uint32_t), 1, fptr);
-
 
207
 
247
 
208
        fclose(fptr);
248
        fclose(fptr);
209
 
249
 
210
        return true;
250
        return true;
211
}
251
}
Line 270... Line 310...
270
        }
310
        }
271
 
311
 
272
        return bSuccessful;
312
        return bSuccessful;
273
}
313
}
274
 
314
 
275
#ifdef UNICODE
-
 
276
int binary_file_string_replace(std::wstring file_name, const char* asearch, const char* areplace) {
-
 
277
#else
-
 
278
int binary_file_string_replace(std::string file_name, const char* asearch, const char* areplace) {
-
 
279
#endif
-
 
280
        std::ifstream input(file_name, std::ios::binary);
-
 
281
 
-
 
282
        std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>()));
-
 
283
        std::vector<char>::iterator itbegin = buffer.begin();
-
 
284
        std::vector<char>::iterator itend = buffer.end();
-
 
285
 
-
 
286
        if (strlen(asearch) != strlen(areplace)) {
-
 
287
                printf("Replace value length greater than original!\n");
-
 
288
                return -1;
-
 
289
        }
-
 
290
        int MAX_BUFFER = strlen(asearch);
-
 
291
 
-
 
292
        char* needed_str = (char*)malloc(MAX_BUFFER);
-
 
293
        if (needed_str == 0) return -1;
-
 
294
        char* replace_str = (char*)malloc(MAX_BUFFER);
-
 
295
        if (replace_str == 0) return -1;
-
 
296
       
-
 
297
        memcpy(needed_str, asearch, MAX_BUFFER);
-
 
298
        memcpy(replace_str, areplace, MAX_BUFFER);
-
 
299
 
-
 
300
        int ifound = 0;
-
 
301
 
-
 
302
        for (auto it = itbegin; it < itend ; it++) {
-
 
303
                if (memcmp(it._Ptr, needed_str, MAX_BUFFER) == 0) {
-
 
304
                        strncpy(it._Ptr, replace_str, MAX_BUFFER);
-
 
305
                        it += MAX_BUFFER - 1; // -1 because it++ will be set on the next loop
-
 
306
                        ifound++;
-
 
307
                }
-
 
308
        }
-
 
309
 
-
 
310
        if (ifound > 0) {
-
 
311
                std::ofstream ofile(file_name, std::ios::out | std::ios::binary);
-
 
312
                ofile.write((char*)&buffer[0], buffer.size() * sizeof(char));
-
 
313
                ofile.close();
-
 
314
        }
-
 
315
 
-
 
316
        return ifound;
-
 
317
}
-
 
318
 
-
 
319
 
315
 
320
int main()
316
int main()
321
{
317
{
322
        LPCTSTR lpTemplateType = L"TPLT";
318
        LPCTSTR lpTemplateType = L"TPLT";
323
        LPCTSTR lpName32Plugin = (LPCTSTR)1032;
319
        LPCTSTR lpName32Plugin = (LPCTSTR)1032;
Line 395... Line 391...
395
                removeFromFile(file32tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
391
                removeFromFile(file32tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
396
                removeFromFile(file64tmp, lpTemplateType, lpName32Pipl, wLanguageNeutral);
392
                removeFromFile(file64tmp, lpTemplateType, lpName32Pipl, wLanguageNeutral);
397
                removeFromFile(file64tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
393
                removeFromFile(file64tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
398
        }
394
        }
399
 
395
 
400
        // 32 bit (OpenWatcom cosmetics): Export table name "filterfoundry.dll" => "FilterFoundry.8bf"
-
 
401
        // since OpenWatcom cannot link a 8BF file natively.
396
        // Do some cosmetics to OpenWatcom binaries
402
        binary_file_string_replace(file32tmp, "filterfoundry.dll", "FilterFoundry.8bf");
-
 
403
        binary_file_string_replace(file32out, "filterfoundry.dll", "FilterFoundry.8bf");
-
 
404
 
-
 
405
        // More OpenWatcom cosmetics! https://github.com/open-watcom/open-watcom-v2/issues/780 (Rejected)
-
 
406
        // Stack reserved cannot be changed with linker option "OPTION STACK=1m" (Rejected)
-
 
407
        // It is not required for DLLs, but everybody does it, and I think it is cosmetics to fill these fields, even if not required.
-
 
408
        update_pe_stackSizeCommit(file32tmp, 1024 * 1024, 4096);
397
        openWatcomCosmetics(file32tmp);
409
        update_pe_stackSizeCommit(file32out, 1024 * 1024, 4096);
398
        openWatcomCosmetics(file32out);
410
        // Heap reserved can be changed with linker option "OPTION HEAP=1m"
-
 
411
        update_pe_heapSizeCommit(file32tmp, 1024 * 1024, 4096);
-
 
412
        update_pe_heapSizeCommit(file32out, 1024 * 1024, 4096);
-
 
413
 
399
 
414
        // 3. Update timestamp of 32/64 "TMP"
400
        // 3. Update timestamp of 32/64 "TMP"
415
        {
401
        {
416
                if (!update_pe_timestamp(file32tmp, time(0))) {
402
                if (!update_pe_timestamp(file32tmp, (__time32_t)time(0))) {
417
                        DeleteFile(file32out);
403
                        DeleteFile(file32out);
418
                        DeleteFile(file64out);
404
                        DeleteFile(file64out);
419
                        printf("Error: Update TMP timestamp 32\n");
405
                        printf("Error: Update TMP timestamp 32\n");
420
                        return 1;
406
                        return 1;
421
                }
407
                }
422
 
408
 
423
                if (!update_pe_timestamp(file64tmp, time(0))) {
409
                if (!update_pe_timestamp(file64tmp, (__time32_t)time(0))) {
424
                        DeleteFile(file32out);
410
                        DeleteFile(file32out);
425
                        DeleteFile(file64out);
411
                        DeleteFile(file64out);
426
                        printf("Error: Update TMP timestamp 64\n");
412
                        printf("Error: Update TMP timestamp 64\n");
427
                        return 1;
413
                        return 1;
428
                }
414
                }
Line 564... Line 550...
564
                DeleteFile(file64tmp);
550
                DeleteFile(file64tmp);
565
        }
551
        }
566
 
552
 
567
        // 9. Update timestamp of 32/64 "OUT"
553
        // 9. Update timestamp of 32/64 "OUT"
568
        {
554
        {
569
                if (!update_pe_timestamp(file32out, time(0))) {
555
                if (!update_pe_timestamp(file32out, (__time32_t)time(0))) {
570
                        DeleteFile(file32out);
556
                        DeleteFile(file32out);
571
                        DeleteFile(file64out);
557
                        DeleteFile(file64out);
572
                        printf("Error: Update OUT timestamp 32\n");
558
                        printf("Error: Update OUT timestamp 32\n");
573
                        return 1;
559
                        return 1;
574
                }
560
                }
575
 
561
 
576
                if (!update_pe_timestamp(file64out, time(0))) {
562
                if (!update_pe_timestamp(file64out, (__time32_t)time(0))) {
577
                        DeleteFile(file32out);
563
                        DeleteFile(file32out);
578
                        DeleteFile(file64out);
564
                        DeleteFile(file64out);
579
                        printf("Error: Update OUT timestamp 64\n");
565
                        printf("Error: Update OUT timestamp 64\n");
580
                        return 1;
566
                        return 1;
581
                }
567
                }