📄 unitpefile.pas
字号:
ZeroMemory (padding, paddingLen);
end;
if paddingSize > 0 then
s.Write (padding^, paddingSize)
end;
if fEndCommentSize > 0 then // Save the debug info.
s.Write (fEndComment^, fEndCommentSize)
finally
ReallocMem (padding, 0)
end;
f := TMemoryStream.Create; // Now calculate the checksum....
try
s.Seek (0, soFromBeginning);
f.LoadFromStream (s);
ntHeaders := ChecksumMappedFile (f.Memory, f.Size, @oldCheckSum, @newCheckSum);
if Assigned (ntHeaders) then
begin
s.Seek (ckOffset, soFromBeginning);
s.Write (newChecksum, sizeof (newChecksum))
end
finally
f.Free
end;
s.Seek (0, soFromEnd);
end;
{ TImageSection }
(*----------------------------------------------------------------------*
| constructor TImageSection.Create |
| |
| Constructor for TImageSection. |
*----------------------------------------------------------------------*)
constructor TImageSection.Create(AParent: TPEModule;
const AHeader : TImageSectionHeader; rawData : pointer);
begin
fSectionHeader := AHeader;
fRawData := TMemoryStream.Create;
// nb. SizeOfRawData is usually bigger than VirtualSize because it's padded,
// and VirtualSize isn't.
if fSectionHeader.Misc.VirtualSize <= fSectionHeader.SizeOfRawData then
begin
// Some linkers (?) set VirtualSize to 0 - which isn't correct. Work round it.
// (Encountered in MCL Link Lite HHT software )
if fSectionHeader.Misc.VirtualSize = 0 then
fSectionHeader.Misc.VirtualSize := fSectionHeader.SizeOfRawData;
fRawData.Write (rawData^, fSectionHeader.Misc.VirtualSize)
end
else
// nb. If VirtualSize is bigger than SizeOfRawData it implies that extra padding is required.
// Save the amount, so we can get all the COFF header values right. See 'Encode' above.
begin
fRawData.Write (rawData^, fSectionHeader.SizeOfRawData);
fUninitializedDataSize := fSectionHeader.Misc.VirtualSize - fSectionHeader.SizeOfRawData;
end;
fParent := AParent;
end;
(*----------------------------------------------------------------------*
| function TImageSection.GetSectionName |
| |
| Return the section name - eg. .data |
*----------------------------------------------------------------------*)
function TImageSection.GetSectionName: string;
begin
result := PChar (@fSectionHeader.Name)
end;
(*----------------------------------------------------------------------*
| destructor TImageSection.Destroy |
| |
| destructor for TImageSection. |
*----------------------------------------------------------------------*)
destructor TImageSection.destroy;
begin
fRawData.Free;
inherited;
end;
{ TPEResourceModule }
(*----------------------------------------------------------------------*
| function TPEResourceModule. |
| |
| Return the TImageSection that contains 'resource' data. - eg. the |
| .rsrc one. |
*----------------------------------------------------------------------*)
function TPEResourceModule.GetResourceSection : TImageSection;
var
idx : Integer;
begin
idx := FindDictionaryEntrySection (IMAGE_DIRECTORY_ENTRY_RESOURCE);
if idx = -1 then
result := Nil
else
result := ImageSection [idx]
end;
(*----------------------------------------------------------------------*
| procedure TPEResourceModule.DeleteResource |
| |
| Delete the specified resource (by index) |
*----------------------------------------------------------------------*)
procedure TPEResourceModule.DeleteResource(resourceNo: Integer);
var
res : TResourceDetails;
begin
res := ResourceDetails [resourceNo];
inherited;
resourceNo := IndexOfResource (Res);
if resourceNo <> -1 then
fDetailList.Delete (resourceNo);
end;
(*----------------------------------------------------------------------*
| constructor TPEResourceModule.Create |
| |
| Constructor for TPEResourceModule |
*----------------------------------------------------------------------*)
constructor TPEResourceModule.Create;
begin
inherited Create;
fDetailList := TObjectList.Create;
end;
(*----------------------------------------------------------------------*
| destructor TPEResourceModule.Destroy |
| |
| Destructor for TPEResourceModule |
*----------------------------------------------------------------------*)
destructor TPEResourceModule.Destroy;
begin
fDetailList.Free;
inherited;
end;
(*----------------------------------------------------------------------*
| function TPEResourceModule.Decode |
| |
| Decode the section's resource tree into a list of resource details |
*----------------------------------------------------------------------*)
procedure TPEResourceModule.Decode;
var
section : TImageSection;
tp, name : string;
lang : Integer;
// Get string resource name
function GetResourceStr (IdorName : boolean; section : TImageSection; n : DWORD) : string;
var
p : PWideChar;
begin
if IdorName then
result := IntToStr (n)
else
begin
p := PWideChar (PChar (section.fRawData.Memory) + (n and $7fffffff));
result := ResourceWideCharToStr (p)
end
end;
// (recursively) get resources
procedure GetResource (offset, level : Integer);
var
entry : PResourceDirectoryEntry;
i, count : Integer;
IDorName : boolean;
dataEntry : PResourceDataEntry;
table : PResourceDirectoryTable;
details : TResourceDetails;
begin
table := PResourceDirectoryTable (PChar (section.fRawData.memory) + offset);
with table^ do
count := cNameEntries + cIDEntries;
entry := PResourceDirectoryEntry (PChar (section.fRawData.memory) + offset + sizeof (TResourceDirectoryTable));
for i := 0 to count - 1 do
begin
idOrName := i >= table^.cNameEntries;
case level of
0 : tp := GetResourceStr (IDOrName, section, entry^.name);
1 :
name := GetResourceStr (IDOrName, section, entry^.name);
2 :
begin
if not IdOrName then
raise EPEException.Create (rstBadLangID);
lang := entry^.name
end
end;
if (entry^.RVA and $80000000) > 0 then // Not a leaf node - traverse the tree
GetResource (entry^.RVA and $7fffffff, level + 1)
else
begin
// It's a leaf node - create resource details
dataEntry := PResourceDataEntry (PChar (section.fRawData.Memory) + entry^.RVA);
details := TResourceDetails.CreateResourceDetails (self, lang, name, tp, dataEntry^.Size, PChar (section.fRawData.Memory) + dataEntry^.OffsetToData - section.fSectionHeader.VirtualAddress);
details.CodePage := dataEntry^.CodePage;
details.Characteristics := table^.characteristics;
details.DataVersion := DWORD (table^.versionMajor) * 65536 + DWORD (table^.versionMinor);
fDetailList.Add (details);
end;
Inc (entry)
end
end;
begin
inherited;
section := GetResourceSection;
if section <> nil then
GetResource (0, 0)
end;
(*----------------------------------------------------------------------*
| function TPEResourceModule.GetResourceCount |
| |
| Return the number of resources in the resource section |
*----------------------------------------------------------------------*)
function TPEResourceModule.GetResourceCount: Integer;
begin
result := fDetailList.Count
end;
(*----------------------------------------------------------------------*
| function TPEResourceModule.GetResourceDetails |
| |
| Get the resource details for the specified resource. |
*----------------------------------------------------------------------*)
function TPEResourceModule.GetResourceDetails(
idx: Integer): TResourceDetails;
begin
result := TResourceDetails (fDetailList [idx]);
end;
(*----------------------------------------------------------------------*
| function TPEResourceModule.IndexOfResource |
| |
| Return the index of the specified resource details in the resource |
*----------------------------------------------------------------------*)
function TPEResourceModule.IndexOfResource(details: TResourceDetails): Integer;
begin
result := fDetailList.IndexOf (details);
end;
(*----------------------------------------------------------------------*
| function TPEResourceModule.InsertResource |
| |
| Insert a resource in the list. |
*----------------------------------------------------------------------*)
procedure TPEResourceModule.InsertResource(idx: Integer;
details: TResourceDetails);
begin
fDetailList.Insert (idx, details);
end;
(*----------------------------------------------------------------------*
| function TPEResourceModule.Encode |
| |
| Complicated? I'll give you complicated ... |
*----------------------------------------------------------------------*)
procedure TPEResourceModule.Encode;
var
i : Integer;
details : TResourceDetails;
section : TImageSection;
root : TResourceNode;
versMajor, versMinor : word;
TimeStamp : DWORD;
nameSize, nameOffset, namePos, tableOffset : DWORD;
deOffset, dePos, deSize : DWORD;
dataOffset, dataPos, dataSize : DWORD;
nameTable : PChar;
deTable : PChar;
data : PChar;
zeros : PChar;
//------------------------------------------------------------------
// Calculate offset and size of name table and DirectoryEntry table.
// Calculate size of data
procedure GetNameTableSize (node : TResourceNode);
var
i : Integer;
begin
Inc (nameOffset, sizeof (TResourceDirectoryTable));
Inc (deOffset, sizeof (TResourceDirectoryTable));
for i := 0 to node.count - 1 do
begin
Inc (nameOffset, sizeof (TResourceDirectoryEntry));
Inc (deOffset, sizeof (TResourceDirectoryEntry));
if not node.nodes [i].intID then
Inc (nameSize, Length (node.nodes [i].id) * sizeof (WideChar) + sizeof (word));
if not node.nodes [i].leaf then
GetNameTableSize (node.nodes [i].next)
else
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -