Subversion Repositories filter_foundry

Rev

Rev 255 | Rev 268 | 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
 
23
#include "file_compat.h"
24
#include "compat_string.h"
25
#include "versioninfo_modify_win.h"
26
#include "version.h"
27
 
28
extern HINSTANCE hDllInstance;
29
 
30
Boolean doresources(HMODULE srcmod,char *dstname);
31
 
32
void dbglasterror(char *func){
33
        char s[0x100];
34
 
35
        strcpy(s,func);
36
        strcat(s," failed: ");
37
        FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,s+strlen(s),0x100,NULL );
38
        dbg(s);
39
}
40
 
41
/*
42
BOOL CALLBACK enumfunc(HMODULE hModule,LPCTSTR lpszType,LPCTSTR lpszName,WORD wIDLanguage,LONG lParam){
43
        char s[0x100];
44
        sprintf(s,"EnumResourceLanguages callback: module=%#x type=%s name=%s lang=%d",
45
                hModule,lpszType,lpszName,wIDLanguage);
46
        dbg(s);
47
        return TRUE;
48
}
49
*/
50
 
51
int domanifest(char *newmanifest, const char *manifestp, PARM_T* pparm) {
52
        char name[1024];
53
        char description[1024];
54
        size_t i;
55
        int iname = 0;
56
        int idescription = 0;
57
 
58
        // Description
59
        for (i = 0; i < strlen((char*)pparm->category); i++) {
60
                char c = pparm->category[i];
61
                if ((c != '<') && (c != '>')) {
62
                        description[idescription++] = c;
63
                }
64
        }
65
        description[idescription++] = ' ';
66
        description[idescription++] = '-';
67
        description[idescription++] = ' ';
68
        for (i = 0; i < strlen((char*)pparm->title); i++) {
69
                char c = pparm->title[i];
70
                if ((c != '<') && (c != '>')) {
71
                        description[idescription++] = c;
72
                }
73
        }
74
        description[idescription++] = '\0';
75
 
76
        // Name
77
        strcpy(name, "Telegraphics.FilterFoundry.");
78
        iname = strlen("Telegraphics.FilterFoundry.");
79
        for (i = 0; i < strlen((char*)pparm->category); i++) {
80
                char c = pparm->category[i];
81
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) {
82
                        name[iname++] = c;
83
                }
84
        }
85
        name[iname++] = '.';
86
        for (i = 0; i < strlen((char*)pparm->title); i++) {
87
                char c = pparm->title[i];
88
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) {
89
                        name[iname++] = c;
90
                }
91
        }
92
        name[iname++] = '\0';
93
 
94
#ifdef _WIN64
95
        return sprintf(newmanifest, manifestp, (char*)name, "amd64", VERSION_STR, (char*)description);
96
#else
97
        return sprintf(newmanifest, manifestp, (char*)name, "x86", VERSION_STR, (char*)description);
98
#endif
99
}
100
 
101
void changeVersionInfo(char* dstname, PARM_T* pparm, HGLOBAL hupdate) {
102
        char* soleFilename;
103
        LPWSTR changeRequestStr, tmp;
104
 
105
        if (soleFilename = strrchr(dstname, '\\')) {
106
                ++soleFilename;
107
        }
108
        else {
109
                soleFilename = dstname;
110
        }
111
 
112
        // Format of argument "PCWSTR changes" is "<name>\0<value>\0<name>\0<value>\0....."
113
        // You can CHANGE values for any given name
114
        // You can DELETE entries by setting the value to "\b" (0x08 backspace character)
115
        // You cannot (yet) ADD entries.
116
        changeRequestStr = (LPWSTR)malloc(6 * 2 * 100 + 1);
117
 
118
        tmp = changeRequestStr;
119
 
120
        tmp += mbstowcs(tmp, "Comments", 100);
121
        tmp++;
122
        tmp += mbstowcs(tmp, "Built using Filter Foundry " VERSION_STR, 100);
123
        tmp++;
124
 
125
        tmp += mbstowcs(tmp, "CompanyName", 100);
126
        tmp++;
127
        if (strlen((char*)pparm->author) > 0) {
128
                tmp += mbstowcs(tmp, (char*)pparm->author, 100);
129
        }
130
        else {
131
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
132
        }
133
        tmp++;
134
 
135
        tmp += mbstowcs(tmp, "LegalCopyright", 100);
136
        tmp++;
137
        if (strlen((char*)pparm->copyright) > 0) {
138
                tmp += mbstowcs(tmp, (char*)pparm->copyright, 100);
139
        }
140
        else {
141
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
142
        }
143
        tmp++;
144
 
145
        tmp += mbstowcs(tmp, "FileDescription", 100);
146
        tmp++;
147
        if (strlen((char*)pparm->title) > 0) {
148
                tmp += mbstowcs(tmp, (char*)pparm->title, 100);
149
        }
150
        else {
151
                tmp += mbstowcs(tmp, "Untitled filter", 100);
152
        }
153
        tmp++;
154
 
155
        tmp += mbstowcs(tmp, "OriginalFilename", 100);
156
        tmp++;
157
        tmp += mbstowcs(tmp, soleFilename, 100);
158
        tmp++;
159
 
160
        tmp += mbstowcs(tmp, "License", 100);
161
        tmp++;
162
        tmp += mbstowcs(tmp, "\b", 100); // \b = remove, since filter is standalone and might have its own license
163
        tmp++;
164
 
165
        tmp += mbstowcs(tmp, "", 1);
166
 
167
        if (UpdateVersionInfoWithHandle(dstname, hupdate, changeRequestStr) != NOERROR) {
168
                alertuser(_strdup("UpdateVersionInfoWithHandle failed"), _strdup(""));
169
        }
170
 
171
        free(changeRequestStr);
172
}
173
 
174
Boolean doresources(HMODULE srcmod,char *dstname){
175
        HRSRC datarsrc,aetersrc,manifestsrc;
176
        HGLOBAL datah,aeteh,hupdate,manifesth;
177
        Ptr newpipl = NULL, newaete = NULL;
178
        LPVOID datap, aetep, manifestp;
179
        PARM_T *pparm = NULL;
180
        size_t piplsize,aetesize,origsize,manifestsize;
181
        Str255 title;
182
        LPCTSTR parm_type;
183
        int i,parm_id;
184
        Boolean discard = true;
185
 
186
        long event_id;
187
 
188
//      if(!EnumResourceLanguages(srcmod,"PiPL",MAKEINTRESOURCE(16000),enumfunc,0))
189
//            dbglasterror("EnumResourceLanguages");
190
 
191
        if( (hupdate = _BeginUpdateResource(dstname,false)) ){
192
                DBG("BeginUpdateResource OK");
193
                if( (datarsrc = FindResource(srcmod,MAKEINTRESOURCE(16000),"TPLT"))
194
                        && (datah = LoadResource(srcmod,datarsrc))
195
                        && (datap = (Ptr)LockResource(datah))
196
                        && (aetersrc = FindResource(srcmod, MAKEINTRESOURCE(16000), "AETE"))
197
                        && (aeteh = LoadResource(srcmod, aetersrc))
198
                        && (aetep = (Ptr)LockResource(aeteh))
199
                        && (manifestsrc = FindResource(srcmod, MAKEINTRESOURCE(50), "TPLT"))
200
                        && (manifesth = LoadResource(srcmod, manifestsrc))
201
                        && (manifestp = (Ptr)LockResource(manifesth)) )
202
                {
203
                        char newmanifest[5000];
204
 
205
                        DBG("loaded DATA, PiPL");
206
 
207
                        PLstrcpy(title,gdata->parm.title);
208
                        if(gdata->parm.popDialog)
209
                                PLstrcat(title,(StringPtr)"\003...");
210
 
211
                        origsize = SizeofResource(srcmod,datarsrc);
212
 
213
                        if( (newpipl = (Ptr)malloc(origsize+0x300))
214
                         && (newaete = (Ptr)malloc(4096))
215
                         && (pparm = (PARM_T*)malloc(sizeof(PARM_T))) )
216
                        {
217
                                // ====== Generate AETE and PIPL
218
 
219
                                /* add user-specified title and category to new PiPL */
220
                                memcpy(newpipl,datap,origsize);
221
                                /* note that Windows PiPLs have 2 byte version datum in front
222
                                   that isn't reflected in struct definition or Mac resource template: */
223
                                piplsize = fixpipl((PIPropertyList*)(newpipl+2),origsize-2,title, &event_id) + 2;
224
 
225
                                /* set up the PARM resource with saved parameters */
226
                                memcpy(pparm,&gdata->parm,sizeof(PARM_T));
227
 
228
                                /* Generate 'aete' resource (contains names of the parameters for the "Actions" tab in Photoshop) */
229
                                aetesize = aete_generate(newaete, pparm, event_id);
230
 
231
                                // ====== Change Pascal strings to C-Strings
232
 
233
                                /* convert to C strings for Windows PARM resource */
234
                                // Don't do it before aete_generate, because they need Pascal strings
235
                                myp2cstr(pparm->category);
236
                                myp2cstr(pparm->title);
237
                                myp2cstr(pparm->copyright);
238
                                myp2cstr(pparm->author);
239
                                for (i = 0; i < 4; ++i)
240
                                        myp2cstr(pparm->map[i]);
241
                                for (i = 0; i < 8; ++i)
242
                                        myp2cstr(pparm->ctl[i]);
243
 
244
                                manifestsize = domanifest(newmanifest, (const char*)manifestp, pparm);
245
 
246
                                // ====== Change version attributes
247
 
248
                                changeVersionInfo(dstname, pparm, hupdate);
249
 
250
                                // ====== Obfuscate pparm!
251
 
252
                                if(gdata->obfusc){
253
                                        parm_type = RT_RCDATA;
254
                                        parm_id = OBFUSCDATA_ID;
255
                                        obfusc((unsigned char*)pparm,sizeof(PARM_T),OBFUSC_SEED_POS);
256
                                }else{
257
                                        parm_type = "PARM";
258
                                        parm_id = PARM_ID;
259
                                }
260
 
261
                                // ====== Save AETE, PIPL, Manifest and PARM/RCDATA
262
 
263
                                /* Attention: The resource we have found using FindResource() might have a different
264
                                   language than the resource we are saving (Neutral), so we might end up having
265
                                   multiple languages for the same resource. Therefore, the language "Neutral" was
266
                                   set in the Scripting.rc file for the resource AETE and PIPL.rc for the resources PIPL. */
267
                                if( _UpdateResource(hupdate,"PIPL" /* note: caps!! */,MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),newpipl,(DWORD)piplsize)
268
                                        && _UpdateResource(hupdate, "AETE" /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newaete, (DWORD)aetesize)
269
                                        && _UpdateResource(hupdate, RT_MANIFEST, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newmanifest, (DWORD)manifestsize)
270
                                        && _UpdateResource(hupdate,parm_type,MAKEINTRESOURCE(parm_id), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),pparm,sizeof(PARM_T)) )
271
                                {
272
                                        discard = false;
273
                                } else {
274
                                        dbglasterror(_strdup("UpdateResource"));
275
                                }
276
                        }
277
 
278
                }else dbglasterror(_strdup("Find-, Load- or LockResource"));
279
 
280
                if(!_EndUpdateResource(hupdate,discard))
281
                        dbglasterror(_strdup("EndUpdateResource"));
282
 
283
                if(pparm) free(pparm);
284
                if(newpipl) free(newpipl);
285
                if(newaete) free(newaete);
286
        }else
287
                dbglasterror(_strdup("BeginUpdateResource"));
288
        return !discard;
289
}
290
 
291
OSErr make_standalone(StandardFileReply *sfr){
292
        Boolean res;
293
        char dstname[0x100],srcname[MAX_PATH+1];
294
 
295
        if (!isWin32NT()) {
296
                HMODULE hLib;
297
 
298
                hLib = LoadLibraryA("UNICOWS.DLL");
299
                if (!hLib) {
300
                        char* sysdir;
301
 
302
                        sysdir = (char*)malloc(MAX_PATH);
303
                        GetSystemDirectoryA(sysdir, MAX_PATH);
304
                        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);
305
                        free(sysdir);
306
 
307
                        return false;
308
                }
309
                else {
310
                        FreeLibrary(hLib);
311
                }
312
        }
313
 
314
        //FSpDelete(&sfr->sfFile);
315
        myp2cstrcpy(dstname,sfr->sfFile.name);
316
        res = GetModuleFileName(hDllInstance,srcname,MAX_PATH)
317
                  && CopyFile(srcname,dstname,false)
318
                  && doresources(hDllInstance,dstname);
319
 
320
        if(!res) {
321
                alertuser(_strdup("Could not create standalone plugin."),_strdup(""));
322
        } else {
323
                showmessage(_strdup("Filter was sucessfully created"));
324
        }
325
 
326
        return res ? ioErr : noErr;
327
}