|
|
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.6 ! root 4: Governed by the TrueCrypt License 2.8 the full text of which is contained in ! 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) 229: return FALSE; 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"); 245: return FALSE; 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); 263: return FALSE; 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); 279: return FALSE; 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); 288: return FALSE; 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); 312: goto msep_err; 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"); 345: return FALSE; 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"); 355: return FALSE; 356: } 357: 358: compressedDataLen = CompressBuffer (compressedBuffer, buffer, uncompressedDataLen); 359: if (compressedDataLen <= 0) 360: { 361: remove (outputFile); 362: PkgError ("Failed to compress the data"); 363: return FALSE; 364: } 365: 366: free (buffer); 367: 368: // Write the total size of the compressed data 369: szTmp32bitPtr = szTmp32bit; 370: mputLong (szTmp32bitPtr, (unsigned __int32) compressedDataLen); 371: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE)) 372: { 373: remove (outputFile); 374: PkgError ("Cannot write the total size of the compressed data"); 375: return FALSE; 376: } 377: 378: // Write the compressed data 379: if (!SaveBufferToFile (compressedBuffer, outputFile, compressedDataLen, TRUE)) 380: { 381: remove (outputFile); 382: PkgError ("Cannot write compressed data to the package"); 383: return FALSE; 384: } 385: 386: // Write the end marker 387: if (!SaveBufferToFile (MagEndMarker, outputFile, strlen (MagEndMarker), TRUE)) 388: { 389: remove (outputFile); 390: PkgError ("Cannot write the end marker"); 391: return FALSE; 392: } 393: 394: free (compressedBuffer); 395: 396: // Compute and write CRC-32 hash of the entire package 397: { 398: DWORD tmpFileSize; 399: char *tmpBuffer; 400: 401: tmpBuffer = LoadFile (outputFile, &tmpFileSize); 402: 403: if (tmpBuffer == NULL) 404: { 405: handleWin32Error (hwndDlg); 406: remove (outputFile); 407: PkgError ("Cannot load the package to compute CRC"); 408: return FALSE; 409: } 410: 411: // Zero all bytes that change when the exe is digitally signed (except appended blocks). 412: WipeSignatureAreas (tmpBuffer); 413: 414: szTmp32bitPtr = szTmp32bit; 415: mputLong (szTmp32bitPtr, GetCrc32 (tmpBuffer, tmpFileSize)); 416: if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE)) 417: { 418: remove (outputFile); 419: PkgError ("Cannot write the total size of the compressed data"); 420: return FALSE; 421: } 422: 423: free (tmpBuffer); 424: } 425: 426: sprintf (tmpStr, "Self-extracting package successfully created (%s)", outputFile); 427: PkgInfo (tmpStr); 428: return TRUE; 429: 430: msep_err: 431: free (buffer); 432: free (compressedBuffer); 433: return FALSE; 434: } 435: 436: 437: // Verifies the CRC-32 of the whole self-extracting package (except the digital signature areas, if present) 438: BOOL VerifyPackageIntegrity (void) 439: { 440: int fileDataEndPos = 0; 441: int fileDataStartPos = 0; 442: unsigned __int32 crc = 0; 443: unsigned char *tmpBuffer; 444: int tmpFileSize; 445: char path [TC_MAX_PATH]; 446: 447: GetModuleFileName (NULL, path, sizeof (path)); 448: 449: fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)); 450: if (fileDataEndPos < 0) 451: { 452: Error ("DIST_PACKAGE_CORRUPTED"); 453: return FALSE; 454: } 455: fileDataEndPos--; 456: 457: fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER)); 458: if (fileDataStartPos < 0) 459: { 460: Error ("DIST_PACKAGE_CORRUPTED"); 461: return FALSE; 462: } 463: fileDataStartPos += strlen (MAG_START_MARKER); 464: 465: 466: if (!LoadInt32 (path, &crc, fileDataEndPos + strlen (MagEndMarker) + 1)) 467: { 468: Error ("CANT_VERIFY_PACKAGE_INTEGRITY"); 469: return FALSE; 470: } 471: 472: // Compute the CRC-32 hash of the whole file (except the digital signature area, if present) 473: tmpBuffer = LoadFile (path, &tmpFileSize); 474: 475: if (tmpBuffer == NULL) 476: { 477: Error ("CANT_VERIFY_PACKAGE_INTEGRITY"); 478: return FALSE; 479: } 480: 481: // Zero all bytes that change when an exe is digitally signed (except appended blocks). 482: WipeSignatureAreas (tmpBuffer); 483: 484: if (crc != GetCrc32 (tmpBuffer, fileDataEndPos + 1 + strlen (MagEndMarker))) 485: { 486: free (tmpBuffer); 487: Error ("DIST_PACKAGE_CORRUPTED"); 488: return FALSE; 489: } 490: 491: free (tmpBuffer); 492: 493: return TRUE; 494: } 495: 496: 497: // Determines whether we are a self-extracting package 498: BOOL IsSelfExtractingPackage (void) 499: { 500: char path [TC_MAX_PATH]; 501: 502: GetModuleFileName (NULL, path, sizeof (path)); 503: 504: return (FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)) != -1); 505: } 506: 507: 508: static void FreeAllFileBuffers (void) 509: { 510: int fileNo; 511: 512: if (DecompressedData != NULL) 513: { 514: free (DecompressedData); 515: DecompressedData = NULL; 516: } 517: 518: for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++) 519: { 520: Decompressed_Files[fileNo].fileName = NULL; 521: Decompressed_Files[fileNo].fileContent = NULL; 522: Decompressed_Files[fileNo].fileNameLength = 0; 523: Decompressed_Files[fileNo].fileLength = 0; 524: Decompressed_Files[fileNo].crc = 0; 525: } 526: } 527: 528: 529: // Assumes that VerifyPackageIntegrity() has been used. Returns TRUE, if successful (otherwise FALSE). 530: // Creates a table of pointers to buffers containing the following objects for each file: 531: // filename size, filename (not null-terminated!), file size, file CRC-32, uncompressed file contents. 532: // For details, see the definition of the DECOMPRESSED_FILE structure. 533: BOOL SelfExtractInMemory (char *path) 534: { 1.1.1.5 root 535: unsigned int filePos = 0, fileNo = 0; 536: unsigned int fileDataEndPos = 0; 537: unsigned int fileDataStartPos = 0; 1.1 root 538: unsigned int uncompressedLen = 0; 539: unsigned int compressedLen = 0; 540: unsigned char *compressedData = NULL; 541: unsigned char *bufPos = NULL, *bufEndPos = NULL; 542: 543: FreeAllFileBuffers(); 544: 545: fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)); 546: if (fileDataEndPos < 0) 547: { 548: Error ("CANNOT_READ_FROM_PACKAGE"); 549: return FALSE; 550: } 551: 552: fileDataEndPos--; 553: 554: fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER)); 555: if (fileDataStartPos < 0) 556: { 557: Error ("CANNOT_READ_FROM_PACKAGE"); 558: return FALSE; 559: } 560: 561: fileDataStartPos += strlen (MAG_START_MARKER); 562: 563: filePos = fileDataStartPos; 564: 565: // Read the stored total size of the uncompressed data 566: if (!LoadInt32 (path, &uncompressedLen, filePos)) 567: { 568: Error ("CANNOT_READ_FROM_PACKAGE"); 569: return FALSE; 570: } 571: 572: filePos += 4; 573: 574: // Read the stored total size of the compressed data 575: if (!LoadInt32 (path, &compressedLen, filePos)) 576: { 577: Error ("CANNOT_READ_FROM_PACKAGE"); 578: return FALSE; 579: } 580: 581: filePos += 4; 582: 583: if (compressedLen != fileDataEndPos - fileDataStartPos - 8 + 1) 584: { 585: Error ("DIST_PACKAGE_CORRUPTED"); 586: } 587: 588: DecompressedData = malloc (uncompressedLen + 524288); // + 512K reserve 589: if (DecompressedData == NULL) 590: { 591: Error ("ERR_MEM_ALLOC"); 592: return FALSE; 593: } 594: 595: bufPos = DecompressedData; 596: bufEndPos = bufPos + uncompressedLen - 1; 597: 598: compressedData = LoadFileBlock (path, filePos, compressedLen); 599: 600: if (compressedData == NULL) 601: { 602: free (DecompressedData); 603: DecompressedData = NULL; 604: 605: Error ("CANNOT_READ_FROM_PACKAGE"); 606: return FALSE; 607: } 608: 609: // Decompress the data 1.1.1.5 root 610: if ((unsigned int) DecompressBuffer (DecompressedData, compressedData, compressedLen) != uncompressedLen) 1.1 root 611: { 612: Error ("DIST_PACKAGE_CORRUPTED"); 613: goto sem_end; 614: } 615: 616: while (bufPos <= bufEndPos && fileNo < NBR_COMPRESSED_FILES) 617: { 618: // Filename length 619: Decompressed_Files[fileNo].fileNameLength = mgetWord (bufPos); 620: 621: // Filename 622: Decompressed_Files[fileNo].fileName = bufPos; 623: bufPos += Decompressed_Files[fileNo].fileNameLength; 624: 625: // CRC-32 of the file 626: Decompressed_Files[fileNo].crc = mgetLong (bufPos); 627: 628: // File length 629: Decompressed_Files[fileNo].fileLength = mgetLong (bufPos); 630: 631: // File content 632: Decompressed_Files[fileNo].fileContent = bufPos; 633: bufPos += Decompressed_Files[fileNo].fileLength; 634: 635: // Verify CRC-32 of the file (to verify that it didn't get corrupted while creating the solid archive). 636: if (Decompressed_Files[fileNo].crc 637: != GetCrc32 (Decompressed_Files[fileNo].fileContent, Decompressed_Files[fileNo].fileLength)) 638: { 639: Error ("DIST_PACKAGE_CORRUPTED"); 640: goto sem_end; 641: } 642: 643: fileNo++; 644: } 645: 646: if (fileNo < NBR_COMPRESSED_FILES) 647: { 648: Error ("DIST_PACKAGE_CORRUPTED"); 649: goto sem_end; 650: } 651: 652: free (compressedData); 653: return TRUE; 654: 655: sem_end: 656: FreeAllFileBuffers(); 657: free (compressedData); 658: return FALSE; 659: } 660: 661: 662: void __cdecl ExtractAllFilesThread (void *hwndDlg) 663: { 664: int fileNo; 665: BOOL bSuccess = FALSE; 666: char packageFile [TC_MAX_PATH]; 667: 668: InvalidateRect (GetDlgItem (GetParent (hwndDlg), IDD_INSTL_DLG), NULL, TRUE); 669: 670: ClearLogWindow (hwndDlg); 671: 672: GetModuleFileName (NULL, packageFile, sizeof (packageFile)); 673: 674: if (!(bSuccess = SelfExtractInMemory (packageFile))) 675: goto eaf_end; 676: 677: if (mkfulldir (DestExtractPath, TRUE) != 0) 678: { 679: if (mkfulldir (DestExtractPath, FALSE) != 0) 680: { 681: wchar_t szTmp[TC_MAX_PATH]; 682: 683: handleWin32Error (hwndDlg); 684: wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), DestExtractPath); 685: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND); 686: bSuccess = FALSE; 687: goto eaf_end; 688: } 689: } 690: 691: for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++) 692: { 693: char fileName [TC_MAX_PATH] = {0}; 694: char filePath [TC_MAX_PATH] = {0}; 695: 696: // Filename 697: strncpy (fileName, Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength); 698: fileName [Decompressed_Files[fileNo].fileNameLength] = 0; 699: strcpy (filePath, DestExtractPath); 700: strcat (filePath, fileName); 701: 702: StatusMessageParam (hwndDlg, "EXTRACTING_VERB", filePath); 703: 704: // Write the file 705: if (!SaveBufferToFile ( 706: Decompressed_Files[fileNo].fileContent, 707: filePath, 708: Decompressed_Files[fileNo].fileLength, 709: FALSE)) 710: { 711: wchar_t szTmp[512]; 712: 713: _snwprintf (szTmp, sizeof (szTmp) / 2, GetString ("CANNOT_WRITE_FILE_X"), filePath); 714: MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); 715: bSuccess = FALSE; 716: goto eaf_end; 717: } 718: UpdateProgressBarProc ((int) (100 * ((float) fileNo / NBR_COMPRESSED_FILES))); 719: } 720: 721: eaf_end: 722: FreeAllFileBuffers(); 723: 724: if (bSuccess) 725: PostMessage (MainDlg, TC_APPMSG_EXTRACTION_SUCCESS, 0, 0); 726: else 727: PostMessage (MainDlg, TC_APPMSG_EXTRACTION_FAILURE, 0, 0); 728: } 729:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.