您的位置:首页 > 编程语言 > Delphi

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

2010-07-27 20:48 176 查看
用 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
.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐