"Fossies" - the Fresh Open Source Software Archive

Member "src/Setup/SelfExtract.c" (10 Oct 2018, 19613 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "SelfExtract.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.22_Source_vs_1.23_Source.

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