📄 buildintsfx.cpp
字号:
//---------------------------------------------------------------------------
#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 + -