狠狠撸
Submit Search
L-R
?
Download as PPT, PDF
?
2 likes
?
1,810 views
F
firewood
Follow
Windowsでキーを入れ替える7つの方法 (written in Japanese)
Read less
Read more
1 of 33
Download now
More Related Content
L-R
1.
L ? R
[email_address] [email_address]
2.
Windows でキーを入れ替える 7
つの方法 既存のソフト レジストリ MSKLC メッセージフック LL フック フィルタドライバ その他
3.
対象範囲 以下の入れ替えを 7
種類紹介 「 L 」キーを押すと「 R 」が入力される 「 R 」キーを押すと「 L 」が入力される 対象 OS: Windows 2000/XP たぶん Vista/7 でも可
4.
なぜ L-R 入れ替えなのか
日本人は L と R の区別が苦手 ↓ 入れ替えても気づかないかも!
5.
参考 ULR Vista/Windows
7 におけるキーボードカスタマイズ問題 http://d.hatena.ne.jp/LM-7/20090614/1244980470
6.
今回の手法の位置関係
7.
紹介順序 手軽なものから順に紹介 手軽≒高レベル
より低レベルな方法を追求する 「普通のやつらの下を行け」 「下には下がいる」
8.
方式 1
既存のソフト お手軽な方法 マクロなど凝ったことができる
9.
既存のソフトと手法 メッセージフック XKeymacs
( emacs な人用) LL フック AutoHotkey (スクリプトで色々やりたい人用) フィルタドライバ 窓使いの憂鬱( XP まで) のどか( Vista 以降)
10.
方式 2
レジストリ 単純な入れ替えに最適 設定方法 「 windows keyboard layout 」でぐぐる ヘルパーアプリもある( KeyLayout Fix など)
11.
レジストリのメリット Windows 標準
安全、安定、比較的簡単 処理コストがたぶん低い 全ユーザー、またはユーザー毎に変更できる 共通のキーとユーザー毎のキーがある 特殊なキーも入れ替えられる 定番は Caps キーと Ctrl キーの交換
12.
方式 3 MSKLC
Microsoft Keyboard Layout Creator 「サポートされていない言語のキーボードレイアウトを、簡単に定義できます」 キーマップを定義する DLL を作成?変更できる オレオレ kbd???.dll が作成可能 日本語キーボードには未対応( ! )
13.
MSKLC のメリット 発音記号やデッドキーの割り当てが可能
ウムラウトや 2 ストローク入力 「ほげキー」が作れる
14.
方式 4
メッセージフック SetWindowsHookEx WH_KEYBOARD または WH_GETMESSAGE グローバルフックの場合、 DLL 内で設定する 全プロセス、全スレッドに対してフック可能 ただし 64bit 環境では、同じ環境に対してのみ有効(両方フックするには、 32bit と 64bit 版が必要になる) メッセージの発生の捕捉と消去が可能 交換に使える
15.
WH_KEYBOARD での交換部 LRESULT
CALLBACK KeyboardProc() { if ( nCode == HC_ACTION && ScanCode > 0 ) { switch ( VirtualKeyCode ) { case VK_L: case VK_R: Input.type = INPUT_KEYBOARD; Input.ki.wVk = (WORD)(VirtualKeyCode ^ (VK_L ^ VK_R)); Input.ki.dwFlags = (lParam & 0x80000000) ? KEYEVENTF_KEYUP : 0; ::SendInput( 1, &Input, sizeof(INPUT) ); return 1; } } return ::CallNextHookEx( HookHandle, nCode, VirtualKeyCode, lParam ); }
16.
WH_KEYBOARD について補足 プロセス間通信が必要
処理に必要な DLL がプロセス毎に読み込まれるため 今回はお手軽な共有メモリを使用 自分で挿入したキー操作に対しても反応する 対策しないと無限ループする 今回は、スキャンコードがゼロかどうかで識別 キーを離した操作も交換すること
17.
WH_GETMESSAGE の場合 処理方法は
WH_KEYBOARD と大差なし 全てのメッセージが取れるので、パフォーマンスに影響するかもしれない メッセージを消したい場合は、メッセージの種類を WM_NULL に変更する
18.
方式 5 LL
フック Lightweight Language × ふせいかい Low Level ○ ふつう
19.
方式 5 LL
フック SetWindowsHookEx(WH_KEYBOARD_LL) グローバルフック専用 API DLL 内である必要はない 使い勝手は WH_KEYBOARD とほぼ一緒 NT 系のみ( Windows 9x 系では使えない) C# でも使える 自分で挿入したかどうかがわかる
20.
LL フックの交換部 LRESULT
CALLBACK LowLevelKeyboardProc() { KBDLLHOOKSTRUCT *kbhs = (KBDLLHOOKSTRUCT *)lParam; if ( nCode == HC_ACTION && (kbhs->flags & LLKHF_INJECTED) == 0 ) { switch ( kbhs->vkCode ) { case VK_L: case VK_R: Input.type = INPUT_KEYBOARD; Input.ki.wVk = (WORD)(kbhs->vkCode ^ (VK_L ^ VK_R)); Input.ki.dwFlags = (kbhs->flags & 0x80) ? KEYEVENTF_KEYUP : 0; ::SendInput( 1, &Input, sizeof(INPUT) ); return 1; } } return ::CallNextHookEx( HookHandle, nCode, wParam, lParam ); }
21.
方式 6
フィルタドライバ デバイスドライバの一種 ドライバとドライバの間に配置する中間ドライバ すでに存在するデバイスオブジェクト同士の間にはさみこむ 上位と下位の間の入出力(主に IRP )を監視、変更できる
22.
キーボード入力の通知経路 上位が kbdclass.sys
に対して IRP_MJ_READ を発行する kbdclass.sys は上位に STATUS_PENDING を返し、待つ キー入力があると、キーボードドライバが kbdclass.sys のサービスコールバックを呼び出す キーのデータがバッファに書き込まれる kbdclass.sys が上位に読み取り完了を通知する
23.
フィルタドライバ 1 Windows
サブシステムとキーボードクラスドライバ( kbclass.sys )との間に配置 上位からの IRP_MJ_READ を横取りし、完了(キーデータの通知)を待つ キーデータが通知されたら、変更して上位に返す
24.
フィルタドライバ 1 の処理(準備)
NTSTATUS ReadDispatch() { ... // 読み取り完了ルーチンを設定し、ペンディングにする IoSetCompletionRoutine(Irp, OnReadComplete, Extension, TRUE, TRUE, TRUE); IoMarkIrpPending(Irp); IoCallDriver(Extension->NextLowerDriver, Irp); return STATUS_PENDING; }
25.
フィルタドライバ 1 の処理(交換)
NTSTATUS OnReadComplete() { if (Buffer[0].MakeCode == MAKE_L) { Buffer[0].MakeCode = MAKE_R; } else if (Buffer[0].MakeCode == MAKE_R) { Buffer[0].MakeCode = MAKE_L; } return STATUS_CONTINUE_COMPLETION; }
26.
フィルタドライバ 1 について補足
IRP のフィルタドライバとしては素直な実装 マウスにも適用可能 kbdclass.sys が mouclass.sys になるだけ 処理待ちしている IRP を管理する必要がある 抜かれたときにキャンセルする責務がある kbdclass.sys よりも後にインスタンス化する UpperFilters に追記する
27.
フィルタドライバ 2 kbdclass.sys
とキーボードドライバとの間に配置 kbdclass.sys が提供するサービスコールバックをフックする キーボードドライバに自分の関数をサービスコールバックとして教える キー入力データを変更し、 kbdclass.sys のサービスコールバックを呼び出す WDK のサンプル( kbfiltr )
28.
フィルタドライバ 2 の処理(フック)
NTSTATUS InternalIoControlDispatch() { switch ( IrpStack->Parameters.DeviceIoControl.IoControlCode ) { case IOCTL_INTERNAL_KEYBOARD_CONNECT: CONNECT_DATA *ConnectData = (CONNECT_DATA *) (IrpStack->Parameters.DeviceIoControl.Type3InputBuffer); Extension->KeyboardConnectData = *ConnectData; ConnectData->ClassDeviceObject = DeviceObject; ConnectData->ClassService = (PSERVICE_CALLBACK_ROUTINE) KeyboardServiceCallback; break; } }
29.
フィルタドライバ 2 の処理(交換)
void KeyboardServiceCallback() { PKEYBOARD_INPUT_DATA p; for ( p = InputDataStart; p < InputDataEnd; ++p ) { if (p->MakeCode == MAKE_L) { p->MakeCode = MAKE_R; } else if (p->MakeCode == MAKE_R) { p->MakeCode = MAKE_L; } } ClassService(ClassDeviceObject, InputDataStart, InputDataEnd, InputDataConsumed); }
30.
フィルタドライバ 2 について補足
WDK のサンプルにもある通り、キーボードでは定番の方法 マウスにも適用可能 IRP のキャンセルが不要 サービスコールバックは DPC レベルなので注意 kbdclass.sys よりも先にインスタンス化する UpperFilters の先頭に記述する
31.
フィルタドライバについて補足 64bit 環境では
32bit プロセスにも有効 ただし配布するには署名が必須 ドライバの処理時点では、レジストリによる交換は反映されていない
32.
方式 7
その他 エクストリームダイレクト フィジカルフォースメソッド 訳 : ぶっちゃけ直接交換しちゃえば
33.
End of Fire
Download