⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 selfextractor.cpp

📁 制作自解压文件,此工具不会将资源压缩
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************************
*
*	File:		SelfExtracter.cpp
*	Version:	1.0
*
*	Author:		James Spibey
*	Date:		04/08/1999
*	E-mail:		spib@bigfoot.com
*
*	Implementation of the CSelfExtracter class
*
*	You are free to use, distribute or modify this code
*	as long as this header is not removed or modified.
*
*
*************************************************************************************/

#include "stdafx.h"
#include "SelfExtractor.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

/*******************************************************************************
* 
* Function: CSelfExtractor::CSelfExtractor
* 
* Description: 
*	Default Constructor 
* 
* Parameters: 
*    None
* 
* Return: 
*    None
*******************************************************************************/
CSelfExtractor::CSelfExtractor()
{
	m_nFiles		= 0;
	m_nTOCSize		= 0;
	m_dCurReadSize		= 0;
}

/*******************************************************************************
* 
* Function: CSelfExtractor::~CSelfExtractor
* 
* Description: 
*	 Destructor 
* 
* Parameters: 
*    None
* 
* Return: 
*    None
*******************************************************************************/
CSelfExtractor::~CSelfExtractor()
{

}

/*******************************************************************************
* 
* Function: CSelfExtractor::Create
* 
* Description: 
*    Creates the Self-extracting executable 
* 
* Parameters: 
*    CString ExtractorPath: Path to the Extractor Executable 
*    CString Filename:		Filename of the Self Extracting Archive to create 
*	 funcPtr pFn:			Pointer to a user defined callback function
*	 void*   UserData:		User defined data to pass to the callback function
* 
* Return: 
*    int: Error Code
*		NOTHING_TO_DO		- No files have been selected to be archived
*		COPY_FAILED			- Failed to copy the extractor
*		OUTPUT_FILE_ERROR	- Failed to open the copied file for appending
*		INPUT_FILE_ERROR	- Failed to open an input file
*******************************************************************************/
int CSelfExtractor::Create(CString ExtractorPath, CString Filename, funcPtr pFn /* = NULL */, void* userData /*=NULL*/)
{
	//Make sure we have some files to add
	if(m_nFiles < 1)
		return NOTHING_TO_DO;

	//Copy the extractor to the new archive
	CShellFileOp shOp;
	shOp.SetFlags(FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT);
	shOp.AddFile(SH_SRC_FILE, ExtractorPath);
	shOp.AddFile(SH_DEST_FILE, Filename);
	if(shOp.CopyFiles() != 0)
		return COPY_FAILED;

	//Open the archive
	CFile file;
	if(!file.Open(Filename, CFile::modeWrite))
		return OUTPUT_FILE_ERROR;
	else
	{
		//Start at the end of the archive
		file.SeekToEnd();
		CreateArchive(&file, pFn, userData);

		//Close the archive
		file.Close();
	}
	return SUCCESS;
}

/*******************************************************************************
* 
* Function: CSelfExtractor::Create
* 
* Description: 
*    Creates the Self-extracting executable from an extractor in resources.
*	 Simply import the exe into your resources, making sure you specify the type
*	 as "SFX_EXE". Then just past the resource ID as the first parameter
* 
* Parameters: 
*    UINT	 resource:		Resource ID (eg IDR_SFX_EXE)
*    CString Filename:		Filename of the Self Extracting Archive to create 
*	 funcPtr pFn:			Pointer to a user defined callback function
*	 void*   UserData:		User defined data to pass to the callback function
* 
* Return: 
*    int: Error Code
*		NOTHING_TO_DO		- No files have been selected to be archived
*		COPY_FAILED			- Failed to copy the extractor
*		OUTPUT_FILE_ERROR	- Failed to open the copied file for appending
*		INPUT_FILE_ERROR	- Failed to open an input file
*******************************************************************************/
int CSelfExtractor::Create(UINT resource, CString Filename, funcPtr pFn /* = NULL */, void* userData /*=NULL*/)
{
	//Make sure we have some files to add
	if(m_nFiles < 1)
		return NOTHING_TO_DO;

	//Load the extractor from resources
	HRSRC hrSrc = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(resource), "SFX_EXE");
	if(hrSrc == NULL)
		return RESOURCE_ERROR;

	HGLOBAL hGlobal = LoadResource(AfxGetResourceHandle(), hrSrc);
	if(hGlobal == NULL)
		return RESOURCE_ERROR;

	LPVOID lpExe = LockResource(hGlobal);
	if(lpExe == NULL)
		return RESOURCE_ERROR;

	//Create the new archive from the extractor in the resources
	CFile file;
	if(!file.Open(Filename, CFile::modeCreate | CFile::modeWrite))
		return OUTPUT_FILE_ERROR;
	else
	{
		//Write the extractor exe
		file.Write(lpExe, (UINT)SizeofResource(AfxGetResourceHandle(), hrSrc));
		
		//Do the rest
		CreateArchive(&file, pFn, userData);

		//Close the archive
		file.Close();
	}
	return SUCCESS;
}

int CSelfExtractor::CreateArchive(CFile* pFile, funcPtr pFn, void* userData)
{
	DWORD dwRead = 0;	//Total Data read from input file
	DWORD dw = 0;		//Last amount read from input file
	char buffer[1000];	//Buffer for data
	CFile data;			//Input file
	m_dCurReadSize = 0;
		
	try		
	{
		//Copy all the inout files into the archive
		for(int i = 0; i < m_nFiles; i++)
		{
			//Open the input file
			if(data.Open(m_InfoArray[i].GetPathname(), CFile::modeRead))
			{
				dwRead = 0;

				m_InfoArray[i].SetOffset(pFile->GetPosition());

				//Read data in and write it out until the end of file
				while(static_cast<int>(dwRead) < m_InfoArray[i].GetFileSize())
				{
					dw = data.Read(buffer, 1000);
					pFile->Write(buffer, dw);
					dwRead += dw;
					m_dCurReadSize = dwRead;
					//Call the user defined CallBack
					if(pFn != NULL)
						pFn(static_cast<void*>(&m_InfoArray[i]), userData);
				}

				//Close this input file
				data.Close();
			}
			else
				return INPUT_FILE_ERROR;
		}

		//Now Write the TOC
		for(int j = 0; j < m_nFiles; j++)
		{	
			//Write the File Size
			int Offset = m_InfoArray[j].GetFileOffset();
			pFile->Write(&Offset, sizeof(int));

			//Write the File Size
			int len = m_InfoArray[j].GetFileSize();
			pFile->Write(&len, sizeof(int));
				
			//Write the filename
			len = m_InfoArray[j].GetFilename().GetLength();
			strncpy(buffer, m_InfoArray[j].GetFilename(), len);
			pFile->Write(buffer, len);
		
			//Write the length of the filename
			pFile->Write(&len, sizeof(int));

		}
		
		//Write the total number of files
		pFile->Write((void*)&m_nFiles, sizeof(int));
		
		//Write the SIG
		strcpy(buffer, SIGNATURE);
		pFile->Write(buffer, strlen(SIGNATURE));
	}
	catch(CFileException* e)
	{
		//Got sick of seeing 'unreferenced local variable'
		e->m_cause;
		return OUTPUT_FILE_ERROR;
	}
	return SUCCESS;
}
/*******************************************************************************
* 
* Function: CSelfExtractor::ExtractAll
* 
* Description: 
*	 Extract the current archive to the specified directory 
* 
* Parameters: 
*    CString Dir: Destination Directory 
*	 funcPtr pFn:			Pointer to a user defined callback function
*	 void*   UserData:		User defined data to pass to the callback function
* 
* Return: 
*    int: Error Code
*			INPUT_FILE_ERROR	- Failed to open the input file
*			OUTPUT_FILE_ERROR	- Failed to create an output file
*******************************************************************************/
int CSelfExtractor::ExtractAll(CString Dir, funcPtr pFn /*= 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;

		//Get the files out in reverse order so we can work out the offsets
		//Subtract 1 from the filecount as we are zero-based
		for(int i = (m_nFiles - 1); i >= 0 ; i--)
		{
			ExtractOne(&Thisfile, i, Dir, pFn, userData);
		}

		//Close the archive
		Thisfile.Close();
	}
	return SUCCESS;
}

/*******************************************************************************
* 
* Function: CSelfExtractor::Extract
* 
* Description: 
*	 Extract a single file from the current archive to the specified directory 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -