Subversion Repositories filter_foundry

Rev

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