Subversion Repositories filter_foundry

Rev

Rev 508 | Rev 510 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 508 Rev 509
1
/*
1
/*
2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
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
3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
4
    Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
4
    Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
5
 
5
 
6
    This program is free software; you can redistribute it and/or modify
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
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
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
9
    (at your option) any later version.
10
 
10
 
11
    This program is distributed in the hope that it will be useful,
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
14
    GNU General Public License for more details.
15
 
15
 
16
    You should have received a copy of the GNU General Public License
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
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
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
*/
19
*/
20
 
20
 
21
#include "ff.h"
21
#include "ff.h"
22
 
22
 
23
#include <time.h>
23
#include <time.h>
24
 
24
 
25
#include "file_compat.h"
25
#include "file_compat.h"
26
#include "compat_string.h"
26
#include "compat_string.h"
27
#include "compat_win.h"
27
#include "compat_win.h"
28
#include "versioninfo_modify_win.h"
28
#include "versioninfo_modify_win.h"
29
#include "version.h"
29
#include "version.h"
30
 
30
 
31
extern HINSTANCE hDllInstance;
31
extern HINSTANCE hDllInstance;
32
 
32
 
33
typedef struct _PE32 {
33
typedef struct _PE32 {
34
        uint32_t magic; // 0x50450000
34
        uint32_t magic; // 0x50450000
35
        IMAGE_FILE_HEADER fileHeader; // COFF Header without Signature
35
        IMAGE_FILE_HEADER fileHeader; // COFF Header without Signature
36
        IMAGE_OPTIONAL_HEADER32 optHeader; // Standard COFF fields, Windows Specific Fields, Data Directories
36
        IMAGE_OPTIONAL_HEADER32 optHeader; // Standard COFF fields, Windows Specific Fields, Data Directories
37
} PE32;
37
} PE32;
38
 
38
 
39
Boolean doresources(FSSpec* dst, int bits);
39
Boolean doresources(FSSpec* dst, int bits);
40
 
40
 
41
void showLastError(TCHAR *func){
41
void showLastError(TCHAR *func){
42
        TCHAR s[0x300] = {0};
42
        TCHAR s[0x300] = {0};
43
 
43
 
44
        xstrcpy(&s[0],func);
44
        xstrcpy(&s[0],func);
45
        xstrcat(&s[0],TEXT(" failed: ")); // TODO (Not so important): TRANSLATE
45
        xstrcat(&s[0],TEXT(" failed: ")); // TODO (Not so important): TRANSLATE
46
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
46
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, s + xstrlen(s), 0x300 - (DWORD)xstrlen(s), NULL);
47
        simplealert(&s[0]);
47
        simplealert(&s[0]);
48
}
48
}
49
 
49
 
50
/*
50
/*
51
BOOL CALLBACK enumfunc(HMODULE hModule,LPCTSTR lpszType,LPCTSTR lpszName,WORD wIDLanguage,LONG lParam){
51
BOOL CALLBACK enumfunc(HMODULE hModule,LPCTSTR lpszType,LPCTSTR lpszName,WORD wIDLanguage,LONG lParam){
52
        #ifdef DEBUG
52
        #ifdef DEBUG
53
        char s[0x100];
53
        char s[0x100];
54
        sprintf(s,"EnumResourceLanguages callback: module=%#x type=%s name=%s lang=%d",
54
        sprintf(s,"EnumResourceLanguages callback: module=%#x type=%s name=%s lang=%d",
55
                hModule,lpszType,lpszName,wIDLanguage);
55
                hModule,lpszType,lpszName,wIDLanguage);
56
        dbg(s);
56
        dbg(s);
57
        #endif
57
        #endif
58
        return TRUE;
58
        return TRUE;
59
}
59
}
60
*/
60
*/
61
 
61
 
62
int WriteXmlEscaped(char* description, char c) {
62
int WriteXmlEscaped(char* description, char c) {
63
        int idescription = 0;
63
        int idescription = 0;
64
        if (c == '&') {
64
        if (c == '&') {
65
                description[idescription++] = '&';
65
                description[idescription++] = '&';
66
                description[idescription++] = 'a';
66
                description[idescription++] = 'a';
67
                description[idescription++] = 'm';
67
                description[idescription++] = 'm';
68
                description[idescription++] = 'p';
68
                description[idescription++] = 'p';
69
                description[idescription++] = ';';
69
                description[idescription++] = ';';
70
        }
70
        }
71
        else if (c == '<') {
71
        else if (c == '<') {
72
                description[idescription++] = '&';
72
                description[idescription++] = '&';
73
                description[idescription++] = 'l';
73
                description[idescription++] = 'l';
74
                description[idescription++] = 't';
74
                description[idescription++] = 't';
75
                description[idescription++] = ';';
75
                description[idescription++] = ';';
76
        }
76
        }
77
        else if (c == '>') {
77
        else if (c == '>') {
78
                description[idescription++] = '&';
78
                description[idescription++] = '&';
79
                description[idescription++] = 'g';
79
                description[idescription++] = 'g';
80
                description[idescription++] = 't';
80
                description[idescription++] = 't';
81
                description[idescription++] = ';';
81
                description[idescription++] = ';';
82
        }
82
        }
83
        else {
83
        else {
84
                description[idescription++] = c;
84
                description[idescription++] = c;
85
        }
85
        }
86
        return idescription;
86
        return idescription;
87
}
87
}
88
 
88
 
89
int domanifest(char *newmanifest, char *manifestp, PARM_T* pparm, int bits) {
89
int domanifest(char *newmanifest, char *manifestp, PARM_T* pparm, int bits) {
90
        char* name;
90
        char* name;
91
        char* description, *tmpDescription;
91
        char* description, *tmpDescription;
92
        int res;
92
        int res;
93
        size_t i;
93
        size_t i;
94
        size_t iname;
94
        size_t iname;
95
 
95
 
96
        name = (char*)malloc(40 + (2 * 256) * 5);
96
        name = (char*)malloc(40 + (2 * 256) * 5);
97
        description = (char*)malloc(10 + (2 * 256)); // x4 because & becomes &amp;
97
        description = (char*)malloc(10 + (2 * 256)); // x4 because & becomes &amp;
98
        if (name == NULL || description == NULL) return 0;
98
        if (name == NULL || description == NULL) return 0;
99
       
99
       
100
        // Description
100
        // Description
101
        tmpDescription = description;
101
        tmpDescription = description;
102
        for (i = 0; i < strlen(pparm->szCategory); i++) {
102
        for (i = 0; i < strlen(pparm->szCategory); i++) {
103
                char c = pparm->szCategory[i];
103
                char c = pparm->szCategory[i];
104
                tmpDescription += WriteXmlEscaped(tmpDescription, c);
104
                tmpDescription += WriteXmlEscaped(tmpDescription, c);
105
        }
105
        }
106
        tmpDescription += WriteXmlEscaped(tmpDescription, ' ');
106
        tmpDescription += WriteXmlEscaped(tmpDescription, ' ');
107
        tmpDescription += WriteXmlEscaped(tmpDescription, '-');
107
        tmpDescription += WriteXmlEscaped(tmpDescription, '-');
108
        tmpDescription += WriteXmlEscaped(tmpDescription, ' ');
108
        tmpDescription += WriteXmlEscaped(tmpDescription, ' ');
109
        for (i = 0; i < strlen(pparm->szTitle); i++) {
109
        for (i = 0; i < strlen(pparm->szTitle); i++) {
110
                char c = pparm->szTitle[i];
110
                char c = pparm->szTitle[i];
111
                tmpDescription += WriteXmlEscaped(tmpDescription, c);
111
                tmpDescription += WriteXmlEscaped(tmpDescription, c);
112
        }
112
        }
113
        tmpDescription[0] = '\0';
113
        tmpDescription[0] = '\0';
114
 
114
 
115
        // Name
115
        // Name
116
        strcpy(name, "Telegraphics.FilterFoundry.");
116
        strcpy(name, "Telegraphics.FilterFoundry.");
117
        iname = strlen("Telegraphics.FilterFoundry.");
117
        iname = strlen("Telegraphics.FilterFoundry.");
118
        for (i = 0; i < strlen(pparm->szCategory); i++) {
118
        for (i = 0; i < strlen(pparm->szCategory); i++) {
119
                char c = pparm->szCategory[i];
119
                char c = pparm->szCategory[i];
120
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
120
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
121
                        name[iname++] = c;
121
                        name[iname++] = c;
122
                }
122
                }
123
        }
123
        }
124
        name[iname++] = '.';
124
        name[iname++] = '.';
125
        for (i = 0; i < strlen(pparm->szTitle); i++) {
125
        for (i = 0; i < strlen(pparm->szTitle); i++) {
126
                char c = pparm->szTitle[i];
126
                char c = pparm->szTitle[i];
127
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
127
                if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'))) {
128
                        name[iname++] = c;
128
                        name[iname++] = c;
129
                }
129
                }
130
        }
130
        }
131
        name[iname++] = '\0';
131
        name[iname++] = '\0';
132
 
132
 
133
        if (bits == 64) {
133
        if (bits == 64) {
134
                res = sprintf(newmanifest, manifestp, (char*)name, "amd64", VERSION_STR, (char*)description);
134
                res = sprintf(newmanifest, manifestp, (char*)name, "amd64", VERSION_STR, (char*)description);
135
        }
135
        }
136
        else {
136
        else {
137
                res = sprintf(newmanifest, manifestp, (char*)name, "x86", VERSION_STR, (char*)description);
137
                res = sprintf(newmanifest, manifestp, (char*)name, "x86", VERSION_STR, (char*)description);
138
        }
138
        }
139
 
139
 
140
        free(name);
140
        free(name);
141
        free(description);
141
        free(description);
142
 
142
 
143
        return res;
143
        return res;
144
}
144
}
145
 
145
 
146
ULONG changeVersionInfo(FSSpec* dst, HANDLE hUpdate, PARM_T* pparm, int bits) {
146
ULONG changeVersionInfo(FSSpec* dst, HANDLE hUpdate, PARM_T* pparm, int bits) {
147
        LPTSTR soleFilename;
147
        LPTSTR soleFilename;
148
        LPWSTR changeRequestStrW, tmp;
148
        LPWSTR changeRequestStrW, tmp;
149
        ULONG dwError = NOERROR;
149
        ULONG dwError = NOERROR;
150
        HRSRC hResInfo;
150
        HRSRC hResInfo;
151
        HGLOBAL hg;
151
        HGLOBAL hg;
152
        ULONG size;
152
        ULONG size;
153
        PVOID pv;
153
        PVOID pv;
154
        //BOOL fDiscard = TRUE;
154
        //BOOL fDiscard = TRUE;
155
 
155
 
156
        if (soleFilename = xstrrchr(&dst->szName[0], '\\')) {
156
        if (soleFilename = xstrrchr(&dst->szName[0], '\\')) {
157
                ++soleFilename;
157
                ++soleFilename;
158
        }
158
        }
159
        else {
159
        else {
160
                soleFilename = &dst->szName[0];
160
                soleFilename = &dst->szName[0];
161
        }
161
        }
162
 
162
 
163
        // Format of argument "PCWSTR changes" is "<name>\0<value>\0<name>\0<value>\0....."
163
        // Format of argument "PCWSTR changes" is "<name>\0<value>\0<name>\0<value>\0....."
164
        // You can CHANGE values for any given name
164
        // You can CHANGE values for any given name
165
        // You can DELETE entries by setting the value to "\b" (0x08 backspace character)
165
        // You can DELETE entries by setting the value to "\b" (0x08 backspace character)
166
        // You cannot (yet) ADD entries.
166
        // You cannot (yet) ADD entries.
167
        changeRequestStrW = (LPWSTR)malloc((6 * 2 * 100 + 1) * sizeof(WCHAR));
167
        changeRequestStrW = (LPWSTR)malloc((6 * 2 * 100 + 1) * sizeof(WCHAR));
168
        if (changeRequestStrW == 0) return E_OUTOFMEMORY;
168
        if (changeRequestStrW == 0) return E_OUTOFMEMORY;
169
        memset((char*)changeRequestStrW, 0, sizeof(changeRequestStrW));
169
        memset((char*)changeRequestStrW, 0, sizeof(changeRequestStrW));
170
 
170
 
171
        tmp = changeRequestStrW;
171
        tmp = changeRequestStrW;
172
 
172
 
173
        tmp += mbstowcs(tmp, "Comments", 100);
173
        tmp += mbstowcs(tmp, "Comments", 100);
174
        tmp++;
174
        tmp++;
175
        tmp += mbstowcs(tmp, "Built using Filter Foundry " VERSION_STR, 100);
175
        tmp += mbstowcs(tmp, "Built using Filter Foundry " VERSION_STR, 100);
176
        tmp++;
176
        tmp++;
177
 
177
 
178
        tmp += mbstowcs(tmp, "CompanyName", 100);
178
        tmp += mbstowcs(tmp, "CompanyName", 100);
179
        tmp++;
179
        tmp++;
180
        if (strlen(pparm->szAuthor) > 0) {
180
        if (strlen(pparm->szAuthor) > 0) {
181
                tmp += mbstowcs(tmp, pparm->szAuthor, 100);
181
                tmp += mbstowcs(tmp, pparm->szAuthor, 100);
182
        }
182
        }
183
        else {
183
        else {
184
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
184
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
185
        }
185
        }
186
        tmp++;
186
        tmp++;
187
 
187
 
188
        tmp += mbstowcs(tmp, "LegalCopyright", 100);
188
        tmp += mbstowcs(tmp, "LegalCopyright", 100);
189
        tmp++;
189
        tmp++;
190
        if (strlen(pparm->szCopyright) > 0) {
190
        if (strlen(pparm->szCopyright) > 0) {
191
                tmp += mbstowcs(tmp, pparm->szCopyright, 100);
191
                tmp += mbstowcs(tmp, pparm->szCopyright, 100);
192
        }
192
        }
193
        else {
193
        else {
194
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
194
                tmp += mbstowcs(tmp, "\b", 100); // \b = remove
195
        }
195
        }
196
        tmp++;
196
        tmp++;
197
 
197
 
198
        tmp += mbstowcs(tmp, "FileDescription", 100);
198
        tmp += mbstowcs(tmp, "FileDescription", 100);
199
        tmp++;
199
        tmp++;
200
        if (strlen(pparm->szTitle) > 0) {
200
        if (strlen(pparm->szTitle) > 0) {
201
                tmp += mbstowcs(tmp, pparm->szTitle, 100);
201
                tmp += mbstowcs(tmp, pparm->szTitle, 100);
202
        }
202
        }
203
        else {
203
        else {
204
                tmp += mbstowcs(tmp, "Untitled filter", 100);
204
                tmp += mbstowcs(tmp, "Untitled filter", 100);
205
        }
205
        }
206
        tmp++;
206
        tmp++;
207
 
207
 
208
        tmp += mbstowcs(tmp, "OriginalFilename", 100);
208
        tmp += mbstowcs(tmp, "OriginalFilename", 100);
209
        tmp++;
209
        tmp++;
210
        #ifdef UNICODE
210
        #ifdef UNICODE
211
        xstrcpy(tmp, soleFilename);
211
        xstrcpy(tmp, soleFilename);
212
        tmp += xstrlen(soleFilename);
212
        tmp += xstrlen(soleFilename);
213
        #else
213
        #else
214
        tmp += mbstowcs(tmp, soleFilename, 100);
214
        tmp += mbstowcs(tmp, soleFilename, 100);
215
        #endif
215
        #endif
216
        tmp++;
216
        tmp++;
217
 
217
 
218
        tmp += mbstowcs(tmp, "License", 100);
218
        tmp += mbstowcs(tmp, "License", 100);
219
        tmp++;
219
        tmp++;
220
        tmp += mbstowcs(tmp, "\b", 100); // \b = remove, since filter is standalone and might have its own license
220
        tmp += mbstowcs(tmp, "\b", 100); // \b = remove, since filter is standalone and might have its own license
221
        tmp++;
221
        tmp++;
222
 
222
 
223
        tmp += mbstowcs(tmp, "", 1);
223
        tmp += mbstowcs(tmp, "", 1);
224
 
224
 
225
        if (hResInfo = FindResourceEx(hDllInstance, TEXT("TPLT"), MAKEINTRESOURCE(3000 + bits), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)))
225
        if (hResInfo = FindResourceEx(hDllInstance, TEXT("TPLT"), MAKEINTRESOURCE(3000 + bits), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)))
226
        {
226
        {
227
                if (hg = LoadResource(hDllInstance, hResInfo))
227
                if (hg = LoadResource(hDllInstance, hResInfo))
228
                {
228
                {
229
                        if (size = SizeofResource(hDllInstance, hResInfo))
229
                        if (size = SizeofResource(hDllInstance, hResInfo))
230
                        {
230
                        {
231
                                if (pv = LockResource(hg))
231
                                if (pv = LockResource(hg))
232
                                {
232
                                {
233
                                        if (UpdateVersionRaw(pv, size, &pv, &size, changeRequestStrW))
233
                                        if (UpdateVersionRaw(pv, size, &pv, &size, changeRequestStrW))
234
                                        {
234
                                        {
235
                                                if (_UpdateResource(hUpdate, RT_VERSION, MAKEINTRESOURCE(1), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pv, size))
235
                                                if (_UpdateResource(hUpdate, RT_VERSION, MAKEINTRESOURCE(1), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pv, size))
236
                                                {
236
                                                {
237
                                                        //fDiscard = FALSE;
237
                                                        //fDiscard = FALSE;
238
                                                }
238
                                                }
239
                                                else {
239
                                                else {
240
                                                        //dwError = GetLastError();
240
                                                        //dwError = GetLastError();
241
                                                }
241
                                                }
242
                                        }
242
                                        }
243
                                        LocalFree(pv);
243
                                        LocalFree(pv);
244
                                }
244
                                }
245
                        }
245
                        }
246
                }
246
                }
247
        }
247
        }
248
 
248
 
249
        free(changeRequestStrW);
249
        free(changeRequestStrW);
250
 
250
 
251
        return dwError;
251
        return dwError;
252
}
252
}
253
 
253
 
254
typedef long                          __time32_t;
254
typedef long                          __time32_t;
255
 
255
 
256
Boolean update_pe_timestamp(const FSSpec* dst, __time32_t timestamp) {
256
Boolean update_pe_timestamp(const FSSpec* dst, __time32_t timestamp) {
257
        size_t peoffset;
257
        size_t peoffset;
258
        FILEREF fptr;
258
        FILEREF fptr;
259
        Boolean res;
259
        Boolean res;
260
        FILECOUNT cnt;
260
        FILECOUNT cnt;
261
 
261
 
262
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return false;
262
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return false;
263
 
263
 
264
        res =
264
        res =
265
                SetFPos(fptr, fsFromStart, 0x3C) ||
265
                SetFPos(fptr, fsFromStart, 0x3C) ||
266
                (cnt = sizeof(peoffset), noErr) ||
266
                (cnt = sizeof(peoffset), noErr) ||
267
                FSRead(fptr, &cnt, &peoffset) ||
267
                FSRead(fptr, &cnt, &peoffset) ||
268
                SetFPos(fptr, fsFromStart, (long)peoffset + /*0x0008*/offsetof(PE32, fileHeader.TimeDateStamp)) ||
268
                SetFPos(fptr, fsFromStart, (long)peoffset + /*0x0008*/offsetof(PE32, fileHeader.TimeDateStamp)) ||
269
                (cnt = sizeof(__time32_t), noErr) ||
269
                (cnt = sizeof(__time32_t), noErr) ||
270
                FSWrite(fptr, &cnt, &timestamp);
270
                FSWrite(fptr, &cnt, &timestamp);
271
 
271
 
272
        FSClose(fptr);
272
        FSClose(fptr);
273
 
273
 
274
        return res == noErr; // res=0 means everything was noErr, res=1 means something was !=noErr
274
        return res == noErr; // res=0 means everything was noErr, res=1 means something was !=noErr
275
}
275
}
276
 
276
 
277
int binary_replace_file(FSSpec* dst, uint64_t search, uint64_t replace, Boolean align, int maxamount) {
277
int binary_replace_file(FSSpec* dst, uint64_t search, uint64_t replace, Boolean align, int maxamount) {
278
        uint64_t srecord = 0;
278
        uint64_t srecord = 0;
279
        int found = 0;
279
        int found = 0;
280
        FILEREF fptr;
280
        FILEREF fptr;
281
        FILECOUNT cnt;
281
        FILECOUNT cnt;
282
 
282
 
283
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return -1;
283
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return -1;
284
 
284
 
285
        cnt = sizeof(srecord);
285
        cnt = sizeof(srecord);
286
        while (FSRead(fptr, &cnt, &srecord) == noErr)
286
        while (FSRead(fptr, &cnt, &srecord) == noErr)
287
        {
287
        {
288
                if (cnt != sizeof(srecord)) break; // EOF reached
288
                if (cnt != sizeof(srecord)) break; // EOF reached
289
                if (srecord == search) {
289
                if (srecord == search) {
290
                        srecord = replace;
290
                        srecord = replace;
291
                        SetFPos(fptr, fsFromMark, -1 * (long)sizeof(srecord));
291
                        SetFPos(fptr, fsFromMark, -1 * (long)sizeof(srecord));
292
                        cnt = (int)sizeof(srecord);
292
                        cnt = (int)sizeof(srecord);
293
                        FSWrite(fptr, &cnt, &srecord);
293
                        FSWrite(fptr, &cnt, &srecord);
294
                        SetFPos(fptr, fsFromStart, 0); // important for fseek
294
                        SetFPos(fptr, fsFromStart, 0); // important for fseek
295
                        found++;
295
                        found++;
296
                        if (found == maxamount) break;
296
                        if (found == maxamount) break;
297
                }
297
                }
298
                else {
298
                else {
299
                        if (!align) {
299
                        if (!align) {
300
                                SetFPos(fptr, fsFromMark, -1 * (long)(sizeof(srecord) - 1));
300
                                SetFPos(fptr, fsFromMark, -1 * (long)(sizeof(srecord) - 1));
301
                        }
301
                        }
302
                }
302
                }
303
        }
303
        }
304
        FSClose(fptr);
304
        FSClose(fptr);
305
 
305
 
306
        return found;
306
        return found;
307
}
307
}
308
 
308
 
309
uint32_t calculate_checksum(FSSpec* dst) {
309
uint32_t calculate_checksum(FSSpec* dst) {
310
        //Calculate checksum of image
310
        //Calculate checksum of image
311
        // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
311
        // Taken from "PE Bliss" Cross-Platform Portable Executable C++ Library
312
        // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
312
        // https://github.com/mrexodia/portable-executable-library/blob/master/pe_lib/pe_checksum.cpp
313
        // Converted from C++ to C by Daniel Marschall
313
        // Converted from C++ to C by Daniel Marschall
314
 
314
 
315
        FILEREF fptr;
315
        FILEREF fptr;
316
        unsigned long long checksum = 0;
316
        unsigned long long checksum = 0;
317
        IMAGE_DOS_HEADER header;
317
        IMAGE_DOS_HEADER header;
318
        FILEPOS filesize, i;
318
        FILEPOS filesize, i;
319
        unsigned long long top;
319
        unsigned long long top;
320
        unsigned long pe_checksum_pos;
320
        unsigned long pe_checksum_pos;
321
        static const unsigned long checksum_pos_in_optional_headers = 64;
321
        static const unsigned long checksum_pos_in_optional_headers = 64;
322
        FILECOUNT cnt;
322
        FILECOUNT cnt;
323
 
323
 
324
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return 0x00000000;
324
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return 0x00000000;
325
 
325
 
326
        //Read DOS header
326
        //Read DOS header
327
        SetFPos(fptr, fsFromStart, 0);
327
        SetFPos(fptr, fsFromStart, 0);
328
        cnt = sizeof(IMAGE_DOS_HEADER);
328
        cnt = sizeof(IMAGE_DOS_HEADER);
329
        FSRead(fptr, &cnt, &header);
329
        FSRead(fptr, &cnt, &header);
330
 
330
 
331
        //Calculate PE checksum
331
        //Calculate PE checksum
332
        SetFPos(fptr, fsFromStart, 0);
332
        SetFPos(fptr, fsFromStart, 0);
333
        top = 0xFFFFFFFF;
333
        top = 0xFFFFFFFF;
334
        top++;
334
        top++;
335
 
335
 
336
        //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
336
        //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+
337
        //Calculate real PE headers "CheckSum" field position
337
        //Calculate real PE headers "CheckSum" field position
338
        //Sum is safe here
338
        //Sum is safe here
339
        pe_checksum_pos = header.e_lfanew + sizeof(IMAGE_FILE_HEADER) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
339
        pe_checksum_pos = header.e_lfanew + sizeof(IMAGE_FILE_HEADER) + sizeof(uint32_t) + checksum_pos_in_optional_headers;
340
 
340
 
341
        //Calculate checksum for each byte of file
341
        //Calculate checksum for each byte of file
342
        filesize = 0;
342
        filesize = 0;
343
        GetEOF(fptr, &filesize);
343
        GetEOF(fptr, &filesize);
344
        SetFPos(fptr, fsFromStart, 0);
344
        SetFPos(fptr, fsFromStart, 0);
345
        for (i = 0; i < filesize; i += 4)
345
        for (i = 0; i < filesize; i += 4)
346
        {
346
        {
347
                unsigned long dw = 0;
347
                unsigned long dw = 0;
348
 
348
 
349
                //Read DWORD from file
349
                //Read DWORD from file
350
                cnt = sizeof(dw);
350
                cnt = sizeof(dw);
351
                FSRead(fptr, &cnt, &dw);
351
                FSRead(fptr, &cnt, &dw);
352
                //Skip "CheckSum" DWORD
352
                //Skip "CheckSum" DWORD
353
                if (i == pe_checksum_pos)
353
                if (i == pe_checksum_pos)
354
                        continue;
354
                        continue;
355
 
355
 
356
                //Calculate checksum
356
                //Calculate checksum
357
                checksum = (checksum & 0xffffffff) + dw + (checksum >> 32);
357
                checksum = (checksum & 0xffffffff) + dw + (checksum >> 32);
358
                if (checksum > top)
358
                if (checksum > top)
359
                        checksum = (checksum & 0xffffffff) + (checksum >> 32);
359
                        checksum = (checksum & 0xffffffff) + (checksum >> 32);
360
        }
360
        }
361
 
361
 
362
        //Finish checksum
362
        //Finish checksum
363
        checksum = (checksum & 0xffff) + (checksum >> 16);
363
        checksum = (checksum & 0xffff) + (checksum >> 16);
364
        checksum = (checksum)+(checksum >> 16);
364
        checksum = (checksum)+(checksum >> 16);
365
        checksum = checksum & 0xffff;
365
        checksum = checksum & 0xffff;
366
 
366
 
367
        checksum += (unsigned long)(filesize);
367
        checksum += (unsigned long)(filesize);
368
 
368
 
369
        FSClose(fptr);
369
        FSClose(fptr);
370
 
370
 
371
        //Return checksum
371
        //Return checksum
372
        return (uint32_t)checksum;
372
        return (uint32_t)checksum;
373
}
373
}
374
 
374
 
375
Boolean repair_pe_checksum(FSSpec* dst) {
375
Boolean repair_pe_checksum(FSSpec* dst) {
376
        size_t peoffset;
376
        size_t peoffset;
377
        FILEREF fptr;
377
        FILEREF fptr;
378
        FILECOUNT cnt;
378
        FILECOUNT cnt;
379
        Boolean res;
379
        Boolean res;
380
 
380
 
381
        uint32_t checksum = calculate_checksum(dst);
381
        uint32_t checksum = calculate_checksum(dst);
382
        //if (checksum == 0x00000000) return false;
382
        //if (checksum == 0x00000000) return false;
383
 
383
 
384
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return false;
384
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return false;
385
 
385
 
386
        res =
386
        res =
387
                SetFPos(fptr, fsFromStart, 0x3C) ||
387
                SetFPos(fptr, fsFromStart, 0x3C) ||
388
                (cnt = sizeof(peoffset), noErr) ||
388
                (cnt = sizeof(peoffset), noErr) ||
389
                FSRead(fptr, &cnt, &peoffset) ||
389
                FSRead(fptr, &cnt, &peoffset) ||
390
                SetFPos(fptr, fsFromStart, (long)peoffset + /*0x0058*/offsetof(PE32, optHeader.CheckSum)) ||
390
                SetFPos(fptr, fsFromStart, (long)peoffset + /*0x0058*/offsetof(PE32, optHeader.CheckSum)) ||
391
                (cnt = sizeof(uint32_t), noErr) ||
391
                (cnt = sizeof(uint32_t), noErr) ||
392
                FSWrite(fptr, &cnt, &checksum);
392
                FSWrite(fptr, &cnt, &checksum);
393
 
393
 
394
        FSClose(fptr);
394
        FSClose(fptr);
395
 
395
 
396
        return res == noErr; // res=0 means everything was noErr, res=1 means something was !=noErr
396
        return res == noErr; // res=0 means everything was noErr, res=1 means something was !=noErr
397
}
397
}
398
 
398
 
399
typedef struct {
399
typedef struct {
400
        char funcname[8];
400
        char funcname[8];
401
        uint16_t codelen;
401
        uint16_t codelen;
402
} operdef_t;
402
} operdef_t;
403
 
403
 
404
typedef struct {
404
typedef struct {
405
        char funcname[8];
405
        char funcname[8];
406
        uint16_t numparams;
406
        uint16_t numparams;
407
} funcdef_t;
407
} funcdef_t;
408
 
408
 
409
typedef struct {
409
typedef struct {
410
        char funcname[8];
410
        char funcname[8];
411
        char referencename[8];
411
        char referencename[8];
412
} symndef_t;
412
} symndef_t;
413
 
413
 
414
Boolean doresources(FSSpec* dst, int bits){
414
Boolean doresources(FSSpec* dst, int bits){
415
        HRSRC datarsrc,aetersrc,manifestsrc;
415
        HRSRC datarsrc,aetersrc,manifestsrc;
416
        HGLOBAL datah,aeteh,hupdate,manifesth;
416
        HGLOBAL datah,aeteh,hupdate,manifesth;
417
 
417
 
418
        operdef_t dummy_oper;
418
        operdef_t dummy_oper;
419
        funcdef_t dummy_func;
419
        funcdef_t dummy_func;
420
        symndef_t dummy_symn;
420
        symndef_t dummy_symn;
421
 
421
 
422
        Ptr newpipl = NULL, newaete = NULL;
422
        Ptr newpipl = NULL, newaete = NULL;
423
        LPVOID datap, aetep, manifestp;
423
        LPVOID datap, aetep, manifestp;
424
        char* manifestp_copy;
424
        char* manifestp_copy;
425
        PARM_T *pparm = NULL;
425
        PARM_T *pparm = NULL;
426
        size_t piplsize,aetesize,origsize;
426
        size_t piplsize,aetesize,origsize;
427
        char title[256];
427
        char title[256];
428
        LPCTSTR parm_type;
428
        LPCTSTR parm_type;
429
        LPCTSTR parm_id;
429
        LPCTSTR parm_id;
430
        Boolean discard = true;
430
        Boolean discard = true;
431
        uint64_t obfuscseed = 0, obfuscseed2 = 0;
431
        uint64_t obfuscseed = 0, obfuscseed2 = 0;
432
        long event_id;
432
        long event_id;
433
 
433
 
434
        memset(&dummy_oper, 0, sizeof(operdef_t));
434
        memset(&dummy_oper, 0, sizeof(operdef_t));
435
        memset(&dummy_func, 0, sizeof(funcdef_t));
435
        memset(&dummy_func, 0, sizeof(funcdef_t));
436
        memset(&dummy_symn, 0, sizeof(symndef_t));
436
        memset(&dummy_symn, 0, sizeof(symndef_t));
437
 
437
 
438
        if( (hupdate = _BeginUpdateResource(&dst->szName[0],false)) ){
438
        if( (hupdate = _BeginUpdateResource(&dst->szName[0],false)) ){
439
                if( (datarsrc = FindResource(hDllInstance,MAKEINTRESOURCE(16000 + bits), TEXT("TPLT")))
439
                if( (datarsrc = FindResource(hDllInstance,MAKEINTRESOURCE(16000 + bits), TEXT("TPLT")))
440
                        && (datah = LoadResource(hDllInstance,datarsrc))
440
                        && (datah = LoadResource(hDllInstance,datarsrc))
441
                        && (datap = (Ptr)LockResource(datah))
441
                        && (datap = (Ptr)LockResource(datah))
442
                        && (aetersrc = FindResource(hDllInstance, MAKEINTRESOURCE(16000), TEXT("AETE")))
442
                        && (aetersrc = FindResource(hDllInstance, MAKEINTRESOURCE(16000), TEXT("AETE")))
443
                        && (aeteh = LoadResource(hDllInstance, aetersrc))
443
                        && (aeteh = LoadResource(hDllInstance, aetersrc))
444
                        && (aetep = (Ptr)LockResource(aeteh))
444
                        && (aetep = (Ptr)LockResource(aeteh))
445
                        && (manifestsrc = FindResource(hDllInstance, MAKEINTRESOURCE(1), TEXT("TPLT")))
445
                        && (manifestsrc = FindResource(hDllInstance, MAKEINTRESOURCE(1), TEXT("TPLT")))
446
                        && (manifesth = LoadResource(hDllInstance, manifestsrc))
446
                        && (manifesth = LoadResource(hDllInstance, manifestsrc))
447
                        && (manifestp = (Ptr)LockResource(manifesth)) )
447
                        && (manifestp = (Ptr)LockResource(manifesth)) )
448
                {
448
                {
449
                        char* newmanifest;
449
                        char* newmanifest;
450
                        int manifestsize = SizeofResource(hDllInstance, manifestsrc);
450
                        int manifestsize = SizeofResource(hDllInstance, manifestsrc);
451
 
451
 
452
                        newmanifest = (char*)malloc((size_t)manifestsize + 4096/*+4KiB for name,description,etc.*/);
452
                        newmanifest = (char*)malloc((size_t)manifestsize + 4096/*+4KiB for name,description,etc.*/);
453
 
453
 
454
                        strcpy(title,gdata->parm.szTitle);
454
                        strcpy(title,gdata->parm.szTitle);
455
                        if(gdata->parm.popDialog)
455
                        if(gdata->parm.popDialog)
456
                                strcat(title,"...");
456
                                strcat(title,"...");
457
 
457
 
458
                        origsize = SizeofResource(hDllInstance,datarsrc);
458
                        origsize = SizeofResource(hDllInstance,datarsrc);
459
 
459
 
460
                        if( (newpipl = (Ptr)malloc(origsize+0x300))
460
                        if( (newpipl = (Ptr)malloc(origsize+0x300))
461
                         && (newaete = (Ptr)malloc(4096))
461
                         && (newaete = (Ptr)malloc(4096))
462
                         && (pparm = (PARM_T*)malloc(sizeof(PARM_T))) )
462
                         && (pparm = (PARM_T*)malloc(sizeof(PARM_T))) )
463
                        {
463
                        {
464
                                // ====== Generate AETE and PIPL
464
                                // ====== Generate AETE and PIPL
465
 
465
 
466
                                /* add user-specified title and category to new PiPL */
466
                                /* add user-specified title and category to new PiPL */
467
                                memcpy(newpipl,datap,origsize);
467
                                memcpy(newpipl,datap,origsize);
468
                                /* note that Windows PiPLs have 2 byte version datum in front
468
                                /* note that Windows PiPLs have 2 byte version datum in front
469
                                   that isn't reflected in struct definition or Mac resource template: */
469
                                   that isn't reflected in struct definition or Mac resource template: */
470
                                piplsize = fixpipl((PIPropertyList*)(newpipl+2),origsize-2,&title[0], &event_id) + 2;
470
                                piplsize = fixpipl((PIPropertyList*)(newpipl+2),origsize-2,&title[0], &event_id) + 2;
471
 
471
 
472
                                /* set up the PARM resource with saved parameters */
472
                                /* set up the PARM resource with saved parameters */
473
                                memcpy(pparm,&gdata->parm,sizeof(PARM_T));
473
                                memcpy(pparm,&gdata->parm,sizeof(PARM_T));
474
 
474
 
475
                                /* Generate 'aete' resource (contains names of the parameters for the "Actions" tab in Photoshop) */
475
                                /* Generate 'aete' resource (contains names of the parameters for the "Actions" tab in Photoshop) */
476
                                aetesize = aete_generate(newaete, pparm, event_id);
476
                                aetesize = aete_generate(newaete, pparm, event_id);
477
 
477
 
478
                                // ====== Create fitting manifest for the activation context
478
                                // ====== Create fitting manifest for the activation context
479
 
479
 
480
                                manifestp_copy = (char*)malloc((size_t)manifestsize + 1/*sz*/);
480
                                manifestp_copy = (char*)malloc((size_t)manifestsize + 1/*sz*/);
481
                                if (manifestp_copy != 0) {
481
                                if (manifestp_copy != 0) {
482
                                        memcpy(manifestp_copy, manifestp, manifestsize); // copy manifestp to manifestp_copy, because manifestp is readonly
482
                                        memcpy(manifestp_copy, manifestp, manifestsize); // copy manifestp to manifestp_copy, because manifestp is readonly
483
                                        manifestp_copy[manifestsize] = '\0'; // and add the null-terminating char, because domanifest() uses sprintf() on it
483
                                        manifestp_copy[manifestsize] = '\0'; // and add the null-terminating char, because domanifest() uses sprintf() on it
484
                                        manifestsize = domanifest(newmanifest, manifestp_copy, pparm, bits);
484
                                        manifestsize = domanifest(newmanifest, manifestp_copy, pparm, bits);
485
                                        free(manifestp_copy);
485
                                        free(manifestp_copy);
486
                                }
486
                                }
487
 
487
 
488
                                // ====== Change version attributes
488
                                // ====== Change version attributes
489
 
489
 
490
                                if (changeVersionInfo(dst, hupdate, pparm, bits) != NOERROR) {
490
                                if (changeVersionInfo(dst, hupdate, pparm, bits) != NOERROR) {
491
                                        simplewarning((TCHAR*)TEXT("changeVersionInfo failed")); // TODO (Not so important): TRANSLATE
491
                                        simplewarning((TCHAR*)TEXT("changeVersionInfo failed")); // TODO (Not so important): TRANSLATE
492
                                }
492
                                }
493
 
493
 
494
                                // ====== Obfuscate pparm!
494
                                // ====== Obfuscate pparm!
495
 
495
 
496
                                if (gdata->obfusc) {
496
                                if (gdata->obfusc) {
497
                                        parm_type = OBFUSCDATA_TYPE_NEW;
497
                                        parm_type = OBFUSCDATA_TYPE_NEW;
498
                                        parm_id = OBFUSCDATA_ID_NEW;
498
                                        parm_id = OBFUSCDATA_ID_NEW;
499
 
499
 
500
                                        // Note: After we have finished updating the resources, we will write <obfuscseed> into the binary code of the 8BF file
500
                                        // Note: After we have finished updating the resources, we will write <obfuscseed> into the binary code of the 8BF file
501
                                        obfusc(pparm, &obfuscseed, &obfuscseed2);
501
                                        obfusc(pparm, &obfuscseed, &obfuscseed2);
502
                                }else{
502
                                }else{
503
                                        parm_type = PARM_TYPE;
503
                                        parm_type = PARM_TYPE;
504
                                        parm_id = PARM_ID_NEW;
504
                                        parm_id = PARM_ID_NEW;
505
                                }
505
                                }
506
 
506
 
507
                                // ====== Save AETE, PIPL, Manifest and PARM/RCDATA
507
                                // ====== Save AETE, PIPL, Manifest and PARM/RCDATA
508
 
508
 
509
                                /* Attention: The resource we have found using FindResource() might have a different
509
                                /* Attention: The resource we have found using FindResource() might have a different
510
                                   language than the resource we are saving (Neutral), so we might end up having
510
                                   language than the resource we are saving (Neutral), so we might end up having
511
                                   multiple languages for the same resource. Therefore, the language "Neutral" was
511
                                   multiple languages for the same resource. Therefore, the language "Neutral" was
512
                                   set in the Scripting.rc file for the resource AETE and PIPL.rc for the resources PIPL. */
512
                                   set in the Scripting.rc file for the resource AETE and PIPL.rc for the resources PIPL. */
513
 
513
 
514
                                if(
514
                                if(
515
                                           _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
515
                                           _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
516
                                        && _UpdateResource(hupdate, RT_DIALOG, MAKEINTRESOURCE(ID_BUILDDLG), MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), NULL, 0) // clean up things we don't need in the standalone plugin
516
                                        && _UpdateResource(hupdate, RT_DIALOG, MAKEINTRESOURCE(ID_BUILDDLG), MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), NULL, 0) // clean up things we don't need in the standalone plugin
517
                                        && _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
517
                                        && _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
518
                                        && _UpdateResource(hupdate, RT_DIALOG, MAKEINTRESOURCE(ID_MAINDLG), MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), NULL, 0) // clean up things we don't need in the standalone plugin
518
                                        && _UpdateResource(hupdate, RT_DIALOG, MAKEINTRESOURCE(ID_MAINDLG), MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), NULL, 0) // clean up things we don't need in the standalone plugin
519
                                        && _UpdateResource(hupdate, RT_GROUP_ICON, TEXT("CAUTION_ICO"), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
519
                                        && _UpdateResource(hupdate, RT_GROUP_ICON, TEXT("CAUTION_ICO"), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
520
//                                      && _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
520
//                                      && _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
521
                                        && _UpdateResource(hupdate, RT_GROUP_CURSOR, TEXT("HAND_QUESTION"), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
521
                                        && _UpdateResource(hupdate, RT_GROUP_CURSOR, TEXT("HAND_QUESTION"), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
522
                                        // TODO: Removing the single resources don't work correctly. Sometimes the cursors are numbered 4,5,6 and sometimes 1,2,3 . Probably conflicts with icons
522
                                        // TODO: Removing the single resources don't work correctly. Sometimes the cursors are numbered 4,5,6 and sometimes 1,2,3 . Probably conflicts with icons
523
//                                      && _UpdateResource(hupdate, RT_CURSOR, MAKEINTRESOURCE(3)/*QuestionHand*/, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
523
//                                      && _UpdateResource(hupdate, RT_CURSOR, MAKEINTRESOURCE(3)/*QuestionHand*/, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), NULL, 0) // clean up things we don't need in the standalone plugin
524
                                        && _UpdateResource(hupdate, TEXT("PIPL") /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),newpipl,(DWORD)piplsize)
524
                                        && _UpdateResource(hupdate, TEXT("PIPL") /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),newpipl,(DWORD)piplsize)
525
                                        && _UpdateResource(hupdate, TEXT("AETE") /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newaete, (DWORD)aetesize)
525
                                        && _UpdateResource(hupdate, TEXT("AETE") /* note: caps!! */, MAKEINTRESOURCE(16000), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newaete, (DWORD)aetesize)
526
                                        // 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.
526
                                        // 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.
527
                                        && (gdata->obfusc || _UpdateResource(hupdate, TEXT("OPER"), MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_oper, sizeof(dummy_oper)))
527
                                        && (gdata->obfusc || _UpdateResource(hupdate, TEXT("OPER"), MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_oper, sizeof(dummy_oper)))
528
                                        && (gdata->obfusc || _UpdateResource(hupdate, TEXT("FUNC"), MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_func, sizeof(dummy_func)))
528
                                        && (gdata->obfusc || _UpdateResource(hupdate, TEXT("FUNC"), MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_func, sizeof(dummy_func)))
529
                                        && (gdata->obfusc || _UpdateResource(hupdate, TEXT("SYNM"), MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_symn, sizeof(dummy_symn)))
529
                                        && (gdata->obfusc || _UpdateResource(hupdate, TEXT("SYNM"), MAKEINTRESOURCE(16000), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), &dummy_symn, sizeof(dummy_symn)))
530
                                        && _UpdateResource(hupdate, RT_MANIFEST, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newmanifest, (DWORD)manifestsize)
530
                                        && _UpdateResource(hupdate, RT_MANIFEST, MAKEINTRESOURCE(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), newmanifest, (DWORD)manifestsize)
531
                                        && _UpdateResource(hupdate, parm_type,parm_id, MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),pparm,sizeof(PARM_T)) )
531
                                        && _UpdateResource(hupdate, parm_type,parm_id, MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),pparm,sizeof(PARM_T)) )
532
                                {
532
                                {
533
                                        discard = false;
533
                                        discard = false;
534
                                } else {
534
                                } else {
535
                                        showLastError((TCHAR*)TEXT("UpdateResource"));
535
                                        showLastError((TCHAR*)TEXT("UpdateResource"));
536
                                }
536
                                }
537
                        }
537
                        }
538
 
538
 
539
                        free(newmanifest);
539
                        free(newmanifest);
540
 
540
 
541
                        // Here, the file will be saved
541
                        // Here, the file will be saved
542
                        if (_EndUpdateResource(hupdate, discard)) {
542
                        if (_EndUpdateResource(hupdate, discard)) {
543
                                if (gdata->obfusc) {
543
                                if (gdata->obfusc) {
544
                                        // We modify the binary code to replace the deobfuscate-seed from <cObfuscSeed> to <obfuscseed>
544
                                        // We modify the binary code to replace the deobfuscate-seed from <cObfuscSeed> to <obfuscseed>
545
 
545
 
546
                                        // First try with alignment "4" (this should be the usual case),
546
                                        // First try with alignment "4" (this should be the usual case),
547
                                        // and if that failed, try without alignment ("1").
547
                                        // and if that failed, try without alignment ("1").
548
                                        // We only need to set maxamount to "1", because "const volatile" makes sure that
548
                                        // We only need to set maxamount to "1", because "const volatile" makes sure that
549
                                        // the compiler won't place (inline) it at several locations in the code.
549
                                        // the compiler won't place (inline) it at several locations in the code.
-
 
550
                                        // TODO: This is very slow
550
                                        if ((binary_replace_file(dst, GetObfuscSeed(), obfuscseed, /*align to 1*/0, /*maxamount=*/1) == 0) ||
551
                                        if ((binary_replace_file(dst, GetObfuscSeed(), obfuscseed, /*0 means "align to 1"*/0, /*maxamount=*/1) == 0) ||
551
                                                (binary_replace_file(dst, GetObfuscSeed2(), obfuscseed2, /*align to 1*/0, /*maxamount=*/1) == 0))
552
                                                (binary_replace_file(dst, GetObfuscSeed2(), obfuscseed2, /*0 means "align to 1"*/0, /*maxamount=*/1) == 0))
552
                                        {
553
                                        {
553
                                                simplewarning((TCHAR*)TEXT("binary_replace_file failed")); // TODO (Not so important): TRANSLATE
554
                                                simplewarning((TCHAR*)TEXT("binary_replace_file failed")); // TODO (Not so important): TRANSLATE
554
                                                discard = true;
555
                                                discard = true;
555
                                        }
556
                                        }
556
                                }
557
                                }
557
 
558
 
558
                                if (!update_pe_timestamp(dst, (__time32_t)time(0))) {
559
                                if (!update_pe_timestamp(dst, (__time32_t)time(0))) {
559
                                        simplewarning((TCHAR*)TEXT("update_pe_timestamp failed")); // TODO (Not so important): TRANSLATE
560
                                        simplewarning((TCHAR*)TEXT("update_pe_timestamp failed")); // TODO (Not so important): TRANSLATE
560
                                }
561
                                }
561
 
562
 
562
                                if (!repair_pe_checksum(dst)) {
563
                                if (!repair_pe_checksum(dst)) {
563
                                        simplewarning((TCHAR*)TEXT("repair_pe_checksum failed")); // TODO (Not so important): TRANSLATE
564
                                        simplewarning((TCHAR*)TEXT("repair_pe_checksum failed")); // TODO (Not so important): TRANSLATE
564
                                }
565
                                }
565
                        }else showLastError((TCHAR*)TEXT("EndUpdateResource"));
566
                        }else showLastError((TCHAR*)TEXT("EndUpdateResource"));
566
 
567
 
567
                }else showLastError((TCHAR*)TEXT("Find-, Load- or LockResource"));
568
                }else showLastError((TCHAR*)TEXT("Find-, Load- or LockResource"));
568
 
569
 
569
                if(pparm) free(pparm);
570
                if(pparm) free(pparm);
570
                if(newpipl) free(newpipl);
571
                if(newpipl) free(newpipl);
571
                if(newaete) free(newaete);
572
                if(newaete) free(newaete);
572
        }else
573
        }else
573
        showLastError((TCHAR*)TEXT("BeginUpdateResource"));
574
        showLastError((TCHAR*)TEXT("BeginUpdateResource"));
574
        return !discard;
575
        return !discard;
575
}
576
}
576
 
577
 
577
Boolean remove_64_filename_prefix(LPTSTR dstname) {
578
Boolean remove_64_filename_prefix(LPTSTR dstname) {
578
        // foobar.8bf => foobar.8bf
579
        // foobar.8bf => foobar.8bf
579
        // foobar64.8bf => foobar.8bf
580
        // foobar64.8bf => foobar.8bf
580
        size_t i;
581
        size_t i;
581
        for (i = xstrlen(dstname); i > 2; i--) {
582
        for (i = xstrlen(dstname); i > 2; i--) {
582
                if (dstname[i] == '.') {
583
                if (dstname[i] == '.') {
583
                        if ((dstname[i - 2] == '6') && (dstname[i - 1] == '4')) {
584
                        if ((dstname[i - 2] == '6') && (dstname[i - 1] == '4')) {
584
                                size_t tmp = xstrlen(dstname);
585
                                size_t tmp = xstrlen(dstname);
585
                                memcpy(&dstname[i - 2], &dstname[i], (xstrlen(dstname) - i + 1) * sizeof(TCHAR));
586
                                memcpy(&dstname[i - 2], &dstname[i], (xstrlen(dstname) - i + 1) * sizeof(TCHAR));
586
                                dstname[tmp - 2] = 0;
587
                                dstname[tmp - 2] = 0;
587
                                return true;
588
                                return true;
588
                        }
589
                        }
589
                }
590
                }
590
        }
591
        }
591
        return false;
592
        return false;
592
}
593
}
593
 
594
 
594
Boolean add_64_filename_prefix(LPTSTR dstname) {
595
Boolean add_64_filename_prefix(LPTSTR dstname) {
595
        // foobar.8bf => foobar64.8bf
596
        // foobar.8bf => foobar64.8bf
596
        size_t i;
597
        size_t i;
597
        for (i = xstrlen(dstname); i > 2; i--) {
598
        for (i = xstrlen(dstname); i > 2; i--) {
598
                if (dstname[i] == '.') {
599
                if (dstname[i] == '.') {
599
                        size_t tmp = xstrlen(dstname);
600
                        size_t tmp = xstrlen(dstname);
600
                        memcpy(&dstname[i + 2], &dstname[i], (xstrlen(dstname) - i + 1) * sizeof(TCHAR));
601
                        memcpy(&dstname[i + 2], &dstname[i], (xstrlen(dstname) - i + 1) * sizeof(TCHAR));
601
                        dstname[i] = '6';
602
                        dstname[i] = '6';
602
                        dstname[i + 1] = '4';
603
                        dstname[i + 1] = '4';
603
                        dstname[tmp + 2] = 0;
604
                        dstname[tmp + 2] = 0;
604
                        return true;
605
                        return true;
605
                }
606
                }
606
        }
607
        }
607
        return false;
608
        return false;
608
}
609
}
609
 
610
 
610
BOOL FileExists(LPCTSTR szPath) {
611
BOOL FileExists(LPCTSTR szPath) {
611
        DWORD dwAttrib = GetFileAttributes(szPath);
612
        DWORD dwAttrib = GetFileAttributes(szPath);
612
        return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
613
        return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
613
                !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
614
                !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
614
}
615
}
615
 
616
 
616
Boolean extract_file(LPCTSTR lpType, LPCTSTR lpName, FSSpec* dst) {
617
Boolean extract_file(LPCTSTR lpType, LPCTSTR lpName, FSSpec* dst) {
617
        HGLOBAL datah;
618
        HGLOBAL datah;
618
        LPVOID datap;
619
        LPVOID datap;
619
        HRSRC datarsrc;
620
        HRSRC datarsrc;
620
        FILECOUNT datalen;
621
        FILECOUNT datalen;
621
        FILEREF fptr;
622
        FILEREF fptr;
622
        OSErr res;
623
        OSErr res;
623
 
624
 
624
        if ((datarsrc = FindResource((HMODULE)hDllInstance, lpName, lpType))
625
        if ((datarsrc = FindResource((HMODULE)hDllInstance, lpName, lpType))
625
                && (datah = LoadResource((HMODULE)hDllInstance, datarsrc))
626
                && (datah = LoadResource((HMODULE)hDllInstance, datarsrc))
626
                && (datalen = (FILECOUNT)SizeofResource((HMODULE)hDllInstance, datarsrc))
627
                && (datalen = (FILECOUNT)SizeofResource((HMODULE)hDllInstance, datarsrc))
627
                && (datap = (Ptr)LockResource(datah))) {
628
                && (datap = (Ptr)LockResource(datah))) {
628
 
629
 
629
                FSpDelete(dst);
630
                FSpDelete(dst);
630
                if (FSpCreate(dst, kPhotoshopSignature, PS_FILTER_FILETYPE, 0/*sfr->sfScript*/) != noErr) return false;
631
                if (FSpCreate(dst, kPhotoshopSignature, PS_FILTER_FILETYPE, 0/*sfr->sfScript*/) != noErr) return false;
631
 
632
 
632
                if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return false;
633
                if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return false;
633
 
634
 
634
                res = FSWrite(fptr, &datalen, datap);
635
                res = FSWrite(fptr, &datalen, datap);
635
 
636
 
636
                FSClose(fptr);
637
                FSClose(fptr);
637
 
638
 
638
                return res == noErr;
639
                return res == noErr;
639
        }
640
        }
640
        else {
641
        else {
641
                return false;
642
                return false;
642
        }
643
        }
643
}
644
}
644
 
645
 
645
BOOL StripAuthenticode(FSSpec* dst) {
646
BOOL StripAuthenticode(FSSpec* dst) {
646
        HANDLE hFile = CreateFile(&dst->szName[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
647
        HANDLE hFile = CreateFile(&dst->szName[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
647
        if (hFile == INVALID_HANDLE_VALUE) {
648
        if (hFile == INVALID_HANDLE_VALUE) {
648
                CloseHandle(hFile);
649
                CloseHandle(hFile);
649
                return FALSE;
650
                return FALSE;
650
        }
651
        }
651
        if (!_ImageRemoveCertificate(hFile, 0)) {
652
        if (!_ImageRemoveCertificate(hFile, 0)) {
652
                CloseHandle(hFile);
653
                CloseHandle(hFile);
653
                return FALSE;
654
                return FALSE;
654
        }
655
        }
655
        CloseHandle(hFile);
656
        CloseHandle(hFile);
656
        return TRUE;
657
        return TRUE;
657
}
658
}
658
 
659
 
659
OSErr do_make_standalone(FSSpec* dst, int bits) {
660
OSErr do_make_standalone(FSSpec* dst, int bits) {
660
        Boolean res;
661
        Boolean res;
661
 
662
 
662
        //DeleteFile(dstname);
663
        //DeleteFile(dstname);
663
        if (extract_file(TEXT("TPLT"), MAKEINTRESOURCE(1000 + bits), dst)) {
664
        if (extract_file(TEXT("TPLT"), MAKEINTRESOURCE(1000 + bits), dst)) {
664
                // In case we did digitally sign the FilterFoundry plugin (which is currently not the case though),
665
                // In case we did digitally sign the FilterFoundry plugin (which is currently not the case though),
665
                // we must now remove the signature, because the embedding of parameter data has invalidated it.
666
                // we must now remove the signature, because the embedding of parameter data has invalidated it.
666
                // Do it before we manipulate anything, in order to avoid that there is an invalid binary (which might annoy AntiVirus software)
667
                // Do it before we manipulate anything, in order to avoid that there is an invalid binary (which might annoy AntiVirus software)
667
                StripAuthenticode(dst);
668
                StripAuthenticode(dst);
668
 
669
 
669
                // Now do the resources
670
                // Now do the resources
670
                res = doresources(dst, bits);
671
                res = doresources(dst, bits);
671
                if (!res) {
672
                if (!res) {
672
                        DeleteFile(&dst->szName[0]);
673
                        DeleteFile(&dst->szName[0]);
673
                        alertuser_id(bits == 32 ? MSG_CANNOT_CREATE_32BIT_FILTER_ID : MSG_CANNOT_CREATE_64BIT_FILTER_ID, (TCHAR*)TEXT("doresources failed"));
674
                        alertuser_id(bits == 32 ? MSG_CANNOT_CREATE_32BIT_FILTER_ID : MSG_CANNOT_CREATE_64BIT_FILTER_ID, (TCHAR*)TEXT("doresources failed"));
674
                }
675
                }
675
        }
676
        }
676
        else {
677
        else {
677
                // If you see this error, please make sure that you have called foundry_3264_mixer to include the 32/64 plugins as resource!
678
                // If you see this error, please make sure that you have called foundry_3264_mixer to include the 32/64 plugins as resource!
678
                res = false;
679
                res = false;
679
                //DeleteFile(dstname);
680
                //DeleteFile(dstname);
680
 
681
 
681
                alertuser_id(bits == 32 ? MSG_CANNOT_CREATE_32BIT_FILTER_ID : MSG_CANNOT_CREATE_64BIT_FILTER_ID, (TCHAR*)TEXT("extract_file failed"));
682
                alertuser_id(bits == 32 ? MSG_CANNOT_CREATE_32BIT_FILTER_ID : MSG_CANNOT_CREATE_64BIT_FILTER_ID, (TCHAR*)TEXT("extract_file failed"));
682
        }
683
        }
683
 
684
 
684
        return res ? noErr : ioErr;
685
        return res ? noErr : ioErr;
685
}
686
}
686
 
687
 
687
OSErr make_standalone(StandardFileReply *sfr){
688
OSErr make_standalone(StandardFileReply *sfr){
688
        OSErr tmpErr, outErr;
689
        OSErr tmpErr, outErr;
689
        FSSpec dst = { 0 };
690
        FSSpec dst = { 0 };
690
 
691
 
691
        outErr = noErr;
692
        outErr = noErr;
692
 
693
 
693
        // Make 32 bit:
694
        // Make 32 bit:
694
        // Destfile = no64_or_32(chosenname)
695
        // Destfile = no64_or_32(chosenname)
695
        xstrcpy(dst.szName, sfr->sfFile.szName);
696
        xstrcpy(dst.szName, sfr->sfFile.szName);
696
        remove_64_filename_prefix(&dst.szName[0]);
697
        remove_64_filename_prefix(&dst.szName[0]);
697
        tmpErr = do_make_standalone(&dst, 32);
698
        tmpErr = do_make_standalone(&dst, 32);
698
        if (tmpErr != noErr)
699
        if (tmpErr != noErr)
699
                outErr = tmpErr;
700
                outErr = tmpErr;
700
        else
701
        else
701
                showmessage_id(MSG_BUILT32_ID);
702
                showmessage_id(MSG_BUILT32_ID);
702
 
703
 
703
        // Make 64 bit:
704
        // Make 64 bit:
704
        // Destfile = no64_or_32(chosenname) + 64
705
        // Destfile = no64_or_32(chosenname) + 64
705
        xstrcpy(dst.szName, sfr->sfFile.szName);
706
        xstrcpy(dst.szName, sfr->sfFile.szName);
706
        remove_64_filename_prefix(&dst.szName[0]);
707
        remove_64_filename_prefix(&dst.szName[0]);
707
        add_64_filename_prefix(&dst.szName[0]);
708
        add_64_filename_prefix(&dst.szName[0]);
708
        tmpErr = do_make_standalone(&dst, 64);
709
        tmpErr = do_make_standalone(&dst, 64);
709
        if (tmpErr != noErr)
710
        if (tmpErr != noErr)
710
                outErr = tmpErr;
711
                outErr = tmpErr;
711
        else
712
        else
712
                showmessage_id(MSG_BUILT64_ID);
713
                showmessage_id(MSG_BUILT64_ID);
713
 
714
 
714
        return outErr;
715
        return outErr;
715
}
716
}
716
 
717
 
717
 
718