📄 selfextractor.cpp
字号:
*
* Parameters:
* int index: index in array of file
* CString Dir: Destination Directory
*
* Return:
* int: Error Code
* INPUT_FILE_ERROR - Failed to open the input file
* OUTPUT_FILE_ERROR - Failed to create an output file
*******************************************************************************/
int CSelfExtractor::Extract(int index, CString Dir,
funcPtr function /*= NULL*/, void * userData /*= NULL*/)
{
//Make sure the directory name has a trailing backslash
EnsureTrailingBackSlash(Dir);
CFile Thisfile; //Archive (Usually itself)
//Read the Table of Contents
int res = ReadTOC(GetThisFileName());
if(res != SUCCESS)
return res;
//Open the archive
if(!Thisfile.Open(GetThisFileName(), CFile::modeRead))
return INPUT_FILE_ERROR;
else
{
m_dCurReadSize = 0;
ExtractOne(&Thisfile, index, Dir, function, userData);
//Close the archive
Thisfile.Close();
}
return SUCCESS;
}
/*******************************************************************************
*
* Function: CSelfExtractor::ExtractOne
*
* Description:
* Actual Data Extraction. Seeks to required offset in archive
* and writes new file
*
* Parameters:
* CFile* file: Pointer to the archive
* int index: Index of file in array
* CString Dir: Destination Dir
*
* Return:
* int: Error Code
*******************************************************************************/
int CSelfExtractor::ExtractOne(CFile* file, int index, CString Dir,
funcPtr function /*= NULL*/, void * userData /*= NULL*/)
{
char buffer[1000]; //Buffer to read and write with
CFile NewFile; //Extracted File
//Get the file size (in bytes)
int FileSize = m_InfoArray[index].GetFileSize();
//Create the new file
if(!NewFile.Open(Dir + m_InfoArray[index].GetFilename() , CFile::modeCreate | CFile::modeWrite))
return OUTPUT_FILE_ERROR;
//Seek to the correct Offset
file->Seek(m_InfoArray[index].GetFileOffset(), CFile::begin);
//Loop the data out from the archive
DWORD dwWritten = 0;
DWORD dwRead = 0;
int AmountToRead = 0;
while(TRUE)
{
//Read out 1000 bytes at a time or the remainder if
//there is less than 1000 left. Exit if there is none left
AmountToRead = FileSize - dwWritten;
if(AmountToRead > 1000)
AmountToRead = 1000;
else if(AmountToRead == 0)
break;
dwRead = file->Read(buffer, AmountToRead);
NewFile.Write(buffer, dwRead);
dwWritten += dwRead;
m_dCurReadSize = dwWritten;
//Do the callback
if(function != NULL)
function(static_cast<void*>(&m_InfoArray[index]), userData);
}
//Close the output file
NewFile.Close();
return SUCCESS;
}
/*******************************************************************************
*
* Function: CSelfExtractor::ReadTOC
*
* Description:
* Read the archive's Table of Contents
*
* Parameters:
* CString Filename: Filename of the archive (full path)
*
* Return:
* int: Error Code
*******************************************************************************/
int CSelfExtractor::ReadTOC(CString Filename)
{
CFile Thisfile; //Archive file
char buffer[1000]; //Buffer to read and write with
//Clear the CSEFileInfo class array
Reset();
//Open the archive
if(!Thisfile.Open(Filename, CFile::modeRead))
return NO_SOURCE;
else
{
//Read in the signature
Thisfile.Seek(- static_cast<int>(strlen(SIGNATURE)), CFile::end);
Thisfile.Read(buffer, strlen(SIGNATURE));
//Check that it matches
if(strncmp(buffer, SIGNATURE, strlen(SIGNATURE)) != 0)
return INVALID_SIG;
else
{
//Read Number of files
int LastOffset = strlen(SIGNATURE) + static_cast<int>(sizeof(int));
Thisfile.Seek(-LastOffset, CFile::end);
Thisfile.Read(&m_nFiles, sizeof(int));
//If there are no files in the archive, there is nothing to extract
if(m_nFiles == 0)
return NOTHING_TO_DO;
//Read the TOC in. The array is filled in reverse to ensure that it
//corresponds to the data segment
for(int i = (m_nFiles - 1); i >= 0 ; i--)
{
int nSize = 0;
int nOffset = 0;
int len = 0;
LastOffset += sizeof(int);
//Get Length of Pathname
Thisfile.Seek(-LastOffset, CFile::end);
Thisfile.Read(&len, sizeof(int));
LastOffset += len;
//Get Path Name
Thisfile.Seek(-LastOffset, CFile::end);
Thisfile.Read(buffer, len);
LastOffset += sizeof(int);
//Get File Size
Thisfile.Seek(-LastOffset, CFile::end);
Thisfile.Read(&nSize, sizeof(int));
LastOffset += sizeof(int);
//Get File Offset
Thisfile.Seek(-LastOffset, CFile::end);
Thisfile.Read(&nOffset, sizeof(int));
//Set the data in the array
m_InfoArray[i].SetSize(nSize);
CString Temp(buffer);
m_InfoArray[i].SetFilename(Temp.Left(len));
m_InfoArray[i].SetOffset(nOffset);
}
//Record the total size of the TOC for use
//when extracting the data segment
m_nTOCSize = LastOffset;
}
}
//Close the archive
Thisfile.Close();
return SUCCESS;
}
/*******************************************************************************
*
* Function: CSelfExtractor::AddFile
*
* Description:
* Add a file to the archive
*
* Parameters:
* CString File: Input File path
*
* Return:
* BOOL: Success or Failure
*******************************************************************************/
BOOL CSelfExtractor::AddFile(CString File)
{
if(m_nFiles == MAX_FILES)
return FALSE;
if(m_InfoArray[m_nFiles].SetData(File))
{
m_nFiles++;
return TRUE;
}
return FALSE;
}
/*******************************************************************************
*
* Function: CSelfExtractor::Reset
*
* Description:
* Reset the CSEFileInfo Array
*
* Parameters:
* None
*
* Return:
* None
*******************************************************************************/
void CSelfExtractor::Reset()
{
for(int i = 0; i < MAX_FILES; i++)
m_InfoArray[i].Reset();
m_nFiles = 0;
m_nTOCSize = 0;
}
/*******************************************************************************
*
* Function: CSelfExtractor::EnsureTrailingBackSlash
*
* Description:
* Ensure that the string has a trailing backslash
*
* Parameters:
* CString &string: Pathname
*
* Return:
* CString: Pathname
*******************************************************************************/
CString CSelfExtractor::EnsureTrailingBackSlash(CString &string)
{
int len = string.GetLength();
if(string[len - 1] != '\\')
string += "\\";
return string;
}
/*******************************************************************************
*
* Function: CSelfExtractor::GetThisFileName
*
* Description:
* Get this executable's file path
*
* Parameters:
* None
*
* Return:
* CString: Full Path for this executable
*******************************************************************************/
CString CSelfExtractor::GetThisFileName()
{
char FullName[MAX_PATH+1];
GetModuleFileName(NULL,FullName,MAX_PATH);
return CString(FullName);
}
/*******************************************************************************
*
* Function: CSelfExtractor::GetTotalSize
*
* Description:
* 获取文件数组中所有文件SIZE的总和
*
* Parameters:
* None
*
* Return:
* DWORD: Total Size
*******************************************************************************/
DWORD CSelfExtractor::GetTotalSize()
{
DWORD dTotal = 0;
for(int i = 0; i < m_nFiles; i++)
{
dTotal += GetFileSize(i);
}
return dTotal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -