|
|
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.5 root 540: unsigned int filePos = 0, fileNo = 0; 541: unsigned int fileDataEndPos = 0; 542: unsigned int fileDataStartPos = 0; 1.1 root 543: unsigned int uncompressedLen = 0; 544: unsigned int compressedLen = 0; 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.5 root 615: if ((unsigned int) 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.