別のプロセスでホストされたインターフェイスと Windows RPC メカニズムを介して通信するアプリケーションを作成しています。
マーシャリングは、標準の組み込み NDR によって処理されます。インターフェイスはいくつかの関数を公開しますが、そのうちの 1 つUNICODE_STRING
はパラメーターを介して文字列 ( ) を返します。
この関数は、成功した場合は 0 を返し、それ以外の場合はエラー コードを返します。RPC 関数を呼び出すと、成功し、UNICODE_STRING パラメータが設定されます。
問題は、C++ またはランタイムのいずれかが、関数によって返された文字列を読み取ろうとしているときに発生するエラーを飲み込むことです。多くのコードを読む手間を省くために、私のコードの簡略版を次に示します。
void func()
{
UNICODE_STRING unicode_str;
HMODULE hLib = LoadLibrary(L"Ntdll.dll");
RtlInitUnicodeStringFn fn;
fn = (RtlInitUnicodeStringFn) GetProcAddress(hLib, "RtlInitUnicodeString");
fn(&unicode_str, NULL);
std::cout << "Before calling RPC the buffer was pointing at: " << std::hex << unicode_str.Buffer << std::endl;
if(call(binding.get_binding_handle(), &unicode_str))
{
std::cout << "len: " << unicode_str.Length << " maxlen: " << unicode_str.MaximumLength << std::endl;
std::cout << "After calling RPC the buffer is pointing at: " << std::hex << unicode_str.Buffer << std::endl;
try
{
for(int i = 0; i < unicode_str.Length; i++)
std::wcout << i << ": " << unicode_str.Buffer[i] << std::endl;
}
catch(...)
{
std::cout << "Caught an exception";
}
std::wcout << "I won't be written" << std::endl;
}
}
bool call(void* handle, PUNICODE_STRING str)
{
__try
{
std::cout << "RPC call returned: " << RpcInterfaceFunction(handle, str) << std::endl;
return true;
}
__except(1)
{
std::cout << "Error: " << std::dec << GetExceptionCode() << std::endl;
return false;
}
}
このコードを実行すると、出力は次のようになります。
Before calling RPC the buffer is pointing at : 000000000
RPC call returned: 0
len:68, maxlen: 70
After calling RPC the buffer is pointing at: 00746168
0: #
1: t
2:
そして戻ります。私はこの関数をデバッガーでステップ実行しましたが、68 文字全体を正しく処理し (バッファーの内容に関係なく、ガベージ データです)、最後のI won't be written
wcout 命令に正しくステップインします。コンソールが処理できない判読不能な文字に問題があり、これらの文字が次の文字の動作またはコンソールカーソルを変更する可能性があるかどうか疑問に思いました-それは出力を非表示にしますが、いいえ-出力ストリームを交換して設定しましたファイル (wofstream) に出力し、ファイルのサイズは 47 バイトでした。これは、コンソール ストリームに書き込まれるサイズとまったく同じです。
アクセス違反、例外、ログ エントリなどはありません。デバッガー (VS2010) でさえ、考えられるすべての種類の例外で中断することを選択した後、例外に注意しません。さらに驚くべきことは、デバッガーでコードをステップ実行し、そこでローカルを監視すると、期待値が得られることです (私は 0 から68 に変更され、バッファー内の現在の wchar_t には値 (ガベージ Unicode char) があります。
誰でもこの動作を説明できますか?
編集:
印刷ループを次のように交換します。
for(int i = 0; i < unicode_str.Length; i++)
{
std::wcout << "I'm writing the " << i << "th character" << std::endl;
unsigned short temp = unicode_str.Buffer[i];
std::wcout << i << ": " << temp << std::endl;
}
67 までの値をtemp
正しく出力します。
それでも、これらの文字の wchar_t バージョンを出力すると、出力ストリームが何も受け入れなくなるのはなぜでしょうか?