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

📄 buildintsfx.cpp

📁 zip算法的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop


#include "ZipBuilder.h"
#include "ZipMsg.h"
#include "ZipBuildDefs.h"

#include "BuildIntSfx.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#ifdef INTERNAL_SFX
#define min(x,y) ((x)<(y)?(x):(y))
TInternalSFX::TInternalSFX(TObject *owner)
{
  FOwner = dynamic_cast<TZipBuilder*>(owner) ;
}

//---------------------------------------------------------------------------------
// Search for the right(with our icon) resource directory entry.
DWord __fastcall TInternalSFX::SearchResDirEntry(pIRD ResStart, pIRDirE entry, int Depth)
{
	pIRDatE data;

#if __BORLANDC__ < 1328		// BCB1=0x0520(1312)
	if(entry->u.s.NameIsString) return 0;			// No named resources.
	if(!Depth && entry->u.Id != 3) return 0;			// Only icon resources.
	if(Depth == 1 && entry->u.Id != 1) return 0;	// Only icon with ID 0x1.
	if(!entry->u2.s.DataIsDirectory)
	{
		data = (pIRDatE)((char *)ResStart + entry->u2.OffsetToData);
		if(data->Size == 744)	return data->OffsetToData;
	} else
		return BrowseResDir(ResStart, (pIRD)((char *)ResStart + entry->u2.s.OffsetToDirectory), Depth + 1);
#endif
#if __BORLANDC__ == 1328		// BCB3=0x0530(1328)
	if(entry->_s1.NameIsString) return 0;			// No named resources.
	if(!Depth && entry->Id != 3) return 0;			// Only icon resources.
	if(Depth == 1 && entry->Id != 1) return 0;	// Only icon with ID 0x1.
	if(!entry->_s2.DataIsDirectory)
	{
		data = (pIRDatE)((char *)ResStart + entry->OffsetToData);
		if(data->Size == 744)	return data->OffsetToData;
	} else
		return BrowseResDir(ResStart, (pIRD)((char *)ResStart + entry->_s2.OffsetToDirectory), Depth + 1);
#endif
// And again! changed because unnamed unions are now possible.
#if __BORLANDC__ > 1343		// BCB4=0x0540(1344)
	if(entry->NameIsString) return 0;				// No named resources.
	if(!Depth && entry->Id != 3) return 0;			// Only icon resources.
	if(Depth == 1 && entry->Id != 1) return 0;	// Only icon with ID 0x1.
	if(!entry->DataIsDirectory)
	{
		data = (pIRDatE)((char *)ResStart + entry->OffsetToData);
		if(data->Size == 744)	return data->OffsetToData;
	} else
		return BrowseResDir(ResStart, (pIRD)((char *)ResStart + entry->OffsetToDirectory ), Depth + 1);
#endif
	return 0;
}
//-----------------------------------------------------------------------------------
// Browse through all resource Directories.
DWord __fastcall TInternalSFX::BrowseResDir(pIRD ResStart, pIRD dir, int Depth)
{
	pIRDirE SingleRes = (pIRDirE)((char *)dir + sizeof(IMAGE_RESOURCE_DIRECTORY));
	DWord	Result = 0;

	for(int i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++)
	{
		Result = SearchResDirEntry(ResStart, SingleRes, Depth);
		if(Result) break;   // Found the one w're looking for.
		SingleRes++;
	}
	return Result;
}
//----------------------------------------------------------------------------------------
// Find Resource directory entry.
DWord __fastcall TInternalSFX::LookForDirs(const void *SectionData,
                                          const DWord SectionVirtualStart,
															            const int SectionLen, pIDD directories)
{
	pIRD  ResStart;
	DWord Result = 0;
	pIDD  dirs = directories;

	dirs += IMAGE_DIRECTORY_ENTRY_RESOURCE;
	if(dirs->VirtualAddress && ((char *)dirs->VirtualAddress >= (char *)SectionVirtualStart) &&
		(char *)dirs->VirtualAddress < ((char *)SectionVirtualStart + SectionLen))
	{
		ResStart = (pIRD)((char *)SectionData + (dirs->VirtualAddress - SectionVirtualStart));
		Result = BrowseResDir( ResStart, ResStart, 0);
	}
	return Result;
}
//----------------------------------------------------------------------------
// Replace the icon resource in the copied ZipSFX.bin
// Return values: All ok: =0   Error: <0
int __fastcall TInternalSFX::ReplaceIcon(int SFXFile, int SFXSize)
{
const
	SE_NoFoundError   = -10,
	SE_MemStreamError = -11,
	SE_IconSizeError  = -12;

	char *SFXBuffer = NULL;
	TMemoryStream *IconStream = NULL;
	IMAGE_DOS_HEADER *DOSHead;
	PEheader *Header;
	DWord  FoundAddr = 0;
	pISH SectionHeader;
	int Result = SE_NoFoundError;
  TZipBuilder *zip = dynamic_cast<TZipBuilder *>(FOwner);
	try
	{
  	for(;;)
  	{
  		try
  		{
  			// Put the SFX file into a buffer.
  			SFXBuffer = new char[SFXSize];
  			FileSeek(SFXFile, 0, soFromBeginning);
  			FileRead(SFXFile, SFXBuffer, SFXSize);
  			// Read and check the ZipSFX.bin file for an icon resource.
  			DOSHead = (IMAGE_DOS_HEADER *)SFXBuffer;
  			if(DOSHead->e_magic != IMAGE_DOS_SIGNATURE) break;
  			Header = (PEheader *)((char *)DOSHead + DOSHead->e_lfanew);
  			if(Header->signature != IMAGE_NT_SIGNATURE) break;
  			SectionHeader = &Header->section_header;
  			for(int Section = 0; Section < Header->_head.NumberOfSections; Section++)
  			{	// Walk through sections.
  				if(!StrComp((char *)&SectionHeader->Name[0], ".rsrc"))
  				{	// Found the resource section.
  					FoundAddr = LookForDirs(SFXBuffer + SectionHeader->PointerToRawData,
  					                        SectionHeader->VirtualAddress,
  							                    SectionHeader->SizeOfRawData,
  							                    &Header->opt_head.DataDirectory[0]);
  					if(!FoundAddr) break;
  					// Change memory offset to file offset.
  					FoundAddr = FoundAddr - SectionHeader->VirtualAddress +
  					                        SectionHeader->PointerToRawData;
  					break;
  				}
  				SectionHeader++;
  			}
  			if(!FoundAddr) break;
  			// Save the icon data to a stream.
  			IconStream = new TMemoryStream();
  			zip->FSFXIcon->SaveToStream(IconStream);
  			// Only handle icons with this size.
  			if(IconStream->Size == 766)
  			{
  				// Reposition to the actual data and put it into a buffer.
  				IconStream->Seek(22, soFromBeginning);
  				IconStream->ReadBuffer(SFXBuffer, 744);
  				// Go to start of the icon resource in the new created file.
  				FileSeek(SFXFile, (SeekInt)FoundAddr, soFromBeginning);
  				// And write the changed icon data from the buffer.
  				FileWrite(SFXFile, SFXBuffer, 744);
  				Result = 0;
  			}
  			else Result = SE_IconSizeError;
  		}
  		catch( ... )
  		{
  			Result = SE_MemStreamError;
  		}
  		break;
  	}
  }
  __finally
  {
		delete[] SFXBuffer;
		delete IconStream;
		FileSeek(SFXFile, 0, soFromEnd);
	}
	return Result;
}

//---------------------------------------------------------------------------
// Function to copy the central header of an archive and change while copying
// the Local Header offsets and finally the Central Header offset.
// We return 0 if no error or -2 (SE_CopyError) in case something goes wrong.
int __fastcall TInternalSFX::RWCentralDir(int &OutFile,
                                         struct ZipEndOfCentral &EOC,
                                         int OffsetChange)
{
	struct ZipCentralHeader CEH;
	int Result = 0;
  TZipBuilder *zip = dynamic_cast<TZipBuilder *>(FOwner);
	try
	{
		for(int i = 0; i < EOC.TotalEntries; i++)
		{
			// Read a central header.
			if(FileRead(FInFileHandle, &CEH, sizeof(CEH)) != sizeof(CEH))
				throw EZipBuilder(DS_CEHBadRead);
			if(CEH.HeaderSig != CentralFileHeaderSig) throw EZipBuilder(DS_CEHWrongSig);
			// Change the offset.
			CEH.RelOffLocal += OffsetChange;
			// Write this changed central header to disk
			if(FileWrite(OutFile, &CEH, sizeof(CEH)) != sizeof(CEH))
				throw EZipBuilder(DS_CEHBadWrite);
			// And the remaining bytes of the central header.
			if(zip->CopyBuffer(FInFileHandle, OutFile, CEH.FileNameLen + CEH.ExtraLen + CEH.FileComLen))
				throw EZipBuilder(DS_CEHBadCopy);
		}
		// Skip the EOC record (we already have read it.)
		if(FileSeek(FInFileHandle, (SeekInt)sizeof(EOC), 1 ) == -1) throw EZipBuilder(DS_EOCBadSeek);
		// Write the changed EndOfCentral directory record.
		EOC.CentralOffset += OffsetChange;
		if(FileWrite(OutFile, &EOC, sizeof(EOC)) != sizeof(EOC))
			throw EZipBuilder(DS_EOCBadWrite);
		// And finally the archive comment itself.
		if(zip->CopyBuffer(FInFileHandle, OutFile, EOC.ZipCommentLen))
			throw EZipBuilder(DS_EOCBadCopy);
	}
	catch( ... )
	{
		Result = -2;
	}
	return Result;
}
// TInternalSFX::ConvertSFX------------------------------------------------------
int __fastcall TInternalSFX::ConvertSFX(bool AutoExeViaAdd)
{
	const
		SE_CreateError = -1,  // Error in open of OutFile.
		SE_CopyError = -2,  // Read or write error during copy.
		SE_OpenReadError = -3,  // Error in open of InFile.
		SE_GeneralError = -9;
	int InFile, OutFile, Result = SE_GeneralError;
	int SFXSize = -1, ZipSize = -1, OutSize = -1, SFXBlkSize;
	char dirbuf[MAX_PATH], *sfxblk, cll = 0;
  TZipBuilder *zip = dynamic_cast<TZipBuilder *>(FOwner);

	int L = zip->FSFXCaption.Length() + zip->FSFXDefaultDir.Length() +
	        zip->FSFXCommandLine.Length() + zip->FSFXMessage.Length();
	SFXBlkSize = ((12 + L + 3) / 4)* 4;	// DWord Alignment.

	/* Do a simple validation to ensure that the 4 variable length text
	 * fields are small enough to fit inside the SFX control block. */
	if(zip->FSFXCaption.Length() > 255 || zip->FSFXDefaultDir.Length() > 255 ||
		 zip->FSFXCommandLine.Length() > 255 || zip->FSFXMessage.Length() > 255)
	{
		zip->ShowZipMessage(SF_StringToLong, "\r\nSFXCaption + SFXDefaultDir +"
		                                "SFXCommandLine + SFXMessage = " + IntToStr(SFXBlkSize + 1));
		return Result;
	}
	// Try to find the SFX binary file: ZIPSFX.BIN
	// Look in the location given by the SFXPath property first.
	do{
    if(zip->FSFXPath[zip->FSFXPath.Length()] != '\\')
         zip->FSFXPath += "\\"; // make sure it is a path
		if(FileExists(zip->FSFXPath = ExtractFilePath(zip->FSFXPath) + "ZipSFX.bin")) break;
		// Try the current directory.
		if(FileExists(zip->FSFXPath = "ZipSFX.bin")) break;
		// Try the application directory.
		if(FileExists(zip->FSFXPath = ExtractFilePath(ParamStr(0)) + "\\ZipSFX.bin")) break;
		// Try the Windows System dir.
		::GetSystemDirectory(dirbuf, MAX_PATH);
		if(FileExists(zip->FSFXPath = AnsiString(dirbuf) + "\\ZipSFX.bin")) break;
		// Try the Windows dir.
		::GetWindowsDirectory(dirbuf, MAX_PATH);
		if(FileExists( zip->FSFXPath = AnsiString(dirbuf ) + "\\ZipSFX.bin")) break;
		// Try the dir specified in the DLLDirectory property.
		if(zip->FDLLDirectory != "" && FileExists(zip->FSFXPath = zip->FDLLDirectory + "\\ZipSFX.bin")) break;
		zip->ShowZipMessage(SF_NoZipSFXBin);
		zip->FSFXPath = "";
		return Result;
	} while(true);

⌨️ 快捷键说明

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