|
|
1.1 root 1: /*
1.1.1.6 root 2: Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
1.1 root 3:
1.1.1.7 root 4: Governed by the TrueCrypt License 3.0 the full text of which is contained in
1.1.1.6 root 5: the file License.txt included in TrueCrypt binary and source code distribution
6: packages.
1.1 root 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: {
1.1.1.2 root 209: // Clear bytes 0x130-0x1ff
210: memset (buffer + 0x130, 0, 0x200 - 0x130);
1.1 root 211: }
212:
213:
214: BOOL MakeSelfExtractingPackage (HWND hwndDlg, char *szDestDir)
215: {
216: int i, x;
217: unsigned char inputFile [TC_MAX_PATH];
218: unsigned char outputFile [TC_MAX_PATH];
219: unsigned char szTmpFilePath [TC_MAX_PATH];
220: unsigned char szTmp32bit [4] = {0};
221: unsigned char *szTmp32bitPtr = szTmp32bit;
222: unsigned char *buffer = NULL, *compressedBuffer = NULL;
223: unsigned char *bufIndex = NULL;
224: char tmpStr [2048];
225: int bufLen = 0, compressedDataLen = 0, uncompressedDataLen = 0;
226:
227: x = strlen (szDestDir);
228: if (x < 2)
1.1.1.7 root 229: goto err;
1.1 root 230:
231: if (szDestDir[x - 1] != '\\')
232: strcat (szDestDir, "\\");
233:
234: GetModuleFileName (NULL, inputFile, sizeof (inputFile));
235:
236: strcpy (outputFile, szDestDir);
237: strncat (outputFile, OutputPackageFile, sizeof (outputFile) - strlen (outputFile) - 1);
238:
239: // Clone 'TrueCrypt Setup.exe' to create the base of the new self-extracting archive
240:
241: if (!TCCopyFile (inputFile, outputFile))
242: {
243: handleWin32Error (hwndDlg);
244: PkgError ("Cannot copy 'TrueCrypt Setup.exe' to the package");
1.1.1.7 root 245: goto err;
1.1 root 246: }
247:
248: // Determine the buffer size needed for all the files and meta data and check if all required files exist
249:
250: bufLen = 0;
251:
252: for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++)
253: {
254: _snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]);
255:
256: if (!FileExists (szTmpFilePath))
257: {
258: char tmpstr [1000];
259:
260: _snprintf (tmpstr, sizeof(tmpstr), "File not found:\n\n'%s'", szTmpFilePath);
261: remove (outputFile);
262: PkgError (tmpstr);
1.1.1.7 root 263: goto err;
1.1 root 264: }
265:
266: bufLen += (int) GetFileSize64 (szTmpFilePath);
267:
268: bufLen += 2; // 16-bit filename length
269: bufLen += strlen(szCompressedFiles[i]); // Filename
270: bufLen += 4; // CRC-32
271: bufLen += 4; // 32-bit file length
272: }
273:
274: buffer = malloc (bufLen + 524288); // + 512K reserve
275: if (buffer == NULL)
276: {
277: PkgError ("Cannot allocate memory for uncompressed data");
278: remove (outputFile);
1.1.1.7 root 279: goto err;
1.1 root 280: }
281:
282:
283: // Write the start marker
284: if (!SaveBufferToFile (MAG_START_MARKER, outputFile, strlen (MAG_START_MARKER), TRUE))
285: {
286: PkgError ("Cannot write the start marker");
287: remove (outputFile);
1.1.1.7 root 288: goto err;
1.1 root 289: }
290:
291:
292: bufIndex = buffer;
293:
294: // Copy all required files and their meta data to the buffer
295: for (i = 0; i < sizeof (szCompressedFiles) / sizeof (szCompressedFiles[0]); i++)
296: {
297: DWORD tmpFileSize;
298: unsigned char *tmpBuffer;
299:
300: _snprintf (szTmpFilePath, sizeof(szTmpFilePath), "%s%s", szDestDir, szCompressedFiles[i]);
301:
302: tmpBuffer = LoadFile (szTmpFilePath, &tmpFileSize);
303:
304: if (tmpBuffer == NULL)
305: {
306: char tmpstr [1000];
307:
308: free (tmpBuffer);
309: _snprintf (tmpstr, sizeof(tmpstr), "Cannot load file \n'%s'", szTmpFilePath);
310: remove (outputFile);
311: PkgError (tmpstr);
1.1.1.7 root 312: goto err;
1.1 root 313: }
314:
315: // Copy the filename length to the main buffer
316: mputWord (bufIndex, (WORD) strlen(szCompressedFiles[i]));
317:
318: // Copy the filename to the main buffer
319: memcpy (bufIndex, szCompressedFiles[i], strlen(szCompressedFiles[i]));
320: bufIndex += strlen(szCompressedFiles[i]);
321:
322: // Compute CRC-32 hash of the uncompressed file and copy it to the main buffer
323: mputLong (bufIndex, GetCrc32 (tmpBuffer, tmpFileSize));
324:
325: // Copy the file length to the main buffer
326: mputLong (bufIndex, (unsigned __int32) tmpFileSize);
327:
328: // Copy the file contents to the main buffer
329: memcpy (bufIndex, tmpBuffer, tmpFileSize);
330: bufIndex += tmpFileSize;
331:
332: free (tmpBuffer);
333: }
334:
335: // Calculate the total size of the uncompressed data
336: uncompressedDataLen = (int) (bufIndex - buffer);
337:
338: // Write total size of the uncompressed data
339: szTmp32bitPtr = szTmp32bit;
340: mputLong (szTmp32bitPtr, (unsigned __int32) uncompressedDataLen);
341: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
342: {
343: remove (outputFile);
344: PkgError ("Cannot write the total size of the uncompressed data");
1.1.1.7 root 345: goto err;
1.1 root 346: }
347:
348: // Compress all the files and meta data in the buffer to create a solid archive
349:
350: compressedBuffer = malloc (uncompressedDataLen + 524288); // + 512K reserve
351: if (compressedBuffer == NULL)
352: {
353: remove (outputFile);
354: PkgError ("Cannot allocate memory for compressed data");
1.1.1.7 root 355: goto err;
1.1 root 356: }
357:
358: compressedDataLen = CompressBuffer (compressedBuffer, buffer, uncompressedDataLen);
359: if (compressedDataLen <= 0)
360: {
361: remove (outputFile);
362: PkgError ("Failed to compress the data");
1.1.1.7 root 363: goto err;
1.1 root 364: }
365:
366: free (buffer);
1.1.1.7 root 367: buffer = NULL;
1.1 root 368:
369: // Write the total size of the compressed data
370: szTmp32bitPtr = szTmp32bit;
371: mputLong (szTmp32bitPtr, (unsigned __int32) compressedDataLen);
372: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
373: {
374: remove (outputFile);
375: PkgError ("Cannot write the total size of the compressed data");
1.1.1.7 root 376: goto err;
1.1 root 377: }
378:
379: // Write the compressed data
380: if (!SaveBufferToFile (compressedBuffer, outputFile, compressedDataLen, TRUE))
381: {
382: remove (outputFile);
383: PkgError ("Cannot write compressed data to the package");
1.1.1.7 root 384: goto err;
1.1 root 385: }
386:
387: // Write the end marker
388: if (!SaveBufferToFile (MagEndMarker, outputFile, strlen (MagEndMarker), TRUE))
389: {
390: remove (outputFile);
391: PkgError ("Cannot write the end marker");
1.1.1.7 root 392: goto err;
1.1 root 393: }
394:
395: free (compressedBuffer);
1.1.1.7 root 396: compressedBuffer = NULL;
1.1 root 397:
398: // Compute and write CRC-32 hash of the entire package
399: {
400: DWORD tmpFileSize;
401: char *tmpBuffer;
402:
403: tmpBuffer = LoadFile (outputFile, &tmpFileSize);
404:
405: if (tmpBuffer == NULL)
406: {
407: handleWin32Error (hwndDlg);
408: remove (outputFile);
409: PkgError ("Cannot load the package to compute CRC");
1.1.1.7 root 410: goto err;
1.1 root 411: }
412:
413: // Zero all bytes that change when the exe is digitally signed (except appended blocks).
414: WipeSignatureAreas (tmpBuffer);
415:
416: szTmp32bitPtr = szTmp32bit;
417: mputLong (szTmp32bitPtr, GetCrc32 (tmpBuffer, tmpFileSize));
1.1.1.7 root 418: free (tmpBuffer);
419:
1.1 root 420: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
421: {
422: remove (outputFile);
423: PkgError ("Cannot write the total size of the compressed data");
1.1.1.7 root 424: goto err;
1.1 root 425: }
426: }
427:
428: sprintf (tmpStr, "Self-extracting package successfully created (%s)", outputFile);
429: PkgInfo (tmpStr);
430: return TRUE;
431:
1.1.1.7 root 432: err:
433: if (buffer)
434: free (buffer);
435: if (compressedBuffer)
436: free (compressedBuffer);
437:
1.1 root 438: return FALSE;
439: }
440:
441:
442: // Verifies the CRC-32 of the whole self-extracting package (except the digital signature areas, if present)
443: BOOL VerifyPackageIntegrity (void)
444: {
445: int fileDataEndPos = 0;
446: int fileDataStartPos = 0;
447: unsigned __int32 crc = 0;
448: unsigned char *tmpBuffer;
449: int tmpFileSize;
450: char path [TC_MAX_PATH];
451:
452: GetModuleFileName (NULL, path, sizeof (path));
453:
454: fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker));
455: if (fileDataEndPos < 0)
456: {
457: Error ("DIST_PACKAGE_CORRUPTED");
458: return FALSE;
459: }
460: fileDataEndPos--;
461:
462: fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER));
463: if (fileDataStartPos < 0)
464: {
465: Error ("DIST_PACKAGE_CORRUPTED");
466: return FALSE;
467: }
468: fileDataStartPos += strlen (MAG_START_MARKER);
469:
470:
471: if (!LoadInt32 (path, &crc, fileDataEndPos + strlen (MagEndMarker) + 1))
472: {
473: Error ("CANT_VERIFY_PACKAGE_INTEGRITY");
474: return FALSE;
475: }
476:
477: // Compute the CRC-32 hash of the whole file (except the digital signature area, if present)
478: tmpBuffer = LoadFile (path, &tmpFileSize);
479:
480: if (tmpBuffer == NULL)
481: {
482: Error ("CANT_VERIFY_PACKAGE_INTEGRITY");
483: return FALSE;
484: }
485:
486: // Zero all bytes that change when an exe is digitally signed (except appended blocks).
487: WipeSignatureAreas (tmpBuffer);
488:
489: if (crc != GetCrc32 (tmpBuffer, fileDataEndPos + 1 + strlen (MagEndMarker)))
490: {
491: free (tmpBuffer);
492: Error ("DIST_PACKAGE_CORRUPTED");
493: return FALSE;
494: }
495:
496: free (tmpBuffer);
497:
498: return TRUE;
499: }
500:
501:
502: // Determines whether we are a self-extracting package
503: BOOL IsSelfExtractingPackage (void)
504: {
505: char path [TC_MAX_PATH];
506:
507: GetModuleFileName (NULL, path, sizeof (path));
508:
509: return (FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)) != -1);
510: }
511:
512:
513: static void FreeAllFileBuffers (void)
514: {
515: int fileNo;
516:
517: if (DecompressedData != NULL)
518: {
519: free (DecompressedData);
520: DecompressedData = NULL;
521: }
522:
523: for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
524: {
525: Decompressed_Files[fileNo].fileName = NULL;
526: Decompressed_Files[fileNo].fileContent = NULL;
527: Decompressed_Files[fileNo].fileNameLength = 0;
528: Decompressed_Files[fileNo].fileLength = 0;
529: Decompressed_Files[fileNo].crc = 0;
530: }
531: }
532:
533:
534: // Assumes that VerifyPackageIntegrity() has been used. Returns TRUE, if successful (otherwise FALSE).
535: // Creates a table of pointers to buffers containing the following objects for each file:
536: // filename size, filename (not null-terminated!), file size, file CRC-32, uncompressed file contents.
537: // For details, see the definition of the DECOMPRESSED_FILE structure.
538: BOOL SelfExtractInMemory (char *path)
539: {
1.1.1.8 ! root 540: int filePos = 0, fileNo = 0;
! 541: int fileDataEndPos = 0;
! 542: int fileDataStartPos = 0;
! 543: int uncompressedLen = 0;
! 544: int compressedLen = 0;
1.1 root 545: unsigned char *compressedData = NULL;
546: unsigned char *bufPos = NULL, *bufEndPos = NULL;
547:
548: FreeAllFileBuffers();
549:
550: fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker));
551: if (fileDataEndPos < 0)
552: {
553: Error ("CANNOT_READ_FROM_PACKAGE");
554: return FALSE;
555: }
556:
557: fileDataEndPos--;
558:
559: fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER));
560: if (fileDataStartPos < 0)
561: {
562: Error ("CANNOT_READ_FROM_PACKAGE");
563: return FALSE;
564: }
565:
566: fileDataStartPos += strlen (MAG_START_MARKER);
567:
568: filePos = fileDataStartPos;
569:
570: // Read the stored total size of the uncompressed data
571: if (!LoadInt32 (path, &uncompressedLen, filePos))
572: {
573: Error ("CANNOT_READ_FROM_PACKAGE");
574: return FALSE;
575: }
576:
577: filePos += 4;
578:
579: // Read the stored total size of the compressed data
580: if (!LoadInt32 (path, &compressedLen, filePos))
581: {
582: Error ("CANNOT_READ_FROM_PACKAGE");
583: return FALSE;
584: }
585:
586: filePos += 4;
587:
588: if (compressedLen != fileDataEndPos - fileDataStartPos - 8 + 1)
589: {
590: Error ("DIST_PACKAGE_CORRUPTED");
591: }
592:
593: DecompressedData = malloc (uncompressedLen + 524288); // + 512K reserve
594: if (DecompressedData == NULL)
595: {
596: Error ("ERR_MEM_ALLOC");
597: return FALSE;
598: }
599:
600: bufPos = DecompressedData;
601: bufEndPos = bufPos + uncompressedLen - 1;
602:
603: compressedData = LoadFileBlock (path, filePos, compressedLen);
604:
605: if (compressedData == NULL)
606: {
607: free (DecompressedData);
608: DecompressedData = NULL;
609:
610: Error ("CANNOT_READ_FROM_PACKAGE");
611: return FALSE;
612: }
613:
614: // Decompress the data
1.1.1.8 ! root 615: if (DecompressBuffer (DecompressedData, compressedData, compressedLen) != uncompressedLen)
1.1 root 616: {
617: Error ("DIST_PACKAGE_CORRUPTED");
618: goto sem_end;
619: }
620:
621: while (bufPos <= bufEndPos && fileNo < NBR_COMPRESSED_FILES)
622: {
623: // Filename length
624: Decompressed_Files[fileNo].fileNameLength = mgetWord (bufPos);
625:
626: // Filename
627: Decompressed_Files[fileNo].fileName = bufPos;
628: bufPos += Decompressed_Files[fileNo].fileNameLength;
629:
630: // CRC-32 of the file
631: Decompressed_Files[fileNo].crc = mgetLong (bufPos);
632:
633: // File length
634: Decompressed_Files[fileNo].fileLength = mgetLong (bufPos);
635:
636: // File content
637: Decompressed_Files[fileNo].fileContent = bufPos;
638: bufPos += Decompressed_Files[fileNo].fileLength;
639:
640: // Verify CRC-32 of the file (to verify that it didn't get corrupted while creating the solid archive).
641: if (Decompressed_Files[fileNo].crc
642: != GetCrc32 (Decompressed_Files[fileNo].fileContent, Decompressed_Files[fileNo].fileLength))
643: {
644: Error ("DIST_PACKAGE_CORRUPTED");
645: goto sem_end;
646: }
647:
648: fileNo++;
649: }
650:
651: if (fileNo < NBR_COMPRESSED_FILES)
652: {
653: Error ("DIST_PACKAGE_CORRUPTED");
654: goto sem_end;
655: }
656:
657: free (compressedData);
658: return TRUE;
659:
660: sem_end:
661: FreeAllFileBuffers();
662: free (compressedData);
663: return FALSE;
664: }
665:
666:
667: void __cdecl ExtractAllFilesThread (void *hwndDlg)
668: {
669: int fileNo;
670: BOOL bSuccess = FALSE;
671: char packageFile [TC_MAX_PATH];
672:
673: InvalidateRect (GetDlgItem (GetParent (hwndDlg), IDD_INSTL_DLG), NULL, TRUE);
674:
675: ClearLogWindow (hwndDlg);
676:
677: GetModuleFileName (NULL, packageFile, sizeof (packageFile));
678:
679: if (!(bSuccess = SelfExtractInMemory (packageFile)))
680: goto eaf_end;
681:
682: if (mkfulldir (DestExtractPath, TRUE) != 0)
683: {
684: if (mkfulldir (DestExtractPath, FALSE) != 0)
685: {
686: wchar_t szTmp[TC_MAX_PATH];
687:
688: handleWin32Error (hwndDlg);
689: wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), DestExtractPath);
690: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
691: bSuccess = FALSE;
692: goto eaf_end;
693: }
694: }
695:
696: for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
697: {
698: char fileName [TC_MAX_PATH] = {0};
699: char filePath [TC_MAX_PATH] = {0};
700:
701: // Filename
702: strncpy (fileName, Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength);
703: fileName [Decompressed_Files[fileNo].fileNameLength] = 0;
704: strcpy (filePath, DestExtractPath);
705: strcat (filePath, fileName);
706:
707: StatusMessageParam (hwndDlg, "EXTRACTING_VERB", filePath);
708:
709: // Write the file
710: if (!SaveBufferToFile (
711: Decompressed_Files[fileNo].fileContent,
712: filePath,
713: Decompressed_Files[fileNo].fileLength,
714: FALSE))
715: {
716: wchar_t szTmp[512];
717:
718: _snwprintf (szTmp, sizeof (szTmp) / 2, GetString ("CANNOT_WRITE_FILE_X"), filePath);
719: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
720: bSuccess = FALSE;
721: goto eaf_end;
722: }
723: UpdateProgressBarProc ((int) (100 * ((float) fileNo / NBR_COMPRESSED_FILES)));
724: }
725:
726: eaf_end:
727: FreeAllFileBuffers();
728:
729: if (bSuccess)
730: PostMessage (MainDlg, TC_APPMSG_EXTRACTION_SUCCESS, 0, 0);
731: else
732: PostMessage (MainDlg, TC_APPMSG_EXTRACTION_FAILURE, 0, 0);
733: }
734:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.