查看: 962|回复: 3
|
一个奇怪的DLL问题
[复制链接]
|
|
我用visual c++制作的一个DLL,不过出现了非常奇怪的问题。。。
DLL有个hook function。这个DLL被连接去vb程序,做成 “键盘钩子”。
“键盘钩子”已经成功了。。vb程序不管是不是active,还是被minimize掉,都可以拦截键盘。
现在,它的问题是,如果vb程序在background的时候或被minimize掉,它可以拦到键盘,但是vb程序不能取到DLL的variable。
各位大大,你们知道这是什么问题吗?

 |
|
|
|
|
|
|
|

楼主 |
发表于 12-6-2006 12:02 AM
|
显示全部楼层
[size=-1]vb的编码
Option Explicit
Private Const WH_KEYBOARD = 2&
'这些API是用来安装和卸掉键盘钩子
Private Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
'这些API是用来找出function的address
Private Declare Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" _
(ByVal hLibModule As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" _
(ByVal hModule As Long, ByVal lpProcName As String) As Long
'这里是DLL export出来的函数,用来跟vb交换数据
Private Declare Sub SetReplyThread Lib "kbproc" (ByVal ThreadID As Long)
Private Declare Function GetReplyThread Lib "kbproc" () As Long
Private Declare Sub SetHookID Lib "kbproc" (ByVal hhk As Long)
Dim KbHook As Long
Dim PtrOfKBProc As Long
Dim hModule As Long
Dim HookToThreadId As Long
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
Me.Caption = KeyCode
End Sub
Private Sub Form_Load()
'Store the ThreadId that you want to capture the keyboard state
'use GetWindowThreadProcessId to get the ThreadId
'and use FindWindow to get the Hwnd
HookToThreadId = 0
SetReplyThread App.ThreadID
MsgBox App.ThreadID
hModule = GetModuleHandle("kbproc")
MsgBox hModule
PtrOfKBProc = GetProcAddress(hModule, "KeyboardProc")
SetHook
End Sub
Private Sub Form_Unload(Cancel As Integer)
UnHook
End Sub
'我用GetReplyThread取到DLL的variable数值
'所以Form的TITLE BAR是-275735
Private Sub Timer1_Timer()
Me.Caption = GetReplyThread
End Sub
Public Sub SetHook()
KbHook = SetWindowsHookEx(WH_KEYBOARD, PtrOfKBProc, hModule, HookToThreadId)
MsgBox KbHook, , "result of hook"
SetHookID KbHook
End Sub
Public Sub UnHook()
MsgBox IIf(UnhookWindowsHookEx(KbHook), "Unhook successful", "Error in unhook process")
End Sub
DLL编码
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
DWORD ReplyThread;
HHOOK mHook;
void _stdcall SetReplyThread(DWORD idThread)
{
ReplyThread = idThread;
return;
}
unsigned long _stdcall GetReplyThread(VOID)
{
return ReplyThread;
}
void _stdcall SetHookID(HHOOK hhk)
{
mHook = hhk;
return;
}
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
char buffer[20];
if (code >= 0)
{
_ltoa(ReplyThread, buffer, 10);
MessageBox(NULL, buffer, "value of ReplyThread",0);
//' 当vb不active时, ReplyThread =0
//' 但是我把ReplyThread带回vb时,它却-275735
if (ReplyThread)
{
//' 当vb不active时,这一行不会被执行,因为 ReplyThread =0
}
mKeyCode = wParam;
}
_ltoa((long)mHook, buffer, 10);
MessageBox(NULL, buffer, "handle of hook process",0);
//' 当vb不active时, 这里也是0
return ((mHook) ? CallNextHookEx(mHook, code, wParam, lParam) : 0);
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
[ 本帖最后由 meemee 于 12-6-2006 12:08 AM 编辑 ] |
|
|
|
|
|
|
|
发表于 12-6-2006 12:53 AM
|
显示全部楼层
你的鍵盤鈎子是以DLL方式截取所有程式的按键,每个程式都会共用这个DLL,但每个程式都有各自的一个ReplyThread。
VB程式active时,“看”到的是屬於它的那个ReplyThread,而其內容已經被SetReplyThread改过。
其它程式则“看”到屬於自己的ReplyThread,其內容并未被改过。
试试這樣,将ReplyThread设在共用空間:
#pragma data_seg(".SHARED")
DWORD ReplyThread;
#pragma data_seg()
#pragma comment(linker, "/section:.SHARED,RWS")
// .SHARED 只是一个名字,可以改變,最多8个字
// R = Read, W = Write, S = Shared
请參考How To Share Data Between Different Mappings of a DLL
[ 本帖最后由 fxam 于 12-6-2006 01:00 AM 编辑 ] |
|
|
|
|
|
|
|

楼主 |
发表于 12-6-2006 02:23 PM
|
显示全部楼层
谢谢fxam版主的细心解答。。。
据我猜测。。。大慨也是这样。。。因为,对DLL和系统内核不是很了解,不过现在有肯定的答案和solution,应该不难解决了。。。 |
|
|
|
|
|
|
| |
本周最热论坛帖子
|