الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

*dll Exports Functions * Memory Mapped Files*

مغلق
بدأه tmaaa في 2 فبراير 2002 · 3 رد · 1,795 مشاهدة · في أرشيف منتدى الدلفي
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

DLL Exports Functions

الكود الآتي يمكنك من الحصول على الدوال التي يصدرها الـ DLL

أضف Unit جديدة و سمها DLLTools و هذا هو الكود الخاص بها

 
  //   By : Peter Below  http://www.teamb.com   
unit DLLTools; 

  interface  

  Uses Windows, Classes, Sysutils, imagehlp ;  

  type  
    TDLLExportCallback = function (const name: String; ordinal: Integer; 
        address: Pointer): Boolean of Object;  
    { Note: address is a RVA here, not a usable virtual address! }      
    DLLToolsError = Class( Exception );  

  Procedure ListDLLExports( const filename: String; callback:   
  TDLLExportCallback );  
  Procedure DumpExportDirectory( Const ExportDirectory: TImageExportDirectory;  
               lines: TStrings; const Image: LoadedImage  );  
  Function RVAToPchar( rva: DWORD; const Image: LoadedImage ): PChar;  
  Function RVAToPointer( rva: DWORD; const Image: LoadedImage ): Pointer;  

  implementation  

  resourcestring  
    eDLLNotFound =  
      'ListDLLExports: DLL %s does not exist!';  

  {+----------------------------------------------------------------------  
   | Procedure EnumExports  
   |  
   | Parameters :  
   |   ExportDirectory: IMAGE_EXPORT_DIRECTORY record to enumerate  
   |   image    : LOADED_IMAGE record for the DLL the export directory belongs  
   |              to.  
   |   callback : callback function to hand the found exports to, must not be   
  Nil  
   | Description:  
   |   The export directory of a PE image contains three RVAs that point at   
  tables  
   |   which describe the exported functions. The first is an array of RVAs   
  that  
   |   refer to the exported function names, these we translate to PChars to  
   |   get the exported name. The second array is an array of Word that   
  contains  
   |   the export ordinal for the matching entry in the names array. The   
  ordinal  
   |   is biased, that is we have to add the ExportDirectory.Base value to it   
  to  
   |   get the actual export ordinal. The biased ordinal serves as index for   
  the  
   |   third array, which is an array of RVAs that give the position of the  
   |   function code in the image. We don't translate these RVAs since the DLL  
   |   is not relocated since we load it via MapAndLoad. The function array is  
   |   usually much larger than the names array, since the ordinals for the  
   |   exported functions do not have to be in sequence, there can be (and  
   |   frequently are) gaps in the sequence, for which the matching entries in   
  the  
   |   function RVA array are garbage.  
   | Error Conditions: none  
   | Created: 9.1.2000 by P. Below  
   +----------------------------------------------------------------------}  
  Procedure EnumExports( const ExportDirectory : TImageExportDirectory ;  
                         const image : LoadedImage ;  
                         callback : TDLLExportCallback ) ;  
    Type  
      TDWordArray = Array [0..$FFFFF] of DWORD;  
    Var  
      i: Cardinal;  
      pNameRVAs, pFunctionRVas: ^TDWordArray;  
      pOrdinals: ^TWordArray;  
      name: String;  
      address: Pointer;  
      ordinal: Word;  
    Begin { EnumExports }  
      pNameRVAs :=  
        RVAToPointer( DWORD(ExportDirectory.AddressOfNames), image );  
      pFunctionRVAs :=  
        RVAToPointer( DWORD(ExportDirectory.AddressOfFunctions), image );  
      pOrdinals :=  
        RVAToPointer( DWORD(ExportDirectory.AddressOfNameOrdinals), image );  
      For i:= 0 to Pred( ExportDirectory.NumberOfNames ) Do Begin  
        name := RVAToPChar( pNameRVAs^, image );  
        ordinal := pOrdinals^;  
        address := Pointer( pFunctionRVAs^[ ordinal ] );  
        If not callback( name, ordinal+ExportDirectory.Base, address ) Then  
          Exit;  
      End; { For }  
    End; { EnumExports }  

  {+----------------------------------------------------------------------  
   | Procedure ListDLLExports  
   |  
   | Parameters :  
   |   filename : full pathname of DLL to examine  
   |   callback : callback to hand the found exports to, must not be Nil  
   | Description:  
   |   Loads the passed DLL using the LoadImage function, finds the exported  
   |   names table and reads it. Each found entry is handed to the callback  
   |   for further processing, until no more entries remain or the callback  
   |   returns false. Note that the address passed to the callback for a   
  exported  
   |   function is an RVA, so not identical to the address the function would  
   |   have in a properly loaded and relocated DLL!  
   | Error Conditions:  
   |   Exceptions are raised if  
   |   - the passed DLL does not exist or could not be loaded  
   |   - no callback was passed (only if assertions are on)  
   |   - an API function failed  
   | Created: 9.1.2000 by P. Below  
   +----------------------------------------------------------------------}  
  Procedure ListDLLExports( const filename : String ; callback :   
  TDLLExportCallback ) ;  
    Var  
      imageinfo: LoadedImage;  
      pExportDirectory: PImageExportDirectory;  
      dirsize: Cardinal;  
    Begin { ListDLLExports }  
      Assert( Assigned( callback ));  
      If not FileExists( filename ) Then  
        raise DLLToolsError.CreateFmt( eDLLnotFound, [filename] );  

      If MapAndLoad( PChar( filename ), nil, @imageinfo, true, true ) Then  
        try  
          pExportDirectory :=  
            ImageDirectoryEntryToData(  
              imageinfo.MappedAddress, false,  
              IMAGE_DIRECTORY_ENTRY_EXPORT, dirsize );  

          If pExportDirectory = Nil Then  
            RaiseLastWin32Error  
          Else  
            EnumExports( pExportDirectory^, imageinfo, callback );  
        finally  
          UnMapAndLoad( @imageinfo );  
        end  
      Else  
        RaiseLastWin32Error;  
    End; { ListDLLExports }  

  {+----------------------------------------------------------------------  
   | Procedure DumpExportDirectory  
   |  
   | Parameters :  
   |   ExportDirectory: a IMAGE_EXPORT_DIRECTORY record  
   |   lines    : a TStrings descendend to put the info into, must not be Nil  
   | Description:  
   |   Dumps the fields of the passed structure to the passed strings   
  descendent  
   |   as strings.  
   | Error Conditions:  
   |   will raise an exception if lines is Nil and assertions are enabled.  
   | Created: 9.1.2000 by P. Below  
   +----------------------------------------------------------------------}  
  Procedure DumpExportDirectory( Const ExportDirectory : TImageExportDirectory;  
      lines : TStrings; const Image: LoadedImage ) ;  
    Begin { DumpExportDirectory }  
      Assert( Assigned( lines ));  

      lines.add( 'Dump of IMAGE_EXPORT_DIRECTORY' );  
      lines.add( format('Characteristics: %d',  
                       [ExportDirectory.Characteristics]));  
      lines.add( format('TimeDateStamp: %d',  
                       [ExportDirectory.TimeDateStamp]));  
      lines.add( format('Version: %d.%d',  
                       [ExportDirectory.MajorVersion,   
  ExportDirectory.MinorVersion]));  
      lines.add( format('Name (RVA): %x',  
                       [ExportDirectory.Name]));  
      lines.add( format('Name (translated): %s',  
                        [RVAToPchar( ExportDirectory.name, Image )]));  
      lines.add( format('Base: %d',  
                       [ExportDirectory.Base]));  
      lines.add( format('NumberOfFunctions: %d',  
                       [ExportDirectory.NumberOfFunctions]));  
      lines.add( format('NumberOfNames: %d',  
                       [ExportDirectory.NumberOfNames]));  
      lines.add( format('AddressOfFunctions (RVA): %p',  
                       [Pointer(ExportDirectory.AddressOfFunctions)]));  
      lines.add( format('AddressOfNames (RVA): %p',  
                       [Pointer(ExportDirectory.AddressOfNames)]));  
      lines.add( format('AddressOfNameOrdinals (RVA): %p',  
                       [Pointer(ExportDirectory.AddressOfNameOrdinals)]));  
    End; { DumpExportDirectory }  

  {+----------------------------------------------------------------------  
   | Function RVAToPointer  
   |  
   | Parameters :  
   |   rva      : a relative virtual address to translate  
   |   Image    : LOADED_IMAGE structure for the image the RVA relates to  
   | Returns    : translated address  
   | Description:  
   |   Uses the ImageRVAToVA function to translate the RVA to a virtual  
   |   address.  
   | Error Conditions:  
   |   Will raise an exception if the translation failed  
   | Created: 9.1.2000 by P. Below  
   +----------------------------------------------------------------------}  
  Function RVAToPointer( rva : DWORD ; const Image : LoadedImage ) : Pointer;  
    var  
      pDummy: PImageSectionHeader;  
    Begin { RVAToPchar }  
      pDummy := nil;  
      Result :=  
        ImageRvaToVa( Image.FileHeader, Image.MappedAddress, rva,  
                      pDummy );  
      If Result = Nil Then  
        RaiseLastWin32Error;  
    End; { RVAToPointer }  

  {+----------------------------------------------------------------------  
   | Function RVAToPchar  
   |  
   | Parameters :  
   |   rva      : a relative virtual address to translate  
   |   Image    : LOADED_IMAGE structure for the image the RVA relates to  
   | Returns    : translated address  
   | Description:  
   |   Uses the RVAToPointer function to translate the RVA to a virtual  
   |   address. Note that we do not check that the address does indeed point  
   |   to a zero-terminated string!  
   | Error Conditions:  
   |   Will raise an exception if the translation failed  
   | Created: 9.1.2000 by P. Below  
   +----------------------------------------------------------------------}  
  Function RVAToPchar( rva : DWORD ; const Image : LoadedImage ) : PChar ;  
    Begin { RVAToPchar }  
      Result := RVAToPointer( rva, image );  
    End; { RVAToPchar }  

  end.

-------------------------------------

هنا استخدام الـ Unit السابقة

* أضف DLLTools الى Uses

* أضف Button , listview , opendialog

* أضف التصريح التالي للدالة ListExport في Private

 
private 
    { Private declarations } 
    function ListExport( const name: String; ordinal: Integer; address:Pointer ): Boolean;

وهذا هو الكود الخاص بالدالة

 
function TForm1.ListExport( const name: String; ordinal: Integer; address:Pointer ): Boolean; 
  var  
    listentry: TListItem;  
  begin  
    Result := true; 
    listentry:= listview1.Items.Add; 
    listentry.Caption := Format('%p',[address] ); 
    listentry.Subitems.Add( format('%d',[ordinal] )); 
    listentry.Subitems.Add( name );  
  end;

* في الحدث Onclick للـ Button المضاف أضف الكود الآتي

 
procedure TForm1.Button1Click(Sender: TObject); 
begin 
  if opendialog1.execute then 
    begin  
      listview1.items.clear; 
      ListDLLExports( opendialog1.filename, listexport ); 
    end;  
end;

--------------------------

هناك مقال نشر في Delphi3000 و قمت بتجربته لكن لم يقم بأي شئ :(

وهذا هو الموضوع

 
Add the unit ImageHlp in USES of the form.  



procedure ListDLLFunctions(DLLName: String; List: TStrings);  
type  
chararr = array [0..$FFFFFF] of Char;  
var H: THandle;  
    I,  
    fc: integer;  
    st: string;  
    arr: Pointer;  
    ImageDebugInformation: PImageDebugInformation;  

begin  
  List.Clear;  
  DLLName := ExpandFileName(DLLName);  
  if FileExists(DLLName) then  
  begin  
    H := CreateFile(PChar(DLLName), GENERIC_READ, FILE_SHARE_READ or  
    FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);  
    if H<>INVALID_HANDLE_VALUE then  
      try  
        ImageDebugInformation := MapDebugInformation(H, PChar(DLLName), nil, 0);  
        if ImageDebugInformation<>nil then  
          try  
            arr := ImageDebugInformation^.ExportedNames;  
            fc := 0;  
            for I := 0 to ImageDebugInformation^.ExportedNamesSize - 1 do  
              if chararr(arr^)=#0 then  
              begin  
                st := PChar(@chararr(arr^)[fc]);  
                if Length(st)>0 then  
                  List.Add(st);  
                  if (I>0) and (chararr(arr^)[I-1]=#0) then  
                    Break;  
                  fc := I + 1  
              end  
          finally  
            UnmapDebugInformation(ImageDebugInformation)  
          end  
      finally  
        CloseHandle(H)  
      end  
  end  
end;  



To call this procedure in your application, put a button and a list box in your form and do the follow:  

procedure TForm1.Button1Click(Sender: TObject);  
var  
List: TStrings;  
I: integer;  

begin  
  List := TStringList.Create;  
  listbox1.clear;  
  ListDLLFunctions('PATH OF DLL', List);  
  for I := 0 to List.Count - 1 do  
    listbox1.items.add(list);  
  List.Free  
end;

------------------------

------------------------

Memory Mapped Files

Working with extremely large text files

هذا موضوع جيد نشر في DelphiPages يمكن الاطلاع عليه هنا

http://www.delphipages.com/news/detaildocs.cfm?ID=41

لمزيد من المعلومات عن Memory Mapped Files فما نشره الأخ هاني الأتاسي واحد من أجمل المواضيع المنشورة هنا وقد وعد بنشر معلومات في هذا الموضوع ( منتظرين على نار ;) ).

هناك حتى الأحلام أصبحت ممنوعة ...

إنه لعار أن ننتمي لهكذا أوطان ... لكن ... ربما العار أن نكون نحن أبناء لتلكم أوطان .. من يدري ؟!!

ليعلم أولئك ... إنّ الشعوب إنْ هي استيقظت تسحق ظُلامََهَا ...

There, even in dreams u r wanted

To be a programmer, how a nice dream it was

Leaving ...

أعيدوا لإسمي لونه المفضل

#2

اشكرك اخي tmaaa كثيراً على جهودك الكبيرة في هذا المنتدى

على العموم بالنسبة لعملية exported Dll functions

فيمكنك علمها عن طريق هذا الكود :

uses imagehlp; 

function ListDLLExports(const FileName: string): TStringList; 
type 
  TDWordArray = array [0..$FFFFF] of DWORD; 
var 
  imageinfo: LoadedImage; 
  pExportDirectory: PImageExportDirectory; 
  dirsize: Cardinal; 
  pDummy: PImageSectionHeader; 
  i: Cardinal; 
  pNameRVAs: ^TDWordArray; 
  Name: string; 
begin 
  Result := TStringList.Create; 
  if MapAndLoad(PChar(FileName), nil, @imageinfo, True, True) then 
  begin 
    try 
      pExportDirectory := ImageDirectoryEntryToData(imageinfo.MappedAddress, 
        False, IMAGE_DIRECTORY_ENTRY_EXPORT, dirsize); 
      if (pExportDirectory <> nil) then 
      begin 
        pNameRVAs := ImageRvaToVa(imageinfo.FileHeader, imageinfo.MappedAddress, 
          DWORD(pExportDirectory^.AddressOfNames), pDummy); 
        for i := 0 to pExportDirectory^.NumberOfNames - 1 do 
        begin 
          Name := PChar(ImageRvaToVa(imageinfo.FileHeader, imageinfo.MappedAddress, 
            pNameRVAs^, pDummy)); 
          Result.Add(Name); 
        end; 
      end; 
    finally 
      UnMapAndLoad(@imageinfo); 
    end; 
  end; 
end;

طريقة استدعاء الكود السابق :

 

var 
  slExports: TStringList; 
begin 
  if OpenDialog1.Execute then 
  begin 
    slExports := ListDLLExports(OpenDialog1.FileName); 
    ShowMessage(slExports.Text); 
    FreeAndNil(slExports) 
  end;

طبعاً بالنسبة للأكواد التي ذكرتها انت مسبقاً فقد قمت بتجريبها فالكود الأول ليس جيد ولايقوم بالعمل والكود الثاني عمل معي ولكن مشكتله انه يظهر بعض ال Function وليست كامله :)

وتقبل اطيب تحياتي اخوك SUM

#3

السلام عليكم

بالنسبة للكود الاول يعمل بشكل جيد وهو نفس الكود الذي تفضلت بذكره . الكود الثاني لا يعمل عندي .

بالنسبه للكود الاول :

يتم اضافة 3 column الى الـlistview1 و تغير خاصية ViewStyle الى vsReport .

بالنسبه للمثال الذي ذكرته يفضل استدعاء الدالة مع استخدام listbox مثلا . باستخدام showmessage لن تتمكن من رؤيه كل اسماء الدوال ان كان عددها كبير ;)

if opendialog1.Execute then
begin
 Listbox1.Items:=ListDLLExports(Opendialog1.FileName);
end;

(f)

CIONO1

هناك حتى الأحلام أصبحت ممنوعة ...

إنه لعار أن ننتمي لهكذا أوطان ... لكن ... ربما العار أن نكون نحن أبناء لتلكم أوطان .. من يدري ؟!!

ليعلم أولئك ... إنّ الشعوب إنْ هي استيقظت تسحق ظُلامََهَا ...

There, even in dreams u r wanted

To be a programmer, how a nice dream it was

Leaving ...

أعيدوا لإسمي لونه المفضل

#4

اهلاً اخي tmaaa

كلامك صحيح انه افضل لو كان العرض على ListBox ولكن بعض الأعضاء المبتدئين قد يقومون بتجربة الكود الذي يعرض على ال ListBox ثم يجدوا خطأ عند كلمة listbox وذلك لعدم وجود هذا العنصر على الفورم فيحسبون ان الكود خاطيء :D

ولكن عند استخدام MessageBox لايظهر ذلك ;)

وتقبل اطيب تحياتي اخوك SUM

هذا الموضوع مغلق.

مواضيع مشابهة