Subversion Repositories filter_foundry

Rev

Rev 352 | Rev 360 | 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
 
274 daniel-mar 33
Boolean doresources(HMODULE srcmod,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
62
        for (i = 0; i < strlen((char*)pparm->category); i++) {
63
                char c = pparm->category[i];
64
                if ((c != '<') && (c != '>')) {
65
                        description[idescription++] = c;
66
                }
67
        }
68
        description[idescription++] = ' ';
69
        description[idescription++] = '-';
70
        description[idescription++] = ' ';
71
        for (i = 0; i < strlen((char*)pparm->title); i++) {
72
                char c = pparm->title[i];
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.");
82
        for (i = 0; i < strlen((char*)pparm->category); i++) {
83
                char c = pparm->category[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++] = '.';
89
        for (i = 0; i < strlen((char*)pparm->title); i++) {
90
                char c = pparm->title[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++;
131
        if (strlen((char*)pparm->author) > 0) {
132
                tmp += mbstowcs(tmp, (char*)pparm->author, 100);
133
        }
134
        else {
135
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
136
        }
137
        tmp++;
138
 
139
        tmp += mbstowcs(tmp, "LegalCopyright", 100);
140
        tmp++;
141
        if (strlen((char*)pparm->copyright) > 0) {
142
                tmp += mbstowcs(tmp, (char*)pparm->copyright, 100);
143
        }
144
        else {
145
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
146
        }
147
        tmp++;
148
 
149
        tmp += mbstowcs(tmp, "FileDescription", 100);
150
        tmp++;
151
        if (strlen((char*)pparm->title) > 0) {
152
                tmp += mbstowcs(tmp, (char*)pparm->title, 100);
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;
181
 
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
 
274 daniel-mar 360
Boolean doresources(HMODULE srcmod,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;
258 daniel-mar 373
        Str255 title;
374
        LPCTSTR parm_type;
375
        int i,parm_id;
376
        Boolean discard = true;
347 daniel-mar 377
        uint64_t obfuscseed = 0;
258 daniel-mar 378
        long event_id;
319 daniel-mar 379
        Boolean mustFreeSrcMod;
258 daniel-mar 380
 
345 daniel-mar 381
        memset(&dummy_oper, 0, sizeof(operdef_t));
382
        memset(&dummy_func, 0, sizeof(funcdef_t));
383
        memset(&dummy_symn, 0, sizeof(symndef_t));
384
 
319 daniel-mar 385
        if (srcmod == NULL) {
386
                srcmod = LoadLibraryEx(dstname, NULL, LOAD_LIBRARY_AS_DATAFILE);
387
                if (!srcmod) {
388
                        dbglasterror(_strdup("LoadLibraryEx"));
389
                        return false;
390
                }
391
                mustFreeSrcMod = true;
392
        }
393
        else {
394
                mustFreeSrcMod = false;
395
        }
396
 
258 daniel-mar 397
        if( (hupdate = _BeginUpdateResource(dstname,false)) ){
398
                DBG("BeginUpdateResource OK");
308 daniel-mar 399
                if( (datarsrc = FindResource(srcmod,MAKEINTRESOURCE(16000), "TPLT"))
258 daniel-mar 400
                        && (datah = LoadResource(srcmod,datarsrc))
401
                        && (datap = (Ptr)LockResource(datah))
402
                        && (aetersrc = FindResource(srcmod, MAKEINTRESOURCE(16000), "AETE"))
403
                        && (aeteh = LoadResource(srcmod, aetersrc))
404
                        && (aetep = (Ptr)LockResource(aeteh))
405
                        && (manifestsrc = FindResource(srcmod, MAKEINTRESOURCE(50), "TPLT"))
406
                        && (manifesth = LoadResource(srcmod, manifestsrc))
407
                        && (manifestp = (Ptr)LockResource(manifesth)) )
408
                {
324 daniel-mar 409
                        char* newmanifest;
410
                        int manifestsize = SizeofResource(srcmod, manifestsrc);
258 daniel-mar 411
 
324 daniel-mar 412
                        newmanifest = (char*)malloc(manifestsize + 4096/*+4KiB for name,description,etc.*/);
413
 
258 daniel-mar 414
                        DBG("loaded DATA, PiPL");
415
 
416
                        PLstrcpy(title,gdata->parm.title);
417
                        if(gdata->parm.popDialog)
418
                                PLstrcat(title,(StringPtr)"\003...");
419
 
420
                        origsize = SizeofResource(srcmod,datarsrc);
421
 
422
                        if( (newpipl = (Ptr)malloc(origsize+0x300))
423
                         && (newaete = (Ptr)malloc(4096))
424
                         && (pparm = (PARM_T*)malloc(sizeof(PARM_T))) )
425
                        {
426
                                // ====== Generate AETE and PIPL
427
 
428
                                /* add user-specified title and category to new PiPL */
429
                                memcpy(newpipl,datap,origsize);
430
                                /* note that Windows PiPLs have 2 byte version datum in front
431
                                   that isn't reflected in struct definition or Mac resource template: */
432
                                piplsize = fixpipl((PIPropertyList*)(newpipl+2),origsize-2,title, &event_id) + 2;
433
 
434
                                /* set up the PARM resource with saved parameters */
435
                                memcpy(pparm,&gdata->parm,sizeof(PARM_T));
436
 
437
                                /* Generate 'aete' resource (contains names of the parameters for the "Actions" tab in Photoshop) */
438
                                aetesize = aete_generate(newaete, pparm, event_id);
439
 
440
                                // ====== Change Pascal strings to C-Strings
441
 
442
                                /* convert to C strings for Windows PARM resource */
443
                                // Don't do it before aete_generate, because they need Pascal strings
444
                                myp2cstr(pparm->category);
445
                                myp2cstr(pparm->title);
446
                                myp2cstr(pparm->copyright);
447
                                myp2cstr(pparm->author);
448
                                for (i = 0; i < 4; ++i)
449
                                        myp2cstr(pparm->map[i]);
450
                                for (i = 0; i < 8; ++i)
451
                                        myp2cstr(pparm->ctl[i]);
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
 
465
                                changeVersionInfo(dstname, pparm, hupdate);
466
 
467
                                // ====== Obfuscate pparm!
468
 
292 daniel-mar 469
                                if (gdata->obfusc) {
258 daniel-mar 470
                                        parm_type = RT_RCDATA;
471
                                        parm_id = OBFUSCDATA_ID;
276 daniel-mar 472
 
473
                                        // Note: After we have finished updating the resources, we will write <obfuscseed> into the binary code of the 8BF file
292 daniel-mar 474
                                        obfuscseed = obfusc(pparm);
258 daniel-mar 475
                                }else{
476
                                        parm_type = "PARM";
477
                                        parm_id = PARM_ID;
478
                                }
479
 
480
                                // ====== Save AETE, PIPL, Manifest and PARM/RCDATA
481
 
482
                                /* Attention: The resource we have found using FindResource() might have a different
483
                                   language than the resource we are saving (Neutral), so we might end up having
484
                                   multiple languages for the same resource. Therefore, the language "Neutral" was
485
                                   set in the Scripting.rc file for the resource AETE and PIPL.rc for the resources PIPL. */
274 daniel-mar 486
 
308 daniel-mar 487
                                if(_UpdateResource(hupdate, "TPLT" /* note: caps!! */, MAKEINTRESOURCE(50), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0)  // clean up things we don't need in the standalone plugin
488
                                        && _UpdateResource(hupdate, "TPLT" /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
489
                                        && _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
490
                                        && _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
491
                                        && _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
492
                                        && _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
493
                                        && _UpdateResource(hupdate, RT_GROUP_CURSOR, MAKEINTRESOURCE(IDC_FF_HAND_QUESTION), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
494
                                        && _UpdateResource(hupdate, RT_CURSOR, MAKEINTRESOURCE(6)/*QuestionHand*/, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
331 daniel-mar 495
                                        && ((bits != 32) || _UpdateResource(hupdate, "DLL", "UNICOWS", MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0)) // clean up things we don't need in the standalone plugin
308 daniel-mar 496
                                        && _UpdateResource(hupdate, "PIPL" /* note: caps!! */,MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),newpipl,(DWORD)piplsize)
258 daniel-mar 497
                                        && _UpdateResource(hupdate, "AETE" /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newaete, (DWORD)aetesize)
345 daniel-mar 498
                                        // 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.
499
                                        && (gdata->obfusc || _UpdateResource(hupdate, "OPER", MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_oper, sizeof(dummy_oper)))
500
                                        && (gdata->obfusc || _UpdateResource(hupdate, "FUNC", MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_func, sizeof(dummy_func)))
501
                                        && (gdata->obfusc || _UpdateResource(hupdate, "SYNM", MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_symn, sizeof(dummy_symn)))
258 daniel-mar 502
                                        && _UpdateResource(hupdate, RT_MANIFEST, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newmanifest, (DWORD)manifestsize)
308 daniel-mar 503
                                        && _UpdateResource(hupdate, parm_type,MAKEINTRESOURCE(parm_id), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),pparm,sizeof(PARM_T)) )
258 daniel-mar 504
                                {
505
                                        discard = false;
506
                                } else {
507
                                        dbglasterror(_strdup("UpdateResource"));
508
                                }
509
                        }
510
 
511
                }else dbglasterror(_strdup("Find-, Load- or LockResource"));
512
 
276 daniel-mar 513
                // Here, the file will be saved
319 daniel-mar 514
                if (mustFreeSrcMod) {
515
                        FreeLibrary(srcmod);
516
                }
517
                if (!_EndUpdateResource(hupdate, discard)) {
258 daniel-mar 518
                        dbglasterror(_strdup("EndUpdateResource"));
319 daniel-mar 519
                }
520
                else {
258 daniel-mar 521
 
319 daniel-mar 522
                        if (gdata->obfusc) {
347 daniel-mar 523
                                // We modify the binary code to replace the deobfuscate-seed from <cObfuscSeed> to <obfuscseed>
524
 
525
                                // First try with alignment "4" (this should be the usual case),
526
                                // and if that failed, try without alignment ("1").
527
                                // We only need to set maxamount to "1", because "const volatile" makes sure that
528
                                // the compiler won't place (inline) it at several locations in the code.
529
                                if ((binary_replace_file(dstname, cObfuscSeed, obfuscseed, /*align to 4*/1, /*maxamount=*/1) == 0) &&
530
                                        (binary_replace_file(dstname, cObfuscSeed, obfuscseed, /*align to 1*/0, /*maxamount=*/1) == 0))
531
                                {
319 daniel-mar 532
                                        dbg("binary_replace_file failed");
533
                                        discard = true;
534
                                }
276 daniel-mar 535
                        }
536
 
319 daniel-mar 537
                        update_pe_timestamp(dstname, time(0));
278 daniel-mar 538
 
319 daniel-mar 539
                        repair_pe_checksum(dstname);
540
                }
541
 
258 daniel-mar 542
                if(pparm) free(pparm);
543
                if(newpipl) free(newpipl);
544
                if(newaete) free(newaete);
545
        }else
546
                dbglasterror(_strdup("BeginUpdateResource"));
547
        return !discard;
548
}
549
 
278 daniel-mar 550
Boolean remove_64_filename_prefix(char* dstname) {
274 daniel-mar 551
        // foobar.8bf => foobar.8bf
552
        // foobar64.8bf => foobar.8bf
276 daniel-mar 553
        size_t i;
274 daniel-mar 554
        for (i = strlen(dstname); i > 2; i--) {
555
                if (dstname[i] == '.') {
556
                        if ((dstname[i - 2] == '6') && (dstname[i - 1] == '4')) {
276 daniel-mar 557
                                size_t tmp = strlen(dstname);
274 daniel-mar 558
                                memcpy(&dstname[i - 2], &dstname[i], strlen(dstname) - i + 1);
559
                                dstname[tmp - 2] = 0;
560
                                return true;
561
                        }
562
                }
563
        }
564
        return false;
565
}
566
 
278 daniel-mar 567
Boolean add_64_filename_prefix(char* dstname) {
274 daniel-mar 568
        // foobar.8bf => foobar64.8bf
276 daniel-mar 569
        size_t i;
274 daniel-mar 570
        for (i = strlen(dstname); i > 2; i--) {
571
                if (dstname[i] == '.') {
276 daniel-mar 572
                        size_t tmp = strlen(dstname);
274 daniel-mar 573
                        memcpy(&dstname[i + 2], &dstname[i], strlen(dstname) - i + 1);
574
                        dstname[i] = '6';
575
                        dstname[i + 1] = '4';
576
                        dstname[tmp + 2] = 0;
577
                        return true;
578
                }
579
        }
580
        return false;
581
}
582
 
583
BOOL FileExists(LPCTSTR szPath) {
584
        DWORD dwAttrib = GetFileAttributes(szPath);
585
        return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
586
                !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
587
}
588
 
314 daniel-mar 589
Boolean extract_file(LPCTSTR lpType, LPCTSTR lpName, const char* outName) {
308 daniel-mar 590
        HGLOBAL datah;
591
        LPVOID datap;
592
        HRSRC datarsrc;
593
        size_t datalen;
594
 
595
        if ((datarsrc = FindResource((HMODULE)hDllInstance, lpName, lpType))
596
                && (datah = LoadResource((HMODULE)hDllInstance, datarsrc))
597
                && (datalen = SizeofResource((HMODULE)hDllInstance, datarsrc))
598
                && (datap = (Ptr)LockResource(datah))) {
599
 
600
                FILE* fp = fopen(outName, "wb+");
601
                if (fp == NULL) return false;
602
                if (fwrite(datap, 1, datalen, fp) != datalen) return false;
603
                if (fclose(fp)) return false;
604
 
605
                return true;
606
        }
607
        else {
608
                return false;
609
        }
610
}
611
 
357 daniel-mar 612
BOOL StripAuthenticode(const char* pszFileName) {
613
        HANDLE hFile = CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
614
        if (hFile == INVALID_HANDLE_VALUE) return FALSE;
615
        if (!_ImageRemoveCertificate(hFile, 0)) return FALSE;
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)) {
319 daniel-mar 626
                res = doresources(NULL, dstname, bits);
627
                if (!res) {
292 daniel-mar 628
                        DeleteFile(dstname);
319 daniel-mar 629
                        sprintf(err, "Could not create %d bit standalone plugin (doresources failed).", bits);
292 daniel-mar 630
                        alertuser(_strdup(&err[0]), _strdup(""));
274 daniel-mar 631
                }
357 daniel-mar 632
 
633
                // In case we did digitally sign the FilterFoundry plugin (which is currently not the case though),
634
                // we must now remove the signature, because the embedding of parameter data has invalidated it.
635
                StripAuthenticode(dstname);
274 daniel-mar 636
        }
637
        else {
308 daniel-mar 638
                // 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 639
                res = false;
292 daniel-mar 640
                //DeleteFile(dstname);
308 daniel-mar 641
                sprintf(err, "Could not create %d bit standalone plugin (File extraction failed).", bits);
274 daniel-mar 642
                alertuser(_strdup(&err[0]), _strdup(""));
643
        }
644
 
645
        return res ? noErr : ioErr;
646
}
647
 
314 daniel-mar 648
Boolean check_unicows() {
649
        // Unicows.dll is required for Win9x to implement the BeginUpdateResource functionalities
650
 
651
        if (isWin32NT()) {
652
                // Modern Windows don't require UnicoWS
653
                return true;
654
        } else {
258 daniel-mar 655
                HMODULE hLib;
656
 
657
                hLib = LoadLibraryA("UNICOWS.DLL");
658
                if (!hLib) {
318 daniel-mar 659
                        char dstname[MAX_PATH + 1];
258 daniel-mar 660
 
314 daniel-mar 661
                        // Try to install UnicoWS automatically
318 daniel-mar 662
                        GetSystemDirectoryA(&dstname[0], MAX_PATH);
663
                        strcat(&dstname[0], "\\UNICOWS.DLL");
664
                        extract_file("DLL", "UNICOWS", &dstname[0]); // included in make_win.rc
279 daniel-mar 665
 
314 daniel-mar 666
                        hLib = LoadLibraryA("UNICOWS.DLL");
667
                        if (!hLib) {
668
                                // This should not happen
316 daniel-mar 669
                                simplealert(_strdup("To build standalone plugins using this version of\nWindows, you need to install UNICOWS.DLL\n\nPlease download it from the Internet\nand place it into your system directory"));
258 daniel-mar 670
 
314 daniel-mar 671
                                return false;
672
                        }
673
                        else {
674
                                FreeLibrary(hLib);
675
                                return true;
676
                        }
258 daniel-mar 677
                }
678
                else {
679
                        FreeLibrary(hLib);
314 daniel-mar 680
                        return true;
258 daniel-mar 681
                }
682
        }
314 daniel-mar 683
}
258 daniel-mar 684
 
314 daniel-mar 685
OSErr make_standalone(StandardFileReply *sfr){
686
        OSErr tmpErr, outErr;
687
        char dstname[MAX_PATH+1];
688
 
274 daniel-mar 689
        outErr = noErr;
314 daniel-mar 690
 
691
        check_unicows();
308 daniel-mar 692
 
693
        // Make 32 bit:
694
        // Destfile = no64_or_32(chosenname)
274 daniel-mar 695
        myp2cstrcpy(dstname, sfr->sfFile.name);
696
        remove_64_filename_prefix(dstname);
308 daniel-mar 697
        tmpErr = do_make_standalone(&dstname[0], 32);
274 daniel-mar 698
        if (tmpErr != noErr)
699
                outErr = tmpErr;
700
        else
308 daniel-mar 701
                showmessage(_strdup("32 bit standalone filter was successfully created"));
274 daniel-mar 702
 
308 daniel-mar 703
        if (isWin32NT()) {
704
                // Make 64 bit:
705
                // Destfile = no64_or_32(chosenname) + 64
274 daniel-mar 706
                myp2cstrcpy(dstname, sfr->sfFile.name);
707
                remove_64_filename_prefix(dstname);
308 daniel-mar 708
                add_64_filename_prefix(dstname);
709
                tmpErr = do_make_standalone(&dstname[0], 64);
274 daniel-mar 710
                if (tmpErr != noErr)
711
                        outErr = tmpErr;
712
                else
308 daniel-mar 713
                        showmessage(_strdup("64 bit standalone filter was successfully created"));
277 daniel-mar 714
        }
279 daniel-mar 715
        else {
331 daniel-mar 716
                // Unicows.dll cannot edit resources of 64 bit DLLs. (Tested with UnicoWS 1.1.3790.0)
346 daniel-mar 717
                // On WinNT+, the normal Kernel function BeginUpdateResource can edit 64 bit DLLs, even in NT4.0 SP6
320 daniel-mar 718
                simplewarning(_strdup("Note: A 64 bit standalone filter cannot be created with your Windows version"));
279 daniel-mar 719
        }
274 daniel-mar 720
 
721
        return outErr;
258 daniel-mar 722
}
308 daniel-mar 723