2009-08-28 11 views
0

現在、CreateRemoteThread()を使用して作成したスレッドがあります。すべて素晴らしいです。 終了時(または完了前にエラーが発生した場合)、スレッドは定義した5つの戻りコードのいずれかを返します。リモートスレッドから2つの値を返します。(C、windows)

問題が発生し、GetLastError()の結果も返す必要があります。 2つの値を返す方法はありますか?

私はWaitForSingleObject()とGetExitCodeThread()を使用してスレッドの終了値を取得しています。

2つの値を必要とする理由は(GetLastErrorのみを返すのとは対照的に)、リモートスレッドのどこでエラーが発生したかを知る必要があり、それが第1の値によって返されるためです。

コードをいただければ幸いです。

ありがとう

答えて

2

スレッドを開始する前に、ヒープに構造体を割り当て、エラーリターンパラメータを格納します。それをCreateThreadのlpParameter引数を介してスレッドに渡します。終了する前に、エラーコードをそこに残しておきます。

このスレッドを待っているスレッドの構造体の位置を覚えておき、そこから結果を読み込みます。例えば

:リモートスレッドに話をしている場合は

struct threadinfo { 
    void *someArgument; 
    DWORD error_code; 
    int error_flag; 
}; 

DWORD WINAPI threadproc(LPVOID arg) { 
    struct threadinfo *ti = (struct threadinfo *)arg; 
    // do things using ti->someArgument 
    ti->error_code = GetLastError(); 
    ti->error_flag = 42; 
    return 0; // return code ignored 
} 

void start_and_wait() { 
    struct threadinfo *ti = (struct threadinfo *)malloc(sizeof(*ti)); 
    ti->someArgument = &something; 

    HANDLE hThread = CreateThread(NULL, 0, threadproc, (LPVOID)ti, 0, NULL); 
    WaitForSingleObject(hThread, INFINITE); 
    CloseHandle(hThread); 

    printf("Exit code %08x, flag %d\n", ti->error_code, ti->error_flag); 
    free((void*)ti); 
} 

、一つの選択肢はlpParameterなどの共有メモリ・セグメントへのハンドルを渡すことがあります。ハンドルをDuplicateHandle経由でリモートプロセスに注入してから、スレッドを起動することができます。スレッドは、戻される前に共有メモリー・セグメントをマップし(まだない場合)、その結果を共有メモリー・セグメントに入れてから、マップ解除してハンドルを閉じることができます。

例えば

、リモートプロセス内:

DWORD WINAPI threadproc(LPVOID arg) { 
    LPVOID shmem = MapViewOfFile((HANDLE)arg, FILE_MAP_ALL_ACCESS, 0, 0, 4096); 
    struct threadinfo *ti = (struct threadinfo *)shmem; 

    // do stuff 
    ti->error_code = GetLastError(); 
    ti->error_flag = 42; 

    UnmapViewOfFile(shmem); 
    CloseHandle((HANDLE)arg); 
    return 0; 
} 

そして、呼び出し元のプロセスで:

HANDLE mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL); 
LPVOID shmem = MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 4096); 
struct threadinfo *ti = (struct threadinfo *)shmem; 
ti->someArgument = ...; 

HANDLE remote_handle; 
DuplicateHandle(GetCurrentProcess(), mapping, hRemoteProcess, &remote_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); 
HANDLE hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, startAddress, remote_handle, 0, NULL); 

WaitForSingleObject(hRemoteThread); 
printf("err %08x flag %d\n", ti->error_code, ti->error_flag); 
UnmapViewOfFile(shmem); 
CloseHandle(mapping); 
+0

構造体へのポインタをリモートスレッドに渡すことはできますか? – wonderer

+0

ああ、私は参照してください。私はCreateThreadではなくCreateRemoteThread()を使用しています。スレッドは別のプロセスのコンテキストで実行されるので、私は構造体へのポインタを送ることができないと思う。 – wonderer

+0

ああ、申し訳ありません - それを見ませんでした。この技術は共有メモリを使用しても動作します。 – bdonlan

0

必要なフィールドを持つ構造体へのポインタを返します。

+1

これは64ビットでは機能しません。スレッド戻りコードはDWORDで、DWORDは32ビット幅であるため、64ビットポインタを保持するには小さすぎます。 – bdonlan

+0

ああ。その場合は、bdonlanの提案を使用してください。 –

0

一つの古典的な、そしてひどく醜い、一度に2つの値を返す方法をシフトすることで、 orをより大きなタイプに変換します。

たとえば、2つのintを返すには、intのビット数を1つ上にシフトし、もう一方の値をorに設定します。

あなたの呼び出しコードは、その部分を引き離さなければなりません。

もちろん、緊急の場合のみです。

+0

ここで緊急事態はありません。エラーコードがDWORDの32ビットすべてを使用するとどうなりますか? – bdonlan

+0

あなたは運がありません。それはひどい解決策です。私は人生で2,3の緊急事態を抱えていましたが、あなたが住んでいる場所に緊急事態がなければ、忘れてはいけません。 :-) – Nosredna

関連する問題