现在的位置: 首页 > 综合 > 正文

Delphi中编写无输出函数名的DLL文件

2013年10月14日 ⁄ 综合 ⁄ 共 3533字 ⁄ 字号 评论关闭

用 Delphi 用长了,总是发现,有些和 MS 不同的地方。例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用。一旦知道如何调用,可以给自己的应用程序提供很强的功能和很大的灵活性。但,这些函数通常又没有函数名(即使用 ExeScope 查看 DLL 文件的导出表也看不出函数意义),仅仅只有一个序号来表示。有时候我又自己想,为什么我在写程序的时候不能学学 MS 隐藏一些自己不希望公开的函数呢?
 
其实用 Delphi 写 DLL 的时候,使用简单的技巧就可以实现隐藏函数名的效果。让我们来看看下面这个 DLL 源码:
 
library   proDll;
 
uses
   Windows;
 
{$R *.res}
 
procedure   ShowMessageA(hWnd: HWND);  stdcall ;
begin
   MessageBox(hWnd, '您调用的是 ShowMessageA 函数', 'DLL 函数信息',
     MB_ICONINFORMATION);
end ;
 
procedure   ShowMessageB(hWnd: HWND);  stdcall ;
begin
   MessageBox(hWnd, '您调用的是 ShowMessageB 函数', 'DLL 函数信息',
     MB_ICONINFORMATION);
end ;
 
exports
   ShowMessageA  index   1  name   '',
   ShowMessageB  index   2  name   '';
 
begin
end .
 
注意看 exports 部分,用 index 关键字指定输出函数的序号,后面紧跟一个 name 关键字指明输出函数名称。关键就在这里,name 后面是一个空字符串,这样就给函数生成了一个空字符串名。实际效果既是隐藏了输出函数的名称。是不是很容易呢?
 
那么我们怎样调用这样的输出函数呢?由于没有了函数名,我们调用起来会显得和以前不一样。其实也不用担心,调用同样非常简单。我下面就静态调用和动态调用制作了两个工程,源码如下:
 
静态调用例子:
 
unit   Unit1;
 
interface
 
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls;
 
type
   TForm1 =  class (TForm)
     Button1: TButton;
     Button2: TButton;
     procedure Button1Click(Sender: TObject);
     procedure Button2Click(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end ;
 
var
   Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure   ShowMessageA(hWnd: HWND);  stdcall ;  external   'proDll.dll' index 1;
procedure   ShowMessageB(hWnd: HWND);  stdcall ;  external   'proDll.dll' index 2;
 
procedure   TForm1.Button1Click(Sender: TObject);
begin
   ShowMessageA(Handle);
end ;
 
procedure   TForm1.Button2Click(Sender: TObject);
begin
   ShowMessageB(Handle);
end ;
 
end .
 
动态调用的例子:
 
unit   Unit2;
 
interface
 
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls;
 
type
   TForm2 =  class (TForm)
     Button1: TButton;
     Button2: TButton;
     procedure Button1Click(Sender: TObject);
     procedure Button2Click(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end ;
 
var
   Form2: TForm2;
 
implementation
 
{$R *.dfm}
 
type
   TDllShowMessageFunc =  procedure   (hWnd: HWND);  stdcall ;
 
var
   hDllHandle: THandle;
   ShowMessageA, ShowMessageB: TDllShowMessageFunc;
 
procedure   LoadFuncDll;
begin
   if   hDllHandle = 0  then
   begin
     hDllHandle := LoadLibrary('proDll.dll');
     if   hDllHandle = 0  then
       raise   Exception.Create('proDll.dll 加载失败');
     try
       {
       lpProcName: the second argument of function GetProcAddress
         Points to a null-terminated string containing the function name,
         or specifies the function's ordinal value. If this parameter is
         an ordinal value, it must be in the low-order word; the high-order
         word must be zero.
       }
       @ShowMessageA := GetProcAddress(hDllHandle, Pointer(HiWord(0)  or   LoWord(1)));
       if   @ShowMessageA =  nil then
         raise   Exception.Create('proDll.dll 中没有输出 ShowMessageA 函数');
       @ShowMessageB := GetProcAddress(hDllHandle, Pointer(HiWord(0)  or   LoWord(2)));
       if   @ShowMessageB =  nil then
         raise   Exception.Create('proDll.dll 中没有输出 ShowMessageB 函数');
     except
       FreeLibrary(hDllHandle);
       hDllHandle := 0;
       raise ;
     end ;
   end ;
end ;
 
procedure   FreeFuncDll;
begin
   if   hDllHandle <> 0  then
   begin
     FreeLibrary(hDllHandle);
     hDllHandle := 0;
     @ShowMessageA :=  nil ;
     @ShowMessageB :=  nil ;
   end ;
end ;
 
procedure   TForm2.Button1Click(Sender: TObject);
begin
   if   @ShowMessageA =  nil then   LoadFuncDll;
   ShowMessageA(Handle);
end ;
 
procedure   TForm2.Button2Click(Sender: TObject);
begin
   if   @ShowMessageB =  nil then   LoadFuncDll;
   ShowMessageB(Handle);
end ;
 
initialization
   // do nothing
finalization
   FreeFuncDll;
end .

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/aroc_lo/archive/2010/07/27/5769801.aspx

抱歉!评论已关闭.