Annotation of truecrypt/setup/selfextract.c, revision 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.