Subversion Repositories filter_foundry

Rev

Rev 311 | Rev 455 | 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
4
        Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft
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>
27
 
28
bool update_pe_timestamp(LPCTSTR filename, time_t timestamp) {
29
        size_t peoffset;
30
        FILE* fptr;
31
 
32
        fptr = _wfopen(filename, L"rb+");
33
        if (fptr == NULL) return false;
34
 
35
        fseek(fptr, 0x3C, SEEK_SET);
36
        fread(&peoffset, sizeof(peoffset), 1, fptr);
37
 
38
        fseek(fptr, (long)peoffset + 8, SEEK_SET);
39
        fwrite(&timestamp, sizeof(time_t), 1, fptr);
40
 
41
        fclose(fptr);
42
 
43
        return true;
44
}
45
 
46
//DOS .EXE header
47
struct image_dos_header
48
{
49
        uint16_t e_magic;                     // Magic number
50
        uint16_t e_cblp;                      // Bytes on last page of file
51
        uint16_t e_cp;                        // Pages in file
52
        uint16_t e_crlc;                      // Relocations
53
        uint16_t e_cparhdr;                   // Size of header in paragraphs
54
        uint16_t e_minalloc;                  // Minimum extra paragraphs needed
55
        uint16_t e_maxalloc;                  // Maximum extra paragraphs needed
56
        uint16_t e_ss;                        // Initial (relative) SS value
57
        uint16_t e_sp;                        // Initial SP value
58
        uint16_t e_csum;                      // Checksum
59
        uint16_t e_ip;                        // Initial IP value
60
        uint16_t e_cs;                        // Initial (relative) CS value
61
        uint16_t e_lfarlc;                    // File address of relocation table
62
        uint16_t e_ovno;                      // Overlay number
63
        uint16_t e_res[4];                    // Reserved words
64
        uint16_t e_oemid;                     // OEM identifier (for e_oeminfo)
65
        uint16_t e_oeminfo;                   // OEM information; e_oemid specific
66
        uint16_t e_res2[10];                  // Reserved words
67
        int32_t  e_lfanew;                    // File address of new exe header
68
};
69
 
70
struct image_file_header
71
{
72
        uint16_t Machine;
73
        uint16_t NumberOfSections;
74
        uint32_t TimeDateStamp;
75
        uint32_t PointerToSymbolTable;
76
        uint32_t NumberOfSymbols;
77
        uint16_t SizeOfOptionalHeader;
78
        uint16_t Characteristics;
79
};
80
 
81
uint32_t calculate_checksum(LPCTSTR filename) {
82
        //Calculate checksum of image
83
        // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
84
        // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
85
        // Converted from C++ to C by Daniel Marschall
86
 
87
        FILE* fptr;
88
        unsigned long long checksum = 0;
89
        struct image_dos_header header;
90
        size_t filesize;
91
        unsigned long long top;
92
        unsigned long pe_checksum_pos;
93
        static const unsigned long checksum_pos_in_optional_headers = 64;
94
        size_t i;
95
 
96
        fptr = _wfopen(filename, L"rb");
97
        if (fptr == NULL) return 0x00000000;
98
 
99
        //Read DOS header
100
        fseek(fptr, 0, SEEK_SET);
101
        fread(&header, sizeof(struct image_dos_header), 1, fptr);
102
 
103
        //Calculate PE checksum
104
        fseek(fptr, 0, SEEK_SET);
105
        top = 0xFFFFFFFF;
106
        top++;
107
 
108
        //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
109
        //Calculate real PE headers "CheckSum" field position
110
        //Sum is safe here
111
        pe_checksum_pos = header.e_lfanew + sizeof(struct image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
112
 
113
        //Calculate checksum for each byte of file
114
        fseek(fptr, 0L, SEEK_END);
115
        filesize = ftell(fptr);
116
        fseek(fptr, 0L, SEEK_SET);
117
        for (i = 0; i < filesize; i += 4)
118
        {
119
                unsigned long dw = 0;
120
 
121
                //Read DWORD from file
122
                fread(&dw, sizeof(dw), 1, fptr);
123
                //Skip "CheckSum" DWORD
124
                if (i == pe_checksum_pos)
125
                        continue;
126
 
127
                //Calculate checksum
128
                checksum = (checksum & 0xffffffff) + dw + (checksum >> 32);
129
                if (checksum > top)
130
                        checksum = (checksum & 0xffffffff) + (checksum >> 32);
131
        }
132
 
133
        //Finish checksum
134
        checksum = (checksum & 0xffff) + (checksum >> 16);
135
        checksum = (checksum)+(checksum >> 16);
136
        checksum = checksum & 0xffff;
137
 
138
        checksum += (unsigned long)(filesize);
139
 
140
        fclose(fptr);
141
 
142
        //Return checksum
143
        return (uint32_t)checksum;
144
}
145
 
146
bool repair_pe_checksum(LPCTSTR filename) {
147
        size_t peoffset;
148
        FILE* fptr;
149
 
150
        uint32_t checksum = calculate_checksum(filename);
151
        //if (checksum == 0x00000000) return false;
152
 
153
        fptr = _wfopen(filename, L"rb+");
154
        if (fptr == NULL) return false;
155
 
156
        fseek(fptr, 0x3C, SEEK_SET);
157
        fread(&peoffset, sizeof(peoffset), 1, fptr);
158
 
159
        fseek(fptr, (long)peoffset + 88, SEEK_SET);
160
        fwrite(&checksum, sizeof(uint32_t), 1, fptr);
161
 
162
        fclose(fptr);
163
 
164
        return true;
165
}
166
 
167
bool removeFromFile(LPCTSTR pluginfile, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage) {
168
        bool bSuccessful = false;
169
 
170
        HANDLE hRes = BeginUpdateResource(pluginfile, false);
171
        if (hRes != NULL) {
172
                if (UpdateResource(hRes, lpType, lpName, wLanguage, NULL, 0)) {
173
                        if (EndUpdateResource(hRes, false)) {
174
                                bSuccessful = true;
175
                        }
176
                }
177
                else {
178
                        EndUpdateResource(hRes, true);
179
                }
180
        }
181
 
182
        return bSuccessful;
183
}
184
 
185
bool addToFile(LPCTSTR pluginfile, LPCTSTR otherfile, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage) {
186
        HANDLE hFile;
187
        DWORD dwFileSize, dwBytesRead;
188
        LPBYTE lpBuffer;
189
        bool bSuccessful = false;
190
 
191
        hFile = CreateFile(otherfile, GENERIC_READ,
192
                0,
193
                NULL,
194
                OPEN_EXISTING,
195
                FILE_ATTRIBUTE_NORMAL,
196
                NULL);
197
 
198
        if (INVALID_HANDLE_VALUE != hFile)
199
        {
200
                dwFileSize = GetFileSize(hFile, NULL);
201
 
202
                //lpBuffer = new BYTE[dwFileSize];
203
                lpBuffer = (LPBYTE)malloc(dwFileSize);
204
 
205
                if (ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL) != FALSE)
206
                {
207
                        HANDLE hRes = BeginUpdateResource(pluginfile, false);
208
                        if (hRes != NULL) {
209
                                if (UpdateResource(hRes, lpType, lpName, wLanguage, lpBuffer, dwFileSize)) {
210
                                        if (EndUpdateResource(hRes, false)) {
211
                                                bSuccessful = true;
212
                                        }
213
                                }
214
                                else {
215
                                        EndUpdateResource(hRes, true);
216
                                }
217
                        }
218
                }
219
 
220
                //delete[] lpBuffer;
221
                free(lpBuffer);
222
 
223
                CloseHandle(hFile);
224
        }
225
 
226
        return bSuccessful;
227
}
228
 
229
int main()
230
{
416 daniel-mar 231
        LPCTSTR lpTemplateType = L"TPLT";
232
        LPCTSTR lpName32Plugin = (LPCTSTR)1032;
233
        LPCTSTR lpName64Plugin = (LPCTSTR)1064;
234
        LPCTSTR lpName32Version = (LPCTSTR)3032;
235
        LPCTSTR lpName64Version = (LPCTSTR)3064;
236
        LPCTSTR lpName32Pipl = (LPCTSTR)16032;
237
        LPCTSTR lpName64Pipl = (LPCTSTR)16064;
238
        WORD wLanguageEnUs = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); // 1033 en-US
239
        WORD wLanguageNeutral = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); // 0 Neutral
308 daniel-mar 240
 
311 daniel-mar 241
        LPCTSTR file32in = L"in\\FilterFoundry.8bf";
242
        LPCTSTR file64in = L"in\\FilterFoundry64.8bf";
243
        LPCTSTR file32out = L"out\\FilterFoundry.8bf";
244
        LPCTSTR file64out = L"out\\FilterFoundry64.8bf";
245
        LPCTSTR file32tmp = L"FilterFoundry.tmp";
246
        LPCTSTR file64tmp = L"FilterFoundry64.tmp";
308 daniel-mar 247
 
416 daniel-mar 248
        // 1a. Copy 32 "IN" to 32 "TMP", and 64 "IN" to 64 "TMP"
249
        {
250
                if (!CopyFile(file32in, file32tmp, false)) {
251
                        DeleteFile(file32out);
252
                        DeleteFile(file64out);
253
                        printf("Error: Copyfile 32in > 32tmp\n");
254
                        return 1;
255
                }
308 daniel-mar 256
 
416 daniel-mar 257
                if (!CopyFile(file64in, file64tmp, false)) {
258
                        DeleteFile(file32out);
259
                        DeleteFile(file64out);
260
                        printf("Error: Copyfile 64in > 64tmp\n");
261
                        return 1;
262
                }
308 daniel-mar 263
        }
264
 
416 daniel-mar 265
        // 1b. Copy 32 "IN" to 32 "OUT", and 64 "IN" to 64 "OUT" (will be edited later)
266
        {
267
                if (!CopyFile(file32in, file32out, false)) {
268
                        DeleteFile(file32out);
269
                        DeleteFile(file64out);
270
                        printf("Error: Copyfile 32in > 32out\n");
271
                        return 1;
272
                }
273
 
274
                if (!CopyFile(file64in, file64out, false)) {
275
                        DeleteFile(file32out);
276
                        DeleteFile(file64out);
277
                        printf("Error: Copyfile 64in > 64out\n");
278
                        return 1;
279
                }
308 daniel-mar 280
        }
281
 
416 daniel-mar 282
        // 2. Remove any template residues at 32/64 "TMP", since they are only used for building
283
        //    "TMP" is our "standalone plugin skelleton"
284
        // TODO: Also remove build dialogs, cursors and icons (like done in make_win.c)?
285
        {
286
                // Remove TPLT 1 (Manifest template)
287
                removeFromFile(file32tmp, lpTemplateType, MAKEINTRESOURCE(1), wLanguageNeutral);
288
                removeFromFile(file64tmp, lpTemplateType, MAKEINTRESOURCE(1), wLanguageNeutral);
308 daniel-mar 289
 
416 daniel-mar 290
                // Remove TPLT 1032/1064 (8BF included)
291
                removeFromFile(file32tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs);
292
                removeFromFile(file32tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs);
293
                removeFromFile(file64tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs);
294
                removeFromFile(file64tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs);
308 daniel-mar 295
 
416 daniel-mar 296
                // Remove TPLT 3032/3064 (Versioninfo included)
297
                removeFromFile(file32tmp, lpTemplateType, lpName32Version, wLanguageEnUs);
298
                removeFromFile(file32tmp, lpTemplateType, lpName64Version, wLanguageEnUs);
299
                removeFromFile(file64tmp, lpTemplateType, lpName32Version, wLanguageEnUs);
300
                removeFromFile(file64tmp, lpTemplateType, lpName64Version, wLanguageEnUs);
308 daniel-mar 301
 
416 daniel-mar 302
                // Remove TPLT 16032/16064 (PIPL template)
303
                removeFromFile(file32tmp, lpTemplateType, lpName32Pipl, wLanguageNeutral);
304
                removeFromFile(file32tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
305
                removeFromFile(file64tmp, lpTemplateType, lpName32Pipl, wLanguageNeutral);
306
                removeFromFile(file64tmp, lpTemplateType, lpName64Pipl, wLanguageNeutral);
308 daniel-mar 307
        }
308
 
416 daniel-mar 309
        // 3. Update timestamp of 32/64 "TMP"
310
        {
311
                if (!update_pe_timestamp(file32tmp, time(0))) {
312
                        DeleteFile(file32out);
313
                        DeleteFile(file64out);
314
                        printf("Error: Update TMP timestamp 32\n");
315
                        return 1;
316
                }
317
 
318
                if (!update_pe_timestamp(file64tmp, time(0))) {
319
                        DeleteFile(file32out);
320
                        DeleteFile(file64out);
321
                        printf("Error: Update TMP timestamp 64\n");
322
                        return 1;
323
                }
308 daniel-mar 324
        }
325
 
416 daniel-mar 326
        // 4. Repair checksums of 32/64 "TMP"
327
        {
328
                if (!repair_pe_checksum(file32tmp)) {
329
                        DeleteFile(file32out);
330
                        DeleteFile(file64out);
331
                        printf("Error: Repair TMP checksum 32\n");
332
                        return 1;
333
                }
334
                if (!repair_pe_checksum(file64tmp)) {
335
                        DeleteFile(file32out);
336
                        DeleteFile(file64out);
337
                        printf("Error: Repair TMP checksum 64\n");
338
                        return 1;
339
                }
308 daniel-mar 340
        }
341
 
416 daniel-mar 342
        // 6. Add 32/64 "TMP" to 64/32 "OUT" ("criss-cross")
343
        {
344
                if (!addToFile(file32out, file32tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs)) {
345
                        DeleteFile(file32out);
346
                        DeleteFile(file64out);
347
                        printf("Error: Add 32 to 32\n");
348
                        return 1;
349
                }
350
                if (!addToFile(file32out, file64tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs)) {
351
                        DeleteFile(file32out);
352
                        DeleteFile(file64out);
353
                        printf("Error: Add 64 to 32\n");
354
                        return 1;
355
                }
308 daniel-mar 356
 
416 daniel-mar 357
                if (!addToFile(file64out, file32tmp, lpTemplateType, lpName32Plugin, wLanguageEnUs)) {
358
                        DeleteFile(file32out);
359
                        DeleteFile(file64out);
360
                        printf("Error: Add 32 to 64\n");
361
                        return 1;
362
                }
363
 
364
                if (!addToFile(file64out, file64tmp, lpTemplateType, lpName64Plugin, wLanguageEnUs)) {
365
                        DeleteFile(file32out);
366
                        DeleteFile(file64out);
367
                        printf("Error: Add 64 to 64\n");
368
                        return 1;
369
                }
308 daniel-mar 370
        }
371
 
416 daniel-mar 372
        // 7a. Read Version Info from 32 bit "TMP", and copy it to 32/64 "OUT" template
373
        {
374
                HMODULE lib = LoadLibraryEx(file32tmp, NULL, LOAD_LIBRARY_AS_DATAFILE);
375
                if (!lib) {
376
                        printf("Loadlib failed at versioninfo TPLT 32");
377
                        return 1;
378
                }
379
                HRSRC resinfo = FindResource(lib, MAKEINTRESOURCE(1), RT_VERSION);
380
                if (!resinfo) {
381
                        printf("FindResource failed at versioninfo TPLT 32");
382
                        return 1;
383
                }
384
                size_t cbVersionInfo = SizeofResource(lib, resinfo);
385
                HGLOBAL hvinfo = LoadResource(lib, resinfo);
386
                if (!hvinfo) {
387
                        printf("LoadResource failed at versioninfo TPLT 32");
388
                        return 1;
389
                }
390
                char* vinfo = (char*)LockResource(hvinfo);
391
                char* vinfocpy = (char*)malloc(cbVersionInfo);
392
                if (vinfocpy == NULL) return 1;
393
                memcpy(vinfocpy, vinfo, cbVersionInfo);
394
                UnlockResource(hvinfo);
395
                FreeLibrary(lib);
308 daniel-mar 396
 
416 daniel-mar 397
                // Write Version info to TPLT Resource of 32 bit "OUT"
308 daniel-mar 398
 
416 daniel-mar 399
                HANDLE hupd = BeginUpdateResource(file32out, false);
400
                UpdateResource(hupd, TEXT("TPLT"), lpName32Version, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), vinfocpy, cbVersionInfo);
401
                EndUpdateResource(hupd, false);
308 daniel-mar 402
 
416 daniel-mar 403
                // Write Version info to TPLT Resource of 64 bit "OUT"
404
 
405
                hupd = BeginUpdateResource(file64out, false);
406
                UpdateResource(hupd, TEXT("TPLT"), lpName32Version, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), vinfocpy, cbVersionInfo);
407
                EndUpdateResource(hupd, false);
408
 
409
                // Free memory
410
 
411
                free(vinfocpy);
308 daniel-mar 412
        }
413
 
416 daniel-mar 414
        // 7b. Read Version Info from 64 bit "TMP", and copy it to 32/64 "OUT" template
415
        {
416
                HMODULE lib = LoadLibraryEx(file64tmp, NULL, LOAD_LIBRARY_AS_DATAFILE);
417
                if (!lib) {
418
                        printf("Loadlib failed at versioninfo TPLT 64");
419
                        return 1;
420
                }
421
                HRSRC resinfo = FindResource(lib, MAKEINTRESOURCE(1), RT_VERSION);
422
                if (!resinfo) {
423
                        printf("FindResource failed at versioninfo TPLT 64");
424
                        return 1;
425
                }
426
                size_t cbVersionInfo = SizeofResource(lib, resinfo);
427
                HGLOBAL hvinfo = LoadResource(lib, resinfo);
428
                if (!hvinfo) {
429
                        printf("LoadResource failed at versioninfo TPLT 64");
430
                        return 1;
431
                }
432
                char* vinfo = (char*)LockResource(hvinfo);
433
                char* vinfocpy = (char*)malloc(cbVersionInfo);
434
                if (vinfocpy == NULL) return 1;
435
                memcpy(vinfocpy, vinfo, cbVersionInfo);
436
                UnlockResource(hvinfo);
437
                FreeLibrary(lib);
308 daniel-mar 438
 
416 daniel-mar 439
                // Write Version info to TPLT Resource of 32 bit "OUT"
308 daniel-mar 440
 
416 daniel-mar 441
                HANDLE hupd = BeginUpdateResource(file32out, false);
442
                UpdateResource(hupd, TEXT("TPLT"), lpName64Version, 1033, vinfocpy, cbVersionInfo);
443
                EndUpdateResource(hupd, false);
308 daniel-mar 444
 
416 daniel-mar 445
                // Write Version info to TPLT Resource of 64 bit "OUT"
446
 
447
                hupd = BeginUpdateResource(file64out, false);
448
                UpdateResource(hupd, TEXT("TPLT"), lpName64Version, 1033, vinfocpy, cbVersionInfo);
449
                EndUpdateResource(hupd, false);
450
 
451
                // Free memory
452
 
453
                free(vinfocpy);
308 daniel-mar 454
        }
455
 
416 daniel-mar 456
        // 8. Delete 32/64 "TMP"
457
        {
458
                DeleteFile(file32tmp);
459
                DeleteFile(file64tmp);
308 daniel-mar 460
        }
461
 
416 daniel-mar 462
        // 9. Update timestamp of 32/64 "OUT"
463
        {
464
                if (!update_pe_timestamp(file32out, time(0))) {
465
                        DeleteFile(file32out);
466
                        DeleteFile(file64out);
467
                        printf("Error: Update OUT timestamp 32\n");
468
                        return 1;
469
                }
308 daniel-mar 470
 
416 daniel-mar 471
                if (!update_pe_timestamp(file64out, time(0))) {
472
                        DeleteFile(file32out);
473
                        DeleteFile(file64out);
474
                        printf("Error: Update OUT timestamp 64\n");
475
                        return 1;
476
                }
308 daniel-mar 477
        }
416 daniel-mar 478
 
479
        // 10. Repair checksums of 32/64 "OUT"
480
        {
481
                if (!repair_pe_checksum(file32out)) {
482
                        DeleteFile(file32out);
483
                        DeleteFile(file64out);
484
                        printf("Error: Repair OUT checksum 32\n");
485
                        return 1;
486
                }
487
                if (!repair_pe_checksum(file64out)) {
488
                        DeleteFile(file32out);
489
                        DeleteFile(file64out);
490
                        printf("Error: Repair OUT checksum 64\n");
491
                        return 1;
492
                }
308 daniel-mar 493
        }
494
 
416 daniel-mar 495
        // 11. All done!
308 daniel-mar 496
 
497
        printf("All OK!\n");
498
        return 0;
499
}