Subversion Repositories filter_foundry

Rev

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