📄 exeimage.pas
字号:
i:=ACount mod Max_Buf;
if i>0 then
begin
FExeStream.Read(ResBuffer,i);
tmpSegStream.Write(ResBuffer,i);
end;
result:=tmpSegStream;
end;
{ 返回资源中经过处理的光标文件流 }
function TExeImage.GetCursorStream(AOffset, ACount, HeaderOffset,NameID: Integer): TMemoryStream;
const
Max_Buf = 1024;
var
tmpSegStream: TMemoryStream;
tmpIconFileHeader: TIconFileHeader;
tmpIconHeader: TIconHeader;
dBitCount: Word;
tmpCursorResInfo: TCursorResInfo;
ResBuffer:array[0..Max_Buf-1] of Byte;
i:Integer;
begin
FExeStream.Seek(HeaderOffset,soFromBeginning);
FExeStream.Read(tmpIconHeader,SizeOf(tmpIconHeader));
with tmpIconFileHeader do
begin
idReserved:=0;
idType:=1;//实际保存成文件时将此标记为2;
idCount:=1;
dwImageOffset:=SizeOf(tmpIconFileHeader);
bReserved:=0;
end;
for i:=0 to tmpIconHeader.wCount-1 do
begin
FExeStream.Read(tmpCursorResInfo,SizeOf(tmpCursorResInfo));
if tmpCursorResInfo.wNameOrdinal=NameID then
begin
with tmpIconFileHeader do
begin
bWidth := tmpCursorResInfo.wWidth;
bHeight:= tmpCursorResInfo.wHeight div 2;
dwBytesInRes:=tmpCursorResInfo.lBytesInRes-2*SizeOf(dBitCount); //此值应该=ACount-4;
//wPlanes:=tmpIconResInfo.wPlanes;
//wBitCount:=tmpIconResInfo.wBitCount;
//bColorCount:=tmpIconResInfo.bColorCount;
end;
break;
end;
end;
FExeStream.Seek(AOffSet,soFromBeginning);
FExeStream.Read(dBitCount,SizeOf(dBitCount));
tmpIconFileHeader.wPlanes := dBitCount;
FExeStream.Read(dBitCount,SizeOf(dBitCount));
tmpIconFileHeader.wBitCount:= dBitCount;
ACount:=tmpCursorResInfo.lBytesInRes-2*SizeOf(dBitCount);// ACount-2*SizeOf(dBitCount);
tmpSegStream:=TMemoryStream.Create;
tmpSegStream.SetSize(ACount+SizeOf(tmpIconFileHeader));
tmpSegStream.Write(tmpIconFileHeader,SizeOf(tmpIconFileHeader));
if ACount>=Max_Buf then
for i:=0 to (ACount div Max_Buf)-1 do
begin
FExeStream.Read(ResBuffer,Max_Buf);
tmpSegStream.Write(ResBuffer,Max_Buf);
end;
i:=ACount mod Max_Buf;
if i>0 then
begin
FExeStream.Read(ResBuffer,i);
tmpSegStream.Write(ResBuffer,i);
end;
result:=tmpSegStream;
end;
{ 返回资源中经过处理的图标文件流 }
function TExeImage.GetIconStream(AOffset, ACount, HeaderOffset,NameID: Integer): TMemoryStream;
Const
Max_Buf=1024;
var
tmpSegStream: TMemoryStream;
tmpIconFileHeader: TIconFileHeader;
tmpIconHeader: TIconHeader;
tmpIconResInfo: TIconResInfo;
ResBuffer:array[0..Max_Buf-1] of Byte;
i:Integer;
begin
FExeStream.Seek(HeaderOffset,soFromBeginning);
FExeStream.Read(tmpIconHeader,SizeOf(tmpIconHeader));
with tmpIconFileHeader do
begin
idReserved:=0;
idType:=1;
idCount:=1;
dwImageOffset:=SizeOf(tmpIconFileHeader);
bReserved:=0;
end;
for i:=0 to tmpIconHeader.wCount-1 do
begin
FExeStream.Read(tmpIconResInfo,SizeOf(tmpIconResInfo));
if tmpIconResInfo.wNameOrdinal=NameID then
begin
with tmpIconFileHeader do
begin
bWidth := tmpIconResInfo.bWidth;
bHeight := tmpIconResInfo.bHeight;
dwBytesInRes:=tmpIconResInfo.lBytesInRes; //此值应该=ACount;
wPlanes:=tmpIconResInfo.wPlanes;
wBitCount:=tmpIconResInfo.wBitCount;
bColorCount:=tmpIconResInfo.bColorCount;
end;
break;
end;
end;
tmpSegStream:=TMemoryStream.Create;
tmpSegStream.SetSize(ACount+SizeOf(tmpIconFileHeader));
tmpSegStream.Write(tmpIconFileHeader,SizeOf(tmpIconFileHeader));
FExeStream.Seek(AOffSet,soFromBeginning);
if ACount>=Max_Buf then
for i:=0 to ACount div Max_Buf do
begin
FExeStream.Read(ResBuffer,Max_Buf);
tmpSegStream.Write(ResBuffer,Max_Buf);
end;
i:=ACount mod Max_Buf;
if i>0 then
begin
FExeStream.Read(ResBuffer,i);
tmpSegStream.Write(ResBuffer,i);
end;
result:=tmpSegStream;
end;
{ 判断资源数据是否有 }
function TExeImage.IsResourceExists: Boolean;
var
i,j:Word;
tmpStr: String;
IsResExists:Boolean;
begin
IsResExists:=false;
//检测是否有资源节表[简单以名称来判断,此办法对某些文件无效]
for i:=0 to FPENTHead.FileHeader.NumberOfSections-1 do
begin
{ section name }
tmpStr:='';
for j:=0 to 7 do
tmpStr:=tmpStr+ Chr(FPESectionHead[i].Name[j]);
{ check resource directory }
if TmpStr='.rsrc'+#0+#0+#0 then
begin
FResourceInSectionIndex:=i;
IsResExists:=true;
break;
end;
end;
Result:=IsResExists;
end;
{ 遍历资源目录获取资源数据的个数 }
function TExeImage.GetResDataNum: Word;
var
ResNum : Word;
i,iNum,jNum:Integer;
myOffSet,tmpOffSet:Cardinal; { 资源目录物理地址 }
ResDir:array of TImageResourceDirectory;
PEResourceDirectory:TImageResourceDirectory;
begin
//tmpVirtualAddress := FPESectionHead[FResourceInSectionIndex].VirtualAddress;
tmpOffset := FPESectionHead[FResourceInSectionIndex].PointerToRawData;
resNum:=0;
FExeStream.Seek(tmpOffSet,0);
FExeStream.Read(PEResourceDirectory,SizeOf(PEResourceDirectory));
iNum:=PEResourceDirectory.NumberOfNamedEntries +
PEResourceDirectory.NumberOfIdEntries;
if iNum>0 then
begin
SetLength(ResDir,iNum);
tmpOffSet:=tmpOffSet+SizeOf(PEResourceDirectory)
+(iNum)*SizeOf(TImageResourceDirectoryEntry);
MyOffSet:=0;
ResNum:=0;
for i:=0 to iNum-1 do
begin
FExeStream.Seek(tmpOffSet+myOffSet,0);
FExeStream.Read(ResDir[i],SizeOf(ResDir[i]));
jNum:=ResDir[i].NumberOfNamedEntries+ResDir[i].NumberOfIdEntries;
ResNum := ResNum + jNum;
MyOffSet := MyOffSet + SizeOf(ResDir[i])
+ jNum * SizeOf(TImageResourceDirectoryEntry);
end;
end;
result:=resNum;
end;
{****************************************************
GetResourceDataDir 返回资源数据目录
在调用之后需要检测一下ResDataNum是否为0,如果为0,则
变体的值为空。
****************************************************}
function TExeImage.GetResourceDataDir: Variant;
var
v: Variant;
iNum,jNum,i,j:Integer;
TmpPos:LongInt; { 文件临时位置 }
TmpStr:String; { 临时字符串 }
tmpResName,tmpResType:String;
CurResDataNum:Word;
tmpOffSet,tmpSize:DWord;
PEResourceDirectoryPointerToRawData:Cardinal;{ 资源目录物理地址 }
PEResourceDirectoryVirtualAddress:Cardinal; { 资源相对实际地址 }
PEResourceDirectory:TImageResourceDirectory;
PEResDataEnt:TImageResourceDataEntry;
PEResourceDirStringU:TImageResourceDirStringU;
ResWName:array[0..MAX_PATH] of WChar;
ResSName:WideString; { PEResourceDirStringU.Name for String }
iName:Integer;
ResDir_1:array of TImageResourceDirectory;
ResDir_2:TImageResourceDirectory;
ResdirEnt_1,ResdirEnt_2:array of TImageResourceDirectoryEntry;
ResdirEnt_3:TImageResourceDirectoryEntry;
begin
if FResDataNum=0 then
begin
result:=null;
exit;
end;
PEResourceDirectoryVirtualAddress:=FPESectionHead[FResourceInSectionIndex].VirtualAddress;
PEResourceDirectoryPointerToRawData:=FPESectionHead[FResourceInSectionIndex].PointerToRawData;
v:=VarArrayCreate([0,FResDataNum-1],VarVariant);
FExeStream.Seek(PEResourceDirectoryPointerToRawData,0);
FExeStream.Read(PEResourceDirectory,SizeOf(PEResourceDirectory));
iNum:=PEResourceDirectory.NumberOfNamedEntries+
PEResourceDirectory.NumberOfIdEntries;
SetLength(ResDir_1,iNum);
SetLength(ResDirEnt_1,iNum);
for i:=0 to iNum-1 do
FExeStream.Read(ResDirEnt_1[i],SizeOf(ResDirEnt_1[i]));
CurResDataNum:=0;
for i:=0 to iNum-1 do
begin
FExeStream.Read(ResDir_1[i],SizeOf(ResDir_1[i]));
//获取资源类型
if (ResDirEnt_1[i].Name and $80000000)=0 then
begin { 最高位为 0 ,剩余的 31 位为一个整数ID }
tmpResType := CheckResourceType(ResDirEnt_1[i].Name);
end else { 最高位为 1 ,剩下 31 位为 IMAGE_RESOURCE_DIR_STRING_U 结构的偏移位置 从 Resource Section 开始 }
begin
TmpPos:=FExeStream.Seek(0,1); { 记忆文件位置 }
FExeStream.Seek(ResDirEnt_1[i].Name and $7FFFFFFF
+PEResourceDirectoryPointerToRawData,
soFromBeginning);
FExeStream.Read(PEResourceDirStringU,SizeOf(PEResourceDirStringU));
FExeStream.Read(ResWName,(PEResourceDirStringU.Length-1)*2);
ResSName:=PEResourceDirStringU.NameString;
for iName:=0 to PEResourceDirStringU.Length-2 do
ResSName:=ResSName+ResWName[iName];
FExeStream.Seek(TmpPos,0); { 恢复文件位置 i 位置 }
tmpResType := ResSName;
end;
jNum:=ResDir_1[i].NumberOfNamedEntries+ResDir_1[i].NumberOfIdEntries;
SetLength(ResDirEnt_2,jNum);
for j:=0 to jNum-1 do
begin
FExeStream.Read(ResDirEnt_2[j],SizeOf(ResDirEnt_2[j]));
TmpPos:=FExeStream.Seek(0,1); { 保存地址 }
FExeStream.Seek(PEResourceDirectoryPointerToRawData+ResDirEnt_2[j].OffsetToData-$80000000,0);
FExeStream.Read(ResDir_2,SizeOf(ResDir_2));
FExeStream.Read(ResDirEnt_3,SizeOf(ResDirEnt_3));
//获取指定类型的资源名称:
if (ResDirEnt_2[j].Name and $80000000)=0 then
begin { 最高位为 0 ,剩余的 31 位为一个整数ID }
tmpResName := Format('%u',[ResDirEnt_2[j].Name]);
end else { 最高位为 1 ,剩下 31 位为 IMAGE_RESOURCE_DIR_STRING_U 结构的偏移位置 从 Resource Section 开始 }
begin
FExeStream.Seek(ResDirEnt_2[j].Name and $7FFFFFFF
+PEResourceDirectoryPointerToRawData,
soFromBeginning);
FExeStream.Read(PEResourceDirStringU,SizeOf(PEResourceDirStringU));
FExeStream.Read(ResWName,(PEResourceDirStringU.Length-1)*2);
ResSName:=PEResourceDirStringU.NameString;
for iName:=0 to PEResourceDirStringU.Length-2 do
ResSName:=ResSName+ResWName[iName];
tmpResName := ResSName;
end;
{ 最终的资源位置 }
FExeStream.Seek(ResDirEnt_3.OffsetToData+PEResourceDirectoryPointerToRawData,0);
FExeStream.Read(PEResDataEnt,SizeOf(PEResDataEnt));
{ 存在资源,需要一一解析出来存到
v[x][0]=资源类型,
v[x][1]=资源名称,
v[x][2]=偏移量
v[x][3]=大小
v[x][4]=父类
v[x][5]=描述
}
tmpOffSet := PEResourceDirectoryPointerToRawData
+PEResDataEnt.OffsetToData
-PEResourceDirectoryVirtualAddress;
tmpSize := PEResDataEnt.Size;
v[CurResDataNum]:=VarArrayOf([tmpResType,tmpResName,tmpOffSet,tmpSize]);
inc(CurResDataNum);
FExeStream.Seek(TmpPos,0);
end;
end;
result:=v;
end;
function TExeImage.AnalysisIconOrCursorGroupInfo(
AOffset: Integer): Variant;
const
IconFieldCount=8;
CursorFieldCount=6;
var
tmpVar: Variant;
tmpStrType:String;
tmpAddr: Integer; //地址
tmpValue: String;//值
tmpMemo: String; //含义
tmpIconHeader: TIconHeader;
tmpIconResInfo: TIconResInfo;
tmpCursorResInfo:TCursorResInfo;
i: Word;
begin
FExeStream.Seek(AOffset,0);
FExeStream.Read(tmpIconHeader,SizeOf(tmpIconHeader));
with tmpIconHeader do
begin
if wType=2 then
begin
FGroupVarCount:= 3 + wCount*CursorFieldCount;
tmpStrType := '光标';
end
else
begin
FGroupVarCount:= 3 + wCount*IconFieldCount;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -