找回密码
 加入计匠网
搜索
热搜: BIOS ACPI CPU Windows
查看: 15829|回复: 0

[转载]支持 PS/2 与 USB 的键盘过滤驱动(可卸载) -- by sinister

[复制链接]
发表于 2007-11-16 12:01:11 | 显示全部楼层 |阅读模式
Author:  sinister( C- ?5 w; g. ?- o' q
Email:   [email]sinister@whitecell.org[/email]
- G! I# n% W8 F' eHomepage:[url]http://www.whitecell.org[/url]
# ~8 ?8 x" i/ ~Date:    2007-02-26
3 [, ]. e9 T% [7 N
- p( B) ~+ ]7 N! P+ j
3 C+ `, \) R/ G/*******************************************************************
& _- `$ v$ ~$ p6 ~4 e+ |' W1 Z5 N
这个键盘过滤驱动是一个定时锁定计算机程序的功能部分,以前 lgx& k( u& ]) D& b& J9 w+ w, l+ x
写过一个 linux 版,现在我们需要实现一个 windows 版。这部分的
7 ?0 t7 D5 @6 e+ R+ C* E5 t' Q6 Z功能要求如下:
1 A7 x) M/ s' w0 Y% r% S
9 ]4 A: F  ]8 a; X$ s- T1、强制锁定键盘/鼠标。
: H' e, I7 g# M( j2、可动态加/解锁7 f  ~) z! g+ z* O' Y
3、兼容所有 NT 系列的操作系统。
2 y+ p: m( W9 |
' u$ B& g; N& J就这个需求而言,能马上能想到的就有7,8种方案,这些方案可以说都能够实" j0 y! E. d9 w; R/ E0 g
现,但如何更合理,更稳定、更彻底的实现,如何尽量少的消耗系统资源,如
8 S/ w6 p& ^3 m  I; V' b何保证其兼容性,等一系列问题不得不让我们去重新评估这几种方法。首先在, l+ ]0 h& d2 M0 T1 g
上层实现,一是怕被饶过,二是怕调用频繁影响系统性能。在底层实现,一是8 u; |. O; P) c4 u& F
怕考虑不周有兼容性问题,二是怕过多使用未公开方法导致系统不稳定。下面: j9 k) [; \2 ^! C: {7 r
就来看一下我想到的几种实现方法:
0 p- H. g+ Z% z, R; b* d
$ n1 C5 Z5 m/ y6 [1、全局键盘/鼠标钩子" |0 M' ]# o$ `9 ~6 f, F
2、BlockInput() API6 c2 c. l: S  b7 E' h4 k+ b
3、使用 setupapi 进行控制
* Y; H) j! l& m* E4、全局键盘/鼠标钩子+远线程插入 WINLOGON 进程屏蔽 CTRL+AL+DEL
7 @( y# R( t: P/ M5、拦截 win23k!RawInputThread() 函数
% F# g' }9 A& [6 ]9 o+ x; z1 u2 i: S6、修改 DDK 中自带的 kbfilter 的键盘(Port Driver)过滤驱动/ I! z% R4 P* ^1 l# P6 r
7、拦截 kdbclass 驱动的 driver dispatch routine- t. K( \' S, o/ B' L* \( R
8、实现一个 PS/2 与 USB 键盘过滤驱动8 q5 `3 l5 D- E6 ?( N5 j

. e8 D  {5 Z8 y- E" {# c0 Q+ B3 R/ z4 ]: P. L
我们先看一下以上这些方案的实用性与通用性。第1,2套方案不在考虑
6 S5 H+ z1 i* ]! P3 w# U$ {6 ~/ {$ t之内了,因为有办法解锁,屏蔽不了 CTRL+ALT+DEL 组合键。第3套方
  y' H2 @) V; q8 c4 a% R& W案经过我的测试使用 Keyboard 的 CLASSID 不是什么环境都好使,存在: C. z+ B1 H" G4 ^; G
兼容性的问题。第4套方案系统效率会大大降低,而且存在很多不稳定因1 P. g5 U) r7 B1 u7 e6 v
素,对于全局钩子这种东西我一直很排斥。第5套方案,同样存在兼容性
" I; ^+ l; B& k" }; z; L" j问题和不稳定因素。第6套方案看似完美,但无法实现动态卸载,无法卸; |9 y8 v$ n9 q8 j- ~; g
载就意味着你需要一个开关来控制是否锁定,这样还要与应用层通讯,我
. X6 ~, b- U) Z3 o. O的目的是不让应用层与驱动有任何交互。且使用 WDM 形式这种安装起来
$ B- T; d& C( ^, k. B5 S也很麻烦,要么 INF 要么自己 setupapi,这都不是我想看到的,还有如9 g& R' u# Q' [: Y! [' c* m
果仅为实现这么一个功能,就让一个核心驱动一直存在系统中的话,我有8 ]' d" h4 S: b: U; J$ K
障碍。第7套方案看似实现起来很简单,其实有很多问题。如仅是拦截
$ N0 X+ {! ?4 s) A* iIRP_MJ_READ 并粗暴的返回拒绝后,系统无法恢复到初始状态。且对于
7 K) K& S4 y  h. J; lUSB 键盘存在兼容性问题。那么最后只有自己实现一个 PS/2 与 USB 键2 N4 i% i5 g+ g4 _1 H
盘过滤驱动了,既然要实现这么一个驱动,那么就必须能实现到第6套方
  v2 x  X  x+ y3 ]% R" C案的全部功能且不存在它所带来的问题,否则就没有什么意义了。4 s7 P8 P* J/ Z; ?" Y* E* {
# w" E  T8 R- X# M

+ Q6 [) ?& K% L6 U3 a: I: |我们都知道实现一个可直接使用 SERVICE API 来动态装载的 KMD 键盘过
3 R, X: q3 N. h: L* i滤驱动,首先需要先 ATTACH 到 \\Device\\KeyboardClass0 设备上再进* t  W: X! S" I5 F5 k: E' R3 _
行按键过滤。但如果仅 ATTACH 这个设备的话,会存在很多问题,那就是
! F: O. @1 l2 l8 Q4 [# ~只能过滤到 PS/2 键盘,而对于使用 USB 键盘的机器毫无作用。现在越  V) K' T* z* V2 E4 E- _! o
来越多的品牌机都预配的是 USB 键盘(如:DELL)。大家可能会想,从9 u$ `: B1 o( x0 Q
KeyboardClass0 一直到 N 都 ATTACH 不就可以了么?总有一个是 USB
8 P. x$ k( q" H" v键盘设备,经过实践这是不可行的,只要是 USB 键盘设备的话,在使用4 T+ Y# y( r8 U/ l6 f! O
IoGetDeviceObjectPointer() 函数从设备名得到设备对象都会获取失败,+ s0 A  u* D  X
我还曾尝试使用 USB 键盘设备名来转换,还是一样失败。还有一个问题
% e( X( n  ?# O0 d" C, ^% [就是 USB 键盘设备不是都有名称的,即使有它的名称也都是动态生成的
1 j+ a2 i* u4 Q/ E而不是固定的。那么这就带来了一个问题,既然系统提供的函数无法使
4 d/ \' O. i/ M! N用,且我们又是为了动态安装/卸载,使用的是 KMD 类型驱动,无法通
' w; h9 P7 g% i, c( `" ?过 AddDevice 例程来获得 USB 键盘的设备对象进行挂接。那么如何来
- A8 k5 q6 p9 l' j屏蔽 USB 键盘按键?要达到这个目的只有自己分析下 USB 协议栈,通
; _% G4 T( L1 u: ]! u! s7 x过使用 DriverTree 观察发现,所有 USB 外设都挂在了 \Driver\hidusb
5 p) i* Q% N  c1 y0 E7 B上面,USB 键盘驱动名为 \Driver\kbdhid,而它则是 \Driver\kbdhid
0 x" E/ F6 Y4 Y5 O4 D$ B的一个 FilterDriver,且这个 \Driver\kbdhid 没有设备名称,也就意
7 |7 _7 k' U6 f% q( G: V- L# S味着,我们无法 IoGetDeviceObjectPointer() 得到设备对象并 ATTACH。: _) ^  t; p, ~# f+ N
经过对多个系统多台使用 USB 键盘机器的分析,可以确定让我使用它们# E+ E& L8 m% g1 I* c4 |
来作为得到 USB 键盘设备的依据。(这里仅是对 USB 键盘设备很功利
1 m( [" R7 r, `3 W  ^+ s! U的分析,如果想了解 WINDOWS 的 USB 设备栈如何组建,请阅读 tiamo
+ J7 C1 o$ J+ n( D; ~的 《Windows 的 USB 体系结构》。在此向所有公开研究成果的人致
& p  u: y' F  I; z9 v; n. ?敬!)有了这些依据,下面就没什么好说的了,自己遍历 USB 设备栈,% _5 s5 d1 Y+ O9 d+ u2 S' E
根据驱动名称获得 USB 设备对象,然后 ATTACH,过滤按键。具体流程$ G  w% t; `0 o# @( e
见下面代码。
* z+ i9 f- O7 K# S
" q1 ^/ B. R2 f9 f3 s这里有必要说下动态卸载,我尝试了两种方式,一种是在 UNLOAD 例程
  R% M. b( T: \, s2 B里直接取消 IRP,这种方法在 W2K 系统下,无论是 PS/2 还是 USB 键
$ ]2 i8 {+ S; |$ ]2 A1 v% q  A* @盘都可以很好的实现。但在 XP/2003 系统上则无法成功,在 XP/2003
% O0 ]2 _% Y7 i  W上暂时使用一个 IRP 计数器,在 UNLOAD 例程里判断如果还有一个没有- x( P# Y: f2 z
完成的 IRP 则等待,这样的话,需要在 UNLOAD 后用户按下任意键才可
2 w) E  g+ p+ S; n继续,虽然能够安全卸载但还需要一次用户介入。考虑实现的仅是一个
+ W7 F* P- z/ }0 d锁定功能,这样也算是能够忍受了。以后考虑在驱动中直接模拟用户按
8 F- Y: N- B: ~* W$ {4 N8 G: @键来实现,当然这种按键要有通用性和兼容性,支持 PS/2 与 USB 键盘。
! B6 u  c9 f# b; s  y( i; |! o8 m+ o/ P! P. a- b, m: b2 Z

$ h2 W8 ^' G  G/ x9 g5 j9 W8 q, B完成了上述工作后看起来好象完美了,其实不然,当你屏蔽了当前使用
4 v! H8 n+ ~) x的键盘时别忘了还可以再插入一个 USB 键盘,而后续插入的这个键盘是
% t5 X4 E: T+ \6 T3 ^6 K' j6 Q可以被识别的。这就需要我们处理 IRP_MJ_PNP 选项,对其中我们有兴趣
: r) j$ p  v5 q. w9 a5 i的 IRP_MN_XXX 做相应处理,可以处理 IRP_MN_START_DEVICE,在这时我% P( K7 k5 P' b  a, s
们动态挂接。还可以处理其他的 IRP,索性返回错误,让识别失效。但我/ m5 z  j" v0 @; N
们的驱动是 KMD 类型,只要加上一句对 DriverObject->DriverExtension5 ?  ?/ o* ^; `9 Z( K$ e
->AddDevice 的赋值操作则无法直接使用 SERVICE API 来动态加载了。: ~* U- [4 H- U- s
如何保持 KMD 又可以获得 PNP 的处理权呢?这可能要直接对 PnpManager
6 ^& F6 @* x- S进行操作了。这个问题有待大家来完善了。
4 P0 v4 L6 y" |/ C& H8 D) ?
( E7 F# D2 Z; V8 g5 }5 a: o- K  W9 R. m  L. O
要问为什么把文章插在代码当中,那可能是我觉得,既然把全部代码都贴出  {0 g6 {& u9 K: o% D, I* ^
来了,写文章就不如直接看代码来的真切。我这里所写也仅仅是对这些天的
+ |& |: _$ J9 k) x, u分析做个记录而已。我更愿意把它看做是一段注释。
8 }2 \/ F; V: n& |' R, j# y
' m+ [4 s4 X8 W7 i, A0 J6 ]+ h最后在此代码中要
+ a2 |5 \; J0 S7 A# U. @, K. d( t' \* h* o3 J
感谢:PolyMeta,他在放假前提醒我 USB 键盘的不同。, F; y6 r; d0 H
8 o. V  }. n. J, v
感谢:lgx,过节前给我找了些事,以至于没有让我觉得过节那么无聊。8 b3 P# o% _4 r4 F
3 \3 K4 V. m/ B7 Y
感谢:齐佳佳,过节请我吃好吃的。8 |% a+ I# s* `  n9 l3 i5 T* h
* R* s, z9 X! f7 @

4 H8 b% @7 q' g" n7 `9 ^" B******************************************************************/
+ G% `# D9 ~: A8 o2 u
% J- p: q0 z, W+ X2 ^7 f, G' X2 Y" z0 }) |9 Q# t
/*****************************************************************
* C9 b! M# p, ~5 @" G, } 文件名        : WssLockKey.c/ P( `& t4 V* U0 L! I* [
描述          : 键盘过滤驱动+ B" Y. g. L& X) p: Y# A/ S
作者          : sinister
& s4 F, F2 x9 H- l% T9 \ 最后修改日期  : 2007-02-26- i5 N3 N/ y: g$ L* O& P) ^. w
*****************************************************************/
+ v+ O  J/ s5 g4 y  Q5 }1 a# N# t, b- F0 X, M" F
7 ?' p* M* x2 f; k) T% k
#include "WssLockKey.h"' j* l2 Y9 _3 u7 t- i' @
0 g% H6 ~  \( M8 g
NTSTATUS! x/ b  @) R6 z
DriverEntry( IN PDRIVER_OBJECT KeyDriverObject,
2 t( |6 l. P& C. b# ]$ a2 d             IN PUNICODE_STRING RegistryPath )& V# S9 o* u$ s
{! X% C2 r  Z& F4 I3 S
  UNICODE_STRING KeyDeviceName;
" p8 Z0 m/ \. z3 u* |  PDRIVER_OBJECT KeyDriver;
9 Z5 o+ K5 D8 V" M' N% r  PDEVICE_OBJECT UsbDeviceObject;- h$ T3 G9 w1 ^+ G& V" l
  NTSTATUS ntStatus;
7 x6 U/ j; i/ O) i' N  ULONG i; ; g& {0 T9 o; v0 A* c
4 n+ E" y$ F+ C- O( z0 v
  //
- \' r$ q5 L1 W' `! D+ v, c  // 保存设备名,调试使用4 Y7 ]+ g' d. q0 @0 Z( h, I" J% X
  //! R: l6 w2 [3 f4 M  n" `  V
  WCHAR szDeviceName[MAXLEN + MAXLEN] =
% A% Z7 K& S, d: ]3 _4 i  {0 c$ b7 U& v" O) g( f6 x% `
    0
! S0 M0 y9 a! o5 a; p  };3 [( u1 U! l, M6 l) G) k2 w
6 v6 x7 p7 q9 d
  KeyDriverObject->DriverUnload = KeyDriverUnload;
$ p: H9 F2 c5 y" c- |0 z
/ z6 B$ X/ Q* J" Z  //
: l4 ]1 D* o. Q4 ^+ W# o2 A: T  // 先尝试获得 USB 键盘设备对象,如果成功则挂接 USB 键盘
( ]+ q' C1 n9 w, b+ o; O! o  //
$ F* M: |/ i, D8 I2 I% t* V* U  // 注意:因为 USB 键盘设备名不固定,且即使得到名称也无法/ M& r) r* D6 ^1 J4 Z4 o
  // 使用 IoGetDeviceObjectPointer() 函数根据设备名称得到其
  U+ u0 Q: e- R8 K* _# B  // 设备对象,所以这里我们只能自己枚举 USB 设备栈,并得到
$ _% ?$ R5 \2 j% I/ D  q  // USB 键盘设备来进行挂接/ S. L! G7 J5 e
  //0 w: ~4 z& X- e' S2 G" X
  ntStatus = GetUsbKeybordDevice( &UsbDeviceObject );8 f4 y* z  _& ?- \  N7 c" T
  if ( NT_SUCCESS( ntStatus ) && UsbDeviceObject != NULL )
3 o$ n# s4 Y8 c/ W3 M; V* p. O  {
* h5 ?# L& ~6 T6 n5 M# m9 F! _    //
9 W$ q- s; w+ k0 L# `    // 调试使用,USB 键盘设备 kbdhid 没有设备名只有驱动名
4 f& p: H, ?4 d& A5 }6 o' W9 E1 V% o    // 所以这里打印为空; \7 q/ u0 m' ?
    //
! u' b3 u6 a8 x, W    RtlInitUnicodeString( &KeyDeviceName, szDeviceName );  // USB KEYBOARD
& u* Y9 H4 I* I, F* M7 y    DbgPrint( "KeyDeviceName:%S\n", KeyDeviceName.Buffer );8 ?/ @3 e( ^7 p2 B# I+ c( ?8 P' m2 g

* x  }7 X9 m2 e. V; h    //8 W3 p2 L0 N1 ?2 C2 a
    // 挂接 USB 键盘设备$ f8 S3 _, t1 _
    //5 f  t9 d! p, ]7 {8 L/ _
    ntStatus = AttachUSBKeyboardDevice( UsbDeviceObject, KeyDriverObject );
$ w/ l$ y% N; L8 D    if ( !NT_SUCCESS( ntStatus ) )
% ?2 y5 W4 t. X# L) N" ?6 O    {7 f: M. q0 ]! M( `" B
      DbgPrint( "Attach USB Keyboard Device to failed!\n" );
/ n" q8 f$ }8 m7 o& A      return STATUS_INSUFFICIENT_RESOURCES;
4 x: j2 T/ C* R) |- M3 E; K; g    }/ k- X& \/ B3 m8 ]* W+ \4 `
  }
3 V3 J7 N! i( K1 o! Y  else. J/ }$ X  c7 ?* v# r
  {" v$ [/ _/ ]) O* q' S! E0 _0 n
    //
5 G0 S7 _1 _4 ~1 d: m# n$ L" g9 Q    // 如果没有 USB 键盘,则尝试挂接 PS/2 键盘设备
+ e% d, A7 ?; Z( \; [  K5 @    //
5 a5 Z; x/ V/ f8 D" E9 t    RtlInitUnicodeString( &KeyDeviceName, PS2KEYBOARDNAME );
  m3 a0 x0 ^* ~/ x
8 b% F0 l/ z/ U$ O4 G    ntStatus = AttachPS2KeyboardDevice( &KeyDeviceName,
5 x* a' X- D$ {3 t& n                                        KeyDriverObject,9 z1 U* F% n1 e" G9 o: E
                                        &KeyDriver );$ U, M. h0 c* s' K, k# @
    if ( !NT_SUCCESS( ntStatus ) || KeyDriver == NULL ), u' B( X( A; ?) A- z- ^
    {
9 M, P$ i; ~& S. ?0 s; g      DbgPrint( "Attach PS2 Keyboard Device to failed!\n" );8 Q; [  |( Z& g8 s
      return STATUS_INSUFFICIENT_RESOURCES;
" W! |  `% k! @: O  l8 Q, h$ D/ E5 Y    }
; g% T, P$ ]8 P7 I9 j  }
/ d0 E$ u5 i8 _( D- {* ~% M" _
4 B9 n# {* q; \; `% m' @3 v  //& O5 Q: i6 \* A3 g4 }! s# V8 ]
  // 这里没有过滤其他例程,仅处理了按键操作。这样处理会禁止
3 B, U2 s* r( ?4 Q( N0 \8 N  // 休眠。因在锁定时不允许休眠,所以也就无须处理其他例程9 i! X8 a* U# H+ S' n, V/ e
  //
2 |4 h, W! f  Q4 |% Q  KeyDriverObject->MajorFunction[IRP_MJ_READ] = KeyReadPassThrough; , M/ [; Q: `: ?6 `  T- f9 g# n
2 z) X7 @* f0 p. w+ l% N$ {
  return STATUS_SUCCESS;. Y9 x8 T$ s, Z/ D
} + j2 l/ ]" `; I; W
3 [; n% s7 k( W. ^( }, U7 Y
/////////////////////////////////////////////////////////////////& G- h  }( H! [
// 函数类型 : 系统函数' t$ w" f4 G" A: P* E7 K
// 函数模块 : 键盘过滤模块# ~9 T  y+ N: A# H8 n$ x$ t
////////////////////////////////////////////////////////////////
: m; C- B5 i$ M# [4 |// 功能 : 尝试取消队列里的异步 IRP,如果失败则等待用户按键,) y2 C9 I, ?# Q" [; h
//        卸载键盘过滤驱动
9 m9 L& N0 D1 `+ h, F, s// 注意 : 取消 IRP 操作在 2000 系统上可以成功,在 XP / 2003 上
' H. a# t5 g0 i5 j. e//        则需要等待用户按键,以后有待完善3 U6 N) e/ A* h
/////////////////////////////////////////////////////////////////
2 P4 |) x. r) Z/ V' J/ X// 作者 : sinister
2 k4 ~* L, T9 j; a) ?3 {( s# d// 发布版本 : 1.00.00
' d* ?8 f/ a( [: {+ B// 发布日期 : 2005.12.27
# _( K& T0 \6 P" m( N/////////////////////////////////////////////////////////////////+ S8 q3 N2 u) b8 k1 S
// 重   大   修   改   历   史
1 [: h8 m7 Q9 [+ u; o/ Q/ `////////////////////////////////////////////////////////////////
2 o3 ~9 A: K6 f: @  V// 修改者 :' c1 {- q* E, }- K$ d1 j# U" I# Y
// 修改日期 :
5 _% }& \& H" ~. R8 y// 修改内容 :
5 n9 b5 C1 c# Y* C, N. h# A/////////////////////////////////////////////////////////////////; {1 B1 s$ V1 ?  y  B

8 |- O( I* j: y+ H: ~: i& z$ uVOID
5 o, b  g0 R; J# u' jKeyDriverUnload( PDRIVER_OBJECT KeyDriver )
; m: B( V7 ~1 k1 S# k& @: p1 ?' ~{' W  `* w' d& k8 ?) X$ s
  PDEVICE_OBJECT KeyFilterDevice ;      
* l  ^/ L# ~2 m5 _) j  B" N+ R  P  PDEVICE_OBJECT KeyDevice ;' u$ g8 g4 ]) p" _+ g. J+ k
  PDEVICE_EXTENSION KeyExtension;
+ Q9 e4 ^* q9 x3 G6 o0 q  PIRP Irp;
3 F2 s6 m; z& ^2 A( D( @. ]6 h  NTSTATUS ntStatus;
; l+ h$ j* j' k& h+ V6 Y+ Q2 r- T2 K+ k! \0 G
  KeyFilterDevice = KeyDriver->DeviceObject; , K- M1 n. C: K8 {7 ^, `
  KeyExtension = ( PDEVICE_EXTENSION ) KeyFilterDevice->DeviceExtension; & L5 j. A3 u# A3 J0 V- V
  KeyDevice = KeyExtension->TargetDevice;
' I5 r& U; u. z' p$ H  g# R7 t8 q7 `; ^
  IoDetachDevice( KeyDevice );
' l5 d& U9 @' K9 m8 g. Q$ s' K8 J# @2 r$ C' S) Y6 M
  //& ?6 H0 s0 K8 C/ R! b7 q" R
  // 如果还有 IRP 未完成,且当前 IRP 有效则尝试取消这个 IRP
9 p7 z; M/ u. X: j  //: t0 ]! C: |& _' h: x8 [# t) M
  if ( KeyExtension->IrpsInProgress > 0 && KeyDevice->CurrentIrp != NULL )
3 }7 b6 J/ \: @8 d  {
" B- K, Z( r( C9 |) v7 }    if ( CancelKeyboardIrp( KeyDevice->CurrentIrp ) ). Q) ?/ J. s( [
    {8 a8 v0 b% A, ^/ X" A
      //
) r: w: L; x4 {) \3 ]% [      // 成功则直接退出删除键盘过滤设备3 v+ s( [, s  e( O  G
      //2 s  ~, Q% S! B( B& N9 L2 M
      DbgPrint( "CancelKeyboardIrp() is ok\n" );
( Z# T$ j2 r) a9 H      goto __End;
' Z. \5 [9 k+ T: F, g    }' Y% p" j! H, K
  }9 \; S$ t# n0 t
! B3 e+ y1 u$ b3 _& p1 [
  //
/ |# }* s( H# U: c4 c1 F$ _4 L  // 如果取消失败,则一直等待按键
4 s5 S. [: W0 f' @  k: }; X  //
9 c6 l( T8 t! W5 Y  while ( KeyExtension->IrpsInProgress > 0 )0 n$ I# B; J( q9 L
  {
7 i9 d1 {& ^; ^    DbgPrint( "Irp Count:%d\n", KeyExtension->IrpsInProgress );
" `& I1 K% V3 e  }( ^8 F4 L8 {" \

: A8 ^' `* w7 H  __End:
. p2 S+ y) c4 |- ]$ P  IoDeleteDevice( KeyFilterDevice );
1 P# O% Y8 i9 \8 N$ j+ s, E1 }
( _5 b9 i* M. A7 w  return ;& H4 B  H0 T2 e6 v
}
1 S" Q1 h$ x& [1 i( }  `. [0 p6 }1 I; `( T% Y3 f" M, w
/////////////////////////////////////////////////////////////////
6 F; E$ c. D. x7 a. q// 函数类型 : 自定义工具函数
, |  Z" m: j/ E// 函数模块 : 键盘过滤模块+ Q& _, R, X! M! H
/////////////////////////////////////////////////////////////////4 z0 S- j  Y* u
// 功能 : 取消 IRP 操作
; n+ A7 p; p4 l# N1 n// 注意 : 这个函数仅是为配合在 UNLOAD 例程使用,其他例程中不能
9 @$ q9 I; [7 {//        使用此方法来取消 IRP& i& R& F- V1 |& R# t! r
/////////////////////////////////////////////////////////////////
  t/ u; l2 ^- W2 r' O4 V// 作者 : sinister
, N* e- p( A2 g/ V' w: F# V- {// 发布版本 : 1.00.00
8 m2 v' U/ t8 H8 h  C! t0 V// 发布日期 : 2007.02.20! _" ^2 X2 s/ D
/////////////////////////////////////////////////////////////////
$ p7 h" \! L# L( \# [7 h! _// 重   大   修   改   历   史
( g' y' B7 f1 z/////////////////////////////////////////////////////////////////& Z& s( s) @+ D5 t) b; R
// 修改者 : 3 Q* W; W7 ]5 V( h' H9 t# Y
// 修改日期 :
! {( P8 M3 G! {- Y$ Y// 修改内容 :
! b/ r/ |. R, e, g/////////////////////////////////////////////////////////////////
: S$ G* @  ?. q4 r) ?7 a- `7 I" _3 L& h9 s3 q
BOOLEAN
  \5 T% W8 ~: k( j3 YCancelKeyboardIrp( IN PIRP Irp )# ?# }( c, W) F0 C4 @4 `+ S" x
{
' `& U5 x- }; G& k8 _* c, w! v  if ( Irp == NULL )
4 u8 M0 h7 @6 c( ~8 {4 S! h2 f  {
8 f! X3 |0 _( p    DbgPrint( "CancelKeyboardIrp: Irp error\n" );5 Z6 b4 b. m- [3 f6 M- P4 ]% a
    return FALSE;
& F8 R! @# |. a6 y3 i$ X5 J  }
3 V$ R7 R' M. }) i8 g3 R+ W7 m. q2 C  l% j# Q

3 X  m% W4 }; ?3 r$ y& [8 M2 v% F  //
+ U# E" [/ D3 t! D1 B) D; _% `  // 这里有些判断应该不是必须的,比如对 CancelRoutine 字段,
5 `/ s, o# B. n, x0 V7 _0 N+ M  // 因为 IoCancelIrp() 函数中有判断了。但只有偏执狂才能生存 :)。
* y6 |7 E1 c( k2 U4 N  // 小波说 低智、偏执、思想贫乏是最不可容忍的。我这一行代码就占# ^, o- j/ I. ?, C- C! {
  // 了两条 :D,不知 xiaonvwu 看过后会作何感想?:DDD
1 v7 Z2 H, A2 Z. x  //
* t5 g6 @3 [* L" D$ }# m
! f3 H, j2 G' P* |. {  //
) g6 g4 q  P. T' j' m0 u3 }  // 如果正在取消或没有取消例程则直接返回 FALSE
: E  Z" a5 q! c  //
" @0 v0 g6 G- n  if ( Irp->Cancel || Irp->CancelRoutine == NULL )
/ n6 w; F. R9 `4 n+ f  {0 G9 d/ x9 i& d
    DbgPrint( "Can't Cancel the irp\n" );0 e& ?: m  ~8 F2 G5 G
    return FALSE;' h! s3 |$ ]% D; |. t. u
  }# D/ d4 ^% W3 ]" \5 f2 Z
& h( @: Z. ~+ ]. K
  if ( FALSE == IoCancelIrp( Irp ) )  T3 v% |4 Z0 q: m
  {& i% B, y$ M, b% x
    DbgPrint( "IoCancelIrp() to failed\n" );
" {% J8 ?+ B5 N/ C# f, c    return FALSE;
$ C3 V" a, M2 r0 Z- e( w. L  }
" }1 L  N1 f5 _+ p/ P! @4 y5 R" h* G  C$ H/ T/ X
  //  {% N# n* z# J$ h4 y3 K0 u
  // 取消后重设此例程为空
6 ?/ Z8 J. O0 k, f  //
; k. j' b# v! ^) ?' r& _# o  IoSetCancelRoutine( Irp, NULL );
7 A* \6 D' t4 @" R. F6 {0 X) a  R
+ e4 ?. e  l/ x8 l  return TRUE;
' p- {: e8 u$ o}! T+ _# A" |4 {, c5 M& O
, i) R+ D, k3 D+ A  l
/////////////////////////////////////////////////////////////////
, _: P% v3 ~9 A  i. F// 函数类型 : 自定义工具函数3 m- u( f7 Q# b# A" f2 }
// 函数模块 : 设备栈信息模块$ q! W" {5 ?2 w
/////////////////////////////////////////////////////////////////2 [& t' l+ q0 P# z1 C8 z
// 功能 : 遍历 DEVICE_OBJECT 中 AttachedDevice 域,找到 USB 键盘. \* k$ h) d6 r/ P
//        设备上名为 kbdhid 的过滤驱动(Upper Filter Driver)
9 A, y7 J( z2 ?3 S// 注意 :
+ H- F7 z& z. L/////////////////////////////////////////////////////////////////0 o% G9 y/ a  ]7 s
// 作者 : sinister
" Z4 _$ w1 v' `. [) |" }+ x// 发布版本 : 1.00.00
0 ]2 S9 Z+ U/ W/ l7 }  ]: L// 发布日期 : 2005.06.02" M) I% _  _; a' ^+ F9 z' V3 C
/////////////////////////////////////////////////////////////////5 \7 V1 H  o  S1 g' Y# Y
// 重   大   修   改   历   史
2 F2 K$ V" f7 M+ S, x/////////////////////////////////////////////////////////////////
8 _# v* M4 v$ W% p4 a! s) J9 w4 ^% [1 m// 修改者 : sinister
$ y# S4 Z6 c! o6 U: m! S9 [% \// 修改日期 : 2007.2.12
% h) c! {  o5 _5 g' ~) f// 修改内容 : 为匹配 USB 键盘驱动做了相应的修改4 \, O. F, k+ I
/////////////////////////////////////////////////////////////////( t$ c) T  i. P) _  M- x8 ~6 ]
4 m: }- G, \' e5 _0 v2 v
BOOLEAN
( v% N$ v5 J2 {8 f+ l+ \GetAttachedDeviceInfo( IN PDEVICE_OBJECT DevObj )
3 h5 W* r$ x+ Q, L) |, R7 j4 X{
5 r( {% L. u, @0 ]- ^1 y  PDEVICE_OBJECT DeviceObject;' \, G* q4 c; P4 N2 ~
  BOOLEAN bFound = FALSE;+ C& A1 e7 N; w$ G, \  z3 l
8 A, [8 [7 k- p- W" I
  if ( DevObj == NULL )+ d  D* H+ C4 B# ^9 V
  {
' F0 ?/ r8 Z1 u0 s7 g& l% _    DbgPrint( "DevObj is NULL!\n" );7 }9 x2 i3 g- y- k
    return FALSE;
) W- C- j0 B6 F# l' v  }
0 v8 _/ v$ h% r0 K. K5 t4 f4 f1 K( W
  DeviceObject = DevObj->AttachedDevice;
/ o# X4 d, W4 L  a3 s# f" M) j! ~% O. Z* u5 o9 ]
  while ( DeviceObject )
5 g0 l! d* z# ^0 N$ f; w4 V7 x& R  {
$ O: k: v, _8 O% ]& `    //; u# L6 A; \# ?- u$ h. f
    // 一些 OBJECT 的名称都存在分页区,虽然大部分时候不会被交换出去,但
, X. U" t/ ^8 F; T2 g0 Z    // 有一次足够了。这算是经验之谈
0 H) I. |3 B. @8 J    //
/ q+ d( T( e9 f    if ( MmIsAddressValid( DeviceObject->DriverObject->DriverName.Buffer ) )
. y# P% G9 m1 \! x    {" w1 s  m! F! C- l; ^+ g% q
      DbgPrint( "Attached Driver Name:%S,Attached Driver Address:0x%x,Attached DeviceAddress:0x%x\n",
7 b9 Y2 h+ ]  _5 }7 k                DeviceObject->DriverObject->DriverName.Buffer,' R7 i; O% W1 D
                DeviceObject->DriverObject,
) I( X  M. C* i/ N, g                DeviceObject );2 k1 u( d9 ^' r* }
6 h; @: b& ], h! B# ?/ m9 B4 h
      /// H) F$ v6 o" g4 `- A$ Z! c( C
      // 找到 USB 键盘驱动的 kbdhid 设备了么?找到了就不继续了# _8 \* |6 U+ m
      //- \! j4 O2 D) V/ W' n+ @. L
      if ( _wcsnicmp( DeviceObject->DriverObject->DriverName.Buffer,
  P! [* k7 i+ q& B& s! U+ i                      KDBDEVICENAME," ^" _8 A" e& e% s; @
                      wcslen( KDBDEVICENAME ) ) == 0 )
4 |: @  K! b" y) q3 @; a      {
2 o4 u$ N. p1 B% j        DbgPrint( "Found kbdhid Device\n" );
# F  i1 _; H6 B" B7 Y        bFound = TRUE;# b( j/ U! X6 P$ c5 W1 j
        break;8 p+ G7 v1 ^3 _$ T$ ?
      }
! L+ [: s; q, J& \3 k' ^2 {    }
0 v# e' ^0 b  ?- r5 K8 E3 |/ \% l) l6 ^! e2 _$ |. E
    DeviceObject = DeviceObject->AttachedDevice;
8 b9 M+ l- h4 x. C$ X2 L5 H; A  }
; [/ y" s, m: ]* v+ q( O2 K& p) Y! X( z9 J. u  l
  return bFound;
* ]6 b4 t( Z! G7 z! g, }}; x0 M' N" u3 N  Y5 C; ?4 s/ ~; U% a

; K, h+ W5 m6 t9 r$ _- p/////////////////////////////////////////////////////////////////* s- N( L8 R% o, Y# x5 Z2 e0 K! T
// 函数类型 : 自定义工具函数
4 c+ |( s! F, B2 v; T// 函数模块 : 设备栈信息模块
) H# r6 h( P4 N1 ]  w1 w/////////////////////////////////////////////////////////////////. b+ Q+ d1 j0 l; O+ C
// 功能 : 从 DEVICE_OBJECT 中得到设备与驱动名称并打印地址
8 o: t, O8 O/ ?// 注意 : 函数功能只是打印信息,不同环境使用中应该会做修改1 |9 `, J+ j7 I* d  a5 ~
/////////////////////////////////////////////////////////////////
$ O. W' ~. f+ s5 o$ z7 A& t// 作者 : sinister4 d& Q, j- R+ D; I, w! }; c" u
// 发布版本 : 1.00.00) J0 g, i1 r9 ^( N8 i: |) i
// 发布日期 : 2006.05.02$ C! v& ^  r# d4 n# i/ S
/////////////////////////////////////////////////////////////////7 y7 {8 Z8 A8 Y: a
// 重   大   修   改   历   史$ i9 P$ t8 m7 T% i; z
/////////////////////////////////////////////////////////////////
- I8 O1 x* r: g# K& F, O// 修改者 : sinister. o! V3 k5 j8 A! i
// 修改日期 : 2007.2.125 Z# E9 S5 U0 c) r  k; _6 U/ O
// 修改内容 : 打印出 USB 键盘驱动的设备名称,仅作调试使用4 G' ?5 p2 J- P/ m0 x$ {" M
/////////////////////////////////////////////////////////////////* [# k$ q3 ~" w( a6 _; f& ^

. @" i) H1 C# c1 y$ V8 Y+ q# {8 mVOID8 u" h1 v( U2 Z3 e. s
GetDeviceObjectInfo( IN PDEVICE_OBJECT DevObj )
  f) ]5 u3 L3 Z, M4 B  Z8 B0 G{: `9 C8 {4 Z7 v+ S1 `. u
  POBJECT_HEADER ObjectHeader;8 k' z* s& @8 p& p# c0 }. T1 Y2 {$ o5 n
  POBJECT_HEADER_NAME_INFO ObjectNameInfo;
( P3 N3 X' h- `; P, r% j4 O
' K" j& R; f/ E8 T" M0 Q. I2 j: a0 \  if ( DevObj == NULL )
  h: `# M, c0 Q8 Y  {% i3 A. R% H; {7 ?
    DbgPrint( "DevObj is NULL!\n" );4 z3 o$ i9 {6 x
    return;) o: Z3 f- J( b8 \
  }( @' |( e/ u# S7 Z. q
3 C4 i' ?: o7 `6 Y+ q
  //' }  j1 f0 U0 z2 i  X
  // 得到对象头
3 b& g0 e: G6 `& k. J6 M  //
9 V8 c7 j% h# \0 O  ObjectHeader = OBJECT_TO_OBJECT_HEADER( DevObj );! s% J- H2 ~0 j7 }5 T
5 o8 Z+ V" v1 \6 Z  ~0 A6 @
  if ( ObjectHeader )
6 o% p0 l/ v1 A( q; S) F  {
( J0 g: r8 c9 C* ~$ |    //. o/ W: ~4 f) w! T2 u+ P
    // 查询设备名称并打印0 q3 J. p8 G' n& b7 \' _8 n" t, ]
    //
( f' U6 V& Z8 c    ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
! w4 j" u2 l. o# Q+ b% o, }
% Z: p; B0 c- Y7 K    if ( ObjectNameInfo && ObjectNameInfo->Name.Buffer )4 Z4 W0 I7 o& b2 K
    {
/ w$ h, u* B! R2 i" e" g) Y( z      DbgPrint( "Device Name:%S - Device Address:0x%x\n",
5 r) L/ R5 c' `2 l. {% m- A1 B                ObjectNameInfo->Name.Buffer,, u4 L; d% I8 u* ]- r) Y
                DevObj );- N3 B; L  a' G+ m# @

* z( p( n7 a8 V. v7 x      //: t& a7 A% s- J/ @% Z1 s8 O
      // 复制 USB 键盘设备名到一个全局 BUFFER 里,为调试时显示
; ~1 d4 Q6 d/ O; s/ T      // 用,没有实际的功能用途% F, X$ p; {0 a2 W
      //
! ~) A5 z4 {8 }5 ?7 z, z& N      RtlZeroMemory( szUsbDeviceName, sizeof( szUsbDeviceName ) );( w9 l9 A7 c% \4 X

9 e9 J* l; L2 X      wcsncpy( szUsbDeviceName,  g& {3 N! Z1 ?6 Z  e9 `: e
               ObjectNameInfo->Name.Buffer,( D% o/ l1 d. c
               ObjectNameInfo->Name.Length / sizeof( WCHAR ) );0 C- ~' M  u% T4 S1 u& g
    }+ a  _( l* @  A$ p, B+ H
$ x; R. a6 |. B/ M" p, c
    //
* ^. w- ?6 M+ z; ]- @" {    // 对于没有名称的设备,则打印 NULL2 Q$ o3 d$ z# F+ o2 e
    //
6 c3 G# c- Z9 m/ V; A% [: w    else if ( DevObj->DriverObject )% e! _" ^' R' W2 z4 O  Z
    {/ u& L) K1 ], }3 ?. g
      DbgPrint( "Driver Name:%S - Device Name:%S - Driver Address:0x%x - Device Address:0x%x\n",
$ q5 _' t$ ~- u+ O9 I                DevObj->DriverObject->DriverName.Buffer,0 I5 U* J% b% z& X7 @" ?
                L"NULL",# E1 [; k% O5 P7 V9 z0 B2 h
                DevObj->DriverObject,+ w% [# D# u: t$ A  U8 [1 F
                DevObj );
" R, q* {: \% `8 ^- H! Z! r9 s  I4 R    }
9 r1 L, \9 w, x. d* L" W1 x  }
- A! }% \2 B8 k# C4 i}
) g4 H  o3 G. C
+ v+ N4 S$ W/ N3 a7 o$ C/////////////////////////////////////////////////////////////////' A% S+ q3 X4 }) }8 M/ D
// 函数类型 : 自定义工具函数
% B+ R2 p5 f) N. Z$ }& o// 函数模块 : 键盘过滤模块
+ C: e- z7 d/ h9 {/////////////////////////////////////////////////////////////////
* ^, K. [6 t% ^3 k* A1 Z5 o// 功能 : 得到 USB 驱动 hidusb 的驱动对象,并遍历以上所有设备+ h5 E4 K; z3 {/ D2 g! V& O
//        对象,过滤出 USB 键盘设备,将其设备对象返回
2 n7 L6 C. \7 {. j// 注意 :
/ e8 e6 b8 X7 z" H4 _5 \0 Z/////////////////////////////////////////////////////////////////1 R- z% g& S5 x9 y$ s9 {: [
// 作者 : sinister4 w7 K) U  I' j5 o
// 发布版本 : 1.00.00, L( ~% {2 |7 t" C
// 发布日期 : 2007.02.13" D& ?; n3 T9 R/ K
/////////////////////////////////////////////////////////////////
' N- \: U! g& p// 重   大   修   改   历   史0 F! s4 X% N# C$ P
/////////////////////////////////////////////////////////////////
1 g( p* E6 m1 G6 h- }- L: v1 B3 z6 J2 Z// 修改者 : 2 w- N- H& J( f
// 修改日期 :
1 M3 R& p2 B. s: U9 B- @// 修改内容 : % l- F" g7 |6 t
/////////////////////////////////////////////////////////////////9 g9 H1 E; ~9 r" _

; s( w5 u. s9 s, h( E; uNTSTATUS4 `# s$ q+ Q+ }" f/ @/ G" ^
GetUsbKeybordDevice( OUT PDEVICE_OBJECT* UsbDeviceObject )
; K3 e  n/ `- U; ~5 k' F" _{
9 S) [* G$ }4 }2 \2 M  UNICODE_STRING DriverName;
% A( @5 y5 P, u5 S  PDRIVER_OBJECT DriverObject = NULL;) T  x. @8 S) e* K5 B% i
  PDEVICE_OBJECT DeviceObject = NULL;/ b' x3 X, o* D
  BOOLEAN bFound = FALSE;
4 O+ N+ Z# v, {0 {6 W0 x
; j; O, v! F* N& b  RtlInitUnicodeString( &DriverName, USBKEYBOARDNAME );
$ w  |5 B+ `: p' S9 p, t$ ]: Z
" ~* X8 i1 |6 m9 o' {  ObReferenceObjectByName( &DriverName,
4 z; j& F& o2 s3 _$ k5 j                           OBJ_CASE_INSENSITIVE,
/ k0 L9 X% P/ b! ^8 e4 |, v                           NULL,6 q; L. W3 d1 \$ }3 W
                           0,
2 F3 O6 D- D' ^* l. x# @                           ( POBJECT_TYPE ) IoDriverObjectType,
' ~% u3 t( [* D( M6 L6 I8 d; x8 P0 D                           KernelMode,
; }/ M" s( M0 t2 U: |                           NULL,. T% W* w; z! B, |$ F" L3 h
                           &DriverObject );' L* e: v3 v. G7 a

& n; ?% r* v- U" y* W2 _  if ( DriverObject == NULL )3 Y4 ]0 E) h9 O+ r# {& s
  {5 z' |* Z8 j( j1 W5 L1 E; r
    DbgPrint( "Not found USB Keyboard Device hidusb!\n" );5 y% `: V8 I9 H
    return STATUS_UNSUCCESSFUL;) `. r* B3 I; L  g; q
  }
, z/ N: s5 J. V' L" N9 F  B2 D' }) l' u& m+ g
  DeviceObject = DriverObject->DeviceObject;
' o+ ?* ~4 Y) Y* R. M0 Z" `+ m/ v
# q8 |* ^( i" _! H) Y8 f4 `; s  while ( DeviceObject )
$ v* d/ h- [: p( [# `  {0 w; R# ^( K* {' A6 O9 J
    GetDeviceObjectInfo( DeviceObject );
8 |7 a; P  O% h
  Z3 m3 ]. a* P) N1 h' C: Q/ R    if ( DeviceObject->AttachedDevice )
: ?. ~% l' y0 P" f1 R    {
: d; b8 k" D1 a8 {/ I; R4 ~' P      //3 a, e" L! e% X; {! a; u
      // 查找 USB 键盘设备
- a7 _1 G% Q* M% B5 e( s      //" U, P, h+ @+ U" y8 G) q
      if ( GetAttachedDeviceInfo( DeviceObject ) )4 W, ]% z& J+ X3 o
      {
% ]: Y3 j2 M. U8 g        bFound = TRUE;; `0 s! y2 W5 q
        goto __End;
! E7 m- \; e) J      }
4 I% v# C( h) P; b    }
# c: K' G2 T/ x: ?
1 P1 K/ Q+ c  b4 b, y1 y( L    DeviceObject = DeviceObject->NextDevice;, \' u; b/ V7 {5 A2 S. A7 x* D5 q( Q
  }
: J. s: f: B; A9 A2 d9 D: Z3 Q# z8 ]$ b
  __End:
7 K) r$ R, B( h, [
* n1 f0 z9 o/ ^  X: C! [  if ( bFound )
0 M* j% K, g' m+ c4 S! ]* Y- V  {
* y$ r/ f3 i. u  y% t3 M    //& c2 h# o* f' l! ^7 u8 A  C9 _
    // 找到则返回 USB 键盘设备对象, H6 I1 e# F8 _& j
    //
0 z# [( W! u% W0 n8 |    *UsbDeviceObject = DeviceObject;( u" `9 c+ C1 m. d8 }1 T) Z( ~
  }" O; m7 \# g% X$ S7 s# t* c9 X
  else9 d6 y7 O) y, X6 `/ U$ W; X3 I3 b! ^
  {# U5 d5 m  U; _7 I
    *UsbDeviceObject = NULL;6 P5 z. s3 Y& c( s, D( O
  }
/ \0 s, F1 ]5 J/ }1 m# r/ m( H/ y0 ~, F
  return STATUS_SUCCESS;
! s. O6 @8 ]& G+ r}
1 w: g) h) k: V3 Y: K7 W/ p, ]7 i8 H2 o& l$ A6 r& d/ j
/////////////////////////////////////////////////////////////////
* T; _  d4 i& a! W( g7 p, N// 函数类型 : 自定义工具函数
3 I9 ?* T$ Y! H7 h  R0 T) l+ n// 函数模块 : 键盘过滤模块
6 f1 U/ p4 u# ?////////////////////////////////////////////////////////////////& x+ m( j) R9 k) v
// 功能 : 创建过滤设备将其附加到需要跟踪的设备上,保存设备相关. e" T/ I, p/ Z2 D4 a7 \
//        信息,返回附加后的驱动对象
0 L# s/ u4 U) z$ x5 i- K2 b// 注意 : 此函数仅挂接 USB 键盘设备
3 {% f# ^0 P4 \- O4 j+ f/////////////////////////////////////////////////////////////////3 [* G4 b+ |( Q
// 作者 : sinister# z, _* [7 ]+ h9 l2 _
// 发布版本 : 1.00.00. ^, H3 K6 P+ I' h  |
// 发布日期 : 2005.12.27; f+ v" |2 I8 [  I3 m/ G0 T; H) F
/////////////////////////////////////////////////////////////////
$ {" o- Y) g# Q0 i// 重   大   修   改   历   史
9 ]8 u, O6 J$ u////////////////////////////////////////////////////////////////
9 |$ J- O: r* [3 \* d- W// 修改者 :+ |$ q' r1 E( ]6 h+ ]
// 修改日期 :
! J5 L" Q2 x$ s# a- D2 Q// 修改内容 :% r/ l* c6 U8 J) r: a, a. s
/////////////////////////////////////////////////////////////////' a3 X6 t3 Z8 a7 C2 }3 a
6 x& v: |1 K* I: D+ \% q4 G
NTSTATUS6 `; s+ F4 d/ n9 I6 G7 v! y
AttachUSBKeyboardDevice( IN PDEVICE_OBJECT UsbDeviceObject,' S  p& S) @" B
                         IN PDRIVER_OBJECT  DriverObject )
) S/ A) Q: ?  p  u# U4 f{$ Q- v, h# s/ t9 E. y7 w% X1 D# |8 x
  PDEVICE_OBJECT DeviceObject;
2 Y$ P! A  I4 b* S& N* E$ f  PDEVICE_OBJECT TargetDevice; 8 O4 u+ k! [  q0 M: i
  PDEVICE_EXTENSION DevExt;' |8 m, z* i% T# Y
  NTSTATUS ntStatus;* ]. B, v& S0 b

2 F3 ~( [- W% K& d! @. k4 s  //
- k& [' P. V$ }+ m; U  // 创建过滤设备对象% |/ e, F4 [* E0 V
  //; ^4 p7 O1 ]9 Q: @
  ntStatus = IoCreateDevice( DriverObject,# j6 ]+ W$ @! T5 H/ \2 S! Q
                             sizeof( DEVICE_EXTENSION ),
1 e9 W. T5 e8 N7 g. N4 E+ g                             NULL,
; R$ e. r/ p0 ~7 L9 n( o                             FILE_DEVICE_UNKNOWN,
6 {" \7 I3 E' |                             0,! o1 T6 o3 l- ^' Q5 ^0 k! U
                             FALSE,. X) o( N1 [& Y
                             &DeviceObject ); 1 G# V8 }1 v  K9 Q5 l

3 f3 T" F& |/ |  if ( !NT_SUCCESS( ntStatus ) )) H+ Q! I- j6 C% h2 X
  {
/ E) n7 t0 M+ I# }* L    DbgPrint( "IoCreateDevice() 0x%x!\n", ntStatus );
7 M; A" `  Q8 ~; z, N7 K" r    return ntStatus;
: E' k! v2 d2 y9 T  }
4 K2 l2 u0 j0 d# i  E
% ?+ k" {. e- U* S5 C* }  DevExt = ( PDEVICE_EXTENSION ) DeviceObject->DeviceExtension;
+ K5 v& |$ v4 Z0 n
( m9 K7 }) a* G  //
+ W2 V8 K8 x0 T3 ~2 C$ s5 W% ?  // 初始化自旋锁
* ~: l$ |5 C  F9 Z  //
% `2 P0 z  {. n# k  KeInitializeSpinLock( &DevExt->SpinLock );
* v* J  O# I# i! s/ ?9 g
# S9 C! h" q( J0 b: c  //0 u3 L6 |/ a, p8 c2 Q
  // 初始化 IRP 计数器  q6 O, c9 C  J0 P. D, o
  //
7 F$ V3 C9 J  H0 V  DevExt->IrpsInProgress = 0;& r0 _3 c- y5 F2 Q5 l1 q$ J5 R

2 q8 k% z8 N' S0 L/ N8 C  //
' c. [8 C  ?* P7 C) \  // 将过滤设备对象附加在目标设备对象之上,并返回附加后的原设备对象# |/ N: r+ j9 r% ^# Z
  //- @1 z: m: i1 v1 s2 q
/ ]. a2 ?: O0 ]
  TargetDevice = IoAttachDeviceToDeviceStack( DeviceObject, UsbDeviceObject ); ) h5 M: `" e: o
  if ( !TargetDevice )0 Q9 T2 m6 J7 o- ^) R+ G
  {
1 a+ q* l/ ^9 g( v    IoDeleteDevice( DeviceObject );
, o# t5 C( Q( C4 P# x7 L    DbgPrint( "IoAttachDeviceToDeviceStack() 0x%x!\n", ntStatus );
  P# s7 q: M  M    return STATUS_INSUFFICIENT_RESOURCES;5 {4 @" P  W9 T1 ^3 I6 ]% P
  } 4 H) b* Y5 t; V
9 U: }+ N0 m! o
  //5 `4 u2 f7 V. |) b
  // 保存过滤设备信息. g7 {* ~, s( Q+ L1 y0 ~
  //
! [& g2 O. m1 f7 K9 M4 N  DevExt->DeviceObject = DeviceObject; 3 k7 F! X/ A# w7 m: {3 P0 L
  DevExt->TargetDevice = TargetDevice;4 P, D1 N- D# C8 h. I' T0 J9 ]" I

6 t3 s+ Y8 E5 Z; [: }- I& n( e  //: m8 N" X; x8 B: k: ?; [
  // 设置过滤设备相关信息与标志; o1 S7 H' u9 `9 a5 s- d: |
  //
6 w0 W; B  `- V% f  DeviceObject->Flags |= ( DO_BUFFERED_IO | DO_POWER_PAGABLE );
4 U0 N/ o$ }- A7 Z2 e$ ]8 o  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;7 z) s7 Y" z! Q: d( g5 T/ C
* R: i0 A* D% `, n/ G
# A+ x! r% y2 H1 }' q
  return STATUS_SUCCESS;& |: r8 M$ d& [% h2 r  E5 Z
}
, h0 Z% Y6 d2 j2 h; z" S: [% T5 \; ~- ?3 z- W6 C/ R- c' E
/////////////////////////////////////////////////////////////////
* @7 s9 U5 K1 c4 Z" X7 |// 函数类型 : 自定义工具函数
1 C8 A( R& ]: Y$ Y' S0 z2 X- F// 函数模块 : 键盘过滤模块
4 c/ R. r3 n* W# C. {////////////////////////////////////////////////////////////////: K# p- {  }' i& v* F6 w7 O
// 功能 : 创建过滤设备将其附加到需要跟踪的设备上,保存设备相关6 N  z; Z: h0 O7 W5 A) }
//        信息,返回附加后的驱动对象
% {1 n# S; Y3 n) M% l) F# D& d// 注意 : 此函数仅挂接 PS/2 键盘设备
2 v# @) y2 T; h6 n( h- J/////////////////////////////////////////////////////////////////
1 B' m0 R# F( Z, k- g5 N/ J% l// 作者 : sinister
$ T* w6 x  k3 }* _* t: @// 发布版本 : 1.00.00) m% D: h, j: k( s7 V; X5 K- Q
// 发布日期 : 2005.12.27
: ~: B) e! H; i( _( q/////////////////////////////////////////////////////////////////
  H( o- T- L9 v1 R% ^" N; {// 重   大   修   改   历   史6 U* A) F; o7 u9 D- v3 M
////////////////////////////////////////////////////////////////( {1 m2 I2 K2 d9 C# t7 C
// 修改者 :
+ @$ D! {2 O# t, Y// 修改日期 :
. B+ c4 t" \. n& W* J// 修改内容 :
$ X5 `$ {( I  H; R/////////////////////////////////////////////////////////////////
4 g# w! c3 I4 N! p; }! `. e6 O1 \. I* b4 B. z
NTSTATUS
1 l; Y% c. R9 \1 c% i5 F( yAttachPS2KeyboardDevice( IN UNICODE_STRING* DeviceName, // 需要跟踪的设备名0 j& y7 i" f1 a* m; E1 Q/ A
                         IN PDRIVER_OBJECT  DriverObject, // 过滤驱动也就是本驱动的驱动对象3 B! D/ q4 x% j9 a. V+ M4 v
                         OUT PDRIVER_OBJECT* FilterDriverObject ) // 返回附加后的驱动对象, t0 O& d! a& ~& B
{. C* s0 S, h, S) V" ]: i
  PDEVICE_OBJECT DeviceObject; 6 ]7 q2 a# S0 P1 ~5 @1 l/ p
  PDEVICE_OBJECT FilterDeviceObject;
" B+ ?+ s0 w# s, h' U1 P# A  PDEVICE_OBJECT TargetDevice;
7 J7 L0 }/ m# I/ {$ {  PFILE_OBJECT FileObject;
. Q0 L/ P3 S" M0 b& H3 v) e  PDEVICE_EXTENSION DevExt;$ g. `- q) c2 E/ r

- |6 i% j* T' q3 M0 m/ c: w, W$ ?  NTSTATUS ntStatus;
& d$ K( t) w) T) `/ q' R. [9 Y1 [* t$ k" }! }4 b# @
  //
0 p" R, i4 D' a, ^* ?, F# ?  // 根据设备名称找到需要附加的设备对象4 [/ Z( M+ f' ^& g; W# u
  //# d/ }+ x  T5 T9 G# A1 h9 H
  ntStatus = IoGetDeviceObjectPointer( DeviceName,/ {0 L. d9 t1 v/ Q3 z" w0 R2 x% q6 V
                                       FILE_ALL_ACCESS,, ~7 Z. t- j* Q& m
                                       &FileObject,
, Q$ p) H' c' K% X% i' F5 v3 [* H                                       &DeviceObject );
4 R7 Z  T: G) D* e) j" S5 F" X
/ d5 B, @' ~& c- y  if ( !NT_SUCCESS( ntStatus ) )
5 b4 d$ }6 @# Q' d  W1 V  {. A  j" |/ v4 u! T) U- U
    DbgPrint( "IoGetDeviceObjectPointer() 0x%x\n", ntStatus );
1 K. {, l- K8 P: `7 O    return ntStatus;0 |6 r) T/ K, O& w3 U4 {
  } , `4 Z/ d" B2 o8 ~, K
2 S' u# W3 O0 Y% c7 l. D! L0 P
  //
+ S7 F) n' w9 \( ^$ x/ N6 [1 N  // 创建过滤设备对象
$ o, u! r. Y8 p: d8 }& @! o  //0 @  c) a3 f4 r3 a# `2 Q( y8 d
  ntStatus = IoCreateDevice( DriverObject,+ Q' F. Z0 k0 J, l
                             sizeof( DEVICE_EXTENSION ),/ k% f1 h1 P* K# J8 t2 h+ v
                             NULL,& z8 {& W: |: t' g4 Y4 x
                             FILE_DEVICE_KEYBOARD,7 ^) z0 L: z* p# t3 ?
                             0,
5 v9 M1 x* N, j; [- K( X$ D                             FALSE,
+ d) W, a: [' L: }                             &FilterDeviceObject ); % L( b& L1 @7 F- J6 K& Q
6 T% F/ j. ~- I  h5 ~! u
  if ( !NT_SUCCESS( ntStatus ) )
+ R. ?; R- Y, @  {
. I6 R4 ^" K9 P2 i    ObDereferenceObject( FileObject ); ) m9 @# T% u$ w! X4 o, o
    DbgPrint( "IoCreateDevice() 0x%x!\n", ntStatus );
% f. g7 `8 Y3 i' ^0 U/ f! M$ v) @  [    return ntStatus;
" S% F8 N1 f" a8 o9 U  } ! y" J7 m; b* y) o' `$ y' k

6 P% |8 x3 j. y/ w$ a8 \9 p! p8 N7 [  //7 y- B2 |7 X7 f8 k
  // 得到设备扩展结构,以便下面保存过滤设备信息
) p. n7 {/ G8 Q' {1 m9 q- g; x  //, `+ n7 K% B) p" U: [6 C
  DevExt = ( PDEVICE_EXTENSION ) FilterDeviceObject->DeviceExtension;
) [4 v. k) l- T) f& |# {* k3 C1 F) g$ l0 H

4 n: c# W9 z& u6 N  //
1 C$ Y. s  g) V4 F, F, W& E; V  // 初始化自旋锁
, }8 s% G0 l6 `, A( w- a/ ?: f/ x  //( W. L8 o  C2 @' k5 N" U
  KeInitializeSpinLock( &DevExt->SpinLock );4 ^# }& h" B' s9 y% m$ ?7 E3 K1 U$ \
6 n& ]; n$ r0 o# F
  //
$ R; x3 \( I! {" Y5 B4 K  // 初始化 IRP 计数器6 [! k$ y4 x, Q& l' d: c+ w
  //$ h5 f8 l  q; b* V+ [
  DevExt->IrpsInProgress = 0;
5 o% A/ t+ ]1 M. E4 Q% [" \% [7 m1 c2 _
  //1 |# k, j# l" P8 v0 _+ t
  // 将过滤设备对象附加在目标设备对象之上,并返回附加后的原设备对象
4 L) D+ }9 t" P2 y  //
. Y% t1 b5 Y* a* ^! f! l  TargetDevice = IoAttachDeviceToDeviceStack( FilterDeviceObject,
, B3 Y/ m" d9 z. K7 s! O1 V6 N                                              DeviceObject );
0 u0 \% p- J8 M& K& n4 W! ]  if ( !TargetDevice )& l' Q2 B( O; K; n* }" `6 `
  {+ z; P+ V' [* |- P: k# L
    ObDereferenceObject( FileObject );
: h3 d& F+ D- p) e, x2 b    IoDeleteDevice( FilterDeviceObject ); $ p1 e# Z/ y) M% t" a
    DbgPrint( "IoAttachDeviceToDeviceStack() 0x%x!\n", ntStatus );
( m6 S0 |3 A/ f  u/ M( V0 Z    return STATUS_INSUFFICIENT_RESOURCES;! M9 M4 z* H: x/ U" }
  } 8 J, y9 W4 }% v* v( K! A4 f

7 h9 P+ r7 @: B  X* P( M  //
; A, C$ c+ A* R! u7 R9 \  // 保存过滤设备信息
2 }5 S4 {+ O* x8 a, \  //" l- Y- |: o0 }- x6 e
  DevExt->DeviceObject = FilterDeviceObject;
9 B0 V, P3 g' {7 F" K' n' I" f  DevExt->TargetDevice = TargetDevice; * o9 [- m- ?4 `6 q% q
  DevExt->pFilterFileObject = FileObject;
, D$ h/ F& t8 u: R" ^
; n8 F( G' G3 ^, U  //
! m4 k2 O% T4 X6 K! ~7 u; X/ J& \* A& C  // 设置过滤设备相关信息与标志3 H2 \% E& _% ^! e$ K- B
  //2 S. B( i4 [# E
  FilterDeviceObject->DeviceType = TargetDevice->DeviceType; " x) V; Z+ d" K$ Q
  FilterDeviceObject->Characteristics = TargetDevice->Characteristics; / A) ?6 m5 X' |$ }: q& Q+ ^0 r2 S0 O
  FilterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;" s$ a0 H# Z0 y, ^6 }
  FilterDeviceObject->Flags |= ( TargetDevice->Flags & ( DO_DIRECT_IO |
' ?7 u; m$ S1 e                                                         DO_BUFFERED_IO ) ); ! V" b/ y0 a( {2 X/ i

/ o! W0 g. |% H5 r* m. `0 |  //
) ~# G0 ?: S# Z; Z& H- a  // 返回附加后的驱动对象& ]7 j6 }0 v  {6 s0 z
  //3 ?5 ~  ]1 W3 l- d& n9 ?
  *FilterDriverObject = TargetDevice->DriverObject;
% F0 D9 u1 z, X2 j( S( n$ z' u2 Q8 z" c. O) Q" P
  ObDereferenceObject( FileObject );
- `1 o3 u1 @' b3 b# P  h0 ]/ d: o5 s( }. }8 a
  return STATUS_SUCCESS;
3 D+ Q- c4 k$ m5 g4 g8 e% }}  I( p5 Y. ]) Z9 ^

1 E8 S- H+ ^/ n/////////////////////////////////////////////////////////////////
( k0 c! u% a8 c! \. |, N4 B// 函数类型 : 自定义工具函数
2 [" o" x$ j- j7 N: J# N: H// 函数模块 : 键盘过滤模块
# U) p& [8 T$ w  O8 O3 m5 H" l1 ]////////////////////////////////////////////////////////////////
7 X: S; T% u0 Y// 功能 : 键盘过滤驱动的 IRP_MJ_READ 派遣例程,所有按键将触发
. S" v* D  [3 f" [  A  t+ O4 v//        这个 IRP 的完成# t) A1 f4 D, t+ x' Q) k* X
// 注意 : 5 `9 d, `4 t2 q+ w
/////////////////////////////////////////////////////////////////0 l, G9 C7 I6 r- J9 c* V
// 作者 : sinister0 x# t# j3 i0 z5 F
// 发布版本 : 1.00.00, S( @' p# V3 b' g) R
// 发布日期 : 2007.2.15
- L! j/ E0 {; t: Q% A# J# H/////////////////////////////////////////////////////////////////8 W+ k* q4 b; S$ i3 h) X
// 重   大   修   改   历   史
' ^3 R9 s! T9 S0 b* Q4 G////////////////////////////////////////////////////////////////
8 j. E+ k7 e. ?4 m. E// 修改者 :, n  m& s7 B  V% W: J, e
// 修改日期 :5 Y5 n4 g/ U" z# s2 M
// 修改内容 :8 b5 s6 Z- i7 i) S
/////////////////////////////////////////////////////////////////, Y3 }- o" D1 v' x4 {! t  ?

6 T" G" q2 i' L: Y) yNTSTATUS& G) K+ H1 e9 Y1 X8 d) Q4 }
KeyReadPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )+ B# V' b! O3 q. m9 M
{0 a5 i9 m( J3 N
  NTSTATUS status;
, V( _$ P9 {5 Y  KIRQL IrqLevel;! x( B+ [0 w$ z* q; ]5 o- K9 v

( ]3 `* H2 l- E1 h) x8 B  PDEVICE_OBJECT pDeviceObject;
/ t  R6 \8 x% h  P. _- [; m4 B; f  PDEVICE_EXTENSION KeyExtension = ( PDEVICE_EXTENSION )
3 ~) X2 T- G$ j2 X                                   DeviceObject->DeviceExtension; $ X" M+ }: v0 @& C
: D% ]  t! d9 d7 `+ ~

# Z6 G( z+ S# M5 Q$ L( ]) r6 C  IoCopyCurrentIrpStackLocationToNext( Irp );+ j2 ^: q$ R. J; |9 v. `- D

, \  g. w  ?: s( U, v  //
# Z, L& ^2 X' j6 d  // 将 IRP 计数器加一,为支持 SMP 使用自旋锁
* r/ d2 \2 ^& |, _/ R- N  //6 n. @. Z4 `, d) b! U
  KeAcquireSpinLock( &KeyExtension->SpinLock, &IrqLevel );
, H& E- y! E6 D( i  InterlockedIncrement( &KeyExtension->IrpsInProgress );* G) w. T5 G9 X1 W0 s
  KeReleaseSpinLock( &KeyExtension->SpinLock, IrqLevel );7 `6 [9 _. e4 q% u
" }+ v3 I' d' y/ B8 ^
  IoSetCompletionRoutine( Irp,
# {1 ~6 x8 w, H% K" L& ~: n                          KeyReadCompletion,7 h2 s& }1 t& {, a
                          DeviceObject,
' m1 g% d  z- J: F; P5 [' K                          TRUE,
. T1 C7 V; m: z3 C2 U                          TRUE,6 Z% A" w: p8 A1 {$ s- m) j" s6 _
                          TRUE );
! }/ s  y  [% W6 M: i& N7 X$ @4 F
  return IoCallDriver( KeyExtension->TargetDevice, Irp );
- H) ^9 t: Q) A6 \9 {}
- K6 G, S/ ?& a& T7 k, J1 V! \3 h7 O. B3 W( e8 ]
/////////////////////////////////////////////////////////////////3 {. [- r) O# f- D
// 函数类型 :系统回调函数
" h  j' L1 q4 I% i2 E// 函数模块 : 键盘过滤模块
) l0 n% S0 Y, D: C- F////////////////////////////////////////////////////////////////; {3 B- x+ A4 q3 d
// 功能 : 获得键盘按键,用无效扫描码替换,以达到屏蔽键盘的目的
3 ^$ E& F" L7 d0 O- f) W( F8 S  \// 注意 : ) {# J7 D$ E1 g) T0 b7 h
/////////////////////////////////////////////////////////////////4 U. ?( Q! w% I1 D. w8 _' X
// 作者 : sinister' T# @$ v4 S9 q; ]3 Q* B  E
// 发布版本 : 1.00.00
; ]8 ^0 w/ e6 V// 发布日期 : 2007.2.123 D8 P% w) q$ J4 w! L: L: G: K. u+ H
/////////////////////////////////////////////////////////////////- t) q' y3 |8 l9 `1 V
// 重   大   修   改   历   史
# w9 O% U: N: m- D% U% V////////////////////////////////////////////////////////////////
( ]2 G/ _% y$ d% s% N( {// 修改者 :# Q* a* E$ v! v  G2 Q' b' z# v
// 修改日期 :: W/ J7 [5 V# K% a, _1 t8 I1 w
// 修改内容 :
9 z; K3 I3 h  B1 D4 ^3 Y2 T2 q( u+ K# \/////////////////////////////////////////////////////////////////9 U1 I4 _2 f8 u+ K. D
+ Z8 ~8 H6 R: H  {( H! @0 j9 l9 v
NTSTATUS4 U' N! H  y8 W6 Z. N, C
KeyReadCompletion( IN PDEVICE_OBJECT DeviceObject,
, O# `' ^# V- ]& D                   IN PIRP Irp,
+ `. C5 }/ {, ]5 E& {                   IN PVOID Context )# s$ Y* W9 f9 C. S" c3 C
{
6 z; o+ H/ L# S+ X8 x# B8 p7 [$ u7 y  PIO_STACK_LOCATION IrpSp;
( [+ P% h$ D9 I' n) P8 s  PKEYBOARD_INPUT_DATA KeyData;/ k) S. s! [7 z5 U& j8 o5 x
  PDEVICE_EXTENSION KeyExtension = ( PDEVICE_EXTENSION )
# \' w* S5 F2 }# ^$ Z- m, h5 v- g                                   DeviceObject->DeviceExtension;
9 z1 N' r: |) O& ^1 l  int numKeys, i;/ e) Z6 K( K: @: @& ~, h3 R
  KIRQL IrqLevel;: G  c8 Z5 i1 Q* t0 H
6 d$ S: x  o) A4 e) m3 x
  IrpSp = IoGetCurrentIrpStackLocation( Irp );5 Z" U, o. w* x5 P* O5 n2 S  M

& V  s! {$ \3 T, q, g7 R( g
$ s6 h( W$ A! g6 K# g1 [- \  if ( Irp->IoStatus.Status != STATUS_SUCCESS )9 A, b- g. I  y. \3 ~
  {: C! j# M0 X1 y. q3 k; N9 o
    DbgPrint( "ntStatus:0x%x", Irp->IoStatus.Status );' M( \; l) ]8 U: b" T9 T
    goto __RoutineEnd;# u/ p. r& C0 g/ ]
  }5 W$ [# R  j7 k% s) s3 i; R
& v/ n" ?) D8 X3 w9 G
  //4 y1 {  Z# C! p  c4 w
  // 系统在 SystemBuffer 中保存按键信息( c! O8 y. C' [& M4 p5 `
  //
( o! i8 E3 @) t9 _3 Q  KeyData = Irp->AssociatedIrp.SystemBuffer;
0 Y9 L" E) I; E9 X8 `2 c  if ( KeyData == NULL )/ d* I# G% k: E1 Y5 f; V$ c
  {
$ J) U. C7 q* R& F' s    DbgPrint( "KeyData is NULL\n" );! u/ X( M0 B9 r4 I
    goto __RoutineEnd;& t7 S5 g* l1 J+ j
  }
# n( a$ v1 M# C" d2 c( \1 z& y$ Q9 ]% R" S3 w' V
  //
) E7 b# E9 E3 H0 v  // 得到按键数
& u9 k/ N3 r% d: B4 e  S, t, O0 C  //: Y& A/ f4 [4 R4 l3 x4 @6 _6 E
  numKeys = Irp->IoStatus.Information / sizeof( KEYBOARD_INPUT_DATA );5 |& f- B; k6 S7 [/ W4 t
  if ( numKeys < 0 )
5 V) L" w; F; H  {! u( X2 L5 z: K
    DbgPrint( "numKeys less zero\n" );5 r8 h" J8 |- \: v/ [0 o
    goto __RoutineEnd;
9 n: T: S9 t& v1 o/ S  }
3 |0 Z3 x2 j, \3 Z* x) Y1 O
3 h: W6 D2 M. e. U  C  //
$ p1 l" Y0 i! e$ Q) U8 r  // 使用 0 无效扫描码替换,屏蔽所有按键
* i$ c( |, e' w) b; z5 D  //" g/ O! z0 G6 m* I+ \4 j" y; }, `
  for ( i = 0; i < numKeys; i++ )+ N5 Q5 ^7 v4 B4 T  M
  {+ Q1 m: P' q/ O. c) b
    DbgPrint( "KeyDwon: 0x%x\n", KeyData[i].MakeCode );* B! j' x. X+ H/ z# `" `% S
    KeyData[i].MakeCode = 0x00;5 P. e9 v; s- `& X$ J: t
  }
7 \# i2 E1 w( i+ z/ ^. m' }3 J
" d3 l1 i, i# S% q9 h& h6 ~8 K9 h3 X( l
  __RoutineEnd : " o: y' P% T7 X: _3 U! Y6 ]

# \! W" g$ t: O9 o  if ( Irp->PendingReturned )7 B7 b' ~# S* l% B. e7 \
  {% l/ y" ~/ }: \! ^
    IoMarkIrpPending( Irp );
+ [$ h: N' q8 O! B0 M! M2 o1 m  }
. p  C4 Q" N- Y4 l' \
0 s5 _. r1 b7 W  //
2 H# j) f' y  a" N! U; v& `  // 将 IRP 计数器减一,为支持 SMP 使用自旋锁
2 t# U( \2 x: I6 [+ R8 w" h3 ?  //
* r$ J6 O3 h  P9 p" E2 v7 f  KeAcquireSpinLock( &KeyExtension->SpinLock, &IrqLevel );& ^. p& e$ s( [" E2 y7 t, z
  InterlockedDecrement( &KeyExtension->IrpsInProgress );
* u  N8 S$ h; ^  KeReleaseSpinLock( &KeyExtension->SpinLock, IrqLevel );
9 R  G4 v3 I$ k/ I9 [) D9 ~8 L! A; O+ a; G; s
  return Irp->IoStatus.Status ;
' o9 {$ z$ Y; H5 v} 1 n9 e) B) @( e: j* J: }) L
& \$ W5 n9 }# E0 U; ^0 E

9 R  F5 ~; I1 u; @/*****************************************************************2 V+ ?  x5 R3 _7 N+ K& J; i
文件名        : WssLockKey.h
: |; j2 m- S' p 描述          : 键盘过滤驱动
9 a4 S/ _& e) G  M( c; } 作者          : sinister/ W5 S: J" h% F
最后修改日期  : 2007-02-265 }9 c, Y* I# e9 O9 W7 i
*****************************************************************/# h% ~0 M& z  K: l; r

2 R( W* C9 d) {' q! Q9 `3 y! l#ifndef __WSS_LOCKKEY_H_1 L6 _2 b! K8 y( t. ^  `# l7 t
#define __WSS_LOCKKEY_H_2 y" B8 _1 C' f

: e6 }, a, m/ g& E' `) u: R1 E#include "ntddk.h"* N+ Q, N& `4 o$ L( i( J3 }! m
#include "ntddkbd.h"/ Y+ m% g* k6 Z
#include "string.h"
2 y7 R; S( h! z# E- C2 G3 i0 i#include 1 B* \1 n( e8 L' y: s

# l- w. G: ]- @& }) h/ o6 h9 ^+ w. D#define MAXLEN 256+ h* Y8 j4 _! F6 O
! Y# B* n7 @' u# T
#define KDBDEVICENAME L"\\Driver\\kbdhid"
5 I( z; b' c/ n0 n4 R2 U8 f#define USBKEYBOARDNAME L"\\Driver\\hidusb" 5 d& T: Q' U$ e$ p% o
#define PS2KEYBOARDNAME L"\\Device\\KeyboardClass0"
; w3 a/ L0 s) y2 y/ X: x( L
2 v" _+ |' V* C0 u- Ftypedef struct _OBJECT_CREATE_INFORMATION
* e4 K' ^+ Y- ~- A) B8 {( K{
9 M# N' L7 ^: Y9 @    ULONG Attributes;7 d" e% T, L* E% Y. @6 l
    HANDLE RootDirectory;
1 s, R& e) ~! h& r1 a/ I    PVOID ParseContext;
0 O' S8 W3 S7 @    KPROCESSOR_MODE ProbeMode;/ s0 t) u  N1 a( g$ f
    ULONG PagedPoolCharge;
+ i' b' _. m  i    ULONG NonPagedPoolCharge;
& @0 d1 C1 e' g( o    ULONG SecurityDescriptorCharge;0 b% S' j+ a/ W/ }8 W5 j
    PSECURITY_DESCRIPTOR SecurityDescriptor;
3 T0 a* j4 Z' F9 {    PSECURITY_QUALITY_OF_SERVICE SecurityQos;  K. U0 i4 A' h2 a7 z6 V
    SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
: e" `' p0 @+ h) y3 a. K% ~} OBJECT_CREATE_INFORMATION, * POBJECT_CREATE_INFORMATION;. H  r4 p/ \  g5 |9 w- C" [' \) {
3 _. t- M: R8 @. Y" a
typedef struct _OBJECT_HEADER
# c  v2 Q1 R( a, t$ o{" z, c" Y; H# w  f7 i
    LONG PointerCount;4 d6 K! D4 A5 o, q& c( e
    union
+ I  n  n! G( g  G: U    {; U/ c9 K( C& J! F- y* X; Z
        LONG HandleCount;
" L+ }, {& `# `# z- X$ g$ @5 d8 |/ n        PSINGLE_LIST_ENTRY SEntry;
4 y* ^4 Q+ a/ z  P& R& K1 {9 j* ]    };
2 Z- g- F  `+ p& y) O0 }7 I' l& K  W: O    POBJECT_TYPE Type;4 R& S! v+ I0 k/ r: J
    UCHAR NameInfoOffset;7 K" J, o6 S" p
    UCHAR HandleInfoOffset;, }0 [; m7 f7 r- O" Z  {
    UCHAR QuotaInfoOffset;- h' x& o& {9 L0 L- ^$ t! @! L
    UCHAR Flags;
% z: ?) o# N8 z' h" v8 \( D    union/ t" C  O, v+ b+ ^
    {/ {2 F* f- R  w, l$ y- R
        POBJECT_CREATE_INFORMATION ObjectCreateInfo;
4 v& W5 {2 @2 J6 r6 A6 Q        PVOID QuotaBlockCharged;
+ N  ~' F9 V0 o# Y7 ]* j    };) ?5 X; @( z2 |( A3 C

$ x( U9 e3 B( y# @    PSECURITY_DESCRIPTOR SecurityDescriptor;0 v  q- F$ j, Y1 p
    QUAD Body;/ B2 P, [8 T; |
} OBJECT_HEADER, * POBJECT_HEADER;
4 s5 I5 l- \) \8 S
$ Z  D; c5 J% c0 s) R#define NUMBER_HASH_BUCKETS 371 c/ R) y: r% i" }( Z- l& _( z: {
3 x. c9 i7 z. C: i( `
typedef struct _OBJECT_DIRECTORY6 V! s1 L3 K! f
{
+ @$ A0 t5 D+ \8 @/ s    struct _OBJECT_DIRECTORY_ENTRY* HashBuckets[NUMBER_HASH_BUCKETS];
+ d0 O* |$ F3 @  t7 k0 {    struct _OBJECT_DIRECTORY_ENTRY** LookupBucket;' Y/ C$ f' I/ H; g! s
    BOOLEAN LookupFound;, z4 A4 k4 B* r8 y2 o
    USHORT SymbolicLinkUsageCount;* b9 Y6 n; j  F; K- U
    struct _DEVICE_MAP* DeviceMap;# k( Z/ B, E$ x- E* e  f. }
} OBJECT_DIRECTORY, * POBJECT_DIRECTORY;
# \& [+ o6 [0 G0 ]% |7 Y8 F4 M% D- c$ G+ v+ w) p
typedef struct _OBJECT_HEADER_NAME_INFO
' m3 P1 I4 n3 r+ }{$ _9 x* n+ r0 D) P# W
    POBJECT_DIRECTORY Directory;3 R8 J% _( M* M) t* z4 D5 a2 s
    UNICODE_STRING Name;# ~0 L; [+ r- e1 H% f; K  W
    ULONG Reserved;
+ p# f2 v- ~7 B# r6 \#if DBG7 r) k; X! i0 {& N
    ULONG Reserved2 ;
% W) w1 w: t2 Q5 g    LONG DbgDereferenceCount ;" [& A+ K; }$ g, _2 u, ]# I
#endif8 P1 T3 H  n+ G7 d9 @5 M
} OBJECT_HEADER_NAME_INFO, * POBJECT_HEADER_NAME_INFO;/ }3 j; s) P+ m. p1 A
. X+ o1 T& b) X2 C) w2 _% C
#define OBJECT_TO_OBJECT_HEADER( o ) \( J& Q* K1 T3 `6 p' A/ ?2 M# V0 j
    CONTAINING_RECORD( (o), OBJECT_HEADER, Body )! k) N, [  G& @( N& o8 g  P

; v/ e4 f: P4 I#define OBJECT_HEADER_TO_NAME_INFO( oh ) ((POBJECT_HEADER_NAME_INFO) \
% r, P# |% x* ?) }- M* H+ Y    ((oh)->NameInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->NameInfoOffset)))) O0 f" W, M  @+ R

$ G+ }. {9 D$ y" k8 |7 g& Stypedef struct _DEVICE_EXTENSION
. X1 }2 @; F' H; N. G1 e# D; a{
0 j% H8 M, ?& w3 l* [    PDEVICE_OBJECT DeviceObject;) G0 q! \* S6 x* \: ~
    PDEVICE_OBJECT TargetDevice;
5 c  q' P) q  \, r* d; d    PFILE_OBJECT pFilterFileObject;- s) q2 P# G; x9 W9 M9 k
    ULONG DeviceExtensionFlags;
; P; p6 S6 o: Y, U2 c& q$ _  c  y    LONG IrpsInProgress;
6 g1 n4 H$ ^# c) W3 j$ g    KSPIN_LOCK SpinLock;
- c* J4 ~9 C# p; z" V- ^/ K/ b5 _% T}DEVICE_EXTENSION, * PDEVICE_EXTENSION;
7 N  t2 L7 j) W. ]( }! s; t
" Z# U. B) _8 h5 F+ G
6 o. D, X* y; C9 bVOID
: e$ a' \8 M0 I+ G+ }' pKeyDriverUnload( PDRIVER_OBJECT KeyDriver );
4 U  R' Y( k& k5 ^# `* v
  m/ [7 k. k& L1 h  o2 j% l) oBOOLEAN
/ E! U9 Y' _: c$ `2 ]+ VCancelKeyboardIrp( IN PIRP Irp );% K  a$ N( a& K6 j' w0 R6 \

6 v/ w1 |% T: eextern POBJECT_TYPE* IoDriverObjectType;
# e" @9 H' g: o3 g9 v
& x& q: B# O1 G$ PNTSYSAPI+ H& J! ^! O% Y  x! u4 `4 `
NTSTATUS5 J2 |, }: ]. u2 P/ k& W- V+ I
NTAPI ObReferenceObjectByName( IN PUNICODE_STRING ObjectName," n1 [. e/ f: g! f
                               IN ULONG Attributes,0 a9 P: [0 p% Y/ A$ L
                               IN PACCESS_STATE AccessState OPTIONAL,  m) z/ Q5 E9 F* J% e* J5 {
                               IN ACCESS_MASK DesiredAccess OPTIONAL,
  J& Y# b2 X  c1 `! {                               IN POBJECT_TYPE ObjectType,  |2 ~, ^+ u' a* z
                               IN KPROCESSOR_MODE AccessMode,: Q$ s9 a" P4 G' i4 m3 G. c
                               IN OUT PVOID ParseContext OPTIONAL,$ x+ x- T- \6 w8 q; z, e( L
                               OUT PVOID* Object );/ b& M3 J& P3 t$ N% `
, A8 M  e4 v, S7 N4 {
NTSTATUS
) b7 H2 u& ^9 lGetUsbKeybordDevice( OUT PDEVICE_OBJECT* UsbDeviceObject );
1 f$ S8 K1 e. }" _2 S  O: B& j! }! o) i1 y8 J* p
BOOLEAN ( n7 N' H% `. H$ p8 T
GetAttachedDeviceInfo( IN PDEVICE_OBJECT DevObj );6 r  J4 {5 c! F- K% i8 ^3 Y2 ^% v3 e6 G
& e- D$ r) }  N
VOID
) w4 l+ E# i3 b: k  c) ^GetDeviceObjectInfo( IN PDEVICE_OBJECT DevObj );
6 z/ o+ X0 ]( u# `0 W. i9 y) ]+ ^7 C5 [1 `0 G% x
NTSTATUS
9 [: m: Z1 y5 B5 N5 a6 SAttachUSBKeyboardDevice( IN PDEVICE_OBJECT UsbDeviceObject,
+ ]2 o" R6 Y* n" K                                  IN PDRIVER_OBJECT  DriverObject );0 U0 s8 n" ?# x8 _: I

5 [. w  o* i; [# P- GNTSTATUS 4 ^( Y: g" p( c
AttachPS2KeyboardDevice( IN UNICODE_STRING* DeviceName,1 B7 Z3 z& s) b7 c, r1 E
                                  IN PDRIVER_OBJECT  DriverObject,3 z, h6 K8 l( G( o
                                  OUT PDRIVER_OBJECT* FilterDriverObject );
/ d. _/ L; Q! X1 `: J+ t9 p* I* g5 y* I' W# o9 |( X
NTSTATUS 2 O: h6 L+ o: R! O& o' c% z8 ^
KeyReadCompletion( IN PDEVICE_OBJECT DeviceObject,
# n6 q9 Q* U7 T/ n. t                            IN PIRP Irp,4 i. k3 M: T0 t( \/ }
                            IN PVOID Context );3 a5 C& g: @4 u$ k! K
NTSTATUS . N; O9 T5 y# ]/ m& [( w+ J3 l% X& O
KeyReadPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );5 b3 E6 F3 K7 T

3 Y7 K" H# o  r( I9 eWCHAR szUsbDeviceName[MAXLEN];6 A2 c# a* S: q8 g
* m% H, s+ @1 @* E9 _
#endif
) \! w9 j& W; F, p
; U5 U- ^9 D- b' d  k! s  J" x
9 D$ H. E$ G; k$ a
7 p8 \! H( W  V. r. q7 a& i* |0 M; K2 h# [) e+ K
0 f) y7 K, U1 \( p9 q2 k8 O' D
WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
2 j/ x- @: `( m( DWSS 主页:[url]http://www.whitecell.org/[/url] ( _4 z# ]8 c' L+ o3 \
WSS 论坛:[url]http://www.whitecell.org/forums/[/url]
您需要登录后才可以回帖 登录 | 加入计匠网

本版积分规则

Archiver|手机版|小黑屋|计匠网

GMT+8, 2026-9-21 21:25 , Processed in 0.086852 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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