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

简介: 用 Delphi 用长了,总是发现,有些和 MS 不同的地方。例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用。


用 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

相关文章
VC通过函数名调用DLL的标准范例
VC通过函数名调用DLL的标准范例
75 0
|
C#
C#调用dll代码范例
C#调用dll代码范例
127 0
|
C++ Windows 编译器
dll的概念 dll导出变量 函数 类
1、 DLL的概念 DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数、变量或类。这些可以直接拿来使用。 静态链接库与动态链接库的区别:   (1)静态链接库与动态链接库都是共享代码的方式。
1403 0
|
C++ 开发工具
VC 项目中可以使用的路径宏
原文地址:http://blog.csdn.net/collin1211/article/details/2483316 VC 项目中可以使用的路径宏: 宏 说明 $(RemoteMachine) 设置为“调试”属性页上“远程计算机”属性的值。
818 0
|
Windows 编译器
windows编程,加载dll库示例
<h1>第一种方式,手动找到函数地址,进行调用。</h1> <p><span style="font-family:Consolas,'Courier New',Courier,mono,serif; line-height:18px">LoadLibrary();</span><br></p> <p><span style="font-family:Consolas,'Courier
926 0
|
C++ 索引
VC通过函数索引调用DLL范例
VC通过函数索引调用DLL范例
70 0
|
编译器 API C++
python 外部传参程序编写并打包exe及其调用方式
每种编程语言相互联系又相互独立,为此使用某种编程语言编写的程序都能够独立封装和生成自己的运行程序exe或者其他的API接口。而对于这样的运行程序目的往往不是用于双击使其运行的,而是通过外部传入的参数运行其中的内核函数达到某种目的的。所以在此研究python如何编写外部传参的程序,并将其封装未exe便于外部使用。
872 0
python 外部传参程序编写并打包exe及其调用方式

热门文章

最新文章