Subversion Repositories filter_foundry

Rev

Rev 311 | Go to most recent revision | Details | 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
{
231
        LPCTSTR lpType = L"TPLT";
232
        LPCTSTR lpName32 = (LPCTSTR)1032;
233
        LPCTSTR lpName64 = (LPCTSTR)1064;
234
        WORD wLanguage = 1033; // en-US
235
 
236
        LPCTSTR file32in = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\in\\FilterFoundry.8bf";
237
        LPCTSTR file64in = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\in\\FilterFoundry64.8bf";
238
        LPCTSTR file32out = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\out\\FilterFoundry.8bf";
239
        LPCTSTR file64out = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\out\\FilterFoundry64.8bf";
240
        LPCTSTR file32tmp = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\FilterFoundry.tmp";
241
        LPCTSTR file64tmp = L"d:\\SVN\\FilterFoundry\\trunk\\3264_mixer\\FilterFoundry64.tmp";
242
 
243
        // 1. Copy "IN" to "TMP"
244
 
245
        if (!CopyFile(file32in, file32tmp, false)) {
246
                DeleteFile(file32out);
247
                DeleteFile(file64out);
248
                printf("Error: Copyfile 32in > 32tmp\n");
249
                return 1;
250
        }
251
 
252
        if (!CopyFile(file64in, file64tmp, false)) {
253
                DeleteFile(file32out);
254
                DeleteFile(file64out);
255
                printf("Error: Copyfile 64in > 64tmp\n");
256
                return 1;
257
        }
258
 
259
        // 2. Remove any 32/64 residue in "TMP"
260
 
261
        removeFromFile(file32tmp, lpType, lpName32, wLanguage);
262
        removeFromFile(file32tmp, lpType, lpName64, wLanguage);
263
        removeFromFile(file64tmp, lpType, lpName32, wLanguage);
264
        removeFromFile(file64tmp, lpType, lpName64, wLanguage);
265
 
266
        // 3. Update timestamp
267
 
268
        if (!update_pe_timestamp(file32tmp, time(0))) {
269
                DeleteFile(file32out);
270
                DeleteFile(file64out);
271
                printf("Error: Update TMP timestamp 32\n");
272
                return 1;
273
        }
274
 
275
        if (!update_pe_timestamp(file64tmp, time(0))) {
276
                DeleteFile(file32out);
277
                DeleteFile(file64out);
278
                printf("Error: Update TMP timestamp 64\n");
279
                return 1;
280
        }
281
 
282
        // 4. Repair checksums
283
 
284
        if (!repair_pe_checksum(file32tmp)) {
285
                DeleteFile(file32out);
286
                DeleteFile(file64out);
287
                printf("Error: Repair TMP checksum 32\n");
288
                return 1;
289
        }
290
        if (!repair_pe_checksum(file64tmp)) {
291
                DeleteFile(file32out);
292
                DeleteFile(file64out);
293
                printf("Error: Repair TMP checksum 64\n");
294
                return 1;
295
        }
296
 
297
        // 5. Copy "TMP" to "OUT" (will be edited later)
298
 
299
        if (!CopyFile(file32tmp, file32out, false)) {
300
                DeleteFile(file32out);
301
                DeleteFile(file64out);
302
                printf("Error: Copyfile 32tmp > 32out\n");
303
                return 1;
304
        }
305
        if (!CopyFile(file64tmp, file64out, false)) {
306
                DeleteFile(file32out);
307
                DeleteFile(file64out);
308
                printf("Error: Copyfile 64tmp > 64out\n");
309
                return 1;
310
        }
311
 
312
        // 6. Add 32/64 "TMP" to 64/32 "OUT"
313
 
314
        if (!addToFile(file32out, file32tmp, lpType, lpName32, wLanguage)) {
315
                DeleteFile(file32out);
316
                DeleteFile(file64out);
317
                printf("Error: Add 32 to 32\n");
318
                return 1;
319
        }
320
        if (!addToFile(file32out, file64tmp, lpType, lpName64, wLanguage)) {
321
                DeleteFile(file32out);
322
                DeleteFile(file64out);
323
                printf("Error: Add 64 to 32\n");
324
                return 1;
325
        }
326
 
327
        if (!addToFile(file64out, file32tmp, lpType, lpName32, wLanguage)) {
328
                DeleteFile(file32out);
329
                DeleteFile(file64out);
330
                printf("Error: Add 32 to 64\n");
331
                return 1;
332
        }
333
 
334
        if (!addToFile(file64out, file64tmp, lpType, lpName64, wLanguage)) {
335
                DeleteFile(file32out);
336
                DeleteFile(file64out);
337
                printf("Error: Add 64 to 64\n");
338
                return 1;
339
        }
340
 
341
        // 7. Delete "TMP"
342
 
343
        DeleteFile(file32tmp);
344
        DeleteFile(file64tmp);
345
 
346
        // 8. Update timestamp
347
 
348
        if (!update_pe_timestamp(file32out, time(0))) {
349
                DeleteFile(file32out);
350
                DeleteFile(file64out);
351
                printf("Error: Update OUT timestamp 32\n");
352
                return 1;
353
        }
354
 
355
        if (!update_pe_timestamp(file64out, time(0))) {
356
                DeleteFile(file32out);
357
                DeleteFile(file64out);
358
                printf("Error: Update OUT timestamp 64\n");
359
                return 1;
360
        }
361
 
362
        // 9. Repair checksums
363
 
364
        if (!repair_pe_checksum(file32out)) {
365
                DeleteFile(file32out);
366
                DeleteFile(file64out);
367
                printf("Error: Repair OUT checksum 32\n");
368
                return 1;
369
        }
370
        if (!repair_pe_checksum(file64out)) {
371
                DeleteFile(file32out);
372
                DeleteFile(file64out);
373
                printf("Error: Repair OUT checksum 64\n");
374
                return 1;
375
        }
376
 
377
        // 10. All done!
378
 
379
        printf("All OK!\n");
380
        return 0;
381
}