vb调用dll如何传递字符串指针

assummerflower 2019-05-28 04:17:43
在c++编写的dll头文件中,函数定义如下

int EXPORT_API usb_relay_device_open_with_serial_number(const char *serial_number,unsigned len);
/*open device that serial number is serial number*/
/*return:This funcation return a valid handle to the device on success or NULL on failure*/
/**eg:usb_relay_device_open_with_serial_number("abcde",5")*/



在vb中尝试以下几种方式编写程序(设备序列号为“QAAMZ”)
1、直接传递字符串
声明:
private declare function usb_relay_device_open_with_serial_number Lib“xx路径”(byval SerNum as string,byval lenth as long)as long
调用
dim return as long
return=usb_relay_device_open_with_serial_number(“QAAMZ”,5)
2、传递指针
声明中 byval SerNum as long
其中sernum为序列号数组首字符的指针地址

但都出现“DLL调用约定错误”的提示。

求教~

ps:这个问题的前置提问:https://bbs.csdn.net/topics/392563831
已经解决了利用dll获得设备序列号的问题。


...全文
380 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
assummerflower 2019-05-31
  • 打赏
  • 举报
回复
引用 18 楼 milaoshu1020的回复:
[quote=引用 17 楼 assummerflower 的回复:]
[quote=引用 15 楼 milaoshu1020的回复:][quote=引用 14 楼 assummerflower 的回复:]
[quote=引用 13 楼 脆皮大雪糕的回复:][quote=引用 10 楼 assummerflower 的回复:]
[quote=引用 8 楼 脆皮大雪糕的回复:]要被VB调用的函数都要用stdcall

我不知道我的是不是stdcall,也不知道在哪里改…求指导啊[/quote]

要看DLL的源代码,找到函数的声明,确认是否有声明 stdcall调用,如果没有则需要修改,修改以后要重新编译。[/quote]
哪个是源代码?用什么软件编译?我这有厂家给的.dll,.h和.lab[/quote]
厂家说没说是否支持VB6调用?
厂家试验过,能用VB6调用吗?
是否可以让厂家给你个VB6调用的例子?
[/quote]
商家转卖的一个小东西,联系不到厂家…[/quote]
实在不行的话,你可以用VC的ATL工程包装一下,然后用VB6调用;
因为有可能这个API函数VB6没法直接调用;
方便的话我可以给你包装一下,不过你得把.H和.DLL发给我;
你可以用百度网盘,上传并共享,把地址贴在这里;
也可以把这几个文件打包发送到我的邮箱:milaoshu1020@126.com;[/quote] 感谢感谢,已经发到邮箱了
脆皮大雪糕 2019-05-30
  • 打赏
  • 举报
回复
要被VB调用的函数都要用stdcall
milaoshu1020 2019-05-30
  • 打赏
  • 举报
回复
.cpp、.h 是源代码文件;
试试修改 .cpp、.h(再导出的函数名称前边加上_stdcall);
比如:
int _stdcall EXPORT_API usb_relay_device_open_with_serial_number(const char *serial_number,unsigned len);
.lib、.dll 是编译生成的文件,.dll是vb6实际用到的文件;

因为我没有测试过,仅仅是看别人这么说的,所以也不太确定这个方法能达到效果;
你可以试一试,不行再想其它的办法;
milaoshu1020 2019-05-30
  • 打赏
  • 举报
回复
引用 17 楼 assummerflower 的回复:
[quote=引用 15 楼 milaoshu1020的回复:][quote=引用 14 楼 assummerflower 的回复:]
[quote=引用 13 楼 脆皮大雪糕的回复:][quote=引用 10 楼 assummerflower 的回复:]
[quote=引用 8 楼 脆皮大雪糕的回复:]要被VB调用的函数都要用stdcall

我不知道我的是不是stdcall,也不知道在哪里改…求指导啊[/quote]

要看DLL的源代码,找到函数的声明,确认是否有声明 stdcall调用,如果没有则需要修改,修改以后要重新编译。[/quote]
哪个是源代码?用什么软件编译?我这有厂家给的.dll,.h和.lab[/quote]
厂家说没说是否支持VB6调用?
厂家试验过,能用VB6调用吗?
是否可以让厂家给你个VB6调用的例子?
[/quote]
商家转卖的一个小东西,联系不到厂家…[/quote]
实在不行的话,你可以用VC的ATL工程包装一下,然后用VB6调用;
因为有可能这个API函数VB6没法直接调用;
方便的话我可以给你包装一下,不过你得把.H和.DLL发给我;
你可以用百度网盘,上传并共享,把地址贴在这里;
也可以把这几个文件打包发送到我的邮箱:milaoshu1020@126.com;
assummerflower 2019-05-30
  • 打赏
  • 举报
回复
引用 15 楼 milaoshu1020的回复:
[quote=引用 14 楼 assummerflower 的回复:]
[quote=引用 13 楼 脆皮大雪糕的回复:][quote=引用 10 楼 assummerflower 的回复:]
[quote=引用 8 楼 脆皮大雪糕的回复:]要被VB调用的函数都要用stdcall

我不知道我的是不是stdcall,也不知道在哪里改…求指导啊[/quote]

要看DLL的源代码,找到函数的声明,确认是否有声明 stdcall调用,如果没有则需要修改,修改以后要重新编译。[/quote]
哪个是源代码?用什么软件编译?我这有厂家给的.dll,.h和.lab[/quote]
厂家说没说是否支持VB6调用?
厂家试验过,能用VB6调用吗?
是否可以让厂家给你个VB6调用的例子?
[/quote] 商家转卖的一个小东西,联系不到厂家…
assummerflower 2019-05-30
  • 打赏
  • 举报
回复
商家转卖的一个小东西,联系不到厂家…
assummerflower 2019-05-30
  • 打赏
  • 举报
回复
引用 5 楼 milaoshu1020的回复:
[quote=引用 4 楼 assummerflower 的回复:]
[quote=引用 3 楼 milaoshu1020的回复:]vc的dll中需要把调用模式设为_stdcall才能让vb调用
比如函数:
void add (int a ,int b)
就无法在VB中调用
要改为:
void add _stdcall (int a ,int b)

转自:
https://bbs.csdn.net/topics/350190581
第2楼;

我没看过dll里面的代码。不过之前有两个函数已经运行成了,是不是应该是stdcall的?[/quote]
引用成的函数声明是什么样子的?[/quote] 引用成了两个函数。 1,初始化函数 在dll头文件中声明为: int EXPORT_API usb_relay_init(void) /*init the usb relay library return 0 on success and-1 on failure*/ 在vb中声明为 private declare function usb_relay_init lib."路径"()as long 2,第二个函数是扫描设备信息的,在另一个帖子里大神您回复过我,按照您的方法解决了。 ps:如果要修改dll为stdcall方式,应该怎么修改,现在有.cpp、.h、.lib、.dll好几个文件,应该改哪个?
milaoshu1020 2019-05-30
  • 打赏
  • 举报
回复
引用 14 楼 assummerflower 的回复:
[quote=引用 13 楼 脆皮大雪糕的回复:][quote=引用 10 楼 assummerflower 的回复:]
[quote=引用 8 楼 脆皮大雪糕的回复:]要被VB调用的函数都要用stdcall

我不知道我的是不是stdcall,也不知道在哪里改…求指导啊[/quote]

要看DLL的源代码,找到函数的声明,确认是否有声明 stdcall调用,如果没有则需要修改,修改以后要重新编译。[/quote]
哪个是源代码?用什么软件编译?我这有厂家给的.dll,.h和.lab[/quote]
厂家说没说是否支持VB6调用?
厂家试验过,能用VB6调用吗?
是否可以让厂家给你个VB6调用的例子?
assummerflower 2019-05-30
  • 打赏
  • 举报
回复
引用 13 楼 脆皮大雪糕的回复:
[quote=引用 10 楼 assummerflower 的回复:] [quote=引用 8 楼 脆皮大雪糕的回复:]要被VB调用的函数都要用stdcall
我不知道我的是不是stdcall,也不知道在哪里改…求指导啊[/quote] 要看DLL的源代码,找到函数的声明,确认是否有声明 stdcall调用,如果没有则需要修改,修改以后要重新编译。[/quote] 哪个是源代码?用什么软件编译?我这有厂家给的.dll,.h和.lab
脆皮大雪糕 2019-05-30
  • 打赏
  • 举报
回复
引用 10 楼 assummerflower 的回复:
[quote=引用 8 楼 脆皮大雪糕的回复:]要被VB调用的函数都要用stdcall
我不知道我的是不是stdcall,也不知道在哪里改…求指导啊[/quote] 要看DLL的源代码,找到函数的声明,确认是否有声明 stdcall调用,如果没有则需要修改,修改以后要重新编译。
milaoshu1020 2019-05-30
  • 打赏
  • 举报
回复
引用 11 楼 assummerflower 的回复:
[quote=引用 7 楼 milaoshu1020的回复:].cpp、.h 是源代码文件;
试试修改 .cpp、.h(再导出的函数名称前边加上_stdcall);
比如:
int _stdcall EXPORT_API usb_relay_device_open_with_serial_number(const char *serial_number,unsigned len);
.lib、.dll 是编译生成的文件,.dll是vb6实际用到的文件;

因为我没有测试过,仅仅是看别人这么说的,所以也不太确定这个方法能达到效果;
你可以试一试,不行再想其它的办法;

没什么变化。
vb只用到了dll,dll没有改动,程序也就没有变化了。[/quote]
需要编译源代码为DLL;
就像VB6的生成EXE/DLL/OCX一样;
assummerflower 2019-05-30
  • 打赏
  • 举报
回复
引用 7 楼 milaoshu1020的回复:
.cpp、.h 是源代码文件;
试试修改 .cpp、.h(再导出的函数名称前边加上_stdcall);
比如:
int _stdcall EXPORT_API usb_relay_device_open_with_serial_number(const char *serial_number,unsigned len);
.lib、.dll 是编译生成的文件,.dll是vb6实际用到的文件;

因为我没有测试过,仅仅是看别人这么说的,所以也不太确定这个方法能达到效果;
你可以试一试,不行再想其它的办法;
没什么变化。 vb只用到了dll,dll没有改动,程序也就没有变化了。
assummerflower 2019-05-30
  • 打赏
  • 举报
回复
引用 8 楼 脆皮大雪糕的回复:
要被VB调用的函数都要用stdcall
我不知道我的是不是stdcall,也不知道在哪里改…求指导啊
脆皮大雪糕 2019-05-30
  • 打赏
  • 举报
回复
stdcall的调用约定意味着:参数从右向左压入堆栈,被调用函数自身修改堆栈 cdecl调用约定的参数压栈顺序是和stdcall是一样的,参数首先由有向左压入堆栈。所不同的是,被调用函数本身不清理堆栈,调用者负责清理堆栈。 VB的调用方式是不自行清理堆栈的,其实WINDOWS API函数基本上都是stdcall。 _cdecl是C和C++程序的缺省调用方式。 当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的,被调用者事先无法知道参数的长度,事后的清除工作也无法正常的进行,因此,这种情况我们只能使用cdecl。
milaoshu1020 2019-05-29
  • 打赏
  • 举报
回复
引用 4 楼 assummerflower 的回复:
[quote=引用 3 楼 milaoshu1020的回复:]vc的dll中需要把调用模式设为_stdcall才能让vb调用
比如函数:
void add (int a ,int b)
就无法在VB中调用
要改为:
void add _stdcall (int a ,int b)

转自:
https://bbs.csdn.net/topics/350190581
第2楼;

我没看过dll里面的代码。不过之前有两个函数已经运行成了,是不是应该是stdcall的?[/quote]
引用成的函数声明是什么样子的?
assummerflower 2019-05-29
  • 打赏
  • 举报
回复
引用 3 楼 milaoshu1020的回复:
vc的dll中需要把调用模式设为_stdcall才能让vb调用
比如函数:
void add (int a ,int b)
就无法在VB中调用
要改为:
void add _stdcall (int a ,int b)

转自:
https://bbs.csdn.net/topics/350190581
第2楼;
我没看过dll里面的代码。不过之前有两个函数已经运行成了,是不是应该是stdcall的?
milaoshu1020 2019-05-29
  • 打赏
  • 举报
回复
vc的dll中需要把调用模式设为_stdcall才能让vb调用
比如函数:
void add (int a ,int b)
就无法在VB中调用
要改为:
void add _stdcall (int a ,int b)

转自:
https://bbs.csdn.net/topics/350190581
第2楼;
assummerflower 2019-05-29
  • 打赏
  • 举报
回复
引用 1 楼 脆皮大雪糕的回复:
改一下声明,C里面传入指针的参数,VB里面用byref传入,类型为any private declare function usb_relay_device_open_with_serial_number Lib“xx路径”(byref SerNum as any,byval lenth as long)as long 接下来,C的char 其实就是字节数组。把VB的string转换成字节数组 dim a() as byte a = strconv("1234abcd" ,vbfromunicode) 最后,把数组的第一个元素传递进去,其实DLL那边获得的就是这个数组在内存里的起始地址。也就是这个数组的指针。 dim return as long return=usb_relay_device_open_with_serial_number(a(0) ,ubound(a)+1)
大神,还是不行,还是报dll调用约定错误。这个方法我之前也试过了,会不会除了传递指针那里,其他地方有我没注意到的错误。
脆皮大雪糕 2019-05-28
  • 打赏
  • 举报
回复
改一下声明,C里面传入指针的参数,VB里面用byref传入,类型为any private declare function usb_relay_device_open_with_serial_number Lib“xx路径”(byref SerNum as any,byval lenth as long)as long 接下来,C的char 其实就是字节数组。把VB的string转换成字节数组 dim a() as byte a = strconv("1234abcd" ,vbfromunicode) 最后,把数组的第一个元素传递进去,其实DLL那边获得的就是这个数组在内存里的起始地址。也就是这个数组的指针。 dim return as long return=usb_relay_device_open_with_serial_number(a(0) ,ubound(a)+1)
VB一些常用控件集,以及一些方法模块,编辑框.ctl、进度条、全局热键钩子、网站服务器、托盘控件、WinSock.ctl、曲线图.ctl、压缩算法-升级版.cls、数组加解密.cls、打开文件属性面板.bas等,其中一个模块的部分代码摘录如下:   ------------------------------------------------------------------------------------------    ‘遍历进程,查找notepad.exe    MyRemoteProcessId = OpenProcess(PROCESS_CREATE_THREAD PROCESS_VM_OPERATION PROCESS_VM_WRITE PROCESS_VM_READ, False, ProcessInfo.th32ProcessID)    ‘打开进程获得notepad的句柄供后面的操作使用    DllFileName = "C:Vblegend.dll"    MyDllFileLength = Len(DllFileName) 1    ‘学过C语言的朋友应该知道字符串最后要一个ASCII 0标志结尾,所以要加1    MyDllFileBuffer = VirtualAllocEx(MyRemoteProcessId, 0, MyDllFileLength, MEM_COMMIT, PAGE_READWRITE)    ‘在指定进程里申请一块内存区域出来供我们存放字符串“c: est.dll“    ‘传string给api时,byval byref有区别,应该使用byval,这样会传给api一个标准的C字符指针,不能byref,否则函数调用没问题    ‘但是起不到预期效果,VirtualAllocEx返回的是申请到的内存地址值.    MyReturn = WriteProcessMemory(MyRemoteProcessId, MyDllFileBuffer, DllFileName, MyDllFileLength, temp)    ‘向刚才申请的内存中写入dll文件路径字符串    ‘顺便说一下,很多api浏览器上的api声明都是错的,包括VB6自带的也不例外,writeprocessmemory第二个参数要的是    ‘lpBaseAddress 但是这个值不能传址得到,如果你按byref传址,实际上传的是MyDllFileBuffer变量的地址,而不是它里面存放的那个数字    ‘上面说了MyDllFileBuffer的数值才是WriteProcessMemory要的地址,所以声明API的时候一定要byval,大家知道空着不写就是默认byref    ‘下面还有几处不该传址的参数,只要搞清楚API函数要的到底是什么值才可以确定到底传值还是传址,API浏览器仅能供参考,还是要仔细阅读MSDN    MyStartAddr = GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA")    ‘获取loadlibrary函数的地址,这个函数可以载入指定的dll文件,那他的参数呢?就是我们刚才在notepad.exe进程里写入的“c: est.dll“    ‘不过还得让CreateRemoteThread告诉他.另外简单的说一下windows下应用程序的内存管理,我也不很懂,呵呵,win32下的应用程序    ‘的内存区域是隔开的,每个程序有自己的一块内存不能直接访问别的程序的内存区,当然,这里调用的几个系统函数有访问别的程序内存区域的特权    ‘而且每个应用程序的内存区域都映射到系统内存区域里,也就是说在这里GetProcAddress得到的VB程序里LoadLibraryA函数的入口地址和    ‘notepad程序里的LoadLibraryA函数地址是一致的(映射的作用),所以不必担心.另外在VB写的程序里    ‘要使用LoadLibraryA,notepad不是用vc写的吗?要注意根notepad没关系,我们现在是在自己的VB程序里面找LoadLibraryA函数的入口.    ‘还有要注意函数大小写,api函数和vb不一样的。    MyResult = CreateRemoteThread(MyRemoteProcessId, 0, 0, MyStartAddr, MyDllFileBuffer, 0, temp)    ‘好了,现在该让LoadLibrary载入“c: est.dll“吧,现在CreateRemoteThread做的就是在notepad进程中把控制权转到LoadLibrar
Ring3下注入DLL的另类方法,能过杀软和游戏NP(源码) 注入DLL是做全局钩子或者拦截类软件都有可能用到的技术,如果做外挂的话我们也有 可能需要注入一个DLL到游戏进程中去干点什么“坏事”。 但我们知道现在要注入DLL是越 来越难了。场景1:制作火星文输入法外挂,原理是利用API HOOK拦截并修改输入法相关函 数,需要注入一个DLL到所有进程中,但是后来发现,在开启了瑞星的帐号保险箱后,用户 将不能在QQ中输入火星文。原因是瑞星保护了QQ进程,禁止对其注入DLL,解决方法是提示 用户关闭帐号保险箱 -_-| 确实是很降低用户体验的一个不是办法的办法。场景2:制作某 游戏外挂,需要注入一个DLL到游戏进程中去直接调用游戏函数完成某一功能。结果发现该 游戏有NP保护,OpenProcess打不开,创建远程线程也不行,试用其它方法也一一失败。遇 到上面的情况,高手们自然是转到Ring0下面去,使用驱动之类的办法来对付啦,不过吾等 菜鸟可就是酒井没法子了 -_-| 不过也别太灰心,凡事总会有办法的。我想我们需要一种持久的、稳定的、不容易被安 全软件屏蔽的DLL注入方法,后来发现,输入法程序就是能完成这一任务的理想人选。输入 法程序程序到底是什么?它没有自己的进程,并且在系统还没有登录时就已被加载(在欢迎 界面你也可以调出输入法),它可以在游戏中打开,也可以在控制台程序中打开,还可以在 瑞星保护下的QQ中打开,在杀软中也可以打开,这不就是我们要找的特性吗。那么,输入法 到底是什么呢?根据Windows的规定,输入法其实就是一个DLL,不过它是一个特殊的DLL, 它必须具有标准输入法程序所规定的那些接口,输入法是由输入法管理器(imm32.dll)控 制的,输入法管理器又是由user32.dll控制的。输入法在系统目录是以IME为扩展名的文件 ,当在应用程序中激活某个输入法时,输入法管理器就会在那个应用程序的进程中加载对应 的IME文件,注意,加载IME文件跟加载普通的DLL并没有本质区别,所以,可以认为,输入 法其实就是注入到应用程序中的一个DLL文件,并且,这种“注入”是不会被杀软和游戏NP 拦截的(至少目前是)。现在,我们已经有了一个注入DLL的另类方法,那就是利用输入法 。具体流程是这样,首先制作一个标准输入法文件,但是这个输入法并不完成文字输入工作 ,它的唯一任务就是用来注入DLL,所以称为“服务输入法”,然后,制作一个控制程序, 来控制服务输入法,当然最后还需要一个用于注入的目标DLL,这样一共就有3个文件。开始 工作后,控制程序首先将服务输入法安装到系统中,然后传递几个参数给服务输入法,参数 中包括了需要注入的DLL文件的名称和路径,然后,控制程序将服务输入法设置为系统的默 认输入法,这样新的程序一打开,服务输入法就会注入那个程序。当然,在服务输入法安装 之前打开的程序不会被注入,这时需要向系统中的所有窗口POST一条 WM_INPUTLANGCHANGEREQUEST消息,该消息可以在指定窗口中后台激活服务输入法,这样, 系统中所有拥有窗口的进程就都被我们的服务输入法注入了。服务输入法注入程序之后,就 会根据控制程序传递过来的参数加载目标DLL,这样目标DLL也就随着服务输入法一同注入到 目标程序中了。注意服务输入法是控制程序用WM_INPUTLANGCHANGEREQUEST消息在所有窗口 中自动激活的,如果某个窗口自动激活失败,你就需要在那个窗口中手工切换到服务输入法 ,这样才能注入进去了。至于注入以后,你就可以在窗口中切换到别的输入法,这并不会影 响已经注入进去的DLL。我将这一套功能制作成一个完整的示例,你可以在以下地址下载: http://www.pen88.com/download/imehook.rar 压缩包中的第6个和第8个文件夹演示了此 功能并包含所有源代码。其中文件imedllhost09.dll就是服务输入法,运行时会被安装到系 统中,控制程序退出时会自动卸载该输入法,这样用户就不太容易察觉,你还可以重新编译 该输入法,将名称改为“中文(中国)”,这样隐蔽性更好。文件hxwdllwx.dll是演示用的 目标DLL,你可以替换成自己的DLL,然后那个exe文件就是控制程序了。输入法 imedllhost09.dll在运行时会被复制到系统目录并更名为imedllhost09.ime,它导出了2个 函数用于控制。在VB中的声明为: Public Declare Function IMESetPubString Lib "imedllhost09.ime" (ByVal RunDLLStr As String, ByVal UnloadDll As Long, ByVal loadNextIme As Long, ByVal DllData1 As Long, ByVal DllData2 As Long, ByVal DllData3 As Long) As Long Public Declare Function IMEClearPubString Lib "imedllhost09.ime" () As Long 其中IMESetPubString用于向输入法传递要注入的DLL等参数。RunDLLStr,要注入的DLL命令 和完整路径。UnloadDll,当输入法退出时,是否同时卸载目标DLL 0-是,1-否。 loadNextIme,当切换至该服务输入法时,是否直接切换到下一个输入法(这样服务输入法 就好像被跳过了,可最小限度影响用户的输入法顺序) 0-否,1-是。DllData1,DllData2 ,DllData3是传递给目标DLL的回调函数(函数名称必须为RunDllHostCallBack)的参数, 你可以在目标DLL中导出一个函数,名称为RunDllHostCallBack,这样当输入法注入时会调 用目标DLL的该回调函数并向其传递这3个参数。函数原型为(VC): DWORD RunDllHostCallBack(DWORD calldata1, DWORD calldata2,DWORD calldata3); IMEClearPubString函数用于清除输入法的配置,清除后,输入法将停止在新的程序中注入 目标DLL,但已注入的DLL不会卸载。 好了,利用输入法来注入DLL基本上就是这样了,详细的用法大家可以看压缩包中的第8个文 件夹,其中服务输入法是VC写的,控制程序是VB的,代码都是有注释的。测试发现该方法能 过目前所有杀软,也能注入冰刃。当然缺点还是有的,就是目标程序如果不接受输入法那就 没办法了,但是现在一般的游戏都不会禁止玩家在里面打字吧,而且杀软也不能禁止用户输 入汉字吧,哈哈,所以通用性应该还是蛮好的。 最后,我再介绍另一个注入DLL的方法,估计也很少被用到。是利用一个未公开函数 RegisterUserApiHook,可以在网上搜索关键词“RegisterUserApiHook”,查到有人在 Windows 2003下测试成功,但是我在Windows XP测试却失败。后来终于找到了失效的原因。 RegisterUserApiHook函数可以在系统中注册一个全局钩子,你需要在钩子中指定一个DLL和 一个回调函数,然后,所有加载了user32.dll的程序就都会在启动时加载你指定的这个DLL 。用这个函数来注入DLL也是很不错的。但是测试发现它的注入能力似乎赶不上上面提到的 利用输入法来注入的办法,可以注入一般的程序和某些安全程序,但是对冰刃无效。而且它 有一个限制,就是系统中只能同时存在一个这样的钩子。实际上这个钩子平时是被系统中的 Themes服务占用了,Themes服务正是利用这个钩子HOOK了绘制窗口的相关API,所以才让所 有程序窗口变成XP主题样式的。所以我们要用这个钩子的话,必须先关闭Themes服务,这样 在XP下也可以用了,但是这样系统就变成Windows 2000的样式了 -_-| RegisterUserApiHook函数的VB声明如下: Public Declare Function RegisterUserApiHookXP Lib "user32" Alias "RegisterUserApiHook" (ByVal hInstance As Long, ByVal fnUserApis As Long) As Long Public Declare Function RegisterUserApiHook2003 Lib "user32" Alias "RegisterUserApiHook" (pRegInfo As HookAPIRegInfo2003) As Long 可以看到,在XP和2003下这个函数的参数是不一样的。关于此函数的示例代码,请参见压缩 包中的第5个文件夹。 最后的最后,再介绍一个未公开函数InitializeLpkHooks,这个函数在网上能找到的资料更 少,只有一个声明而已。但是它名称中最后那个“Hooks”误导了我,我以为又是一个可以 用来注入DLL的不错函数,用OD反出来一看,原来只是个局部HOOK而已。虽然没太大用,还 是一并写上吧,也许谁用得着呢。InitializeLpkHooks顾名思义就是HOOK LPK的,Windows 有个lpk.dll,就是支持多语言包的那么个功能。测试发现好多程序在TextOut之前似乎是要 调用lpk.dll里面的相关函数的,可能是支持多语言的程序就需要用这个来判断到底要显示 那种语言吧。而InitializeLpkHooks,就是用来HOOK lpk.dll里面的4个函数的,这4个函数 是LpkTabbedTextOut,LpkPSMTextOut,LpkDrawTextEx,LpkEditControl。我们先打开VB, 在窗体中加入以下代码吧: Private Sub Form_Load() DLLhwnd = LoadLibrary("lpk.dll") '加载DLL DLLFunDre = GetProcAddress(DLLhwnd, "LpkDrawTextEx") '获取回调函数地址 LpkHooksInfo.lpHookProc_LpkTabbedTextOut = 0 LpkHooksInfo.lpHookProc_LpkPSMTextOut = 0 LpkHooksInfo.lpHookProc_LpkDrawTextEx = GetLocalProcAdress(AddressOf HookProc1) '设置要HOOK的LPK函数 LpkHooksInfo.lpHookProc_LpkEditControl = 0 InitializeLpkHooks LpkHooksInfo End Sub Private Sub Form_Unload(Cancel As Integer) LpkHooksInfo.lpHookProc_LpkTabbedTextOut = 0 LpkHooksInfo.lpHookProc_LpkPSMTextOut = 0 LpkHooksInfo.lpHookProc_LpkDrawTextEx = DLLFunDre LpkHooksInfo.lpHookProc_LpkEditControl = 0 InitializeLpkHooks LpkHooksInfo FreeLibrary DLLhwnd End Sub 然后新建一个模块,在模块中加入以下代码: Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long Public Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long ' ----------------未公开函数-------------------------------------- Public Declare Sub InitializeLpkHooks Lib "user32" (lpProcType As Any) Type LpkHooksSetting lpHookProc_LpkTabbedTextOut As Long lpHookProc_LpkPSMTextOut As Long lpHookProc_LpkDrawTextEx As Long lpHookProc_LpkEditControl As Long End Type ' ------------------------------- Public DLLhwnd As Long, DLLFunDre As Long Public LpkHooksInfo As LpkHooksSetting Public Function GetLocalProcAdress(ByVal lpProc As Long) As Long GetLocalProcAdress = lpProc End Function Function HookProc1(ByVal a1 As Long, ByVal a2 As Long, ByVal a3 As Long, ByVal a4 As Long, ByVal a5 As Long, ByVal a6 As Long, ByVal a7 As Long, ByVal a8 As Long, ByVal a9 As Long, ByVal a10 As Long) As Long HookProc1 = 0 End Function 运行一下看看,是不是窗体中标题栏和按钮上的文字都没有了,因为我们把函数 LpkDrawTextEx替换成自己的函数HookProc1了。这个函数有10个参数,其中几个好像是字符 串指针,似乎可以用来截获窗体要显示的文字,然后改成另一种语言的文字,我猜想,也许 就是这个用途吧。哈哈,纯属猜测。以上就是函数InitializeLpkHooks的用法了。 以上就是全部。 本文所有示例代码的下载地址是: http://www.pen88.com/download/imehook.rar 我的QQ511795070,欢迎交流。

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧