작은 PE 파일 분석기를 작성 중이므로 PE 파일의 내용을 읽어야합니다. - 그것은 기적으로 발생Delphi XE2의 비동기 ReadFile
function TMainForm.GetPEData(var filename: string) : boolean;
var
hFile: DWORD;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
ISH: TImageSectionHeader;
dwRead: DWORD;
szBuff: array[0..7] of Char;
i: WORD;
PE: TPEFile;
begin
Result := False;
PE := TPeFile.Create;
if PE.LoadFromFile (filename) then
Form2.edEntryPoint.Text := IntToHex(PE.RvaToFileOffset(PE.AddressOfEntryPoint), 8);
SplashScreen.sLabel1.Caption := 'PE File Loaded';
hFile := CreateFile(PChar(filename), GENERIC_READ,
FILE_SHARE_WRITE, nil,
OPEN_EXISTING, 0, 0);
if hFile <> INVALID_HANDLE_VALUE then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
SplashScreen.sLabel1.Caption := 'Reading DOS File Headers...';
ReadFile(hFile, IDH, 64, dwRead, nil);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN);
SplashScreen.sLabel1.Caption := 'Reading NT File Headers...';
//Here is where the UI freezes while the file is read...
ReadFile(hFile, INH, 248, dwRead, nil);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
Form2.edImageBase.Text := IntToHex(INH.OptionalHeader.ImageBase, 8);
Form2.edSizeOfImage.Text := IntToHex(INH.OptionalHeader.SizeOfImage, 8);
Form2.edLinkerVersion.Text := IntToStr(INH.OptionalHeader.MajorLinkerVersion) + '.' +
IntToStr(INH.OptionalHeader.MinorLinkerVersion);
Form2.edFileAlignment.Text := IntToHex(INH.OptionalHeader.FileAlignment, 8);
Form2.edSectionAlignment.Text := IntToHex(INH.OptionalHeader.SectionAlignment, 8);
Form2.edSubSystem.Text := IntToHex(INH.OptionalHeader.Subsystem, 4);
Form2.edEPFilestamp.Text := IntToStr(INH.FileHeader.TimeDateStamp);
Form2.edFileType.Text := GetPEFileType(PE.ImageNtHeaders.Signature);
for i := 0 to INH.FileHeader.NumberOfSections - 1 do
begin
SetFilePointer(hFile, IDH._lfanew + 248 + i * 40, nil, FILE_BEGIN);
ReadFile(hFile, ISH, 40, dwRead, nil);
CopyMemory(@szBuff[0], @ISH.Name[0], 8);
with Form2.sListView1.Items.Add do
begin
Caption := ShortString(szBuff);
SubItems.Add(IntToHex(ISH.VirtualAddress, 8));
SubItems.Add(IntToHex(ISH.Misc.VirtualSize, 8));
SubItems.Add(IntToHex(ISH.PointerToRawData, 8));
SubItems.Add(IntToHex(ISH.SizeOfRawData, 8));
SubItems.Add(IntToHex(ISH.Characteristics, 8));
end;
end;
end;
end;
CloseHandle(hFile);
Result := True;
end;
end;
나쁜 것은 파일의 크기에 따라, 나는 ReadFile
종종 지연 것을 눈치이다 : 아래 그림과 같이 나는 ReadFile
기능을 통해이 일을하고 있습니다. 그동안 UI는 얼어 붙어서 사용자에게 해를 끼치 지 않습니다. 사용자를 해고하려는 유혹을받을 것입니다. 스레딩을 고려해 봤지만 비동기 모드에서 ReadFile
을 사용할 수있는 방법이 있는지 알고 싶습니다. 존재하지 않는다면 코드 내에서 수정해야 할 부분이 많을지라도 스레딩으로 넘어갈 것입니다.
미리 감사드립니다.
호기심에서 벗어나서 휠을 재발 명할 이유가 있습니까? 2007 이전의 Delphi 버전에는 체육 정보를 덤프하는 데모가 있지만 (데모 이름이 없지만 나중에 게시 할 예정) [JEDI 코드 라이브러리] (http://delphi-jedi.org)에는 이 모든 작업을 수행 할 준비가 된 함수를 포함하는 전체 유닛 ('JclPEImage'). ('DependencyWalker'와 매우 유사한 방식으로 모든 것을 표시하는 PEViewer 데모도 있습니다.) 모든 코드는 UI 문제 또는 지연없이 매우 큰 실행 파일 (5MB +)에서도 잘 수행됩니다. –
안녕하세요, @KenWhite, 구현에 대한 기본 설정이 없습니다. JEDI를 배제한 이유는 하나의 유닛이 다른 유닛과 연결되어 있기 때문입니다. 즉, IMHO를 사용하면 단일 프로젝트를 수행하는 것보다 전체 프로젝트를 유지하기가 어려워집니다. 이전 델파이 데모를 살펴 보겠습니다. 아직 델파이 7 디스크가 있습니다. –
집에 도착하면 D7에서 데모 이름을 찾아서 여기에 의견을 게시합니다. 'JCL'은 유닛을 사용한 후에 'JVCL'보다 낫다. 왜냐하면 그것은 엄격한 코드이기 때문이다. 그것은 다른 것들을 추가하지만,이 경우에는 uses 절에'JclPEImage'를 포함하는 단일 유닛 이름을 추가하고 코드에서 간단한 함수를 호출합니다. 그것은 나쁘지 않습니다. (JVCL이 포함하고있는 다른 유닛들과도 귀찮게 공존 함). –