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

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: 

unix.superglobalmegacorp.com

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