aibika 1.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +11 -0
- data/History.txt +214 -0
- data/LICENSE.md +30 -0
- data/Manifest.txt +11 -0
- data/README.adoc +564 -0
- data/Rakefile +30 -0
- data/aibika.gemspec +50 -0
- data/bin/aibika +25 -0
- data/lib/aibika/aibika_builder.rb +191 -0
- data/lib/aibika/cli.rb +181 -0
- data/lib/aibika/host.rb +40 -0
- data/lib/aibika/library_detector.rb +88 -0
- data/lib/aibika/pathname.rb +158 -0
- data/lib/aibika/version.rb +5 -0
- data/lib/aibika.rb +675 -0
- data/samples/activerecord_sample.rb +6 -0
- data/samples/bundler_git/Gemfile +3 -0
- data/samples/bundler_git/bundler_git.rb +5 -0
- data/samples/mech.rb +8 -0
- data/samples/mime-types_sample.rb +4 -0
- data/samples/pg_sample.rb +4 -0
- data/samples/prawn_sample.rb +9 -0
- data/samples/readchar.rb +4 -0
- data/samples/sysproctable.rb +12 -0
- data/samples/tk.rb +13 -0
- data/samples/tkextlib.rb +4 -0
- data/samples/watir_sample.rb +31 -0
- data/samples/win32_api_sample.rb +5 -0
- data/samples/win32ole.rb +4 -0
- data/samples/wxruby_sample.rbw +29 -0
- data/share/aibika/lzma.exe +0 -0
- data/src/Makefile +37 -0
- data/src/edicon.c +146 -0
- data/src/lzma/LzmaDec.c +1007 -0
- data/src/lzma/LzmaDec.h +223 -0
- data/src/lzma/Types.h +208 -0
- data/src/seb.exe +0 -0
- data/src/stub.c +703 -0
- data/src/stub.rc +1 -0
- data/src/vit-ruby.ico +0 -0
- metadata +109 -0
data/src/stub.c
ADDED
@@ -0,0 +1,703 @@
|
|
1
|
+
/*
|
2
|
+
Single Executable Bundle Stub
|
3
|
+
|
4
|
+
This stub reads itself for embedded instructions to create directory
|
5
|
+
and files in a temporary directory, launching a program.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include <windows.h>
|
9
|
+
#include <string.h>
|
10
|
+
#include <tchar.h>
|
11
|
+
#include <stdio.h>
|
12
|
+
|
13
|
+
const BYTE Signature[] = { 0x41, 0xb6, 0xba, 0x4e };
|
14
|
+
|
15
|
+
#define OP_END 0
|
16
|
+
#define OP_CREATE_DIRECTORY 1
|
17
|
+
#define OP_CREATE_FILE 2
|
18
|
+
#define OP_CREATE_PROCESS 3
|
19
|
+
#define OP_DECOMPRESS_LZMA 4
|
20
|
+
#define OP_SETENV 5
|
21
|
+
#define OP_POST_CREATE_PROCRESS 6
|
22
|
+
#define OP_ENABLE_DEBUG_MODE 7
|
23
|
+
#define OP_CREATE_INST_DIRECTORY 8
|
24
|
+
#define OP_MAX 9
|
25
|
+
|
26
|
+
BOOL ProcessImage(LPVOID p, DWORD size);
|
27
|
+
BOOL ProcessOpcodes(LPVOID* p);
|
28
|
+
void CreateAndWaitForProcess(LPTSTR ApplicationName, LPTSTR CommandLine);
|
29
|
+
|
30
|
+
BOOL OpEnd(LPVOID* p);
|
31
|
+
BOOL OpCreateFile(LPVOID* p);
|
32
|
+
BOOL OpCreateDirectory(LPVOID* p);
|
33
|
+
BOOL OpCreateProcess(LPVOID* p);
|
34
|
+
BOOL OpDecompressLzma(LPVOID* p);
|
35
|
+
BOOL OpSetEnv(LPVOID* p);
|
36
|
+
BOOL OpPostCreateProcess(LPVOID* p);
|
37
|
+
BOOL OpEnableDebugMode(LPVOID* p);
|
38
|
+
BOOL OpCreateInstDirectory(LPVOID* p);
|
39
|
+
|
40
|
+
#if WITH_LZMA
|
41
|
+
#include <LzmaDec.h>
|
42
|
+
#endif
|
43
|
+
|
44
|
+
typedef BOOL (*POpcodeHandler)(LPVOID*);
|
45
|
+
|
46
|
+
LPTSTR PostCreateProcess_ApplicationName = NULL;
|
47
|
+
LPTSTR PostCreateProcess_CommandLine = NULL;
|
48
|
+
|
49
|
+
DWORD ExitStatus = 0;
|
50
|
+
BOOL ExitCondition = FALSE;
|
51
|
+
BOOL DebugModeEnabled = FALSE;
|
52
|
+
BOOL DeleteInstDirEnabled = FALSE;
|
53
|
+
BOOL ChdirBeforeRunEnabled = TRUE;
|
54
|
+
TCHAR ImageFileName[MAX_PATH];
|
55
|
+
|
56
|
+
#if _CONSOLE
|
57
|
+
#define FATAL(...) { fprintf(stderr, "FATAL ERROR: "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); }
|
58
|
+
#else
|
59
|
+
#define FATAL(...) { \
|
60
|
+
TCHAR TextBuffer[1024]; \
|
61
|
+
_sntprintf(TextBuffer, 1024, __VA_ARGS__); \
|
62
|
+
MessageBox(NULL, TextBuffer, _T("AIBIKA"), MB_OK | MB_ICONWARNING); \
|
63
|
+
}
|
64
|
+
#endif
|
65
|
+
|
66
|
+
#if _CONSOLE
|
67
|
+
#define DEBUG(...) { if (DebugModeEnabled) { fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); } }
|
68
|
+
#else
|
69
|
+
#define DEBUG(...)
|
70
|
+
#endif
|
71
|
+
|
72
|
+
POpcodeHandler OpcodeHandlers[OP_MAX] =
|
73
|
+
{
|
74
|
+
&OpEnd,
|
75
|
+
&OpCreateDirectory,
|
76
|
+
&OpCreateFile,
|
77
|
+
&OpCreateProcess,
|
78
|
+
#if WITH_LZMA
|
79
|
+
&OpDecompressLzma,
|
80
|
+
#else
|
81
|
+
NULL,
|
82
|
+
#endif
|
83
|
+
&OpSetEnv,
|
84
|
+
&OpPostCreateProcess,
|
85
|
+
&OpEnableDebugMode,
|
86
|
+
&OpCreateInstDirectory,
|
87
|
+
};
|
88
|
+
|
89
|
+
TCHAR InstDir[MAX_PATH];
|
90
|
+
|
91
|
+
/** Decoder: Zero-terminated string */
|
92
|
+
LPTSTR GetString(LPVOID* p)
|
93
|
+
{
|
94
|
+
LPTSTR str = *p;
|
95
|
+
*p += lstrlen(str) + sizeof(TCHAR);
|
96
|
+
return str;
|
97
|
+
}
|
98
|
+
|
99
|
+
/** Decoder: 32 bit unsigned integer */
|
100
|
+
DWORD GetInteger(LPVOID* p)
|
101
|
+
{
|
102
|
+
DWORD dw = *(DWORD*)*p;
|
103
|
+
*p += 4;
|
104
|
+
return dw;
|
105
|
+
}
|
106
|
+
|
107
|
+
/**
|
108
|
+
Handler for console events.
|
109
|
+
*/
|
110
|
+
BOOL WINAPI ConsoleHandleRoutine(DWORD dwCtrlType)
|
111
|
+
{
|
112
|
+
// Ignore all events. They will also be dispatched to the child procress (Ruby) which should
|
113
|
+
// exit quickly, allowing us to clean up.
|
114
|
+
return TRUE;
|
115
|
+
}
|
116
|
+
|
117
|
+
void FindExeDir(TCHAR* d)
|
118
|
+
{
|
119
|
+
strncpy(d, ImageFileName, MAX_PATH);
|
120
|
+
unsigned int i;
|
121
|
+
for (i = strlen(d)-1; i >= 0; --i)
|
122
|
+
{
|
123
|
+
if (i == 0 || d[i] == '\\')
|
124
|
+
{
|
125
|
+
d[i] = 0;
|
126
|
+
break;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
BOOL DeleteRecursively(LPTSTR path)
|
132
|
+
{
|
133
|
+
TCHAR findPath[MAX_PATH];
|
134
|
+
DWORD pathLength;
|
135
|
+
WIN32_FIND_DATA findData;
|
136
|
+
HANDLE handle;
|
137
|
+
BOOL AnyFailed = FALSE;
|
138
|
+
|
139
|
+
lstrcpy(findPath, path);
|
140
|
+
pathLength = lstrlen(findPath);
|
141
|
+
if (pathLength > 1 && pathLength < MAX_PATH - 2) {
|
142
|
+
if (path[pathLength-1] == '\\')
|
143
|
+
lstrcat(findPath, "*");
|
144
|
+
else {
|
145
|
+
lstrcat(findPath, "\\*");
|
146
|
+
++pathLength;
|
147
|
+
}
|
148
|
+
handle = FindFirstFile(findPath, &findData);
|
149
|
+
findPath[pathLength] = 0;
|
150
|
+
if (handle != INVALID_HANDLE_VALUE) {
|
151
|
+
do {
|
152
|
+
if (pathLength + lstrlen(findData.cFileName) < MAX_PATH) {
|
153
|
+
TCHAR subPath[MAX_PATH];
|
154
|
+
lstrcpy(subPath, findPath);
|
155
|
+
lstrcat(subPath, findData.cFileName);
|
156
|
+
if ((lstrcmp(findData.cFileName, ".") != 0) && (lstrcmp(findData.cFileName, "..") != 0)) {
|
157
|
+
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
158
|
+
if (!DeleteRecursively(subPath))
|
159
|
+
AnyFailed = TRUE;
|
160
|
+
} else {
|
161
|
+
if (!DeleteFile(subPath)) {
|
162
|
+
MoveFileEx(subPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
|
163
|
+
AnyFailed = TRUE;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
} else {
|
168
|
+
AnyFailed = TRUE;
|
169
|
+
}
|
170
|
+
} while (FindNextFile(handle, &findData));
|
171
|
+
FindClose(handle);
|
172
|
+
}
|
173
|
+
} else {
|
174
|
+
AnyFailed = TRUE;
|
175
|
+
}
|
176
|
+
if (!RemoveDirectory(findPath)) {
|
177
|
+
MoveFileEx(findPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
|
178
|
+
AnyFailed = TRUE;
|
179
|
+
}
|
180
|
+
return AnyFailed;
|
181
|
+
}
|
182
|
+
|
183
|
+
void MarkForDeletion(LPTSTR path)
|
184
|
+
{
|
185
|
+
TCHAR marker[MAX_PATH];
|
186
|
+
lstrcpy(marker, path);
|
187
|
+
lstrcat(marker, ".aibika-delete-me");
|
188
|
+
HANDLE h = CreateFile(marker, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
189
|
+
CloseHandle(h);
|
190
|
+
}
|
191
|
+
|
192
|
+
void DeleteRecursivelyNowOrLater(LPTSTR path)
|
193
|
+
{
|
194
|
+
DEBUG("DeleteRecursivelyNowOrLater: %s", path);
|
195
|
+
if (!DeleteRecursively(path))
|
196
|
+
MarkForDeletion(path);
|
197
|
+
}
|
198
|
+
|
199
|
+
void DeleteOldFiles()
|
200
|
+
{
|
201
|
+
TCHAR path[MAX_PATH];
|
202
|
+
DWORD len = GetTempPath(MAX_PATH, path);
|
203
|
+
if (path[len-1] != '\\') {
|
204
|
+
lstrcat(path, "\\");
|
205
|
+
len += 1;
|
206
|
+
}
|
207
|
+
lstrcat(path, "*.aibika-delete-me");
|
208
|
+
WIN32_FIND_DATA findData;
|
209
|
+
HANDLE handle = FindFirstFile(path, &findData);
|
210
|
+
path[len] = 0;
|
211
|
+
if (handle == INVALID_HANDLE_VALUE)
|
212
|
+
return;
|
213
|
+
do {
|
214
|
+
TCHAR aibikaPath[MAX_PATH];
|
215
|
+
lstrcpy(aibikaPath, path);
|
216
|
+
lstrcat(aibikaPath, findData.cFileName);
|
217
|
+
DeleteFile(aibikaPath);
|
218
|
+
DWORD len = lstrlen(aibikaPath);
|
219
|
+
len -= lstrlen(".aibika-delete-me");
|
220
|
+
aibikaPath[len] = 0;
|
221
|
+
DeleteRecursivelyNowOrLater(aibikaPath);
|
222
|
+
} while (FindNextFile(handle, &findData));
|
223
|
+
FindClose(handle);
|
224
|
+
}
|
225
|
+
|
226
|
+
BOOL OpCreateInstDirectory(LPVOID* p)
|
227
|
+
{
|
228
|
+
DWORD DebugExtractMode = GetInteger(p);
|
229
|
+
|
230
|
+
DeleteInstDirEnabled = GetInteger(p);
|
231
|
+
ChdirBeforeRunEnabled = GetInteger(p);
|
232
|
+
|
233
|
+
/* Create an installation directory that will hold the extracted files */
|
234
|
+
TCHAR TempPath[MAX_PATH];
|
235
|
+
if (DebugExtractMode)
|
236
|
+
{
|
237
|
+
// In debug extraction mode, create the temp directory next to the exe
|
238
|
+
FindExeDir(TempPath);
|
239
|
+
if (strlen(TempPath) == 0)
|
240
|
+
{
|
241
|
+
FATAL("Unable to find directory containing exe");
|
242
|
+
return FALSE;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
else
|
246
|
+
{
|
247
|
+
GetTempPath(MAX_PATH, TempPath);
|
248
|
+
}
|
249
|
+
|
250
|
+
UINT tempResult = GetTempFileName(TempPath, _T("aibikastub"), 0, InstDir);
|
251
|
+
if (tempResult == 0u)
|
252
|
+
{
|
253
|
+
FATAL("Failed to get temp file name.");
|
254
|
+
return FALSE;
|
255
|
+
}
|
256
|
+
|
257
|
+
DEBUG("Creating installation directory: '%s'", InstDir);
|
258
|
+
|
259
|
+
/* Attempt to delete the temp file created by GetTempFileName.
|
260
|
+
Ignore errors, i.e. if it doesn't exist. */
|
261
|
+
(void)DeleteFile(InstDir);
|
262
|
+
|
263
|
+
if (!CreateDirectory(InstDir, NULL))
|
264
|
+
{
|
265
|
+
FATAL("Failed to create installation directory.");
|
266
|
+
return FALSE;
|
267
|
+
}
|
268
|
+
return TRUE;
|
269
|
+
}
|
270
|
+
|
271
|
+
int CALLBACK _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
|
272
|
+
{
|
273
|
+
DeleteOldFiles();
|
274
|
+
|
275
|
+
/* Find name of image */
|
276
|
+
if (!GetModuleFileName(NULL, ImageFileName, MAX_PATH))
|
277
|
+
{
|
278
|
+
FATAL("Failed to get executable name (error %lu).", GetLastError());
|
279
|
+
return -1;
|
280
|
+
}
|
281
|
+
|
282
|
+
|
283
|
+
/* By default, assume the installation directory is wherever the EXE is */
|
284
|
+
FindExeDir(InstDir);
|
285
|
+
|
286
|
+
/* Set up environment */
|
287
|
+
SetEnvironmentVariable(_T("AIBIKA_EXECUTABLE"), ImageFileName);
|
288
|
+
|
289
|
+
SetConsoleCtrlHandler(&ConsoleHandleRoutine, TRUE);
|
290
|
+
|
291
|
+
/* Open the image (executable) */
|
292
|
+
HANDLE hImage = CreateFile(ImageFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
293
|
+
if (hImage == INVALID_HANDLE_VALUE)
|
294
|
+
{
|
295
|
+
FATAL("Failed to open executable (%s)", ImageFileName);
|
296
|
+
return -1;
|
297
|
+
}
|
298
|
+
|
299
|
+
/* Create a file mapping */
|
300
|
+
DWORD FileSize = GetFileSize(hImage, NULL);
|
301
|
+
HANDLE hMem = CreateFileMapping(hImage, NULL, PAGE_READONLY, 0, FileSize, NULL);
|
302
|
+
if (hMem == INVALID_HANDLE_VALUE)
|
303
|
+
{
|
304
|
+
FATAL("Failed to create file mapping (error %lu)", GetLastError());
|
305
|
+
CloseHandle(hImage);
|
306
|
+
return -1;
|
307
|
+
}
|
308
|
+
|
309
|
+
/* Map the image into memory */
|
310
|
+
LPVOID lpv = MapViewOfFile(hMem, FILE_MAP_READ, 0, 0, 0);
|
311
|
+
if (lpv == NULL)
|
312
|
+
{
|
313
|
+
FATAL("Failed to map view of executable into memory (error %lu).", GetLastError());
|
314
|
+
}
|
315
|
+
else
|
316
|
+
{
|
317
|
+
if (!ProcessImage(lpv, FileSize))
|
318
|
+
{
|
319
|
+
ExitStatus = -1;
|
320
|
+
}
|
321
|
+
|
322
|
+
if (!UnmapViewOfFile(lpv))
|
323
|
+
{
|
324
|
+
FATAL("Failed to unmap view of executable.");
|
325
|
+
}
|
326
|
+
}
|
327
|
+
|
328
|
+
if (!CloseHandle(hMem))
|
329
|
+
{
|
330
|
+
FATAL("Failed to close file mapping.");
|
331
|
+
}
|
332
|
+
|
333
|
+
if (!CloseHandle(hImage))
|
334
|
+
{
|
335
|
+
FATAL("Failed to close executable.");
|
336
|
+
}
|
337
|
+
|
338
|
+
if (ChdirBeforeRunEnabled)
|
339
|
+
{
|
340
|
+
DEBUG("Changing CWD to unpacked directory %s/src", InstDir);
|
341
|
+
SetCurrentDirectory(InstDir);
|
342
|
+
SetCurrentDirectory("./src");
|
343
|
+
}
|
344
|
+
|
345
|
+
if (PostCreateProcess_ApplicationName && PostCreateProcess_CommandLine)
|
346
|
+
{
|
347
|
+
DEBUG("**********");
|
348
|
+
DEBUG("Starting app in: %s", InstDir);
|
349
|
+
DEBUG("**********");
|
350
|
+
CreateAndWaitForProcess(PostCreateProcess_ApplicationName, PostCreateProcess_CommandLine);
|
351
|
+
}
|
352
|
+
|
353
|
+
if (DeleteInstDirEnabled)
|
354
|
+
{
|
355
|
+
DEBUG("Deleting temporary installation directory %s", InstDir);
|
356
|
+
TCHAR SystemDirectory[MAX_PATH];
|
357
|
+
if (GetSystemDirectory(SystemDirectory, MAX_PATH) > 0)
|
358
|
+
SetCurrentDirectory(SystemDirectory);
|
359
|
+
else
|
360
|
+
SetCurrentDirectory("C:\\");
|
361
|
+
DeleteRecursivelyNowOrLater(InstDir);
|
362
|
+
}
|
363
|
+
|
364
|
+
ExitProcess(ExitStatus);
|
365
|
+
|
366
|
+
/* Never gets here */
|
367
|
+
return 0;
|
368
|
+
}
|
369
|
+
|
370
|
+
/**
|
371
|
+
Process the image by checking the signature and locating the first
|
372
|
+
opcode.
|
373
|
+
*/
|
374
|
+
BOOL ProcessImage(LPVOID ptr, DWORD size)
|
375
|
+
{
|
376
|
+
LPVOID pSig = ptr + size - 4;
|
377
|
+
if (memcmp(pSig, Signature, 4) == 0)
|
378
|
+
{
|
379
|
+
DEBUG("Good signature found.");
|
380
|
+
DWORD OpcodeOffset = *(DWORD*)(pSig - 4);
|
381
|
+
LPVOID pSeg = ptr + OpcodeOffset;
|
382
|
+
return ProcessOpcodes(&pSeg);
|
383
|
+
}
|
384
|
+
else
|
385
|
+
{
|
386
|
+
FATAL("Bad signature in executable.");
|
387
|
+
return FALSE;
|
388
|
+
}
|
389
|
+
}
|
390
|
+
|
391
|
+
/**
|
392
|
+
Process the opcodes in memory.
|
393
|
+
*/
|
394
|
+
BOOL ProcessOpcodes(LPVOID* p)
|
395
|
+
{
|
396
|
+
while (!ExitCondition)
|
397
|
+
{
|
398
|
+
DWORD opcode = GetInteger(p);
|
399
|
+
if (opcode < OP_MAX)
|
400
|
+
{
|
401
|
+
if (!OpcodeHandlers[opcode](p))
|
402
|
+
{
|
403
|
+
return FALSE;
|
404
|
+
}
|
405
|
+
}
|
406
|
+
else
|
407
|
+
{
|
408
|
+
FATAL("Invalid opcode '%lu'.", opcode);
|
409
|
+
return FALSE;
|
410
|
+
}
|
411
|
+
}
|
412
|
+
return TRUE;
|
413
|
+
}
|
414
|
+
|
415
|
+
/**
|
416
|
+
Expands a specially formatted string, replacing | with the
|
417
|
+
temporary installation directory.
|
418
|
+
*/
|
419
|
+
void ExpandPath(LPTSTR* out, LPTSTR str)
|
420
|
+
{
|
421
|
+
DWORD OutSize = lstrlen(str) + sizeof(TCHAR);
|
422
|
+
LPTSTR a = str;
|
423
|
+
while ((a = _tcschr(a, L'|')))
|
424
|
+
{
|
425
|
+
OutSize += lstrlen(InstDir) - sizeof(TCHAR);
|
426
|
+
a++;
|
427
|
+
}
|
428
|
+
|
429
|
+
*out = LocalAlloc(LMEM_FIXED, OutSize);
|
430
|
+
|
431
|
+
LPTSTR OutPtr = *out;
|
432
|
+
while ((a = _tcschr(str, L'|')))
|
433
|
+
{
|
434
|
+
int l = a - str;
|
435
|
+
if (l > 0)
|
436
|
+
{
|
437
|
+
memcpy(OutPtr, str, l);
|
438
|
+
OutPtr += l;
|
439
|
+
str += l;
|
440
|
+
}
|
441
|
+
str += sizeof(TCHAR);
|
442
|
+
lstrcpy(OutPtr, InstDir);
|
443
|
+
OutPtr += lstrlen(OutPtr);
|
444
|
+
}
|
445
|
+
lstrcpy(OutPtr, str);
|
446
|
+
}
|
447
|
+
|
448
|
+
/**
|
449
|
+
Finds the start of the first argument after the current one. Handles quoted arguments.
|
450
|
+
*/
|
451
|
+
LPTSTR SkipArg(LPTSTR str)
|
452
|
+
{
|
453
|
+
if (*str == '"')
|
454
|
+
{
|
455
|
+
str++;
|
456
|
+
while (*str && *str != '"') { str++; }
|
457
|
+
if (*str == '"') { str++; }
|
458
|
+
}
|
459
|
+
else
|
460
|
+
{
|
461
|
+
while (*str && *str != ' ') { str++; }
|
462
|
+
}
|
463
|
+
while (*str && *str != ' ') { str++; }
|
464
|
+
return str;
|
465
|
+
}
|
466
|
+
|
467
|
+
/**
|
468
|
+
Create a file (OP_CREATE_FILE opcode handler)
|
469
|
+
*/
|
470
|
+
BOOL OpCreateFile(LPVOID* p)
|
471
|
+
{
|
472
|
+
BOOL Result = TRUE;
|
473
|
+
LPTSTR FileName = GetString(p);
|
474
|
+
DWORD FileSize = GetInteger(p);
|
475
|
+
LPVOID Data = *p;
|
476
|
+
*p += FileSize;
|
477
|
+
|
478
|
+
TCHAR Fn[MAX_PATH];
|
479
|
+
lstrcpy(Fn, InstDir);
|
480
|
+
lstrcat(Fn, _T("\\"));
|
481
|
+
lstrcat(Fn, FileName);
|
482
|
+
|
483
|
+
DEBUG("CreateFile(%s, %lu)", Fn, FileSize);
|
484
|
+
HANDLE hFile = CreateFile(Fn, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
485
|
+
if (hFile != INVALID_HANDLE_VALUE)
|
486
|
+
{
|
487
|
+
DWORD BytesWritten;
|
488
|
+
if (!WriteFile(hFile, Data, FileSize, &BytesWritten, NULL))
|
489
|
+
{
|
490
|
+
FATAL("Write failure (%lu)", GetLastError());
|
491
|
+
Result = FALSE;
|
492
|
+
}
|
493
|
+
if (BytesWritten != FileSize)
|
494
|
+
{
|
495
|
+
FATAL("Write size failure");
|
496
|
+
Result = FALSE;
|
497
|
+
}
|
498
|
+
CloseHandle(hFile);
|
499
|
+
}
|
500
|
+
else
|
501
|
+
{
|
502
|
+
FATAL("Failed to create file '%s'", Fn);
|
503
|
+
Result = FALSE;
|
504
|
+
}
|
505
|
+
|
506
|
+
return Result;
|
507
|
+
}
|
508
|
+
|
509
|
+
/**
|
510
|
+
Create a directory (OP_CREATE_DIRECTORY opcode handler)
|
511
|
+
*/
|
512
|
+
BOOL OpCreateDirectory(LPVOID* p)
|
513
|
+
{
|
514
|
+
LPTSTR DirectoryName = GetString(p);
|
515
|
+
|
516
|
+
TCHAR DirName[MAX_PATH];
|
517
|
+
lstrcpy(DirName, InstDir);
|
518
|
+
lstrcat(DirName, _T("\\"));
|
519
|
+
lstrcat(DirName, DirectoryName);
|
520
|
+
|
521
|
+
DEBUG("CreateDirectory(%s)", DirName);
|
522
|
+
|
523
|
+
if (!CreateDirectory(DirName, NULL))
|
524
|
+
{
|
525
|
+
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
526
|
+
{
|
527
|
+
DEBUG("Directory already exists");
|
528
|
+
}
|
529
|
+
else
|
530
|
+
{
|
531
|
+
FATAL("Failed to create directory '%s'.", DirName);
|
532
|
+
return FALSE;
|
533
|
+
}
|
534
|
+
}
|
535
|
+
|
536
|
+
return TRUE;
|
537
|
+
}
|
538
|
+
|
539
|
+
void GetCreateProcessInfo(LPVOID* p, LPTSTR* pApplicationName, LPTSTR* pCommandLine)
|
540
|
+
{
|
541
|
+
LPTSTR ImageName = GetString(p);
|
542
|
+
LPTSTR CmdLine = GetString(p);
|
543
|
+
|
544
|
+
ExpandPath(pApplicationName, ImageName);
|
545
|
+
|
546
|
+
LPTSTR ExpandedCommandLine;
|
547
|
+
ExpandPath(&ExpandedCommandLine, CmdLine);
|
548
|
+
|
549
|
+
LPTSTR MyCmdLine = GetCommandLine();
|
550
|
+
LPTSTR MyArgs = SkipArg(MyCmdLine);
|
551
|
+
|
552
|
+
*pCommandLine = LocalAlloc(LMEM_FIXED, lstrlen(ExpandedCommandLine) + sizeof(TCHAR) + lstrlen(MyArgs) + sizeof(TCHAR));
|
553
|
+
lstrcpy(*pCommandLine, ExpandedCommandLine);
|
554
|
+
lstrcat(*pCommandLine, _T(" "));
|
555
|
+
lstrcat(*pCommandLine, MyArgs);
|
556
|
+
|
557
|
+
LocalFree(ExpandedCommandLine);
|
558
|
+
}
|
559
|
+
|
560
|
+
/**
|
561
|
+
Create a new process and wait for it to complete (OP_CREATE_PROCESS
|
562
|
+
opcode handler)
|
563
|
+
*/
|
564
|
+
BOOL OpCreateProcess(LPVOID* p)
|
565
|
+
{
|
566
|
+
LPTSTR ApplicationName;
|
567
|
+
LPTSTR CommandLine;
|
568
|
+
GetCreateProcessInfo(p, &ApplicationName, &CommandLine);
|
569
|
+
CreateAndWaitForProcess(ApplicationName, CommandLine);
|
570
|
+
LocalFree(ApplicationName);
|
571
|
+
LocalFree(CommandLine);
|
572
|
+
return TRUE;
|
573
|
+
}
|
574
|
+
|
575
|
+
void CreateAndWaitForProcess(LPTSTR ApplicationName, LPTSTR CommandLine)
|
576
|
+
{
|
577
|
+
PROCESS_INFORMATION ProcessInformation;
|
578
|
+
STARTUPINFO StartupInfo;
|
579
|
+
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
|
580
|
+
StartupInfo.cb = sizeof(StartupInfo);
|
581
|
+
BOOL r = CreateProcess(ApplicationName, CommandLine, NULL, NULL,
|
582
|
+
TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInformation);
|
583
|
+
|
584
|
+
if (!r)
|
585
|
+
{
|
586
|
+
FATAL("Failed to create process (%s): %lu", ApplicationName, GetLastError());
|
587
|
+
return;
|
588
|
+
}
|
589
|
+
|
590
|
+
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
|
591
|
+
|
592
|
+
if (!GetExitCodeProcess(ProcessInformation.hProcess, &ExitStatus))
|
593
|
+
{
|
594
|
+
FATAL("Failed to get exit status (error %lu).", GetLastError());
|
595
|
+
}
|
596
|
+
|
597
|
+
CloseHandle(ProcessInformation.hProcess);
|
598
|
+
CloseHandle(ProcessInformation.hThread);
|
599
|
+
}
|
600
|
+
|
601
|
+
/**
|
602
|
+
* Sets up a process to be created after all other opcodes have been processed. This can be used to create processes
|
603
|
+
* after the temporary files have all been created and memory has been freed.
|
604
|
+
*/
|
605
|
+
BOOL OpPostCreateProcess(LPVOID* p)
|
606
|
+
{
|
607
|
+
DEBUG("PostCreateProcess");
|
608
|
+
if (PostCreateProcess_ApplicationName || PostCreateProcess_CommandLine)
|
609
|
+
{
|
610
|
+
return FALSE;
|
611
|
+
}
|
612
|
+
else
|
613
|
+
{
|
614
|
+
GetCreateProcessInfo(p, &PostCreateProcess_ApplicationName, &PostCreateProcess_CommandLine);
|
615
|
+
return TRUE;
|
616
|
+
}
|
617
|
+
}
|
618
|
+
|
619
|
+
BOOL OpEnableDebugMode(LPVOID* p)
|
620
|
+
{
|
621
|
+
DebugModeEnabled = TRUE;
|
622
|
+
DEBUG("Aibika stub running in debug mode");
|
623
|
+
return TRUE;
|
624
|
+
}
|
625
|
+
|
626
|
+
#if WITH_LZMA
|
627
|
+
void* SzAlloc(void* p, size_t size) { p = p; return LocalAlloc(LMEM_FIXED, size); }
|
628
|
+
void SzFree(void* p, void* address) { p = p; LocalFree(address); }
|
629
|
+
ISzAlloc alloc = { SzAlloc, SzFree };
|
630
|
+
|
631
|
+
#define LZMA_UNPACKSIZE_SIZE 8
|
632
|
+
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNPACKSIZE_SIZE)
|
633
|
+
|
634
|
+
BOOL OpDecompressLzma(LPVOID* p)
|
635
|
+
{
|
636
|
+
BOOL Success = TRUE;
|
637
|
+
|
638
|
+
DWORD CompressedSize = GetInteger(p);
|
639
|
+
DEBUG("LzmaDecode(%ld)", CompressedSize);
|
640
|
+
|
641
|
+
Byte* src = (Byte*)*p;
|
642
|
+
*p += CompressedSize;
|
643
|
+
|
644
|
+
UInt64 unpackSize = 0;
|
645
|
+
int i;
|
646
|
+
for (i = 0; i < 8; i++)
|
647
|
+
{
|
648
|
+
unpackSize += (UInt64)src[LZMA_PROPS_SIZE + i] << (i * 8);
|
649
|
+
}
|
650
|
+
|
651
|
+
Byte* DecompressedData = LocalAlloc(LMEM_FIXED, unpackSize);
|
652
|
+
|
653
|
+
SizeT lzmaDecompressedSize = unpackSize;
|
654
|
+
SizeT inSizePure = CompressedSize - LZMA_HEADER_SIZE;
|
655
|
+
ELzmaStatus status;
|
656
|
+
SRes res = LzmaDecode(DecompressedData, &lzmaDecompressedSize, src + LZMA_HEADER_SIZE, &inSizePure,
|
657
|
+
src, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &alloc);
|
658
|
+
if (res != SZ_OK)
|
659
|
+
{
|
660
|
+
FATAL("LZMA decompression failed.");
|
661
|
+
Success = FALSE;
|
662
|
+
}
|
663
|
+
else
|
664
|
+
{
|
665
|
+
LPVOID decPtr = DecompressedData;
|
666
|
+
if (!ProcessOpcodes(&decPtr))
|
667
|
+
{
|
668
|
+
Success = FALSE;
|
669
|
+
}
|
670
|
+
}
|
671
|
+
|
672
|
+
LocalFree(DecompressedData);
|
673
|
+
return Success;
|
674
|
+
}
|
675
|
+
#endif
|
676
|
+
|
677
|
+
BOOL OpEnd(LPVOID* p)
|
678
|
+
{
|
679
|
+
ExitCondition = TRUE;
|
680
|
+
return TRUE;
|
681
|
+
}
|
682
|
+
|
683
|
+
BOOL OpSetEnv(LPVOID* p)
|
684
|
+
{
|
685
|
+
LPTSTR Name = GetString(p);
|
686
|
+
LPTSTR Value = GetString(p);
|
687
|
+
LPTSTR ExpandedValue;
|
688
|
+
ExpandPath(&ExpandedValue, Value);
|
689
|
+
DEBUG("SetEnv(%s, %s)", Name, ExpandedValue);
|
690
|
+
|
691
|
+
BOOL Result = FALSE;
|
692
|
+
if (!SetEnvironmentVariable(Name, ExpandedValue))
|
693
|
+
{
|
694
|
+
FATAL("Failed to set environment variable (error %lu).", GetLastError());
|
695
|
+
Result = FALSE;
|
696
|
+
}
|
697
|
+
else
|
698
|
+
{
|
699
|
+
Result = TRUE;
|
700
|
+
}
|
701
|
+
LocalFree(ExpandedValue);
|
702
|
+
return Result;
|
703
|
+
}
|
data/src/stub.rc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
101 ICON vit-ruby.ico
|
data/src/vit-ruby.ico
ADDED
Binary file
|