|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
3:
4: Governed by the TrueCrypt License 2.4 the full text of which is contained
5: in the file License.txt included in TrueCrypt binary and source code
6: distribution packages.
7: */
8:
9: #include "Tcdefs.h"
10:
11: #include "Inflate.h"
12: #include "SelfExtract.h"
13: #include "Wizard.h"
14: #include "Setup.h"
15: #include "Crc.h"
16: #include "Endian.h"
17: #include "Dlgcode.h"
18: #include "Dir.h"
19: #include "Language.h"
20: #include "Resource.h"
21:
22: #define OutputPackageFile "TrueCrypt Setup " VERSION_STRING ".exe"
23:
24: #define MAG_START_MARKER "TCINSTRT"
25: #define MAG_END_MARKER_OBFUSCATED "T/C/I/N/S/C/R/C"
26: #define PIPE_BUFFER_LEN (4 * BYTES_PER_KB)
27:
28: unsigned char MagEndMarker [sizeof (MAG_END_MARKER_OBFUSCATED)];
29: char DestExtractPath [TC_MAX_PATH];
30: DECOMPRESSED_FILE Decompressed_Files [NBR_COMPRESSED_FILES];
31:
32: volatile char *PipeWriteBuf = NULL;
33: volatile HANDLE hChildStdinWrite = INVALID_HANDLE_VALUE;
34: unsigned char *DecompressedData = NULL;
35:
36:
37:
38: void SelfExtractStartupInit (void)
39: {
40: DeobfuscateMagEndMarker ();
41: }
42:
43:
44: // The end marker must be included in the self-extracting exe only once, not twice (used e.g.
45: // by IsSelfExtractingPackage()) and that's why MAG_END_MARKER_OBFUSCATED is obfuscated and
46: // needs to be deobfuscated using this function at startup.
47: static void DeobfuscateMagEndMarker (void)
48: {
49: int i;
50:
51: for (i = 0; i < sizeof (MAG_END_MARKER_OBFUSCATED); i += 2)
52: MagEndMarker [i/2] = MAG_END_MARKER_OBFUSCATED [i];
53:
54: MagEndMarker [i/2] = 0;
55: }
56:
57:
58: static void PkgError (char *msg)
59: {
60: MessageBox (NULL, msg, "TrueCrypt", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
61: }
62:
63:
64: static void PkgWarning (char *msg)
65: {
66: MessageBox (NULL, msg, "TrueCrypt", MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST);
67: }
68:
69:
70: static void PkgInfo (char *msg)
71: {
72: MessageBox (NULL, msg, "TrueCrypt", MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST);
73: }
74:
75:
76: // Returns 0 if decompression fails or, if successful, returns the size of the decompressed data
77: static int DecompressBuffer (char *out, char *in, int len)
78: {
79: return (DecompressDeflatedData (out, in, len)); // Inflate
80: }
81:
82:
83: static void __cdecl PipeWriteThread (void *len)
84: {
85: int sendBufSize = PIPE_BUFFER_LEN, bytesSent = 0;
86: int bytesToSend = *((int *) len), bytesSentTotal = 0;
87:
88: if (PipeWriteBuf == NULL || (HANDLE) hChildStdinWrite == INVALID_HANDLE_VALUE)
89: {
90: PkgError ("Failed sending data to the STDIN pipe");
91: return;
92: }
93:
94: while (bytesToSend > 0)
95: {
96: if (bytesToSend < PIPE_BUFFER_LEN)
97: sendBufSize = bytesToSend;
98:
99: if (!WriteFile ((HANDLE) hChildStdinWrite, (char *) PipeWriteBuf + bytesSentTotal, sendBufSize, &bytesSent, NULL)
100: || bytesSent == 0
101: || bytesSent != sendBufSize)
102: {
103: PkgError ("Failed sending data to the STDIN pipe");
104: return;
105: }
106:
107: bytesToSend -= bytesSent;
108: bytesSentTotal += bytesSent;
109: }
110:
111: // Closing the pipe causes the child process to stop reading from it
112:
113: if (!CloseHandle (hChildStdinWrite))
114: {
115: PkgError ("Cannot close pipe");
116: return;
117: }
118: }
119:
120:
121: // Returns 0 if compression fails or, if successful, the size of the compressed data
122: static int CompressBuffer (char *out, char *in, int len)
123: {
124: SECURITY_ATTRIBUTES securityAttrib;
125: DWORD bytesReceived = 0;
126: HANDLE hChildStdoutWrite = INVALID_HANDLE_VALUE;
127: HANDLE hChildStdoutRead = INVALID_HANDLE_VALUE;
128: HANDLE hChildStdinRead = INVALID_HANDLE_VALUE;
129: STARTUPINFO startupInfo;
130: PROCESS_INFORMATION procInfo;
131: char pipeBuffer [PIPE_BUFFER_LEN];
132: int res_len = 0;
133: BOOL bGzipHeaderRead = FALSE;
134:
135: ZeroMemory (&startupInfo, sizeof (startupInfo));
136: ZeroMemory (&procInfo, sizeof (procInfo));
137:
138: // Pipe handle inheritance
139: securityAttrib.bInheritHandle = TRUE;
140: securityAttrib.nLength = sizeof (securityAttrib);
141: securityAttrib.lpSecurityDescriptor = NULL;
142:
143: if (!CreatePipe (&hChildStdoutRead, &hChildStdoutWrite, &securityAttrib, 0))
144: {
145: PkgError ("Cannot create STDOUT pipe.");
146: return 0;
147: }
148: SetHandleInformation (hChildStdoutRead, HANDLE_FLAG_INHERIT, 0);
149:
150: if (!CreatePipe (&hChildStdinRead, &((HANDLE) hChildStdinWrite), &securityAttrib, 0))
151: {
152: PkgError ("Cannot create STDIN pipe.");
153: return 0;
154: }
155: SetHandleInformation (hChildStdinWrite, HANDLE_FLAG_INHERIT, 0);
156:
157: // Create a child process that will compress the data
158:
159: startupInfo.wShowWindow = SW_HIDE;
160: startupInfo.hStdInput = hChildStdinRead;
161: startupInfo.hStdOutput = hChildStdoutWrite;
162: startupInfo.cb = sizeof (startupInfo);
163: startupInfo.hStdError = hChildStdoutWrite;
164: startupInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
165:
166: if (!CreateProcess (NULL, "gzip --best", NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &procInfo))
167: {
168: PkgError ("Error: Cannot run gzip.\n\nBefore you can create a self-extracting TrueCrypt package, you need to have the open-source 'gzip' compression tool placed in any directory in the search path for executable files (for example, in 'C:\\Windows\\').\n\nNote: gzip can be freely downloaded e.g. from www.gzip.org");
169: return 0;
170: }
171:
172: CloseHandle (procInfo.hProcess);
173: CloseHandle (procInfo.hThread);
174:
175: // Start sending the uncompressed data to the pipe (STDIN)
176: PipeWriteBuf = in;
177: _beginthread (PipeWriteThread, PIPE_BUFFER_LEN * 2, (void *) &len);
178:
179: if (!CloseHandle (hChildStdoutWrite))
180: {
181: PkgError ("Cannot close STDOUT write");
182: return 0;
183: }
184:
185: bGzipHeaderRead = FALSE;
186:
187: // Read the compressed data from the pipe (sent by the child process to STDOUT)
188: while (TRUE)
189: {
190: if (!ReadFile (hChildStdoutRead, pipeBuffer, bGzipHeaderRead ? PIPE_BUFFER_LEN : 10, &bytesReceived, NULL))
191: break;
192:
193: if (bGzipHeaderRead)
194: {
195: memcpy (out + res_len, pipeBuffer, bytesReceived);
196: res_len += bytesReceived;
197: }
198: else
199: bGzipHeaderRead = TRUE; // Skip the 10-byte gzip header
200: }
201: return res_len - 8; // A gzip stream ends with a CRC-32 hash and a 32-bit size (those 8 bytes need to be chopped off)
202: }
203:
204:
205: // Clears all bytes that change when an exe file is digitally signed, except the data that are appended.
206: // If those bytes weren't cleared, CRC-32 checks would fail after signing.
207: static void WipeSignatureAreas (char *buffer)
208: {
209: buffer [0x130] = 0;
210: buffer [0x131] = 0;
211: buffer [0x132] = 0;
212:
213: buffer [0x138] = 0;
214: buffer [0x139] = 0;
215: buffer [0x13A] = 0;
216:
217: buffer [0x170] = 0;
218: buffer [0x171] = 0;
219: buffer [0x172] = 0;
220: buffer [0x173] = 0;
221: buffer [0x174] = 0;
222: buffer [0x175] = 0;
223:
224: buffer [0x178] = 0;
225: buffer [0x179] = 0;
226: buffer [0x17A] = 0;
227: buffer [0x17B] = 0;
228: buffer [0x17C] = 0;
229: buffer [0x17D] = 0;
230: }
231:
232:
233: BOOL MakeSelfExtractingPackage (HWND hwndDlg, char *szDestDir)
234: {
235: int i, x;
236: unsigned char inputFile [TC_MAX_PATH];
237: unsigned char outputFile [TC_MAX_PATH];
238: unsigned char szTmpFilePath [TC_MAX_PATH];
239: unsigned char szTmp32bit [4] = {0};
240: unsigned char *szTmp32bitPtr = szTmp32bit;
241: unsigned char *buffer = NULL, *compressedBuffer = NULL;
242: unsigned char *bufIndex = NULL;
243: char tmpStr [2048];
244: int bufLen = 0, compressedDataLen = 0, uncompressedDataLen = 0;
245:
246: x = strlen (szDestDir);
247: if (x < 2)
248: return FALSE;
249:
250: if (szDestDir[x - 1] != '\\')
251: strcat (szDestDir, "\\");
252:
253: GetModuleFileName (NULL, inputFile, sizeof (inputFile));
254:
255: strcpy (outputFile, szDestDir);
256: strncat (outputFile, OutputPackageFile, sizeof (outputFile) - strlen (outputFile) - 1);
257:
258: // Clone 'TrueCrypt Setup.exe' to create the base of the new self-extracting archive
259:
260: if (!TCCopyFile (inputFile, outputFile))
261: {
262: handleWin32Error (hwndDlg);
263: PkgError ("Cannot copy 'TrueCrypt Setup.exe' to the package");
264: return FALSE;
265: }
266:
267: // Determine the buffer size needed for all the files and meta data and check if all required files exist
268:
269: bufLen = 0;
270:
271: for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++)
272: {
273: _snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]);
274:
275: if (!FileExists (szTmpFilePath))
276: {
277: char tmpstr [1000];
278:
279: _snprintf (tmpstr, sizeof(tmpstr), "File not found:\n\n'%s'", szTmpFilePath);
280: remove (outputFile);
281: PkgError (tmpstr);
282: return FALSE;
283: }
284:
285: bufLen += (int) GetFileSize64 (szTmpFilePath);
286:
287: bufLen += 2; // 16-bit filename length
288: bufLen += strlen(szCompressedFiles[i]); // Filename
289: bufLen += 4; // CRC-32
290: bufLen += 4; // 32-bit file length
291: }
292:
293: buffer = malloc (bufLen + 524288); // + 512K reserve
294: if (buffer == NULL)
295: {
296: PkgError ("Cannot allocate memory for uncompressed data");
297: remove (outputFile);
298: return FALSE;
299: }
300:
301:
302: // Write the start marker
303: if (!SaveBufferToFile (MAG_START_MARKER, outputFile, strlen (MAG_START_MARKER), TRUE))
304: {
305: PkgError ("Cannot write the start marker");
306: remove (outputFile);
307: return FALSE;
308: }
309:
310:
311: bufIndex = buffer;
312:
313: // Copy all required files and their meta data to the buffer
314: for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++)
315: {
316: DWORD tmpFileSize;
317: unsigned char *tmpBuffer;
318:
319: _snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]);
320:
321: tmpBuffer = LoadFile (szTmpFilePath, &tmpFileSize);
322:
323: if (tmpBuffer == NULL)
324: {
325: char tmpstr [1000];
326:
327: free (tmpBuffer);
328: _snprintf (tmpstr, sizeof(tmpstr), "Cannot load file \n'%s'", szTmpFilePath);
329: remove (outputFile);
330: PkgError (tmpstr);
331: goto msep_err;
332: }
333:
334: // Copy the filename length to the main buffer
335: mputWord (bufIndex, (WORD) strlen(szCompressedFiles[i]));
336:
337: // Copy the filename to the main buffer
338: memcpy (bufIndex, szCompressedFiles[i], strlen(szCompressedFiles[i]));
339: bufIndex += strlen(szCompressedFiles[i]);
340:
341: // Compute CRC-32 hash of the uncompressed file and copy it to the main buffer
342: mputLong (bufIndex, GetCrc32 (tmpBuffer, tmpFileSize));
343:
344: // Copy the file length to the main buffer
345: mputLong (bufIndex, (unsigned __int32) tmpFileSize);
346:
347: // Copy the file contents to the main buffer
348: memcpy (bufIndex, tmpBuffer, tmpFileSize);
349: bufIndex += tmpFileSize;
350:
351: free (tmpBuffer);
352: }
353:
354: // Calculate the total size of the uncompressed data
355: uncompressedDataLen = (int) (bufIndex - buffer);
356:
357: // Write total size of the uncompressed data
358: szTmp32bitPtr = szTmp32bit;
359: mputLong (szTmp32bitPtr, (unsigned __int32) uncompressedDataLen);
360: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
361: {
362: remove (outputFile);
363: PkgError ("Cannot write the total size of the uncompressed data");
364: return FALSE;
365: }
366:
367: // Compress all the files and meta data in the buffer to create a solid archive
368:
369: compressedBuffer = malloc (uncompressedDataLen + 524288); // + 512K reserve
370: if (compressedBuffer == NULL)
371: {
372: remove (outputFile);
373: PkgError ("Cannot allocate memory for compressed data");
374: return FALSE;
375: }
376:
377: compressedDataLen = CompressBuffer (compressedBuffer, buffer, uncompressedDataLen);
378: if (compressedDataLen <= 0)
379: {
380: remove (outputFile);
381: PkgError ("Failed to compress the data");
382: return FALSE;
383: }
384:
385: free (buffer);
386:
387: // Write the total size of the compressed data
388: szTmp32bitPtr = szTmp32bit;
389: mputLong (szTmp32bitPtr, (unsigned __int32) compressedDataLen);
390: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
391: {
392: remove (outputFile);
393: PkgError ("Cannot write the total size of the compressed data");
394: return FALSE;
395: }
396:
397: // Write the compressed data
398: if (!SaveBufferToFile (compressedBuffer, outputFile, compressedDataLen, TRUE))
399: {
400: remove (outputFile);
401: PkgError ("Cannot write compressed data to the package");
402: return FALSE;
403: }
404:
405: // Write the end marker
406: if (!SaveBufferToFile (MagEndMarker, outputFile, strlen (MagEndMarker), TRUE))
407: {
408: remove (outputFile);
409: PkgError ("Cannot write the end marker");
410: return FALSE;
411: }
412:
413: free (compressedBuffer);
414:
415: // Compute and write CRC-32 hash of the entire package
416: {
417: DWORD tmpFileSize;
418: char *tmpBuffer;
419:
420: tmpBuffer = LoadFile (outputFile, &tmpFileSize);
421:
422: if (tmpBuffer == NULL)
423: {
424: handleWin32Error (hwndDlg);
425: remove (outputFile);
426: PkgError ("Cannot load the package to compute CRC");
427: return FALSE;
428: }
429:
430: // Zero all bytes that change when the exe is digitally signed (except appended blocks).
431: WipeSignatureAreas (tmpBuffer);
432:
433: szTmp32bitPtr = szTmp32bit;
434: mputLong (szTmp32bitPtr, GetCrc32 (tmpBuffer, tmpFileSize));
435: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
436: {
437: remove (outputFile);
438: PkgError ("Cannot write the total size of the compressed data");
439: return FALSE;
440: }
441:
442: free (tmpBuffer);
443: }
444:
445: sprintf (tmpStr, "Self-extracting package successfully created (%s)", outputFile);
446: PkgInfo (tmpStr);
447: return TRUE;
448:
449: msep_err:
450: free (buffer);
451: free (compressedBuffer);
452: return FALSE;
453: }
454:
455:
456: // Verifies the CRC-32 of the whole self-extracting package (except the digital signature areas, if present)
457: BOOL VerifyPackageIntegrity (void)
458: {
459: int fileDataEndPos = 0;
460: int fileDataStartPos = 0;
461: unsigned __int32 crc = 0;
462: unsigned char *tmpBuffer;
463: int tmpFileSize;
464: char path [TC_MAX_PATH];
465:
466: GetModuleFileName (NULL, path, sizeof (path));
467:
468: fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker));
469: if (fileDataEndPos < 0)
470: {
471: Error ("DIST_PACKAGE_CORRUPTED");
472: return FALSE;
473: }
474: fileDataEndPos--;
475:
476: fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER));
477: if (fileDataStartPos < 0)
478: {
479: Error ("DIST_PACKAGE_CORRUPTED");
480: return FALSE;
481: }
482: fileDataStartPos += strlen (MAG_START_MARKER);
483:
484:
485: if (!LoadInt32 (path, &crc, fileDataEndPos + strlen (MagEndMarker) + 1))
486: {
487: Error ("CANT_VERIFY_PACKAGE_INTEGRITY");
488: return FALSE;
489: }
490:
491: // Compute the CRC-32 hash of the whole file (except the digital signature area, if present)
492: tmpBuffer = LoadFile (path, &tmpFileSize);
493:
494: if (tmpBuffer == NULL)
495: {
496: Error ("CANT_VERIFY_PACKAGE_INTEGRITY");
497: return FALSE;
498: }
499:
500: // Zero all bytes that change when an exe is digitally signed (except appended blocks).
501: WipeSignatureAreas (tmpBuffer);
502:
503: if (crc != GetCrc32 (tmpBuffer, fileDataEndPos + 1 + strlen (MagEndMarker)))
504: {
505: free (tmpBuffer);
506: Error ("DIST_PACKAGE_CORRUPTED");
507: return FALSE;
508: }
509:
510: free (tmpBuffer);
511:
512: return TRUE;
513: }
514:
515:
516: // Determines whether we are a self-extracting package
517: BOOL IsSelfExtractingPackage (void)
518: {
519: char path [TC_MAX_PATH];
520:
521: GetModuleFileName (NULL, path, sizeof (path));
522:
523: return (FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)) != -1);
524: }
525:
526:
527: static void FreeAllFileBuffers (void)
528: {
529: int fileNo;
530:
531: if (DecompressedData != NULL)
532: {
533: free (DecompressedData);
534: DecompressedData = NULL;
535: }
536:
537: for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
538: {
539: Decompressed_Files[fileNo].fileName = NULL;
540: Decompressed_Files[fileNo].fileContent = NULL;
541: Decompressed_Files[fileNo].fileNameLength = 0;
542: Decompressed_Files[fileNo].fileLength = 0;
543: Decompressed_Files[fileNo].crc = 0;
544: }
545: }
546:
547:
548: // Assumes that VerifyPackageIntegrity() has been used. Returns TRUE, if successful (otherwise FALSE).
549: // Creates a table of pointers to buffers containing the following objects for each file:
550: // filename size, filename (not null-terminated!), file size, file CRC-32, uncompressed file contents.
551: // For details, see the definition of the DECOMPRESSED_FILE structure.
552: BOOL SelfExtractInMemory (char *path)
553: {
554: int filePos = 0, fileNo = 0;
555: int fileDataEndPos = 0;
556: int fileDataStartPos = 0;
557: unsigned int uncompressedLen = 0;
558: unsigned int compressedLen = 0;
559: unsigned char *compressedData = NULL;
560: unsigned char *bufPos = NULL, *bufEndPos = NULL;
561:
562: FreeAllFileBuffers();
563:
564: fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker));
565: if (fileDataEndPos < 0)
566: {
567: Error ("CANNOT_READ_FROM_PACKAGE");
568: return FALSE;
569: }
570:
571: fileDataEndPos--;
572:
573: fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER));
574: if (fileDataStartPos < 0)
575: {
576: Error ("CANNOT_READ_FROM_PACKAGE");
577: return FALSE;
578: }
579:
580: fileDataStartPos += strlen (MAG_START_MARKER);
581:
582: filePos = fileDataStartPos;
583:
584: // Read the stored total size of the uncompressed data
585: if (!LoadInt32 (path, &uncompressedLen, filePos))
586: {
587: Error ("CANNOT_READ_FROM_PACKAGE");
588: return FALSE;
589: }
590:
591: filePos += 4;
592:
593: // Read the stored total size of the compressed data
594: if (!LoadInt32 (path, &compressedLen, filePos))
595: {
596: Error ("CANNOT_READ_FROM_PACKAGE");
597: return FALSE;
598: }
599:
600: filePos += 4;
601:
602: if (compressedLen != fileDataEndPos - fileDataStartPos - 8 + 1)
603: {
604: Error ("DIST_PACKAGE_CORRUPTED");
605: }
606:
607: DecompressedData = malloc (uncompressedLen + 524288); // + 512K reserve
608: if (DecompressedData == NULL)
609: {
610: Error ("ERR_MEM_ALLOC");
611: return FALSE;
612: }
613:
614: bufPos = DecompressedData;
615: bufEndPos = bufPos + uncompressedLen - 1;
616:
617: compressedData = LoadFileBlock (path, filePos, compressedLen);
618:
619: if (compressedData == NULL)
620: {
621: free (DecompressedData);
622: DecompressedData = NULL;
623:
624: Error ("CANNOT_READ_FROM_PACKAGE");
625: return FALSE;
626: }
627:
628: // Decompress the data
629: if (DecompressBuffer (DecompressedData, compressedData, compressedLen) != uncompressedLen)
630: {
631: Error ("DIST_PACKAGE_CORRUPTED");
632: goto sem_end;
633: }
634:
635: while (bufPos <= bufEndPos && fileNo < NBR_COMPRESSED_FILES)
636: {
637: // Filename length
638: Decompressed_Files[fileNo].fileNameLength = mgetWord (bufPos);
639:
640: // Filename
641: Decompressed_Files[fileNo].fileName = bufPos;
642: bufPos += Decompressed_Files[fileNo].fileNameLength;
643:
644: // CRC-32 of the file
645: Decompressed_Files[fileNo].crc = mgetLong (bufPos);
646:
647: // File length
648: Decompressed_Files[fileNo].fileLength = mgetLong (bufPos);
649:
650: // File content
651: Decompressed_Files[fileNo].fileContent = bufPos;
652: bufPos += Decompressed_Files[fileNo].fileLength;
653:
654: // Verify CRC-32 of the file (to verify that it didn't get corrupted while creating the solid archive).
655: if (Decompressed_Files[fileNo].crc
656: != GetCrc32 (Decompressed_Files[fileNo].fileContent, Decompressed_Files[fileNo].fileLength))
657: {
658: Error ("DIST_PACKAGE_CORRUPTED");
659: goto sem_end;
660: }
661:
662: fileNo++;
663: }
664:
665: if (fileNo < NBR_COMPRESSED_FILES)
666: {
667: Error ("DIST_PACKAGE_CORRUPTED");
668: goto sem_end;
669: }
670:
671: free (compressedData);
672: return TRUE;
673:
674: sem_end:
675: FreeAllFileBuffers();
676: free (compressedData);
677: return FALSE;
678: }
679:
680:
681: void __cdecl ExtractAllFilesThread (void *hwndDlg)
682: {
683: int fileNo;
684: BOOL bSuccess = FALSE;
685: char packageFile [TC_MAX_PATH];
686:
687: InvalidateRect (GetDlgItem (GetParent (hwndDlg), IDD_INSTL_DLG), NULL, TRUE);
688:
689: ClearLogWindow (hwndDlg);
690:
691: GetModuleFileName (NULL, packageFile, sizeof (packageFile));
692:
693: if (!(bSuccess = SelfExtractInMemory (packageFile)))
694: goto eaf_end;
695:
696: if (mkfulldir (DestExtractPath, TRUE) != 0)
697: {
698: if (mkfulldir (DestExtractPath, FALSE) != 0)
699: {
700: wchar_t szTmp[TC_MAX_PATH];
701:
702: handleWin32Error (hwndDlg);
703: wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), DestExtractPath);
704: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
705: bSuccess = FALSE;
706: goto eaf_end;
707: }
708: }
709:
710: for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
711: {
712: char fileName [TC_MAX_PATH] = {0};
713: char filePath [TC_MAX_PATH] = {0};
714:
715: // Filename
716: strncpy (fileName, Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength);
717: fileName [Decompressed_Files[fileNo].fileNameLength] = 0;
718: strcpy (filePath, DestExtractPath);
719: strcat (filePath, fileName);
720:
721: StatusMessageParam (hwndDlg, "EXTRACTING_VERB", filePath);
722:
723: // Write the file
724: if (!SaveBufferToFile (
725: Decompressed_Files[fileNo].fileContent,
726: filePath,
727: Decompressed_Files[fileNo].fileLength,
728: FALSE))
729: {
730: wchar_t szTmp[512];
731:
732: _snwprintf (szTmp, sizeof (szTmp) / 2, GetString ("CANNOT_WRITE_FILE_X"), filePath);
733: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
734: bSuccess = FALSE;
735: goto eaf_end;
736: }
737: UpdateProgressBarProc ((int) (100 * ((float) fileNo / NBR_COMPRESSED_FILES)));
738: }
739:
740: eaf_end:
741: FreeAllFileBuffers();
742:
743: if (bSuccess)
744: PostMessage (MainDlg, TC_APPMSG_EXTRACTION_SUCCESS, 0, 0);
745: else
746: PostMessage (MainDlg, TC_APPMSG_EXTRACTION_FAILURE, 0, 0);
747: }
748:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.