Note that there are some explanatory texts on larger screens.

plurals
  1. POAsynchronous ReadFile in Delphi XE2
    primarykey
    data
    text
    <p>I'm writing a small PE file analyzer and I have to read the contents of the PE file. I'm doing this via the <code>ReadFile</code> function, as shown below:</p> <pre><code>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 &lt;&gt; 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; </code></pre> <p>The bad thing is that, depending on the size of the file, I noticed that the <code>ReadFile</code> would often lag - and it happens synchronously. In the meantime, the UI freezes and looks horribly wrong to the user, who would be tempted to terminate it. I have considered threading, but I just want to see if there is any way I can use <code>ReadFile</code> in asynchronous mode. If there isn't, I'll jump to threading, even if I'll have a lot to modify in my code.</p> <p>Thank you in advance.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. COJust out of curiosity, is there a reason you're reinventing the wheel here? Delphi versions prior to 2007 have a demo that dumps the PE information (don't have the demo name here, but will post it later), and the [JEDI Code Library](http://delphi-jedi.org) has an entire unit (`JclPEImage`) containing ready-to-use functions that do all this stuff for you. (There's even a PEViewer demo that displays everything in a way very similar to `DependencyWalker`.) All of the code performs just fine on even very large executables (5 MB+) without any UI issues or lags.
      singulars
    2. COHey there, @KenWhite, I don't have any preferences on the implementation. Indeed, I excluded JEDI, because of the fact that one unit links to another and so on and this - IMHO - makes the whole project mere difficult to maintain than if I had a single function in place. I'll take a look at the old Delphi demos, I think I still have the disc with Delphi 7 around.
      singulars
    3. COWhen I get to my home system, I'll find the demo name from D7 and post it in a comment here. `JCL` is better than `JVCL` about using unit after unit, because it's strictly code. It does add some other stuff, but in this case you're adding a single unit name to your uses clause to include `JclPEImage`, and calling simple functions from your code. It's not bad (although I agree the JVCL is annoyingly co-dependent on other units it contains).
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload