Subversion Repositories filter_foundry

Rev

Rev 456 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
308 daniel-mar 1
/*
2
        This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
3
        Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
529 daniel-mar 4
        Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
308 daniel-mar 5
 
6
        This program is free software; you can redistribute it and/or modify
7
        it under the terms of the GNU General Public License as published by
8
        the Free Software Foundation; either version 2 of the License, or
9
        (at your option) any later version.
10
 
11
        This program is distributed in the hope that it will be useful,
12
        but WITHOUT ANY WARRANTY; without even the implied warranty of
13
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
        GNU General Public License for more details.
15
 
16
        You should have received a copy of the GNU General Public License
17
        along with this program; if not, write to the Free Software
18
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
*/
20
 
21
#ifndef _CRT_SECURE_NO_WARNINGS
22
#define _CRT_SECURE_NO_WARNINGS
23
#endif
24
 
25
#include <iostream>
26
#include <windows.h>
455 daniel-mar 27
#include <string>
28
#include <fstream>
29
#include <vector>
308 daniel-mar 30
 
456 daniel-mar 31
typedef struct _PE32 {
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
35
} PE32;
308 daniel-mar 36
 
456 daniel-mar 37
#ifdef UNICODE
38
typedef std::wstring tstring;
39
#else
40
typedef std::string tstring;
41
#endif
308 daniel-mar 42
 
456 daniel-mar 43
int binary_file_string_replace(tstring file_name, const char* asearch, const char* areplace) {
44
        std::ifstream input(file_name, std::ios::binary);
308 daniel-mar 45
 
456 daniel-mar 46
        std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>()));
47
        std::vector<char>::iterator itbegin = buffer.begin();
48
        std::vector<char>::iterator itend = buffer.end();
308 daniel-mar 49
 
456 daniel-mar 50
        if (strlen(asearch) != strlen(areplace)) {
51
                printf("Replace value length greater than original!\n");
52
                return -1;
53
        }
54
        int MAX_BUFFER = strlen(asearch);
308 daniel-mar 55
 
456 daniel-mar 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
 
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
                }
72
        }
73
 
74
        if (ifound > 0) {
75
                std::ofstream ofile(file_name, std::ios::out | std::ios::binary);
76
                ofile.write((char*)&buffer[0], buffer.size() * sizeof(char));
77
                ofile.close();
78
        }
79
 
80
        return ifound;
308 daniel-mar 81
}
82
 
456 daniel-mar 83
int binary_file_string_find(tstring file_name, const char* asearch) {
84
        std::ifstream input(file_name, std::ios::binary);
455 daniel-mar 85
 
456 daniel-mar 86
        std::vector<char> buffer((std::istreambuf_iterator<char>(input)), (std::istreambuf_iterator<char>()));
87
        std::vector<char>::iterator itbegin = buffer.begin();
88
        std::vector<char>::iterator itend = buffer.end();
455 daniel-mar 89
 
456 daniel-mar 90
        int MAX_BUFFER = strlen(asearch);
455 daniel-mar 91
 
456 daniel-mar 92
        char* needed_str = (char*)malloc(MAX_BUFFER);
93
        if (needed_str == 0) return -1;
455 daniel-mar 94
 
456 daniel-mar 95
        memcpy(needed_str, asearch, MAX_BUFFER);
455 daniel-mar 96
 
456 daniel-mar 97
        int ifound = 0;
455 daniel-mar 98
 
456 daniel-mar 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
 
106
        return ifound;
455 daniel-mar 107
}
108
 
456 daniel-mar 109
void _set_pe_int32(FILE* fptr, size_t fieldoffset, int32_t val) {
455 daniel-mar 110
        size_t peoffset;
111
 
456 daniel-mar 112
        fseek(fptr, 0x3C, SEEK_SET);
113
        fread(&peoffset, sizeof(peoffset), 1, fptr);
455 daniel-mar 114
 
456 daniel-mar 115
        fseek(fptr, (long)peoffset + fieldoffset, SEEK_SET);
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;
122
 
455 daniel-mar 123
        fseek(fptr, 0x3C, SEEK_SET);
124
        fread(&peoffset, sizeof(peoffset), 1, fptr);
125
 
456 daniel-mar 126
        fseek(fptr, (long)peoffset + fieldoffset, SEEK_SET);
127
        fread(&res, sizeof(int32_t), 1, fptr);
455 daniel-mar 128
 
456 daniel-mar 129
        return res;
130
}
455 daniel-mar 131
 
456 daniel-mar 132
bool update_pe_timestamp(LPCTSTR filename, __time32_t timestamp) {
133
        FILE* fptr = _wfopen(filename, L"rb+");
134
        if (fptr == NULL) return false;
135
 
136
        _set_pe_int32(fptr, /*0x0008*/offsetof(PE32, fileHeader.TimeDateStamp), timestamp);
137
 
455 daniel-mar 138
        fclose(fptr);
139
 
140
        return true;
141
}
142
 
456 daniel-mar 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;
455 daniel-mar 147
 
456 daniel-mar 148
                // Min OS Version 1.11 ... But the actual minimal Windows version is Windows NT 3.11
149
                int32_t minOsVersion = _get_pe_int32(fptr, /*0x0040*/offsetof(PE32, optHeader.MajorOperatingSystemVersion));
150
                if (minOsVersion == 0x000B0001) {
151
                        _set_pe_int32(fptr, /*0x0040*/offsetof(PE32, optHeader.MajorOperatingSystemVersion), 0x00000003); // Windows 3.0
152
                }
308 daniel-mar 153
 
456 daniel-mar 154
                // Stack reserved cannot be changed with linker option "OPTION STACK=1m" (Rejected https://github.com/open-watcom/open-watcom-v2/issues/780)
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.
156
                _set_pe_int32(fptr, /*0x0060*/offsetof(PE32, optHeader.SizeOfStackReserve), 0x00100000);
157
                _set_pe_int32(fptr, /*0x0064*/offsetof(PE32, optHeader.SizeOfStackCommit),  0x00001000);
529 daniel-mar 158
                // Heap reserved can be changed with linker option "OPTION HEAP=1m" before beta 21 Dec 2021 
456 daniel-mar 159
                _set_pe_int32(fptr, /*0x0068*/offsetof(PE32, optHeader.SizeOfHeapReserve),  0x00100000);
160
                _set_pe_int32(fptr, /*0x006C*/offsetof(PE32, optHeader.SizeOfHeapCommit),   0x00001000);
308 daniel-mar 161
 
456 daniel-mar 162
                fclose(fptr);
163
 
164
                // 32 bit (OpenWatcom cosmetics): Export table name "FilterFoundry.dll" => "FilterFoundry.8bf"
165
                // since OpenWatcom cannot link a 8BF file natively.
166
                binary_file_string_replace(filename, "FilterFoundry.dll", "FilterFoundry.8bf");
167
        }
168
 
169
        return true;
170
}
171
 
308 daniel-mar 172
uint32_t calculate_checksum(LPCTSTR filename) {
173
        //Calculate checksum of image
174
        // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
175
        // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
176
        // Converted from C++ to C by Daniel Marschall
177
 
178
        FILE* fptr;
179
        unsigned long long checksum = 0;
456 daniel-mar 180
        IMAGE_DOS_HEADER header;
308 daniel-mar 181
        size_t filesize;
182
        unsigned long long top;
183
        unsigned long pe_checksum_pos;
184
        static const unsigned long checksum_pos_in_optional_headers = 64;
185
        size_t i;
186
 
187
        fptr = _wfopen(filename, L"rb");
188
        if (fptr == NULL) return 0x00000000;
189
 
190
        //Read DOS header
191
        fseek(fptr, 0, SEEK_SET);
456 daniel-mar 192
        fread(&header, sizeof(IMAGE_DOS_HEADER), 1, fptr);
308 daniel-mar 193
 
194
        //Calculate PE checksum
195
        fseek(fptr, 0, SEEK_SET);
196
        top = 0xFFFFFFFF;
197
        top++;
198
 
199
        //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
200
        //Calculate real PE headers "CheckSum" field position
201
        //Sum is safe here
456 daniel-mar 202
        pe_checksum_pos = header.e_lfanew + sizeof(IMAGE_FILE_HEADER) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
308 daniel-mar 203
 
204
        //Calculate checksum for each byte of file
205
        fseek(fptr, 0L, SEEK_END);
206
        filesize = ftell(fptr);
207
        fseek(fptr, 0L, SEEK_SET);
208
        for (i = 0; i < filesize; i += 4)
209
        {
210
                unsigned long dw = 0;
211
 
212
                //Read DWORD from file
213
                fread(&dw, sizeof(dw), 1, fptr);
214
                //Skip "CheckSum" DWORD
215
                if (i == pe_checksum_pos)
216
                        continue;
217
 
218
                //Calculate checksum
219
                checksum = (checksum & 0xffffffff) + dw + (checksum >> 32);
220
                if (checksum > top)
221
                        checksum = (checksum & 0xffffffff) + (checksum >> 32);
222
        }
223
 
224
        //Finish checksum
225
        checksum = (checksum & 0xffff) + (checksum >> 16);
226
        checksum = (checksum)+(checksum >> 16);
227
        checksum = checksum & 0xffff;
228
 
229
        checksum += (unsigned long)(filesize);
230
 
231
        fclose(fptr);
232
 
233
        //Return checksum
234
        return (uint32_t)checksum;
235
}
236
 
237
bool repair_pe_checksum(LPCTSTR filename) {
238
        FILE* fptr;
239
 
240
        uint32_t checksum = calculate_checksum(filename);
241
        //if (checksum == 0x00000000) return false;
242
 
243
        fptr = _wfopen(filename, L"rb+");
244
        if (fptr == NULL) return false;
245
 
456 daniel-mar 246
        _set_pe_int32(fptr, /*0x0058*/offsetof(PE32, optHeader.CheckSum), (int32_t)checksum);
308 daniel-mar 247
 
248
        fclose(fptr);
249
 
250
        return true;
251
}
252
 
253
bool removeFromFile(LPCTSTR pluginfile, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage) {
254
        bool bSuccessful = false;
255
 
256
        HANDLE hRes = BeginUpdateResource(pluginfile, false);
257
        if (hRes != NULL) {
258
                if (UpdateResource(hRes, lpType, lpName, wLanguage, NULL, 0)) {
259
                        if (EndUpdateResource(hRes, false)) {
260
                                bSuccessful = true;
261
                        }
262
                }
263
                else {
264
                        EndUpdateResource(hRes, true);
265
                }
266
        }
267
 
268
        return bSuccessful;
269
}
270
 
271
bool addToFile(LPCTSTR pluginfile, LPCTSTR otherfile, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage) {
272
        HANDLE hFile;
273
        DWORD dwFileSize, dwBytesRead;
274
        LPBYTE lpBuffer;
275
        bool bSuccessful = false;
276
 
277
        hFile = CreateFile(otherfile, GENERIC_READ,
278
                0,
279
                NULL,
280
                OPEN_EXISTING,
281
                FILE_ATTRIBUTE_NORMAL,
282
                NULL);
283
 
284
        if (INVALID_HANDLE_VALUE != hFile)
285
        {
286
                dwFileSize = GetFileSize(hFile, NULL);
287
 
288
                //lpBuffer = new BYTE[dwFileSize];
289
                lpBuffer = (LPBYTE)malloc(dwFileSize);
290
 
291
                if (ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL) != FALSE)
292
                {
293
                        HANDLE hRes = BeginUpdateResource(pluginfile, false);
294
                        if (hRes != NULL) {
295
                                if (UpdateResource(hRes, lpType, lpName, wLanguage, lpBuffer, dwFileSize)) {
296
                                        if (EndUpdateResource(hRes, false)) {
297
                                                bSuccessful = true;
298
                                        }
299
                                }
300
                                else {
301
                                        EndUpdateResource(hRes, true);
302
                                }
303
                        }
304
                }
305
 
306
                //delete[] lpBuffer;
307
                free(lpBuffer);
308
 
309
                CloseHandle(hFile);
310
        }
311
 
312
        return bSuccessful;
313
}
314
 
455 daniel-mar 315
 
308 daniel-mar 316
int main()
317
{
416 daniel-mar 318
        LPCTSTR lpTemplateType = L"TPLT";
319
        LPCTSTR lpName32Plugin = (LPCTSTR)1032;
320
        LPCTSTR lpName64Plugin = (LPCTSTR)1064;
321
        LPCTSTR lpName32Version = (LPCTSTR)3032;
322
        LPCTSTR lpName64Version = (LPCTSTR)3064;
323
        LPCTSTR lpName32Pipl = (LPCTSTR)16032;
324
        LPCTSTR lpName64Pipl = (LPCTSTR)16064;
325
        WORD wLanguageEnUs = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); // 1033 en-US
326
        WORD wLanguageNeutral = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); // 0 Neutral
308 daniel-mar 327
 
311 daniel-mar 328
        LPCTSTR file32in = L"in\\FilterFoundry.8bf";
329
        LPCTSTR file64in = L"in\\FilterFoundry64.8bf";
330
        LPCTSTR file32out = L"out\\FilterFoundry.8bf";
331
        LPCTSTR file64out = L"out\\FilterFoundry64.8bf";
332
        LPCTSTR file32tmp = L"FilterFoundry.tmp";
333
        LPCTSTR file64tmp = L"FilterFoundry64.tmp";
308 daniel-mar 334
 
416 daniel-mar 335
        // 1a. Copy 32 "IN" to 32 "TMP", and 64 "IN" to 64 "TMP"
336
        {
337
                if (!CopyFile(file32in, file32tmp, false)) {
338
                        DeleteFile(file32out);
339
                        DeleteFile(file64out);
340
                        printf("Error: Copyfile 32in > 32tmp\n");
341
                        return 1;
342
                }
308 daniel-mar 343
 
416 daniel-mar 344
                if (!CopyFile(file64in, file64tmp, false)) {
345
                        DeleteFile(file32out);
346
                        DeleteFile(file64out);
347
                        printf("Error: Copyfile 64in > 64tmp\n");
348
                        return 1;
349
                }
308 daniel-mar 350
        }
351
 
416 daniel-mar 352
        // 1b. Copy 32 "IN" to 32 "OUT", and 64 "IN" to 64 "OUT" (will be edited later)
353
        {
354
                if (!CopyFile(file32in, file32out, false)) {
355
                        DeleteFile(file32out);
356
                        DeleteFile(file64out);
357
                        printf("Error: Copyfile 32in > 32out\n");
358
                        return 1;
359
                }
360
 
361
                if (!CopyFile(file64in, file64out, false)) {
362
                        DeleteFile(file32out);
363
                        DeleteFile(file64out);
364
                        printf("Error: Copyfile 64in > 64out\n");
365
                        return 1;
366
                }
308 daniel-mar 367
        }
368
 
416 daniel-mar 369
        // 2. Remove any template residues at 32/64 "TMP", since they are only used for building
370
        //    "TMP" is our "standalone plugin skelleton"
371
        // TODO: Also remove build dialogs, cursors and icons (like done in make_win.c)?
372
        {
373
                // Remove TPLT 1 (Manifest template)
374
                removeFromFile(file32tmp, lpTemplateType, MAKEINTRESOURCE(1), wLanguageNeutral);
375
                removeFromFile(file64tmp, lpTemplateType, MAKEINTRESOURCE(1), wLanguageNeutral);
308 daniel-mar 376
 
416 daniel-mar 377
                // Remove TPLT 1032/1064 (8BF included)
378
                removeFromFile(file32tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs);
379
                removeFromFile(file32tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs);
380
                removeFromFile(file64tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs);
381
                removeFromFile(file64tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs);
308 daniel-mar 382
 
416 daniel-mar 383
                // Remove TPLT 3032/3064 (Versioninfo included)
384
                removeFromFile(file32tmp, lpTemplateType, lpName32Version, wLanguageEnUs);
385
                removeFromFile(file32tmp, lpTemplateType, lpName64Version, wLanguageEnUs);
386
                removeFromFile(file64tmp, lpTemplateType, lpName32Version, wLanguageEnUs);
387
                removeFromFile(file64tmp, lpTemplateType, lpName64Version, wLanguageEnUs);
308 daniel-mar 388
 
416 daniel-mar 389
                // Remove TPLT 16032/16064 (PIPL template)
390
                removeFromFile(file32tmp, lpTemplateType, lpName32Pipl, wLanguageNeutral);
391
                removeFromFile(file32tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
392
                removeFromFile(file64tmp, lpTemplateType, lpName32Pipl, wLanguageNeutral);
393
                removeFromFile(file64tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
308 daniel-mar 394
        }
395
 
456 daniel-mar 396
        // Do some cosmetics to OpenWatcom binaries
397
        openWatcomCosmetics(file32tmp);
398
        openWatcomCosmetics(file32out);
455 daniel-mar 399
 
416 daniel-mar 400
        // 3. Update timestamp of 32/64 "TMP"
401
        {
456 daniel-mar 402
                if (!update_pe_timestamp(file32tmp, (__time32_t)time(0))) {
416 daniel-mar 403
                        DeleteFile(file32out);
404
                        DeleteFile(file64out);
405
                        printf("Error: Update TMP timestamp 32\n");
406
                        return 1;
407
                }
408
 
456 daniel-mar 409
                if (!update_pe_timestamp(file64tmp, (__time32_t)time(0))) {
416 daniel-mar 410
                        DeleteFile(file32out);
411
                        DeleteFile(file64out);
412
                        printf("Error: Update TMP timestamp 64\n");
413
                        return 1;
414
                }
308 daniel-mar 415
        }
416
 
416 daniel-mar 417
        // 4. Repair checksums of 32/64 "TMP"
418
        {
419
                if (!repair_pe_checksum(file32tmp)) {
420
                        DeleteFile(file32out);
421
                        DeleteFile(file64out);
422
                        printf("Error: Repair TMP checksum 32\n");
423
                        return 1;
424
                }
425
                if (!repair_pe_checksum(file64tmp)) {
426
                        DeleteFile(file32out);
427
                        DeleteFile(file64out);
428
                        printf("Error: Repair TMP checksum 64\n");
429
                        return 1;
430
                }
308 daniel-mar 431
        }
432
 
416 daniel-mar 433
        // 6. Add 32/64 "TMP" to 64/32 "OUT" ("criss-cross")
434
        {
435
                if (!addToFile(file32out, file32tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs)) {
436
                        DeleteFile(file32out);
437
                        DeleteFile(file64out);
438
                        printf("Error: Add 32 to 32\n");
439
                        return 1;
440
                }
441
                if (!addToFile(file32out, file64tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs)) {
442
                        DeleteFile(file32out);
443
                        DeleteFile(file64out);
444
                        printf("Error: Add 64 to 32\n");
445
                        return 1;
446
                }
308 daniel-mar 447
 
416 daniel-mar 448
                if (!addToFile(file64out, file32tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs)) {
449
                        DeleteFile(file32out);
450
                        DeleteFile(file64out);
451
                        printf("Error: Add 32 to 64\n");
452
                        return 1;
453
                }
454
 
455
                if (!addToFile(file64out, file64tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs)) {
456
                        DeleteFile(file32out);
457
                        DeleteFile(file64out);
458
                        printf("Error: Add 64 to 64\n");
459
                        return 1;
460
                }
308 daniel-mar 461
        }
462
 
416 daniel-mar 463
        // 7a. Read Version Info from 32 bit "TMP", and copy it to 32/64 "OUT" template
464
        {
465
                HMODULE lib = LoadLibraryEx(file32tmp, NULL, LOAD_LIBRARY_AS_DATAFILE);
466
                if (!lib) {
467
                        printf("Loadlib failed at versioninfo TPLT 32");
468
                        return 1;
469
                }
470
                HRSRC resinfo = FindResource(lib, MAKEINTRESOURCE(1), RT_VERSION);
471
                if (!resinfo) {
472
                        printf("FindResource failed at versioninfo TPLT 32");
473
                        return 1;
474
                }
475
                size_t cbVersionInfo = SizeofResource(lib, resinfo);
476
                HGLOBAL hvinfo = LoadResource(lib, resinfo);
477
                if (!hvinfo) {
478
                        printf("LoadResource failed at versioninfo TPLT 32");
479
                        return 1;
480
                }
481
                char* vinfo = (char*)LockResource(hvinfo);
482
                char* vinfocpy = (char*)malloc(cbVersionInfo);
483
                if (vinfocpy == NULL) return 1;
484
                memcpy(vinfocpy, vinfo, cbVersionInfo);
485
                UnlockResource(hvinfo);
486
                FreeLibrary(lib);
308 daniel-mar 487
 
416 daniel-mar 488
                // Write Version info to TPLT Resource of 32 bit "OUT"
308 daniel-mar 489
 
416 daniel-mar 490
                HANDLE hupd = BeginUpdateResource(file32out, false);
491
                UpdateResource(hupd, TEXT("TPLT"), lpName32Version, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), vinfocpy, cbVersionInfo);
492
                EndUpdateResource(hupd, false);
308 daniel-mar 493
 
416 daniel-mar 494
                // Write Version info to TPLT Resource of 64 bit "OUT"
495
 
496
                hupd = BeginUpdateResource(file64out, false);
497
                UpdateResource(hupd, TEXT("TPLT"), lpName32Version, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), vinfocpy, cbVersionInfo);
498
                EndUpdateResource(hupd, false);
499
 
500
                // Free memory
501
 
502
                free(vinfocpy);
308 daniel-mar 503
        }
504
 
416 daniel-mar 505
        // 7b. Read Version Info from 64 bit "TMP", and copy it to 32/64 "OUT" template
506
        {
507
                HMODULE lib = LoadLibraryEx(file64tmp, NULL, LOAD_LIBRARY_AS_DATAFILE);
508
                if (!lib) {
509
                        printf("Loadlib failed at versioninfo TPLT 64");
510
                        return 1;
511
                }
512
                HRSRC resinfo = FindResource(lib, MAKEINTRESOURCE(1), RT_VERSION);
513
                if (!resinfo) {
514
                        printf("FindResource failed at versioninfo TPLT 64");
515
                        return 1;
516
                }
517
                size_t cbVersionInfo = SizeofResource(lib, resinfo);
518
                HGLOBAL hvinfo = LoadResource(lib, resinfo);
519
                if (!hvinfo) {
520
                        printf("LoadResource failed at versioninfo TPLT 64");
521
                        return 1;
522
                }
523
                char* vinfo = (char*)LockResource(hvinfo);
524
                char* vinfocpy = (char*)malloc(cbVersionInfo);
525
                if (vinfocpy == NULL) return 1;
526
                memcpy(vinfocpy, vinfo, cbVersionInfo);
527
                UnlockResource(hvinfo);
528
                FreeLibrary(lib);
308 daniel-mar 529
 
416 daniel-mar 530
                // Write Version info to TPLT Resource of 32 bit "OUT"
308 daniel-mar 531
 
416 daniel-mar 532
                HANDLE hupd = BeginUpdateResource(file32out, false);
533
                UpdateResource(hupd, TEXT("TPLT"), lpName64Version, 1033, vinfocpy, cbVersionInfo);
534
                EndUpdateResource(hupd, false);
308 daniel-mar 535
 
416 daniel-mar 536
                // Write Version info to TPLT Resource of 64 bit "OUT"
537
 
538
                hupd = BeginUpdateResource(file64out, false);
539
                UpdateResource(hupd, TEXT("TPLT"), lpName64Version, 1033, vinfocpy, cbVersionInfo);
540
                EndUpdateResource(hupd, false);
541
 
542
                // Free memory
543
 
544
                free(vinfocpy);
308 daniel-mar 545
        }
546
 
416 daniel-mar 547
        // 8. Delete 32/64 "TMP"
548
        {
549
                DeleteFile(file32tmp);
550
                DeleteFile(file64tmp);
308 daniel-mar 551
        }
552
 
416 daniel-mar 553
        // 9. Update timestamp of 32/64 "OUT"
554
        {
456 daniel-mar 555
                if (!update_pe_timestamp(file32out, (__time32_t)time(0))) {
416 daniel-mar 556
                        DeleteFile(file32out);
557
                        DeleteFile(file64out);
558
                        printf("Error: Update OUT timestamp 32\n");
559
                        return 1;
560
                }
308 daniel-mar 561
 
456 daniel-mar 562
                if (!update_pe_timestamp(file64out, (__time32_t)time(0))) {
416 daniel-mar 563
                        DeleteFile(file32out);
564
                        DeleteFile(file64out);
565
                        printf("Error: Update OUT timestamp 64\n");
566
                        return 1;
567
                }
308 daniel-mar 568
        }
416 daniel-mar 569
 
570
        // 10. Repair checksums of 32/64 "OUT"
571
        {
572
                if (!repair_pe_checksum(file32out)) {
573
                        DeleteFile(file32out);
574
                        DeleteFile(file64out);
575
                        printf("Error: Repair OUT checksum 32\n");
576
                        return 1;
577
                }
578
                if (!repair_pe_checksum(file64out)) {
579
                        DeleteFile(file32out);
580
                        DeleteFile(file64out);
581
                        printf("Error: Repair OUT checksum 64\n");
582
                        return 1;
583
                }
308 daniel-mar 584
        }
585
 
416 daniel-mar 586
        // 11. All done!
308 daniel-mar 587
 
588
        printf("All OK!\n");
589
        return 0;
590
}