📄 selfextract.c
字号:
free (buffer);
// Write the total size of the compressed data
szTmp32bitPtr = szTmp32bit;
mputLong (szTmp32bitPtr, (unsigned __int32) compressedDataLen);
if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
{
remove (outputFile);
PkgError ("Cannot write the total size of the compressed data");
return FALSE;
}
// Write the compressed data
if (!SaveBufferToFile (compressedBuffer, outputFile, compressedDataLen, TRUE))
{
remove (outputFile);
PkgError ("Cannot write compressed data to the package");
return FALSE;
}
// Write the end marker
if (!SaveBufferToFile (MagEndMarker, outputFile, strlen (MagEndMarker), TRUE))
{
remove (outputFile);
PkgError ("Cannot write the end marker");
return FALSE;
}
free (compressedBuffer);
// Compute and write CRC-32 hash of the entire package
{
DWORD tmpFileSize;
char *tmpBuffer;
tmpBuffer = LoadFile (outputFile, &tmpFileSize);
if (tmpBuffer == NULL)
{
handleWin32Error (hwndDlg);
remove (outputFile);
PkgError ("Cannot load the package to compute CRC");
return FALSE;
}
// Zero all bytes that change when the exe is digitally signed (except appended blocks).
WipeSignatureAreas (tmpBuffer);
szTmp32bitPtr = szTmp32bit;
mputLong (szTmp32bitPtr, GetCrc32 (tmpBuffer, tmpFileSize));
if (!SaveBufferToFile (szTmp32bit, outputFile, sizeof (szTmp32bit), TRUE))
{
remove (outputFile);
PkgError ("Cannot write the total size of the compressed data");
return FALSE;
}
free (tmpBuffer);
}
sprintf (tmpStr, "Self-extracting package successfully created (%s)", outputFile);
PkgInfo (tmpStr);
return TRUE;
msep_err:
free (buffer);
free (compressedBuffer);
return FALSE;
}
// Verifies the CRC-32 of the whole self-extracting package (except the digital signature areas, if present)
BOOL VerifyPackageIntegrity (void)
{
int fileDataEndPos = 0;
int fileDataStartPos = 0;
unsigned __int32 crc = 0;
unsigned char *tmpBuffer;
int tmpFileSize;
char path [TC_MAX_PATH];
GetModuleFileName (NULL, path, sizeof (path));
fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker));
if (fileDataEndPos < 0)
{
Error ("DIST_PACKAGE_CORRUPTED");
return FALSE;
}
fileDataEndPos--;
fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER));
if (fileDataStartPos < 0)
{
Error ("DIST_PACKAGE_CORRUPTED");
return FALSE;
}
fileDataStartPos += strlen (MAG_START_MARKER);
if (!LoadInt32 (path, &crc, fileDataEndPos + strlen (MagEndMarker) + 1))
{
Error ("CANT_VERIFY_PACKAGE_INTEGRITY");
return FALSE;
}
// Compute the CRC-32 hash of the whole file (except the digital signature area, if present)
tmpBuffer = LoadFile (path, &tmpFileSize);
if (tmpBuffer == NULL)
{
Error ("CANT_VERIFY_PACKAGE_INTEGRITY");
return FALSE;
}
// Zero all bytes that change when an exe is digitally signed (except appended blocks).
WipeSignatureAreas (tmpBuffer);
if (crc != GetCrc32 (tmpBuffer, fileDataEndPos + 1 + strlen (MagEndMarker)))
{
free (tmpBuffer);
Error ("DIST_PACKAGE_CORRUPTED");
return FALSE;
}
free (tmpBuffer);
return TRUE;
}
// Determines whether we are a self-extracting package
BOOL IsSelfExtractingPackage (void)
{
char path [TC_MAX_PATH];
GetModuleFileName (NULL, path, sizeof (path));
return (FindStringInFile (path, MagEndMarker, strlen (MagEndMarker)) != -1);
}
static void FreeAllFileBuffers (void)
{
int fileNo;
if (DecompressedData != NULL)
{
free (DecompressedData);
DecompressedData = NULL;
}
for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
{
Decompressed_Files[fileNo].fileName = NULL;
Decompressed_Files[fileNo].fileContent = NULL;
Decompressed_Files[fileNo].fileNameLength = 0;
Decompressed_Files[fileNo].fileLength = 0;
Decompressed_Files[fileNo].crc = 0;
}
}
// Assumes that VerifyPackageIntegrity() has been used. Returns TRUE, if successful (otherwise FALSE).
// Creates a table of pointers to buffers containing the following objects for each file:
// filename size, filename (not null-terminated!), file size, file CRC-32, uncompressed file contents.
// For details, see the definition of the DECOMPRESSED_FILE structure.
BOOL SelfExtractInMemory (char *path)
{
int filePos = 0, fileNo = 0;
int fileDataEndPos = 0;
int fileDataStartPos = 0;
unsigned int uncompressedLen = 0;
unsigned int compressedLen = 0;
unsigned char *compressedData = NULL;
unsigned char *bufPos = NULL, *bufEndPos = NULL;
FreeAllFileBuffers();
fileDataEndPos = (int) FindStringInFile (path, MagEndMarker, strlen (MagEndMarker));
if (fileDataEndPos < 0)
{
Error ("CANNOT_READ_FROM_PACKAGE");
return FALSE;
}
fileDataEndPos--;
fileDataStartPos = (int) FindStringInFile (path, MAG_START_MARKER, strlen (MAG_START_MARKER));
if (fileDataStartPos < 0)
{
Error ("CANNOT_READ_FROM_PACKAGE");
return FALSE;
}
fileDataStartPos += strlen (MAG_START_MARKER);
filePos = fileDataStartPos;
// Read the stored total size of the uncompressed data
if (!LoadInt32 (path, &uncompressedLen, filePos))
{
Error ("CANNOT_READ_FROM_PACKAGE");
return FALSE;
}
filePos += 4;
// Read the stored total size of the compressed data
if (!LoadInt32 (path, &compressedLen, filePos))
{
Error ("CANNOT_READ_FROM_PACKAGE");
return FALSE;
}
filePos += 4;
if (compressedLen != fileDataEndPos - fileDataStartPos - 8 + 1)
{
Error ("DIST_PACKAGE_CORRUPTED");
}
DecompressedData = malloc (uncompressedLen + 524288); // + 512K reserve
if (DecompressedData == NULL)
{
Error ("ERR_MEM_ALLOC");
return FALSE;
}
bufPos = DecompressedData;
bufEndPos = bufPos + uncompressedLen - 1;
compressedData = LoadFileBlock (path, filePos, compressedLen);
if (compressedData == NULL)
{
free (DecompressedData);
DecompressedData = NULL;
Error ("CANNOT_READ_FROM_PACKAGE");
return FALSE;
}
// Decompress the data
if (DecompressBuffer (DecompressedData, compressedData, compressedLen) != uncompressedLen)
{
Error ("DIST_PACKAGE_CORRUPTED");
goto sem_end;
}
while (bufPos <= bufEndPos && fileNo < NBR_COMPRESSED_FILES)
{
// Filename length
Decompressed_Files[fileNo].fileNameLength = mgetWord (bufPos);
// Filename
Decompressed_Files[fileNo].fileName = bufPos;
bufPos += Decompressed_Files[fileNo].fileNameLength;
// CRC-32 of the file
Decompressed_Files[fileNo].crc = mgetLong (bufPos);
// File length
Decompressed_Files[fileNo].fileLength = mgetLong (bufPos);
// File content
Decompressed_Files[fileNo].fileContent = bufPos;
bufPos += Decompressed_Files[fileNo].fileLength;
// Verify CRC-32 of the file (to verify that it didn't get corrupted while creating the solid archive).
if (Decompressed_Files[fileNo].crc
!= GetCrc32 (Decompressed_Files[fileNo].fileContent, Decompressed_Files[fileNo].fileLength))
{
Error ("DIST_PACKAGE_CORRUPTED");
goto sem_end;
}
fileNo++;
}
if (fileNo < NBR_COMPRESSED_FILES)
{
Error ("DIST_PACKAGE_CORRUPTED");
goto sem_end;
}
free (compressedData);
return TRUE;
sem_end:
FreeAllFileBuffers();
free (compressedData);
return FALSE;
}
void __cdecl ExtractAllFilesThread (void *hwndDlg)
{
int fileNo;
BOOL bSuccess = FALSE;
char packageFile [TC_MAX_PATH];
InvalidateRect (GetDlgItem (GetParent (hwndDlg), IDD_INSTL_DLG), NULL, TRUE);
ClearLogWindow (hwndDlg);
GetModuleFileName (NULL, packageFile, sizeof (packageFile));
if (!(bSuccess = SelfExtractInMemory (packageFile)))
goto eaf_end;
if (mkfulldir (DestExtractPath, TRUE) != 0)
{
if (mkfulldir (DestExtractPath, FALSE) != 0)
{
wchar_t szTmp[TC_MAX_PATH];
handleWin32Error (hwndDlg);
wsprintfW (szTmp, GetString ("CANT_CREATE_FOLDER"), DestExtractPath);
MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
bSuccess = FALSE;
goto eaf_end;
}
}
for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
{
char fileName [TC_MAX_PATH] = {0};
char filePath [TC_MAX_PATH] = {0};
// Filename
strncpy (fileName, Decompressed_Files[fileNo].fileName, Decompressed_Files[fileNo].fileNameLength);
fileName [Decompressed_Files[fileNo].fileNameLength] = 0;
strcpy (filePath, DestExtractPath);
strcat (filePath, fileName);
StatusMessageParam (hwndDlg, "EXTRACTING_VERB", filePath);
// Write the file
if (!SaveBufferToFile (
Decompressed_Files[fileNo].fileContent,
filePath,
Decompressed_Files[fileNo].fileLength,
FALSE))
{
wchar_t szTmp[512];
_snwprintf (szTmp, sizeof (szTmp) / 2, GetString ("CANNOT_WRITE_FILE_X"), filePath);
MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
bSuccess = FALSE;
goto eaf_end;
}
UpdateProgressBarProc ((int) (100 * ((float) fileNo / NBR_COMPRESSED_FILES)));
}
eaf_end:
FreeAllFileBuffers();
if (bSuccess)
PostMessage (MainDlg, TC_APPMSG_EXTRACTION_SUCCESS, 0, 0);
else
PostMessage (MainDlg, TC_APPMSG_EXTRACTION_FAILURE, 0, 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -