《VC++深入详解》学习笔记 第二十章 HOOK和数据库访问

 1. 基本知识

1)对某些特殊的消息进行屏蔽,为了实现这一功能,我们可以安装一个HOOK过程,称为钩子过程,操作系统在传递消息时,将我们感兴趣的消息先传递给HOOK过程,在此函数中进行检查,然后再决定是否放行该消息

2安装钩子过程:SetWindowsHookEx函数

     函数原型:HHOOK SetWindowsHookEx

             int  idHook,//指定要安装的钩子过程的类型(例如:WH_CALLWNDPROC 在操作系统将消息发送到目标窗口处理过程之前,对该消息进行监视 WH_KEYBOARD 对键盘按键消息进行监控  WH_MOUSE 对鼠标消息进行监视)

         HOOKPROC  lpfn,//指向相应的钩子过程,如果参数dwThreadId0,或者指定了一个其他进程创建的线程之标识符,那么该参数必须指向一个位于某动态链接库中的钩子过程,否则,指向当前进程相关的代码中定义的一个钩子过程

         HINSTANCE  hMod,//指向lpfn指向的钩子过程所在的DLL句柄(若dwThreadId指定的线程是当前进程所创建且钩子过程定义与当前进程的代码中,则此参数为NULL

         DWORD   dwThreadId//指定与钩子过程相关的线程标识,若为0,那么钩子过程将与桌面上运行的所有线程都相关

);

3SetWindowsHookEx函数的作用是安装一个应用程序定义的钩子过程,并将其放到钩子链中(最后安装的钩子过程总是排列在该链的前面)

2.进程内钩子

1)安装鼠标钩子(定义鼠标钩子过程)

   函数原型:LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam);

//第一个参数确定钩子过程如何处理当前消息

HC_NOREMOVE 表明参数wParamlParam包含了关于该消息的信息,并且此鼠标消息尚未从消息队列中删除

    2)在钩子过程中对信息处理完成之后,如果想把信息继续传递给下一个钩子过程,可以调用CallNextHookEx函数来实现,该函数的功能是把钩子信息传递给钩子链中下一个等待接受信息的钩子过程

 函数原型:LRESULT CallNextHookEx(HHOOK hhk,int nCode,WPARAM wParam,LPARAM lParam);

//第一个参数指定当前钩子过程句柄也就是调用SetWindowsHookEx函数得到的返回值

    3如果钩子函数返回非0值,表明已经对当前消息进行了处理,这样,系统就不会再将这个消息传递给目标窗口过程了

    4GetCurrentThreadId()函数返回当前线程的ID

5)安装键盘钩子(定义键盘钩子过程)

     1,仅屏蔽空格键消息:参数wParam是产生当前按键消息的键盘按键的虚拟键代码,当按下键盘上的按键时,它实际上发送的是一个脉冲信号,Windows定义了一些虚拟键代码来表示这些信号,并由键盘设备驱动程序负责解释,因此,在钩子过程中可以通过wParam参数得到当前按下的是哪个键(VK_SPACE宏:空格键的虚拟键码)

     2.屏蔽组合键消息ALT+F4:参数lParam是一个32位的整数,它的每一位或某些位表示特定的含义,用来指定按键重复的次数扫描码扩展键标记上下文等标记,其中第29位表示上下文代码,如果Alt键被按下,则其值为1,否则为0

6)将安装的钩子过程移除:UnhookWindowsHookEx函数,该函数的作用是从钩子链中移走一个已安装的钩子

     函数原型:BOOL UnhookWindowsHookEx(HHOOK hhk);

3.全局钩子

1)如果想要屏蔽当前正在运行的所有进程的鼠标和键盘消息,那么安装钩子过程的代码必须放到动态链接库中区实现,应该将SetWindowsHookEx函数的第四个参数设置为0,并将它的第三个参数指定为安装钩子过程的代码所在的DLL的句柄

2.CPP文件

    #include<windows.h>

HHOOK g_hMouse = NULL;

LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam)

{

        return 1;

}

void SetHook()

{

       g_hMouse = SetWindowsHookEx(WH_MOUSE,MouseProc,GetModuleHandle("HOOK"),0);

}

3)得到安装钩子过程所在的DLL模块的句柄(第三个参数)

     1.DLL程序提供一个DllMain函数,当第一次加载DLL时,系统会调用这个函数,并传递当前DLL模块的句柄,因此可以在HOOK这一DLL中提供一个DllMain函数,并定义一个全局的实例变量:g_hInst,然后在DllMain函数中保存系统传递来的DLL模块句柄  

      HINSTANCE g_hInst

     BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved);

{

   g_hInst = hinstDLL;

}

     void SetHook()

     {

      g_hMouse = SetWindowsHookEx(WH_MOUSE,MouseProc,g_hInst,0);

}

2.另一种方法:GetModuleHandle函数,如果指定的模块已经被映射到当前进程的地址空间中,那么该函数将返回该指定模块的句柄

  函数原型:HMODULE GetModuleHandleLPCTSTR lPModuleName;

// lPModuleName指向一个字符串,该字符串指定了想要获取其模块句柄的模块名称,可以

//是一个.exe文件也可以是一个.Dll文件,该函数将返回指定模块的句柄,返回值是HMODULE

//类型,该类型和HINSTANCE类型可以通用

4)模块定义文件(DEF

      LIBRARY Hook

      EXPORTS

      SetHook @2

//第一行语句指定DLL内部名称

//EXPORTS关键字指定该DLL导出函数的名称,从DLL中导出的函数有一个序号,如果

//想自己指定序号,可以在导出函数符号名后加上@接上一个序号数字,这个数字就是序号

5)编写客户程序加载这个DLLHookTest

     1.调用DLL中函数前先进行声明

      _declspec(dllimport) void SetHook();

    2.添加与Hook.dll文件的链接

    3.OnInitialDialog函数中调用DLL中的SetHook()函数

4.多个进程访问同一个DLL时的共享问题

1)写入时复制机制:在改变数据之前,多个进程共享一份数据,改变时复制一份到新页面,改变数据的进程独享改变后的数据,其他进程使用原先的数据

2)共享:DLL创建一个新的节,并将此节设置为一个共享的节,然后将要共享的变量等放如此节中,就可以在多个进程中共享

3)创建一个新的节

     #pragma data_seg(“.MySec”)

     HWND g_hWnd = NULL;//要向新建的节中放置变量的话,该变量必须是已初始化的

     #pragma data_seg()

#pragma comment(linker,”/section:MySec,RWS”)  //将新建的节设置为共享的节

// linker表明该行代码用来指定链接选项

//字符串”/section:MySec,RWS”含义是表明将这个节设置为可读(R)写(W)共享(S)类型

4)除了利用上述方法将新建的节设置为共享之外,还可以在DLL的模块定义文件中利用SEGMENTS关键字来实现

    Hook.def

            LIBRARY  Hook

            EXPORTS

            SetHook   @2

            SEGMENTS

            MySec  READ WRITE SHARED

5.数据库访问技术

1ODBCOpen Database Connectivity,开放数据库互联)

     OLE DB(对象链接与嵌入数据库):OLE DB在两个方面对ODBC进行了扩展,首先,OLE DB提供了一个数据库编程的COM接口;第二,OLE DB提供了一个可用于关系型和非关系型数据源的接口,OLE DB的两个基本结构是OLE DB提供程序(ProviderOLE DB用户程序(Consumer

     ADOActiveX Data ObjectActiveX数据对象)

     ADO建立在OLE DB之上,ADO是一个OLE DB用户程序,即它本身也是一个Consumer,使用ADO的应用程序都要间接地使用OLE DBADO简化了OLE DB,提供了对自动化的支持

2ADO有三个核心对象

     1.Connection对象:表示到数据库的连接,它管理应用程序和数据库之间的通信

     2.Command对象:用来处理重复执行的查询,或处理需要检测在存储过程调用中的输出或返回参数的值的查询

     3.Recordset对象:用来获取数据,Recordset对象存放查询的结果,这些结果由数据的行(记录)和列(字段)组成,每一列都存放在RecordsetFields集合中的一个Field对象中

3)在VC中利用ADO访问数据库

     1.导入ADO库(可以在stdafx.h中导入该库)

       #import” C:\Program Files\Common Files\System\ado\msado15.dll”no_namespace rename(“EOF”,”rsEOF”)//最后用renameEOF改为rsEOF,为了避免和文件结尾冲突

     2.利用ADO对象访问数据库

       void CAdoDlg::OnBtnQuery()

       {

CoInitialize(NULL);

_ConnectionPtr pConn(_uuidof(Connection));

_RecordsetPtr pRst(_uuidof(Recordset));

pConn->ConnectionString = "Provider = SQLOLEDB.1;Password = sa;Persist SecurityInfo = True;User ID = sa;Initial Catalog = pubs";

pConn->Open("","","",adConnectUnspecified);

pRst = pConn ->Execute("Select * from authors",NULL,addCmdText);

while(!pRst->rsEOF)

{

          ((CListBox*)GetDlgItem(IDC_LIST1))->AddString((_bstr_t)pRst->GetCollect("au_lname"));

          pRst->MoveNext();

}

pRst->Close();

pConn->Close();

pRst.Release();

pConn.Release();

CoUninitialize();

       }

     3.ADO本身也是一个COM组件,COM组件在使用时,需要初始化COM库,这需要调用ConInitialize函数实现,该函数有一个参数,该参数是保留的,直接传递NULL即可

同时,在访问完COM库后,程序还需要调用CoUninitialize函数卸载COM

     4._ConnectionPtr是一个智能类型,允许用户访问ADO Connection对象,我们利用这个智能指针类型定义了一个ADO Connection对象:pConn,同时使用关键字_uuidof获取ADO Connection接口的全局唯一标识符GUID)对pConn对象进行初始化

     5.记录集智能指针对象:pRst

     6.为数据库连接对象的连接字符串ConnectionString赋值

     7.Open方法打开与数据库的连接

     8.调用连接对象的Execute方法,获得记录集数据后,将它添加到列表框中

     9.从记录集中获取数据时,可以利用GetCollect方法,该方法有一个_variant_t类型的参数,该类型也是一个COM支持类

    10.在获取记录集数据的循环的最后,一定要记得调用记录集对象的MoveNext函数,以便让游标向下移动

    11.数据操作完成之后,调用Close方法把记录集对象和连接对象关闭,最后释放智能指针在COM接口上的引用计数

    12.VC中同样可以用Command智能指针对象来访问数据库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值