Login | ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/filter_foundry/trunk/make_win.c
Revision: 357
Committed: Sat Oct 16 18:45:48 2021 UTC (8 months, 2 weeks ago) by daniel-marschall
Content type: text/x-csrc
File size: 24190 byte(s)
Log Message:
In case filter is digitally signed, the signature will be removed for standalone filters

File Contents

# User Rev Content
1 daniel-marschall 258 /*
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    
23 daniel-marschall 278 #include <time.h>
24    
25 daniel-marschall 258 #include "file_compat.h"
26     #include "compat_string.h"
27 daniel-marschall 357 #include "compat_win.h"
28 daniel-marschall 258 #include "versioninfo_modify_win.h"
29     #include "version.h"
30    
31     extern HINSTANCE hDllInstance;
32    
33 daniel-marschall 274 Boolean doresources(HMODULE srcmod,char *dstname, int bits);
34 daniel-marschall 258
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    
54 daniel-marschall 324 int domanifest(char *newmanifest, char *manifestp, PARM_T* pparm, int bits) {
55 daniel-marschall 258 char name[1024];
56     char description[1024];
57     size_t i;
58 daniel-marschall 276 size_t iname = 0;
59 daniel-marschall 258 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];
84 daniel-marschall 352 if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
85 daniel-marschall 258 name[iname++] = c;
86     }
87     }
88     name[iname++] = '.';
89     for (i = 0; i < strlen((char*)pparm->title); i++) {
90     char c = pparm->title[i];
91 daniel-marschall 352 if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
92 daniel-marschall 258 name[iname++] = c;
93     }
94     }
95     name[iname++] = '\0';
96    
97 daniel-marschall 274 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     }
103 daniel-marschall 258 }
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) {
172 daniel-marschall 315 simplealert(_strdup("UpdateVersionInfoWithHandle failed"));
173 daniel-marschall 258 }
174    
175     free(changeRequestStr);
176     }
177    
178 daniel-marschall 278 Boolean update_pe_timestamp(const char* filename, time_t timestamp) {
179 daniel-marschall 280 size_t peoffset;
180     FILE* fptr;
181    
182     fptr = fopen(filename, "rb+");
183 daniel-marschall 278 if (fptr == NULL) return false;
184    
185     fseek(fptr, 0x3C, SEEK_SET);
186     fread(&peoffset, sizeof(peoffset), 1, fptr);
187    
188 daniel-marschall 280 fseek(fptr, (long)peoffset + 8, SEEK_SET);
189 daniel-marschall 278 fwrite(&timestamp, sizeof(time_t), 1, fptr);
190    
191     fclose(fptr);
192    
193     return true;
194     }
195    
196 daniel-marschall 347 int binary_replace_file(const char* filename, uint64_t search, uint64_t replace, Boolean align, int maxamount) {
197     uint64_t srecord = 0;
198 daniel-marschall 276 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++;
211 daniel-marschall 347 if (found == maxamount) break;
212 daniel-marschall 276 }
213     else {
214 daniel-marschall 347 if (!align) {
215     fseek(fptr, -1*(long)(sizeof(srecord) - 1), SEEK_CUR);
216     }
217 daniel-marschall 276 }
218     }
219     fclose(fptr);
220    
221     return found;
222     }
223    
224 daniel-marschall 281 //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-marschall 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    
360 daniel-marschall 274 Boolean doresources(HMODULE srcmod,char *dstname, int bits){
361 daniel-marschall 258 HRSRC datarsrc,aetersrc,manifestsrc;
362     HGLOBAL datah,aeteh,hupdate,manifesth;
363 daniel-marschall 345
364     operdef_t dummy_oper;
365     funcdef_t dummy_func;
366     symndef_t dummy_symn;
367    
368 daniel-marschall 258 Ptr newpipl = NULL, newaete = NULL;
369     LPVOID datap, aetep, manifestp;
370 daniel-marschall 324 char* manifestp_copy;
371 daniel-marschall 258 PARM_T *pparm = NULL;
372 daniel-marschall 324 size_t piplsize,aetesize,origsize;
373 daniel-marschall 258 Str255 title;
374     LPCTSTR parm_type;
375     int i,parm_id;
376     Boolean discard = true;
377 daniel-marschall 347 uint64_t obfuscseed = 0;
378 daniel-marschall 258 long event_id;
379 daniel-marschall 319 Boolean mustFreeSrcMod;
380 daniel-marschall 258
381 daniel-marschall 345 memset(&dummy_oper, 0, sizeof(operdef_t));
382     memset(&dummy_func, 0, sizeof(funcdef_t));
383     memset(&dummy_symn, 0, sizeof(symndef_t));
384    
385 daniel-marschall 319 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    
397 daniel-marschall 258 if( (hupdate = _BeginUpdateResource(dstname,false)) ){
398     DBG("BeginUpdateResource OK");
399 daniel-marschall 308 if( (datarsrc = FindResource(srcmod,MAKEINTRESOURCE(16000), "TPLT"))
400 daniel-marschall 258 && (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     {
409 daniel-marschall 324 char* newmanifest;
410     int manifestsize = SizeofResource(srcmod, manifestsrc);
411 daniel-marschall 258
412 daniel-marschall 324 newmanifest = (char*)malloc(manifestsize + 4096/*+4KiB for name,description,etc.*/);
413    
414 daniel-marschall 258 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    
453 daniel-marschall 324 // ====== Create fitting manifest for the activation context
454 daniel-marschall 258
455 daniel-marschall 324 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    
463 daniel-marschall 258 // ====== Change version attributes
464    
465     changeVersionInfo(dstname, pparm, hupdate);
466    
467     // ====== Obfuscate pparm!
468    
469 daniel-marschall 292 if (gdata->obfusc) {
470 daniel-marschall 258 parm_type = RT_RCDATA;
471     parm_id = OBFUSCDATA_ID;
472 daniel-marschall 276
473     // Note: After we have finished updating the resources, we will write <obfuscseed> into the binary code of the 8BF file
474 daniel-marschall 292 obfuscseed = obfusc(pparm);
475 daniel-marschall 258 }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. */
486 daniel-marschall 274
487 daniel-marschall 308 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
495 daniel-marschall 331 && ((bits != 32) || _UpdateResource(hupdate, "DLL", "UNICOWS", MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0)) // clean up things we don't need in the standalone plugin
496 daniel-marschall 308 && _UpdateResource(hupdate, "PIPL" /* note: caps!! */,MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),newpipl,(DWORD)piplsize)
497 daniel-marschall 258 && _UpdateResource(hupdate, "AETE" /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newaete, (DWORD)aetesize)
498 daniel-marschall 345 // 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)))
502 daniel-marschall 258 && _UpdateResource(hupdate, RT_MANIFEST, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newmanifest, (DWORD)manifestsize)
503 daniel-marschall 308 && _UpdateResource(hupdate, parm_type,MAKEINTRESOURCE(parm_id), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),pparm,sizeof(PARM_T)) )
504 daniel-marschall 258 {
505     discard = false;
506     } else {
507     dbglasterror(_strdup("UpdateResource"));
508     }
509     }
510    
511     }else dbglasterror(_strdup("Find-, Load- or LockResource"));
512    
513 daniel-marschall 276 // Here, the file will be saved
514 daniel-marschall 319 if (mustFreeSrcMod) {
515     FreeLibrary(srcmod);
516     }
517     if (!_EndUpdateResource(hupdate, discard)) {
518 daniel-marschall 258 dbglasterror(_strdup("EndUpdateResource"));
519 daniel-marschall 319 }
520     else {
521 daniel-marschall 258
522 daniel-marschall 319 if (gdata->obfusc) {
523 daniel-marschall 347 // 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     {
532 daniel-marschall 319 dbg("binary_replace_file failed");
533     discard = true;
534     }
535 daniel-marschall 276 }
536    
537 daniel-marschall 319 update_pe_timestamp(dstname, time(0));
538 daniel-marschall 278
539 daniel-marschall 319 repair_pe_checksum(dstname);
540     }
541    
542 daniel-marschall 258 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    
550 daniel-marschall 278 Boolean remove_64_filename_prefix(char* dstname) {
551 daniel-marschall 274 // foobar.8bf => foobar.8bf
552     // foobar64.8bf => foobar.8bf
553 daniel-marschall 276 size_t i;
554 daniel-marschall 274 for (i = strlen(dstname); i > 2; i--) {
555     if (dstname[i] == '.') {
556     if ((dstname[i - 2] == '6') && (dstname[i - 1] == '4')) {
557 daniel-marschall 276 size_t tmp = strlen(dstname);
558 daniel-marschall 274 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    
567 daniel-marschall 278 Boolean add_64_filename_prefix(char* dstname) {
568 daniel-marschall 274 // foobar.8bf => foobar64.8bf
569 daniel-marschall 276 size_t i;
570 daniel-marschall 274 for (i = strlen(dstname); i > 2; i--) {
571     if (dstname[i] == '.') {
572 daniel-marschall 276 size_t tmp = strlen(dstname);
573 daniel-marschall 274 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    
589 daniel-marschall 314 Boolean extract_file(LPCTSTR lpType, LPCTSTR lpName, const char* outName) {
590 daniel-marschall 308 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    
612 daniel-marschall 357 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    
620 daniel-marschall 308 OSErr do_make_standalone(char* dstname, int bits) {
621 daniel-marschall 274 Boolean res;
622 daniel-marschall 292 char err[MAX_PATH + 200];
623    
624 daniel-marschall 274 //DeleteFile(dstname);
625 daniel-marschall 314 if (extract_file("TPLT", MAKEINTRESOURCE(1000 + bits), dstname)) {
626 daniel-marschall 319 res = doresources(NULL, dstname, bits);
627     if (!res) {
628 daniel-marschall 292 DeleteFile(dstname);
629 daniel-marschall 319 sprintf(err, "Could not create %d bit standalone plugin (doresources failed).", bits);
630 daniel-marschall 292 alertuser(_strdup(&err[0]), _strdup(""));
631 daniel-marschall 274 }
632 daniel-marschall 357
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);
636 daniel-marschall 274 }
637     else {
638 daniel-marschall 308 // If you see this error, please make sure that you have called foundry_3264_mixer to include the 32/64 plugins as resource!
639 daniel-marschall 274 res = false;
640 daniel-marschall 292 //DeleteFile(dstname);
641 daniel-marschall 308 sprintf(err, "Could not create %d bit standalone plugin (File extraction failed).", bits);
642 daniel-marschall 274 alertuser(_strdup(&err[0]), _strdup(""));
643     }
644    
645     return res ? noErr : ioErr;
646     }
647    
648 daniel-marschall 314 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 {
655 daniel-marschall 258 HMODULE hLib;
656    
657     hLib = LoadLibraryA("UNICOWS.DLL");
658     if (!hLib) {
659 daniel-marschall 318 char dstname[MAX_PATH + 1];
660 daniel-marschall 258
661 daniel-marschall 314 // Try to install UnicoWS automatically
662 daniel-marschall 318 GetSystemDirectoryA(&dstname[0], MAX_PATH);
663     strcat(&dstname[0], "\\UNICOWS.DLL");
664     extract_file("DLL", "UNICOWS", &dstname[0]); // included in make_win.rc
665 daniel-marschall 279
666 daniel-marschall 314 hLib = LoadLibraryA("UNICOWS.DLL");
667     if (!hLib) {
668     // This should not happen
669 daniel-marschall 316 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"));
670 daniel-marschall 258
671 daniel-marschall 314 return false;
672     }
673     else {
674     FreeLibrary(hLib);
675     return true;
676     }
677 daniel-marschall 258 }
678     else {
679     FreeLibrary(hLib);
680 daniel-marschall 314 return true;
681 daniel-marschall 258 }
682     }
683 daniel-marschall 314 }
684 daniel-marschall 258
685 daniel-marschall 314 OSErr make_standalone(StandardFileReply *sfr){
686     OSErr tmpErr, outErr;
687     char dstname[MAX_PATH+1];
688    
689 daniel-marschall 274 outErr = noErr;
690 daniel-marschall 314
691     check_unicows();
692 daniel-marschall 308
693     // Make 32 bit:
694     // Destfile = no64_or_32(chosenname)
695 daniel-marschall 274 myp2cstrcpy(dstname, sfr->sfFile.name);
696     remove_64_filename_prefix(dstname);
697 daniel-marschall 308 tmpErr = do_make_standalone(&dstname[0], 32);
698 daniel-marschall 274 if (tmpErr != noErr)
699     outErr = tmpErr;
700     else
701 daniel-marschall 308 showmessage(_strdup("32 bit standalone filter was successfully created"));
702 daniel-marschall 274
703 daniel-marschall 308 if (isWin32NT()) {
704     // Make 64 bit:
705     // Destfile = no64_or_32(chosenname) + 64
706 daniel-marschall 274 myp2cstrcpy(dstname, sfr->sfFile.name);
707     remove_64_filename_prefix(dstname);
708 daniel-marschall 308 add_64_filename_prefix(dstname);
709     tmpErr = do_make_standalone(&dstname[0], 64);
710 daniel-marschall 274 if (tmpErr != noErr)
711     outErr = tmpErr;
712     else
713 daniel-marschall 308 showmessage(_strdup("64 bit standalone filter was successfully created"));
714 daniel-marschall 277 }
715 daniel-marschall 279 else {
716 daniel-marschall 331 // Unicows.dll cannot edit resources of 64 bit DLLs. (Tested with UnicoWS 1.1.3790.0)
717 daniel-marschall 346 // On WinNT+, the normal Kernel function BeginUpdateResource can edit 64 bit DLLs, even in NT4.0 SP6
718 daniel-marschall 320 simplewarning(_strdup("Note: A 64 bit standalone filter cannot be created with your Windows version"));
719 daniel-marschall 279 }
720 daniel-marschall 274
721     return outErr;
722 daniel-marschall 258 }
723 daniel-marschall 308