Annotation of truecrypt/setup/selfextract.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.