佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

查看: 962|回复: 3

一个奇怪的DLL问题

[复制链接]
发表于 12-6-2006 12:01 AM | 显示全部楼层 |阅读模式
我用visual c++制作的一个DLL,不过出现了非常奇怪的问题。。。

DLL有个hook function。这个DLL被连接去vb程序,做成 “键盘钩子”。
“键盘钩子”已经成功了。。vb程序不管是不是active,还是被minimize掉,都可以拦截键盘。

现在,它的问题是,如果vb程序在background的时候或被minimize掉,它可以拦到键盘,但是vb程序不能取到DLL的variable。

各位大大,你们知道这是什么问题吗?



回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 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,应该不难解决了。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 22-8-2025 01:42 PM , Processed in 0.110449 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表