スポンサーサイト
--.--.-- *--
デバッグ特権
2012.04.04 *Wed
デバッグ特権ですが、VisualStudioでデバッグすると最初から付加されている模様。
したがって、特に SeDebugPrivilege せずともOKそうです。
ただし、管理者で実行していないと失敗します。
でもOpenProcess出来なかった記憶があるんだけどなぁ・・・
したがって、特に SeDebugPrivilege せずともOKそうです。
ただし、管理者で実行していないと失敗します。
でもOpenProcess出来なかった記憶があるんだけどなぁ・・・
PROCESS_VM_READのアクセス権回避
2012.03.05 *Mon
CreateProcessで、DACLに制限を加えて起動されたプロセスに対して、
PROCESS_VM_READのアクセス権を無視する方法があります。
キーワードはデバッグ特権。
SeDebugPrivilege
PROCESS_VM_READのアクセス権を無視する方法があります。
キーワードはデバッグ特権。
SeDebugPrivilege
keyboardクラスからのServiceCallback
2011.07.29 *Fri
kbfiltr のフィルタドライバを参考にして、
PS/2のキーボードで発生したキー入力がどのように上位に
通知されるか試してみました。
キー通知は、内部I/Oリクエストの時に登録した
ServiceCallback ルーチンが呼ばれます。
ServiceCallback ルーチンは、
VOID
KbFilter_ServiceCallback(
IN PDEVICE_OBJECT DeviceObject,
IN PKEYBOARD_INPUT_DATA InputDataStart,
IN PKEYBOARD_INPUT_DATA InputDataEnd,
IN OUT PULONG InputDataConsumed
)
の引数で通知があります。
InputDataStart: 最初のキー入力情報(KEYBOARD_INPUT_DATA構造体)のポインタ
InputDataEnd: 最後のキー入力情報(KEYBOARD_INPUT_DATA構造体)のポインタ
InputDataConsumed: キー入力情報の数へのポインタ
となっており、InputDataStart->InputDataEndの連続領域に*InputDataConsumed個の
キー情報があることになります。
試しに↑キーを押して内容を見てみます。
---
*** Kbfilter Inner Service Routine: start
KbFilter Inner Service Class size of KEYBOARD_INPUT_DATA: 12 bytes
KbFilter Inner Service Class DeviceObject: 0x87263b20
KbFilter Inner Service InputDataConsumed: 0x83164c74, value: 0
KbFilter Inner Service InputDataStart: 0x87341be0
KbFilter Inner Service InputDataEnd: 0x87341bec
KbFilter Inner Service(0) UnitID: 0x0
KbFilter Inner Service(0) MakeCode: 0x48
KbFilter Inner Service(0) Flags: 0x2
KbFilter Inner Service(0) Reserved: 0x0
KbFilter Inner Service(0) ExtraInformation: 0x0
KbFilter Inner Service(1) UnitID: 0x0
KbFilter Inner Service(1) MakeCode: 0x48
KbFilter Inner Service(1) Flags: 0x3
KbFilter Inner Service(1) Reserved: 0x0
KbFilter Inner Service(1) ExtraInformation: 0x0
*** Kbfilter Upper Service Callback Routine: called
*** Kbfilter Upper Service Callback Routine: end
---
まず1つ目。
KEYBOARD_INPUT_DATA構造体サイズが 12 bytes
StartとEndから、構造体が2つ分。
UnitID は デバイスごとに振られるIDだが1つしかないので常に0
MakeCodeは押されたキーのスキャンコード
Flagsは 0: KEY_MAKE(押)、1: KEY_BREAK(離)、
2: KEY_E0(拡張押)、3: KEY_E1(拡張離)
なので、
押されて離された状態がレポートされているのがわかる。
PS/2のキーボードで発生したキー入力がどのように上位に
通知されるか試してみました。
キー通知は、内部I/Oリクエストの時に登録した
ServiceCallback ルーチンが呼ばれます。
ServiceCallback ルーチンは、
VOID
KbFilter_ServiceCallback(
IN PDEVICE_OBJECT DeviceObject,
IN PKEYBOARD_INPUT_DATA InputDataStart,
IN PKEYBOARD_INPUT_DATA InputDataEnd,
IN OUT PULONG InputDataConsumed
)
の引数で通知があります。
InputDataStart: 最初のキー入力情報(KEYBOARD_INPUT_DATA構造体)のポインタ
InputDataEnd: 最後のキー入力情報(KEYBOARD_INPUT_DATA構造体)のポインタ
InputDataConsumed: キー入力情報の数へのポインタ
となっており、InputDataStart->InputDataEndの連続領域に*InputDataConsumed個の
キー情報があることになります。
試しに↑キーを押して内容を見てみます。
---
*** Kbfilter Inner Service Routine: start
KbFilter Inner Service Class size of KEYBOARD_INPUT_DATA: 12 bytes
KbFilter Inner Service Class DeviceObject: 0x87263b20
KbFilter Inner Service InputDataConsumed: 0x83164c74, value: 0
KbFilter Inner Service InputDataStart: 0x87341be0
KbFilter Inner Service InputDataEnd: 0x87341bec
KbFilter Inner Service(0) UnitID: 0x0
KbFilter Inner Service(0) MakeCode: 0x48
KbFilter Inner Service(0) Flags: 0x2
KbFilter Inner Service(0) Reserved: 0x0
KbFilter Inner Service(0) ExtraInformation: 0x0
KbFilter Inner Service(1) UnitID: 0x0
KbFilter Inner Service(1) MakeCode: 0x48
KbFilter Inner Service(1) Flags: 0x3
KbFilter Inner Service(1) Reserved: 0x0
KbFilter Inner Service(1) ExtraInformation: 0x0
*** Kbfilter Upper Service Callback Routine: called
*** Kbfilter Upper Service Callback Routine: end
---
まず1つ目。
KEYBOARD_INPUT_DATA構造体サイズが 12 bytes
StartとEndから、構造体が2つ分。
UnitID は デバイスごとに振られるIDだが1つしかないので常に0
MakeCodeは押されたキーのスキャンコード
Flagsは 0: KEY_MAKE(押)、1: KEY_BREAK(離)、
2: KEY_E0(拡張押)、3: KEY_E1(拡張離)
なので、
押されて離された状態がレポートされているのがわかる。
TableAdapter クエリ構成ウィザードでの引数順番
2011.05.19 *Thu
Visual Basic 2010 Express で TableAdapter をクエリウィザードで構成している場合、
関数の引数順番がクエリオプションの順番と異なる場合があるため備忘録。
構成ウィザードのクエリのプロパティにあるパラメータの設定で、
順序0:opt1、順序1:opt2、関数名func を設定し、
func(opt1, opt2) と指定すると、渡されたopt1とopt2が逆の順序で
SQLを実行されてしまいうまくいかない場合がある。
要は、クエリテキストに現れるパラメータの順番でopt1、opt2が割当られてしまうから。
例えば、以下の条件だと func(opt1, opt2) で指定してもうまくいかない。
SELECT UID, GID, UNAME, GNAME
FROM GroupMember
WHERE (GID=@opt2) AND (UID=@opt1)
※関数定義 func(opt1, opt2)
※クエリのパラメータプロパティの順番は 0: opt1, 1:opt2 と定義
これは、クエリの最初に現れる @opt2 がfuncの第1引数 opt1 に割当され、
@opt1が第2引数のopt2に割当されるから。
この場合、関数の引数と、SQL構文中の出現パラメータの順番が一致するよう変更する。
SELECT UID, GID, UNAME, GNAME
FROM GroupMember
WHERE (UID=@opt1) AND (GID=@opt2)
これは、VBの関数が生成されるときにSQL構文内の変数対応まで考慮してくれていない仕様だから。
実際にデバッグしてcommand.CommandText をみるとよくわかります。
関数の引数順番がクエリオプションの順番と異なる場合があるため備忘録。
構成ウィザードのクエリのプロパティにあるパラメータの設定で、
順序0:opt1、順序1:opt2、関数名func を設定し、
func(opt1, opt2) と指定すると、渡されたopt1とopt2が逆の順序で
SQLを実行されてしまいうまくいかない場合がある。
要は、クエリテキストに現れるパラメータの順番でopt1、opt2が割当られてしまうから。
例えば、以下の条件だと func(opt1, opt2) で指定してもうまくいかない。
SELECT UID, GID, UNAME, GNAME
FROM GroupMember
WHERE (GID=@opt2) AND (UID=@opt1)
※関数定義 func(opt1, opt2)
※クエリのパラメータプロパティの順番は 0: opt1, 1:opt2 と定義
これは、クエリの最初に現れる @opt2 がfuncの第1引数 opt1 に割当され、
@opt1が第2引数のopt2に割当されるから。
この場合、関数の引数と、SQL構文中の出現パラメータの順番が一致するよう変更する。
SELECT UID, GID, UNAME, GNAME
FROM GroupMember
WHERE (UID=@opt1) AND (GID=@opt2)
これは、VBの関数が生成されるときにSQL構文内の変数対応まで考慮してくれていない仕様だから。
実際にデバッグしてcommand.CommandText をみるとよくわかります。
WCHAR, TCHAR, char など文字列変換
2011.04.04 *Mon
デバイスドライバを作成していて、WCHAR やら TCHAR やら UNICODE やら
文字列を格納する方法が複数あってわけわかめになるときがありますので
まとめ。
---
char は 1バイト文字列を表現するために使用する。
WCHAR は マルチバイト(2バイト)文字列を表現するために使用する。
TCHARはというと、#define UNICODE をするとWCHARになり、
ないとcharになる。
TCHARを使用すれば容易に相互共用できるって所でしょう。
UNICODEは構造体であって、Length と WCHAR[...] をまとめたもの。
この構造体を初期化 または WCHAR配列から変換する関数として
RtlInitUnicodeStringを使用する。
// UNICODE_STRING DeviceName; WCHAR _DeviceName[256]
例:RtlInitUnicodeString(&DeviceName, _DeviceName);
--
書式付でUNICODEに格納するにはどうしたらよいか。
StringCbPrintfW で WCHAR 型配列を作成したあとに、
RtlInitUnicodeString で WCHAR から UNICODE に変換すればよい。
【サンプル例】
#define FILTER_DEVICE_NAME L"FLTDEV"
WCHAR _DeviceName[256];
int devNo;
// 書式付でWCHAR配列に格納する。
StringCbPrintfW(_DeviceName,
sizeof(_DeviceName),
L"\\Device\\%S%02d", ・・・(1)
FILTER_DEVICE_NAME, ・・・(2)
devNo-1);
UNICODE_STRING DeviceName;
// WCHAR型からUNICODE_STRINGに変換
RtlInitUnicodeString(&DeviceName, _DeviceName);
こんなかんじ。
ポイントは、書式指定でもマルチバイトを指定することと、
引数で指定する文字列配列は全て同じマルチバイトであること。
あと、L"文字列" での指定と TEXT(文字列)の違いについて。
L:WCHARの文字列
TEXT:TCHARの文字列
なので、展開すれば一緒になるかもだしならないかもだしだし。
文字列を格納する方法が複数あってわけわかめになるときがありますので
まとめ。
---
char は 1バイト文字列を表現するために使用する。
WCHAR は マルチバイト(2バイト)文字列を表現するために使用する。
TCHARはというと、#define UNICODE をするとWCHARになり、
ないとcharになる。
TCHARを使用すれば容易に相互共用できるって所でしょう。
UNICODEは構造体であって、Length と WCHAR[...] をまとめたもの。
この構造体を初期化 または WCHAR配列から変換する関数として
RtlInitUnicodeStringを使用する。
// UNICODE_STRING DeviceName; WCHAR _DeviceName[256]
例:RtlInitUnicodeString(&DeviceName, _DeviceName);
--
書式付でUNICODEに格納するにはどうしたらよいか。
StringCbPrintfW で WCHAR 型配列を作成したあとに、
RtlInitUnicodeString で WCHAR から UNICODE に変換すればよい。
【サンプル例】
#define FILTER_DEVICE_NAME L"FLTDEV"
WCHAR _DeviceName[256];
int devNo;
// 書式付でWCHAR配列に格納する。
StringCbPrintfW(_DeviceName,
sizeof(_DeviceName),
L"\\Device\\%S%02d", ・・・(1)
FILTER_DEVICE_NAME, ・・・(2)
devNo-1);
UNICODE_STRING DeviceName;
// WCHAR型からUNICODE_STRINGに変換
RtlInitUnicodeString(&DeviceName, _DeviceName);
こんなかんじ。
ポイントは、書式指定でもマルチバイトを指定することと、
引数で指定する文字列配列は全て同じマルチバイトであること。
あと、L"文字列" での指定と TEXT(文字列)の違いについて。
L:WCHARの文字列
TEXT:TCHARの文字列
なので、展開すれば一緒になるかもだしならないかもだしだし。

