Subversion Repositories filter_foundry

Rev

Rev 281 | Rev 294 | 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
 
274 daniel-mar 53
int domanifest(char *newmanifest, const 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) {
171
                alertuser(_strdup("UpdateVersionInfoWithHandle failed"), _strdup(""));
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
 
274 daniel-mar 341
Boolean doresources(HMODULE srcmod,char *dstname, int bits){
258 daniel-mar 342
        HRSRC datarsrc,aetersrc,manifestsrc;
343
        HGLOBAL datah,aeteh,hupdate,manifesth;
344
        Ptr newpipl = NULL, newaete = NULL;
345
        LPVOID datap, aetep, manifestp;
346
        PARM_T *pparm = NULL;
347
        size_t piplsize,aetesize,origsize,manifestsize;
348
        Str255 title;
349
        LPCTSTR parm_type;
350
        int i,parm_id;
351
        Boolean discard = true;
276 daniel-mar 352
        unsigned int obfuscseed = 0;
258 daniel-mar 353
        long event_id;
354
 
355
        if( (hupdate = _BeginUpdateResource(dstname,false)) ){
356
                DBG("BeginUpdateResource OK");
357
                if( (datarsrc = FindResource(srcmod,MAKEINTRESOURCE(16000),"TPLT"))
358
                        && (datah = LoadResource(srcmod,datarsrc))
359
                        && (datap = (Ptr)LockResource(datah))
360
                        && (aetersrc = FindResource(srcmod, MAKEINTRESOURCE(16000), "AETE"))
361
                        && (aeteh = LoadResource(srcmod, aetersrc))
362
                        && (aetep = (Ptr)LockResource(aeteh))
363
                        && (manifestsrc = FindResource(srcmod, MAKEINTRESOURCE(50), "TPLT"))
364
                        && (manifesth = LoadResource(srcmod, manifestsrc))
365
                        && (manifestp = (Ptr)LockResource(manifesth)) )
366
                {
367
                        char newmanifest[5000];
368
 
369
                        DBG("loaded DATA, PiPL");
370
 
371
                        PLstrcpy(title,gdata->parm.title);
372
                        if(gdata->parm.popDialog)
373
                                PLstrcat(title,(StringPtr)"\003...");
374
 
375
                        origsize = SizeofResource(srcmod,datarsrc);
376
 
377
                        if( (newpipl = (Ptr)malloc(origsize+0x300))
378
                         && (newaete = (Ptr)malloc(4096))
379
                         && (pparm = (PARM_T*)malloc(sizeof(PARM_T))) )
380
                        {
381
                                // ====== Generate AETE and PIPL
382
 
383
                                /* add user-specified title and category to new PiPL */
384
                                memcpy(newpipl,datap,origsize);
385
                                /* note that Windows PiPLs have 2 byte version datum in front
386
                                   that isn't reflected in struct definition or Mac resource template: */
387
                                piplsize = fixpipl((PIPropertyList*)(newpipl+2),origsize-2,title, &event_id) + 2;
388
 
389
                                /* set up the PARM resource with saved parameters */
390
                                memcpy(pparm,&gdata->parm,sizeof(PARM_T));
391
 
392
                                /* Generate 'aete' resource (contains names of the parameters for the "Actions" tab in Photoshop) */
393
                                aetesize = aete_generate(newaete, pparm, event_id);
394
 
395
                                // ====== Change Pascal strings to C-Strings
396
 
397
                                /* convert to C strings for Windows PARM resource */
398
                                // Don't do it before aete_generate, because they need Pascal strings
399
                                myp2cstr(pparm->category);
400
                                myp2cstr(pparm->title);
401
                                myp2cstr(pparm->copyright);
402
                                myp2cstr(pparm->author);
403
                                for (i = 0; i < 4; ++i)
404
                                        myp2cstr(pparm->map[i]);
405
                                for (i = 0; i < 8; ++i)
406
                                        myp2cstr(pparm->ctl[i]);
407
 
274 daniel-mar 408
                                manifestsize = domanifest(newmanifest, (const char*)manifestp, pparm, bits);
258 daniel-mar 409
 
410
                                // ====== Change version attributes
411
 
412
                                changeVersionInfo(dstname, pparm, hupdate);
413
 
414
                                // ====== Obfuscate pparm!
415
 
292 daniel-mar 416
                                if (gdata->obfusc) {
258 daniel-mar 417
                                        parm_type = RT_RCDATA;
418
                                        parm_id = OBFUSCDATA_ID;
276 daniel-mar 419
 
420
                                        // Note: After we have finished updating the resources, we will write <obfuscseed> into the binary code of the 8BF file
292 daniel-mar 421
                                        obfuscseed = obfusc(pparm);
258 daniel-mar 422
                                }else{
423
                                        parm_type = "PARM";
424
                                        parm_id = PARM_ID;
425
                                }
426
 
427
                                // ====== Save AETE, PIPL, Manifest and PARM/RCDATA
428
 
429
                                /* Attention: The resource we have found using FindResource() might have a different
430
                                   language than the resource we are saving (Neutral), so we might end up having
431
                                   multiple languages for the same resource. Therefore, the language "Neutral" was
432
                                   set in the Scripting.rc file for the resource AETE and PIPL.rc for the resources PIPL. */
274 daniel-mar 433
 
434
                                if(_UpdateResource(hupdate, "TPLT" /* note: caps!! */, MAKEINTRESOURCE(50), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0)
435
                                        && _UpdateResource(hupdate, "TPLT" /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0)
436
                                        && _UpdateResource(hupdate, RT_DIALOG, MAKEINTRESOURCE(ID_BUILDDLG), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), NULL, 0)
437
                                        && _UpdateResource(hupdate,"PIPL" /* note: caps!! */,MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),newpipl,(DWORD)piplsize)
258 daniel-mar 438
                                        && _UpdateResource(hupdate, "AETE" /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newaete, (DWORD)aetesize)
439
                                        && _UpdateResource(hupdate, RT_MANIFEST, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newmanifest, (DWORD)manifestsize)
440
                                        && _UpdateResource(hupdate,parm_type,MAKEINTRESOURCE(parm_id), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),pparm,sizeof(PARM_T)) )
441
                                {
442
                                        discard = false;
443
                                } else {
444
                                        dbglasterror(_strdup("UpdateResource"));
445
                                }
446
                        }
447
 
448
                }else dbglasterror(_strdup("Find-, Load- or LockResource"));
449
 
276 daniel-mar 450
                // Here, the file will be saved
258 daniel-mar 451
                if(!_EndUpdateResource(hupdate,discard))
452
                        dbglasterror(_strdup("EndUpdateResource"));
453
 
276 daniel-mar 454
                if (gdata->obfusc) {
277 daniel-mar 455
                        // We modify the binary code to replace the deobfuscate-seed from <cObfuscV4Seed> to <obfuscseed>
278 daniel-mar 456
                        if (binary_replace_file(dstname, cObfuscV4Seed, obfuscseed) != 1) {
457
                                // The seed must only be exactly 1 time inside the 8BF file,
458
                                // since "const volatile" makes sure that the compiler won't place
459
                                // it at several locations in the code.
276 daniel-mar 460
                                dbg("binary_replace_file failed");
461
                                discard = true;
462
                        }
463
                }
464
 
278 daniel-mar 465
                update_pe_timestamp(dstname, time(0));
466
 
281 daniel-mar 467
                repair_pe_checksum(dstname);
468
 
258 daniel-mar 469
                if(pparm) free(pparm);
470
                if(newpipl) free(newpipl);
471
                if(newaete) free(newaete);
472
        }else
473
                dbglasterror(_strdup("BeginUpdateResource"));
474
        return !discard;
475
}
476
 
278 daniel-mar 477
Boolean remove_64_filename_prefix(char* dstname) {
274 daniel-mar 478
        // foobar.8bf => foobar.8bf
479
        // foobar64.8bf => foobar.8bf
276 daniel-mar 480
        size_t i;
274 daniel-mar 481
        for (i = strlen(dstname); i > 2; i--) {
482
                if (dstname[i] == '.') {
483
                        if ((dstname[i - 2] == '6') && (dstname[i - 1] == '4')) {
276 daniel-mar 484
                                size_t tmp = strlen(dstname);
274 daniel-mar 485
                                memcpy(&dstname[i - 2], &dstname[i], strlen(dstname) - i + 1);
486
                                dstname[tmp - 2] = 0;
487
                                return true;
488
                        }
489
                }
490
        }
491
        return false;
492
}
493
 
278 daniel-mar 494
Boolean add_64_filename_prefix(char* dstname) {
274 daniel-mar 495
        // foobar.8bf => foobar64.8bf
276 daniel-mar 496
        size_t i;
274 daniel-mar 497
        for (i = strlen(dstname); i > 2; i--) {
498
                if (dstname[i] == '.') {
276 daniel-mar 499
                        size_t tmp = strlen(dstname);
274 daniel-mar 500
                        memcpy(&dstname[i + 2], &dstname[i], strlen(dstname) - i + 1);
501
                        dstname[i] = '6';
502
                        dstname[i + 1] = '4';
503
                        dstname[tmp + 2] = 0;
504
                        return true;
505
                }
506
        }
507
        return false;
508
}
509
 
510
BOOL FileExists(LPCTSTR szPath) {
511
        DWORD dwAttrib = GetFileAttributes(szPath);
512
        return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
513
                !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
514
}
515
 
516
OSErr do_make_standalone(char* srcname, char* dstname, int bits) {
517
        Boolean res;
292 daniel-mar 518
        char err[MAX_PATH + 200];
519
 
274 daniel-mar 520
        //DeleteFile(dstname);
521
        if (CopyFile(srcname, dstname, false)) {
522
                HMODULE hSrcmod;
523
                hSrcmod = LoadLibraryEx(srcname, NULL, LOAD_LIBRARY_AS_DATAFILE);
524
                if (hSrcmod) {
525
                        res = doresources(hSrcmod, dstname, bits);
526
                        if (!res) {
527
                                DeleteFile(dstname);
292 daniel-mar 528
                                sprintf(err, "Could not create %d bit standalone plugin (doresources failed).", bits);
529
                                alertuser(_strdup(&err[0]), _strdup(""));
274 daniel-mar 530
                        }
531
                        FreeLibrary(hSrcmod);
532
                }
533
                else {
292 daniel-mar 534
                        DWORD dwErr = GetLastError();
274 daniel-mar 535
                        res = false;
292 daniel-mar 536
                        DeleteFile(dstname);
537
                        // TODO: Also translate Win32 error to use readable text ( https://docs.microsoft.com/en-us/windows/win32/debug/retrieving-the-last-error-code )
538
                        sprintf(err, "Could not create %d bit standalone plugin (LoadLibraryEx failed, Win32 error %d).", bits, dwErr);
539
                        alertuser(_strdup(&err[0]), _strdup(""));
274 daniel-mar 540
                }
541
        }
542
        else {
292 daniel-mar 543
                DWORD dwErr = GetLastError();
274 daniel-mar 544
                res = false;
292 daniel-mar 545
                //DeleteFile(dstname);
546
                // TODO: Also translate Win32 error to use readable text ( https://docs.microsoft.com/en-us/windows/win32/debug/retrieving-the-last-error-code )
547
                sprintf(err, "Could not create %d bit standalone plugin (CopyFile failed, Win32 error %d).", bits, dwErr);
274 daniel-mar 548
                alertuser(_strdup(&err[0]), _strdup(""));
549
        }
550
 
551
        return res ? noErr : ioErr;
552
}
553
 
258 daniel-mar 554
OSErr make_standalone(StandardFileReply *sfr){
274 daniel-mar 555
        OSErr tmpErr, outErr;
258 daniel-mar 556
        char dstname[0x100],srcname[MAX_PATH+1];
557
 
558
        if (!isWin32NT()) {
559
                HMODULE hLib;
560
 
561
                hLib = LoadLibraryA("UNICOWS.DLL");
562
                if (!hLib) {
563
                        char* sysdir;
564
 
279 daniel-mar 565
                        // Unicows.dll is required to implement the BeginUpdateResource functionalities in Win9x
566
 
258 daniel-mar 567
                        sysdir = (char*)malloc(MAX_PATH);
568
                        GetSystemDirectoryA(sysdir, MAX_PATH);
569
                        alertuser(_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 following directory:"), sysdir);
570
                        free(sysdir);
571
 
572
                        return false;
573
                }
574
                else {
575
                        FreeLibrary(hLib);
576
                }
577
        }
578
 
274 daniel-mar 579
        outErr = noErr;
258 daniel-mar 580
 
274 daniel-mar 581
#ifdef _WIN64
582
 
583
        //64 bit DLL makes 64 bit:
584
        // Source file = module filename
585
        GetModuleFileName(hDllInstance, srcname, MAX_PATH);
586
        // Destfile = no64_or_32(chosenname) + 64
587
        myp2cstrcpy(dstname, sfr->sfFile.name);
588
        remove_64_filename_prefix(dstname);
589
        add_64_filename_prefix(dstname);
590
        tmpErr = do_make_standalone(&srcname[0], &dstname[0], 64);
591
        if (tmpErr != noErr)
592
                outErr = tmpErr;
593
        else
594
                showmessage(_strdup("64 bit standalone filter was successfully created"));
595
 
596
        //64 bit DLL makes 32 bit:
597
        // Source file = no32(modulefilename)
598
        GetModuleFileName(hDllInstance, srcname, MAX_PATH);
599
        if (!remove_64_filename_prefix(srcname)) {
600
                char err[MAX_PATH + 200];
601
                sprintf(err, "Cannot create the %d bit version of this filter, because the 32-bit variant of this plugin could not be found", 32);
602
                alertuser(_strdup(&err[0]), _strdup(""));
258 daniel-mar 603
        }
274 daniel-mar 604
        else if (!FileExists(srcname)) {
605
                char err[MAX_PATH + 200];
606
                sprintf(err, "%s was not found. Therefore, the %d bit version of the standalone filter could not be created!", srcname, 32);
607
                alertuser(_strdup(&err[0]), _strdup(""));
608
        }
609
        else {
610
                // Destfile = no64_or_32(chosenname)
611
                myp2cstrcpy(dstname, sfr->sfFile.name);
612
                remove_64_filename_prefix(dstname);
613
                tmpErr = do_make_standalone(&srcname[0], &dstname[0], 32);
614
                if (tmpErr != noErr)
615
                        outErr = tmpErr;
616
                else
617
                        showmessage(_strdup("32 bit standalone filter was successfully created"));
277 daniel-mar 618
        }
258 daniel-mar 619
 
274 daniel-mar 620
#else
621
 
622
        //32 bit DLL makes 32 bit:
623
        // Source file = module filename
624
        GetModuleFileName(hDllInstance, srcname, MAX_PATH);
625
        // Destfile = no64_or_32(chosenname)
626
        myp2cstrcpy(dstname, sfr->sfFile.name);
627
        remove_64_filename_prefix(dstname);
628
        tmpErr = do_make_standalone(&srcname[0], &dstname[0], 32);
629
        if (tmpErr != noErr)
630
                outErr = tmpErr;
631
        else
632
                showmessage(_strdup("32 bit standalone filter was successfully created"));
633
 
279 daniel-mar 634
        if (isWin32NT()) {
274 daniel-mar 635
                //32 bit DLL makes 64 bit:
636
                // Source file = module filename + 64
637
                GetModuleFileName(hDllInstance, srcname, MAX_PATH);
638
                add_64_filename_prefix(srcname);
639
                if (!FileExists(srcname)) {
640
                        char err[MAX_PATH + 200];
641
                        sprintf(err, "%s was not found. Therefore, the %d bit version of the standalone filter could not be created!", srcname, 64);
642
                        alertuser(_strdup(&err[0]), _strdup(""));
643
                }
644
                else {
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(&srcname[0], &dstname[0], 64);
650
                        if (tmpErr != noErr)
651
                                outErr = tmpErr;
652
                        else
653
                                showmessage(_strdup("64 bit standalone filter was successfully created"));
654
                }
655
        }
279 daniel-mar 656
        else {
657
                // Unicows.dll cannot edit resources of 64 bit DLLs.
658
                // The normal Kernel function BeginUpdateResource can edit 64 bit DLLs, even in NT4.0 SP6
659
                simplealert(_strdup("Note: A 64 bit standalone filter cannot be created with your Windows version"));
660
        }
274 daniel-mar 661
#endif
662
 
663
        return outErr;
258 daniel-mar 664
}