SSブログ

String buffers and IRQL [ドライバ開発]

String buffers and IRQL
http://blogs.msdn.com/doronh/archive/2006/03/03/543140.aspx

嘘訳
RtlString関数のほとんどはPASSIVE_LEVELでしか使えないと、WDKのドキュメントには書いてある。
これがRtlだけではなくCRTもそうではないのは、いくつか理由がある。

*Rtl関数はPAGEableと宣言されている。そのため関数は自分自身でさえも実行できない。
*UNICODE_STRING内のバッファはスタックベースではないなら普通はPagedPoolから確保される。
*NLSのような文字変換テーブルはPAGEableである

NonPagedPoolからバッファを確保するように作ることによって2つ目の弾丸をovercomeできるだろう。
しかし、そうしたとしてもsurrounding infrastructureのために、まったく助けにならない。
You can overcome the 2nd bullet by making sure your buffer allocations come from NonPagedPool, but that doesn't help you very much because the surrounding infrastructure.

しかし、ちょっと待って欲しい。ここにDISPATCH_LEVEL以上でも動くstrlenとsprintfを使ったサンプルがある。
ドライバの中でもっとも一般的に使われる関数はDbgPrintの機能を実装するのに使われる。

which is invoked like this PRINT(2, ("Number of instances %d\n", DevExt->NumInstances")); and this actually works.
以下のサンプルはPRINT(2, ("Number of instances %d\n", DevExt->NumInstances"));とのようにinvokedされ、そして問題なく動く。なぜだろうか?
なぜならformat stringに%sおよびそれに類するformat specifiersが含まれていないからである。
もし、%sを使おうとすると、aforementioned tableをヒットし、潜在的にpaged out pool(とbugcheck)をヒットすることになる
何が起きるのか? PASSIVE_LEVELより高いIRQLでは、デバッグ出力に文字(%sなど)を渡してはいけない。当然、なぜ高いIRQLで文字列を取り扱う必要があるのか良く考えなければならない。
比較やそれに似た操作はしないことを希望する?。
また、文字を使うところでWPPを使うことも考えたほうがいい。(なぜならWPPは文字列をコピーし、後でユーザーモードで処理するからである)


ところどころうまく訳せなかったが、ドライバ内で文字列を扱うときは、

・ドライバ内部の文字列操作は常にPASSIVEであることを前提にしている
 付随してASSERT(KeGetCurrentIrql()==PASSIVE_LEVEL)としておくのがいいだろう。
・PASSIVEでない場合には、本当にそこで文字列が必要か考えること(操作はしなくてもいいようにするとか、WPP?を使うなど)
・どーしてもRtl関数をPASSIVEより高いIRQLで使いたい場合は、フォーマット文字列に%sなどの文字列さえ使わなければ動いてくれる。

ドライバのサンプルなどで、よく文字列操作関数を自作しているのを見かけたが、DISPATCH_LEVELなどで動くように自作していたんだろう。 VOID MyPrint(PSTR Format, ...) { CHAR ach[128]; va_list va; NTSTATUS status; va_start(va, Format); status = RtlStringCbVPrintfA(ach, sizeof(ach), Format, va); if (NT_SUCCESS(status)) { DbgPrint(ach); } va_end(va); }
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。