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

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

unix.superglobalmegacorp.com

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