Subversion Repositories filter_foundry

Rev

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

Rev Author Line No. Line
258 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
#include "ff.h"
22
 
278 daniel-mar 23
#include <time.h>
24
 
258 daniel-mar 25
#include "file_compat.h"
26
#include "compat_string.h"
357 daniel-mar 27
#include "compat_win.h"
258 daniel-mar 28
#include "versioninfo_modify_win.h"
29
#include "version.h"
30
 
31
extern HINSTANCE hDllInstance;
32
 
402 daniel-mar 33
Boolean doresources(char *dstname, int bits);
258 daniel-mar 34
 
35
void dbglasterror(char *func){
36
        char s[0x100];
37
 
38
        strcpy(s,func);
39
        strcat(s," failed: ");
40
        FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,s+strlen(s),0x100,NULL );
41
        dbg(s);
42
}
43
 
44
/*
45
BOOL CALLBACK enumfunc(HMODULE hModule,LPCTSTR lpszType,LPCTSTR lpszName,WORD wIDLanguage,LONG lParam){
46
        char s[0x100];
47
        sprintf(s,"EnumResourceLanguages callback: module=%#x type=%s name=%s lang=%d",
48
                hModule,lpszType,lpszName,wIDLanguage);
49
        dbg(s);
50
        return TRUE;
51
}
52
*/
53
 
324 daniel-mar 54
int domanifest(char *newmanifest, char *manifestp, PARM_T* pparm, int bits) {
258 daniel-mar 55
        char name[1024];
56
        char description[1024];
57
        size_t i;
276 daniel-mar 58
        size_t iname = 0;
258 daniel-mar 59
        int idescription = 0;
60
 
61
        // Description
393 daniel-mar 62
        for (i = 0; i < strlen(pparm->szCategory); i++) {
63
                char c = pparm->szCategory[i];
258 daniel-mar 64
                if ((c != '<') && (c != '>')) {
65
                        description[idescription++] = c;
66
                }
67
        }
68
        description[idescription++] = ' ';
69
        description[idescription++] = '-';
70
        description[idescription++] = ' ';
393 daniel-mar 71
        for (i = 0; i < strlen(pparm->szTitle); i++) {
72
                char c = pparm->szTitle[i];
258 daniel-mar 73
                if ((c != '<') && (c != '>')) {
74
                        description[idescription++] = c;
75
                }
76
        }
77
        description[idescription++] = '\0';
78
 
79
        // Name
80
        strcpy(name, "Telegraphics.FilterFoundry.");
81
        iname = strlen("Telegraphics.FilterFoundry.");
393 daniel-mar 82
        for (i = 0; i < strlen(pparm->szCategory); i++) {
83
                char c = pparm->szCategory[i];
352 daniel-mar 84
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
258 daniel-mar 85
                        name[iname++] = c;
86
                }
87
        }
88
        name[iname++] = '.';
393 daniel-mar 89
        for (i = 0; i < strlen(pparm->szTitle); i++) {
90
                char c = pparm->szTitle[i];
352 daniel-mar 91
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
258 daniel-mar 92
                        name[iname++] = c;
93
                }
94
        }
95
        name[iname++] = '\0';
96
 
274 daniel-mar 97
        if (bits == 64) {
98
                return sprintf(newmanifest, manifestp, (char*)name, "amd64", VERSION_STR, (char*)description);
99
        }
100
        else {
101
                return sprintf(newmanifest, manifestp, (char*)name, "x86", VERSION_STR, (char*)description);
102
        }
258 daniel-mar 103
}
104
 
416 daniel-mar 105
ULONG changeVersionInfo(char* dstname, HANDLE hUpdate, PARM_T* pparm, int bits) {
258 daniel-mar 106
        char* soleFilename;
107
        LPWSTR changeRequestStr, tmp;
416 daniel-mar 108
        ULONG dwError = NOERROR;
109
        HRSRC hResInfo;
110
        HGLOBAL hg;
111
        ULONG size;
112
        PVOID pv;
113
        BOOL fDiscard = TRUE;
258 daniel-mar 114
 
115
        if (soleFilename = strrchr(dstname, '\\')) {
116
                ++soleFilename;
117
        }
118
        else {
119
                soleFilename = dstname;
120
        }
121
 
122
        // Format of argument "PCWSTR changes" is "<name>\0<value>\0<name>\0<value>\0....."
123
        // You can CHANGE values for any given name
124
        // You can DELETE entries by setting the value to "\b" (0x08 backspace character)
125
        // You cannot (yet) ADD entries.
126
        changeRequestStr = (LPWSTR)malloc(6 * 2 * 100 + 1);
127
 
128
        tmp = changeRequestStr;
129
 
130
        tmp += mbstowcs(tmp, "Comments", 100);
131
        tmp++;
132
        tmp += mbstowcs(tmp, "Built using Filter Foundry " VERSION_STR, 100);
133
        tmp++;
134
 
135
        tmp += mbstowcs(tmp, "CompanyName", 100);
136
        tmp++;
393 daniel-mar 137
        if (strlen(pparm->szAuthor) > 0) {
138
                tmp += mbstowcs(tmp, pparm->szAuthor, 100);
258 daniel-mar 139
        }
140
        else {
141
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
142
        }
143
        tmp++;
144
 
145
        tmp += mbstowcs(tmp, "LegalCopyright", 100);
146
        tmp++;
393 daniel-mar 147
        if (strlen(pparm->szCopyright) > 0) {
148
                tmp += mbstowcs(tmp, pparm->szCopyright, 100);
258 daniel-mar 149
        }
150
        else {
151
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
152
        }
153
        tmp++;
154
 
155
        tmp += mbstowcs(tmp, "FileDescription", 100);
156
        tmp++;
393 daniel-mar 157
        if (strlen(pparm->szTitle) > 0) {
158
                tmp += mbstowcs(tmp, pparm->szTitle, 100);
258 daniel-mar 159
        }
160
        else {
161
                tmp += mbstowcs(tmp, "Untitled filter", 100);
162
        }
163
        tmp++;
164
 
165
        tmp += mbstowcs(tmp, "OriginalFilename", 100);
166
        tmp++;
167
        tmp += mbstowcs(tmp, soleFilename, 100);
168
        tmp++;
169
 
170
        tmp += mbstowcs(tmp, "License", 100);
171
        tmp++;
172
        tmp += mbstowcs(tmp, "\b", 100); // \b = remove, since filter is standalone and might have its own license
173
        tmp++;
174
 
175
        tmp += mbstowcs(tmp, "", 1);
176
 
416 daniel-mar 177
        if (hResInfo = FindResourceEx(hDllInstance, "TPLT", MAKEINTRESOURCE(3000 + bits), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)))
178
        {
179
                if (hg = LoadResource(hDllInstance, hResInfo))
180
                {
181
                        if (size = SizeofResource(hDllInstance, hResInfo))
182
                        {
183
                                if (pv = LockResource(hg))
184
                                {
185
                                        if (UpdateVersionRaw(pv, size, &pv, &size, changeRequestStr))
186
                                        {
187
                                                if (_UpdateResource(hUpdate, RT_VERSION, MAKEINTRESOURCE(1), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pv, size))
188
                                                {
189
                                                        fDiscard = FALSE;
190
                                                }
191
 
192
                                                LocalFree(pv);
193
                                        }
194
                                }
195
                        }
196
                }
258 daniel-mar 197
        }
198
 
199
        free(changeRequestStr);
416 daniel-mar 200
 
201
        return dwError;
258 daniel-mar 202
}
203
 
278 daniel-mar 204
Boolean update_pe_timestamp(const char* filename, time_t timestamp) {
280 daniel-mar 205
        size_t peoffset;
206
        FILE* fptr;
393 daniel-mar 207
 
280 daniel-mar 208
        fptr = fopen(filename, "rb+");
278 daniel-mar 209
        if (fptr == NULL) return false;
210
 
211
        fseek(fptr, 0x3C, SEEK_SET);
212
        fread(&peoffset, sizeof(peoffset), 1, fptr);
213
 
280 daniel-mar 214
        fseek(fptr, (long)peoffset + 8, SEEK_SET);
278 daniel-mar 215
        fwrite(&timestamp, sizeof(time_t), 1, fptr);
216
 
217
        fclose(fptr);
218
 
219
        return true;
220
}
221
 
347 daniel-mar 222
int binary_replace_file(const char* filename, uint64_t search, uint64_t replace, Boolean align, int maxamount) {
223
        uint64_t srecord = 0;
276 daniel-mar 224
        int found = 0;
225
 
226
        FILE* fptr = fopen(filename, "rb+");
227
        if (fptr == NULL) return -1;
228
 
229
        while ((fread(&srecord, sizeof(srecord), 1, fptr) == 1))
230
        {
231
                if (srecord == search) {
232
                        srecord = replace;
233
                        fseek(fptr, -1*(long)sizeof(srecord), SEEK_CUR);
234
                        fwrite(&srecord, (int)sizeof(srecord), 1, fptr);
235
                        fseek(fptr, 0, SEEK_CUR); // important!
236
                        found++;
347 daniel-mar 237
                        if (found == maxamount) break;
276 daniel-mar 238
                }
239
                else {
347 daniel-mar 240
                        if (!align) {
241
                                fseek(fptr, -1*(long)(sizeof(srecord) - 1), SEEK_CUR);
242
                        }
276 daniel-mar 243
                }
244
        }
245
        fclose(fptr);
246
 
247
        return found;
248
}
249
 
281 daniel-mar 250
//DOS .EXE header
251
struct image_dos_header
252
{
253
        uint16_t e_magic;                     // Magic number
254
        uint16_t e_cblp;                      // Bytes on last page of file
255
        uint16_t e_cp;                        // Pages in file
256
        uint16_t e_crlc;                      // Relocations
257
        uint16_t e_cparhdr;                   // Size of header in paragraphs
258
        uint16_t e_minalloc;                  // Minimum extra paragraphs needed
259
        uint16_t e_maxalloc;                  // Maximum extra paragraphs needed
260
        uint16_t e_ss;                        // Initial (relative) SS value
261
        uint16_t e_sp;                        // Initial SP value
262
        uint16_t e_csum;                      // Checksum
263
        uint16_t e_ip;                        // Initial IP value
264
        uint16_t e_cs;                        // Initial (relative) CS value
265
        uint16_t e_lfarlc;                    // File address of relocation table
266
        uint16_t e_ovno;                      // Overlay number
267
        uint16_t e_res[4];                    // Reserved words
268
        uint16_t e_oemid;                     // OEM identifier (for e_oeminfo)
269
        uint16_t e_oeminfo;                   // OEM information; e_oemid specific
270
        uint16_t e_res2[10];                  // Reserved words
271
        int32_t  e_lfanew;                    // File address of new exe header
272
};
273
 
274
struct image_file_header
275
{
276
        uint16_t Machine;
277
        uint16_t NumberOfSections;
278
        uint32_t TimeDateStamp;
279
        uint32_t PointerToSymbolTable;
280
        uint32_t NumberOfSymbols;
281
        uint16_t SizeOfOptionalHeader;
282
        uint16_t Characteristics;
283
};
284
 
285
uint32_t calculate_checksum(const char* filename) {
286
        //Calculate checksum of image
287
        // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
288
        // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
289
        // Converted from C++ to C by Daniel Marschall
290
 
291
        FILE* fptr;
292
        unsigned long long checksum = 0;
293
        struct image_dos_header header;
294
        size_t filesize;
295
        unsigned long long top;
296
        unsigned long pe_checksum_pos;
297
        static const unsigned long checksum_pos_in_optional_headers = 64;
298
        size_t i;
299
 
300
        fptr = fopen(filename, "rb");
301
        if (fptr == NULL) return 0x00000000;
302
 
303
        //Read DOS header
304
        fseek(fptr, 0, SEEK_SET);
305
        fread(&header, sizeof(struct image_dos_header), 1, fptr);
306
 
307
        //Calculate PE checksum
308
        fseek(fptr, 0, SEEK_SET);
309
        top = 0xFFFFFFFF;
310
        top++;
311
 
312
        //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
313
        //Calculate real PE headers "CheckSum" field position
314
        //Sum is safe here
315
        pe_checksum_pos = header.e_lfanew + sizeof(struct image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
316
 
317
        //Calculate checksum for each byte of file
318
        fseek(fptr, 0L, SEEK_END);
319
        filesize = ftell(fptr);
320
        fseek(fptr, 0L, SEEK_SET);
321
        for (i = 0; i < filesize; i += 4)
322
        {
323
                unsigned long dw = 0;
324
 
325
                //Read DWORD from file
326
                fread(&dw, sizeof(dw), 1, fptr);
327
                //Skip "CheckSum" DWORD
328
                if (i == pe_checksum_pos)
329
                        continue;
330
 
331
                //Calculate checksum
332
                checksum = (checksum & 0xffffffff) + dw + (checksum >> 32);
333
                if (checksum > top)
334
                        checksum = (checksum & 0xffffffff) + (checksum >> 32);
335
        }
336
 
337
        //Finish checksum
338
        checksum = (checksum & 0xffff) + (checksum >> 16);
339
        checksum = (checksum)+(checksum >> 16);
340
        checksum = checksum & 0xffff;
341
 
342
        checksum += (unsigned long)(filesize);
343
 
344
        fclose(fptr);
345
 
346
        //Return checksum
347
        return (uint32_t)checksum;
348
}
349
 
350
Boolean repair_pe_checksum(const char* filename) {
351
        size_t peoffset;
352
        FILE* fptr;
353
 
354
        uint32_t checksum = calculate_checksum(filename);
355
        //if (checksum == 0x00000000) return false;
356
 
357
        fptr = fopen(filename, "rb+");
358
        if (fptr == NULL) return false;
359
 
360
        fseek(fptr, 0x3C, SEEK_SET);
361
        fread(&peoffset, sizeof(peoffset), 1, fptr);
362
 
363
        fseek(fptr, (long)peoffset + 88, SEEK_SET);
364
        fwrite(&checksum, sizeof(uint32_t), 1, fptr);
365
 
366
        fclose(fptr);
367
 
368
        return true;
369
}
370
 
345 daniel-mar 371
typedef struct {
372
        char funcname[8];
373
        uint16_t codelen;
374
} operdef_t;
375
 
376
typedef struct {
377
        char funcname[8];
378
        uint16_t numparams;
379
} funcdef_t;
380
 
381
typedef struct {
382
        char funcname[8];
383
        char referencename[8];
384
} symndef_t;
385
 
402 daniel-mar 386
Boolean doresources(char *dstname, int bits){
258 daniel-mar 387
        HRSRC datarsrc,aetersrc,manifestsrc;
388
        HGLOBAL datah,aeteh,hupdate,manifesth;
345 daniel-mar 389
 
390
        operdef_t dummy_oper;
391
        funcdef_t dummy_func;
392
        symndef_t dummy_symn;
393
 
258 daniel-mar 394
        Ptr newpipl = NULL, newaete = NULL;
395
        LPVOID datap, aetep, manifestp;
324 daniel-mar 396
        char* manifestp_copy;
258 daniel-mar 397
        PARM_T *pparm = NULL;
324 daniel-mar 398
        size_t piplsize,aetesize,origsize;
393 daniel-mar 399
        char title[256];
258 daniel-mar 400
        LPCTSTR parm_type;
376 daniel-mar 401
        LPCSTR parm_id;
258 daniel-mar 402
        Boolean discard = true;
347 daniel-mar 403
        uint64_t obfuscseed = 0;
258 daniel-mar 404
        long event_id;
405
 
345 daniel-mar 406
        memset(&dummy_oper, 0, sizeof(operdef_t));
407
        memset(&dummy_func, 0, sizeof(funcdef_t));
408
        memset(&dummy_symn, 0, sizeof(symndef_t));
409
 
258 daniel-mar 410
        if( (hupdate = _BeginUpdateResource(dstname,false)) ){
411
                DBG("BeginUpdateResource OK");
402 daniel-mar 412
                if( (datarsrc = FindResource(hDllInstance,MAKEINTRESOURCE(16000 + bits), "TPLT"))
413
                        && (datah = LoadResource(hDllInstance,datarsrc))
258 daniel-mar 414
                        && (datap = (Ptr)LockResource(datah))
402 daniel-mar 415
                        && (aetersrc = FindResource(hDllInstance, MAKEINTRESOURCE(16000), "AETE"))
416
                        && (aeteh = LoadResource(hDllInstance, aetersrc))
258 daniel-mar 417
                        && (aetep = (Ptr)LockResource(aeteh))
402 daniel-mar 418
                        && (manifestsrc = FindResource(hDllInstance, MAKEINTRESOURCE(1), "TPLT"))
419
                        && (manifesth = LoadResource(hDllInstance, manifestsrc))
258 daniel-mar 420
                        && (manifestp = (Ptr)LockResource(manifesth)) )
421
                {
324 daniel-mar 422
                        char* newmanifest;
402 daniel-mar 423
                        int manifestsize = SizeofResource(hDllInstance, manifestsrc);
258 daniel-mar 424
 
324 daniel-mar 425
                        newmanifest = (char*)malloc(manifestsize + 4096/*+4KiB for name,description,etc.*/);
426
 
258 daniel-mar 427
                        DBG("loaded DATA, PiPL");
428
 
393 daniel-mar 429
                        strcpy(title,gdata->parm.szTitle);
258 daniel-mar 430
                        if(gdata->parm.popDialog)
393 daniel-mar 431
                                strcat(title,"...");
258 daniel-mar 432
 
402 daniel-mar 433
                        origsize = SizeofResource(hDllInstance,datarsrc);
258 daniel-mar 434
 
435
                        if( (newpipl = (Ptr)malloc(origsize+0x300))
436
                         && (newaete = (Ptr)malloc(4096))
437
                         && (pparm = (PARM_T*)malloc(sizeof(PARM_T))) )
438
                        {
439
                                // ====== Generate AETE and PIPL
440
 
441
                                /* add user-specified title and category to new PiPL */
442
                                memcpy(newpipl,datap,origsize);
443
                                /* note that Windows PiPLs have 2 byte version datum in front
444
                                   that isn't reflected in struct definition or Mac resource template: */
393 daniel-mar 445
                                piplsize = fixpipl((PIPropertyList*)(newpipl+2),origsize-2,&title[0], &event_id) + 2;
258 daniel-mar 446
 
447
                                /* set up the PARM resource with saved parameters */
448
                                memcpy(pparm,&gdata->parm,sizeof(PARM_T));
449
 
450
                                /* Generate 'aete' resource (contains names of the parameters for the "Actions" tab in Photoshop) */
451
                                aetesize = aete_generate(newaete, pparm, event_id);
452
 
324 daniel-mar 453
                                // ====== Create fitting manifest for the activation context
258 daniel-mar 454
 
324 daniel-mar 455
                                manifestp_copy = (char*)malloc(manifestsize + 1/*sz*/);
456
                                if (manifestp_copy != 0) {
457
                                        memcpy(manifestp_copy, manifestp, manifestsize); // copy manifestp to manifestp_copy, because manifestp is readonly
458
                                        manifestp_copy[manifestsize] = '\0'; // and add the null-terminating char, because domanifest() uses sprintf() on it
459
                                        manifestsize = domanifest(newmanifest, manifestp_copy, pparm, bits);
460
                                        free(manifestp_copy);
461
                                }
462
 
258 daniel-mar 463
                                // ====== Change version attributes
464
 
416 daniel-mar 465
                                if (changeVersionInfo(dstname, hupdate, pparm, bits) != NOERROR) {
466
                                        simplealert(_strdup("changeVersionInfo failed"));
467
                                }
258 daniel-mar 468
 
469
                                // ====== Obfuscate pparm!
470
 
292 daniel-mar 471
                                if (gdata->obfusc) {
375 daniel-mar 472
                                        parm_type = OBFUSCDATA_TYPE_NEW;
473
                                        parm_id = OBFUSCDATA_ID_NEW;
276 daniel-mar 474
 
475
                                        // Note: After we have finished updating the resources, we will write <obfuscseed> into the binary code of the 8BF file
292 daniel-mar 476
                                        obfuscseed = obfusc(pparm);
258 daniel-mar 477
                                }else{
375 daniel-mar 478
                                        parm_type = PARM_TYPE;
479
                                        parm_id = PARM_ID_NEW;
258 daniel-mar 480
                                }
481
 
482
                                // ====== Save AETE, PIPL, Manifest and PARM/RCDATA
483
 
484
                                /* Attention: The resource we have found using FindResource() might have a different
485
                                   language than the resource we are saving (Neutral), so we might end up having
486
                                   multiple languages for the same resource. Therefore, the language "Neutral" was
487
                                   set in the Scripting.rc file for the resource AETE and PIPL.rc for the resources PIPL. */
274 daniel-mar 488
 
416 daniel-mar 489
                                if(
490
                                           _UpdateResource(hupdate, RT_DIALOG, MAKEINTRESOURCE(ID_BUILDDLG), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), NULL, 0) // clean up things we don't need in the standalone plugin
308 daniel-mar 491
                                        && _UpdateResource(hupdate, RT_DIALOG, MAKEINTRESOURCE(ID_MAINDLG), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), NULL, 0) // clean up things we don't need in the standalone plugin
492
                                        && _UpdateResource(hupdate, RT_GROUP_ICON, "CAUTION_ICO", MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
393 daniel-mar 493
//                                      && _UpdateResource(hupdate, RT_ICON, MAKEINTRESOURCE(1)/*Caution*/, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
402 daniel-mar 494
                                        && _UpdateResource(hupdate, RT_GROUP_CURSOR, "HAND_QUESTION", MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
495
                                        // TODO: Removing the single resources don't work correctly. Sometimes the cursors are numbered 4,5,6 and sometimes 1,2,3 . Probably conflicts with icons
496
//                                      && _UpdateResource(hupdate, RT_CURSOR, MAKEINTRESOURCE(3)/*QuestionHand*/, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
308 daniel-mar 497
                                        && _UpdateResource(hupdate, "PIPL" /* note: caps!! */,MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),newpipl,(DWORD)piplsize)
258 daniel-mar 498
                                        && _UpdateResource(hupdate, "AETE" /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newaete, (DWORD)aetesize)
345 daniel-mar 499
                                        // OPER and FUNC are written so that "Plugin Manager 2.1" thinks that this plugin is a Filter Factory plugin! SYNM is not important, though.
500
                                        && (gdata->obfusc || _UpdateResource(hupdate, "OPER", MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_oper, sizeof(dummy_oper)))
501
                                        && (gdata->obfusc || _UpdateResource(hupdate, "FUNC", MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_func, sizeof(dummy_func)))
502
                                        && (gdata->obfusc || _UpdateResource(hupdate, "SYNM", MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_symn, sizeof(dummy_symn)))
258 daniel-mar 503
                                        && _UpdateResource(hupdate, RT_MANIFEST, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newmanifest, (DWORD)manifestsize)
376 daniel-mar 504
                                        && _UpdateResource(hupdate, parm_type,parm_id, MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),pparm,sizeof(PARM_T)) )
258 daniel-mar 505
                                {
506
                                        discard = false;
507
                                } else {
508
                                        dbglasterror(_strdup("UpdateResource"));
509
                                }
510
                        }
511
 
416 daniel-mar 512
                        // Here, the file will be saved
513
                        if (_EndUpdateResource(hupdate, discard)) {
514
                                if (gdata->obfusc) {
515
                                        // We modify the binary code to replace the deobfuscate-seed from <cObfuscSeed> to <obfuscseed>
258 daniel-mar 516
 
416 daniel-mar 517
                                        // First try with alignment "4" (this should be the usual case),
518
                                        // and if that failed, try without alignment ("1").
519
                                        // We only need to set maxamount to "1", because "const volatile" makes sure that
520
                                        // the compiler won't place (inline) it at several locations in the code.
521
                                        if ((binary_replace_file(dstname, cObfuscSeed, obfuscseed, /*align to 4*/1, /*maxamount=*/1) == 0) &&
522
                                                (binary_replace_file(dstname, cObfuscSeed, obfuscseed, /*align to 1*/0, /*maxamount=*/1) == 0))
523
                                        {
524
                                                dbg("binary_replace_file failed");
525
                                                discard = true;
526
                                        }
527
                                }
258 daniel-mar 528
 
416 daniel-mar 529
                                update_pe_timestamp(dstname, time(0));
347 daniel-mar 530
 
416 daniel-mar 531
                                repair_pe_checksum(dstname);
532
                        }else dbglasterror(_strdup("EndUpdateResource"));
276 daniel-mar 533
 
416 daniel-mar 534
                }else dbglasterror(_strdup("Find-, Load- or LockResource"));
278 daniel-mar 535
 
258 daniel-mar 536
                if(pparm) free(pparm);
537
                if(newpipl) free(newpipl);
538
                if(newaete) free(newaete);
539
        }else
540
                dbglasterror(_strdup("BeginUpdateResource"));
541
        return !discard;
542
}
543
 
278 daniel-mar 544
Boolean remove_64_filename_prefix(char* dstname) {
274 daniel-mar 545
        // foobar.8bf => foobar.8bf
546
        // foobar64.8bf => foobar.8bf
276 daniel-mar 547
        size_t i;
274 daniel-mar 548
        for (i = strlen(dstname); i > 2; i--) {
549
                if (dstname[i] == '.') {
550
                        if ((dstname[i - 2] == '6') && (dstname[i - 1] == '4')) {
276 daniel-mar 551
                                size_t tmp = strlen(dstname);
274 daniel-mar 552
                                memcpy(&dstname[i - 2], &dstname[i], strlen(dstname) - i + 1);
553
                                dstname[tmp - 2] = 0;
554
                                return true;
555
                        }
556
                }
557
        }
558
        return false;
559
}
560
 
278 daniel-mar 561
Boolean add_64_filename_prefix(char* dstname) {
274 daniel-mar 562
        // foobar.8bf => foobar64.8bf
276 daniel-mar 563
        size_t i;
274 daniel-mar 564
        for (i = strlen(dstname); i > 2; i--) {
565
                if (dstname[i] == '.') {
276 daniel-mar 566
                        size_t tmp = strlen(dstname);
274 daniel-mar 567
                        memcpy(&dstname[i + 2], &dstname[i], strlen(dstname) - i + 1);
568
                        dstname[i] = '6';
569
                        dstname[i + 1] = '4';
570
                        dstname[tmp + 2] = 0;
571
                        return true;
572
                }
573
        }
574
        return false;
575
}
576
 
577
BOOL FileExists(LPCTSTR szPath) {
578
        DWORD dwAttrib = GetFileAttributes(szPath);
579
        return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
580
                !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
581
}
582
 
314 daniel-mar 583
Boolean extract_file(LPCTSTR lpType, LPCTSTR lpName, const char* outName) {
308 daniel-mar 584
        HGLOBAL datah;
585
        LPVOID datap;
586
        HRSRC datarsrc;
587
        size_t datalen;
588
 
589
        if ((datarsrc = FindResource((HMODULE)hDllInstance, lpName, lpType))
590
                && (datah = LoadResource((HMODULE)hDllInstance, datarsrc))
591
                && (datalen = SizeofResource((HMODULE)hDllInstance, datarsrc))
592
                && (datap = (Ptr)LockResource(datah))) {
593
 
594
                FILE* fp = fopen(outName, "wb+");
595
                if (fp == NULL) return false;
596
                if (fwrite(datap, 1, datalen, fp) != datalen) return false;
597
                if (fclose(fp)) return false;
598
 
599
                return true;
600
        }
601
        else {
602
                return false;
603
        }
604
}
605
 
357 daniel-mar 606
BOOL StripAuthenticode(const char* pszFileName) {
607
        HANDLE hFile = CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
364 daniel-mar 608
        if (hFile == INVALID_HANDLE_VALUE) {
609
                CloseHandle(hFile);
610
                return FALSE;
611
        }
612
        if (!_ImageRemoveCertificate(hFile, 0)) {
613
                CloseHandle(hFile);
614
                return FALSE;
615
        }
357 daniel-mar 616
        CloseHandle(hFile);
617
        return TRUE;
618
}
619
 
308 daniel-mar 620
OSErr do_make_standalone(char* dstname, int bits) {
274 daniel-mar 621
        Boolean res;
292 daniel-mar 622
        char err[MAX_PATH + 200];
623
 
274 daniel-mar 624
        //DeleteFile(dstname);
314 daniel-mar 625
        if (extract_file("TPLT", MAKEINTRESOURCE(1000 + bits), dstname)) {
360 daniel-mar 626
                // In case we did digitally sign the FilterFoundry plugin (which is currently not the case though),
627
                // we must now remove the signature, because the embedding of parameter data has invalidated it.
628
                // Do it before we manipulate anything, in order to avoid that there is an invalid binary (which might annoy AntiVirus software)
629
                StripAuthenticode(dstname);
630
 
631
                // Now do the resources
402 daniel-mar 632
                res = doresources(dstname, bits);
319 daniel-mar 633
                if (!res) {
292 daniel-mar 634
                        DeleteFile(dstname);
319 daniel-mar 635
                        sprintf(err, "Could not create %d bit standalone plugin (doresources failed).", bits);
292 daniel-mar 636
                        alertuser(_strdup(&err[0]), _strdup(""));
274 daniel-mar 637
                }
638
        }
639
        else {
308 daniel-mar 640
                // If you see this error, please make sure that you have called foundry_3264_mixer to include the 32/64 plugins as resource!
274 daniel-mar 641
                res = false;
292 daniel-mar 642
                //DeleteFile(dstname);
308 daniel-mar 643
                sprintf(err, "Could not create %d bit standalone plugin (File extraction failed).", bits);
274 daniel-mar 644
                alertuser(_strdup(&err[0]), _strdup(""));
645
        }
646
 
647
        return res ? noErr : ioErr;
648
}
649
 
314 daniel-mar 650
OSErr make_standalone(StandardFileReply *sfr){
651
        OSErr tmpErr, outErr;
652
        char dstname[MAX_PATH+1];
653
 
274 daniel-mar 654
        outErr = noErr;
314 daniel-mar 655
 
308 daniel-mar 656
        // Make 32 bit:
657
        // Destfile = no64_or_32(chosenname)
274 daniel-mar 658
        myp2cstrcpy(dstname, sfr->sfFile.name);
659
        remove_64_filename_prefix(dstname);
308 daniel-mar 660
        tmpErr = do_make_standalone(&dstname[0], 32);
274 daniel-mar 661
        if (tmpErr != noErr)
662
                outErr = tmpErr;
663
        else
308 daniel-mar 664
                showmessage(_strdup("32 bit standalone filter was successfully created"));
274 daniel-mar 665
 
402 daniel-mar 666
        // Make 64 bit:
667
        // Destfile = no64_or_32(chosenname) + 64
668
        myp2cstrcpy(dstname, sfr->sfFile.name);
669
        remove_64_filename_prefix(dstname);
670
        add_64_filename_prefix(dstname);
671
        tmpErr = do_make_standalone(&dstname[0], 64);
672
        if (tmpErr != noErr)
673
                outErr = tmpErr;
674
        else
675
                showmessage(_strdup("64 bit standalone filter was successfully created"));
274 daniel-mar 676
 
677
        return outErr;
258 daniel-mar 678
}
308 daniel-mar 679