вернуть два значения из удаленного потока (C, Windows) - PullRequest
0 голосов
/ 28 августа 2009

В настоящее время у меня есть поток, который я создал с помощью CreateRemoteThread (). Все отлично работает. После завершения (или ошибки до завершения) поток возвращает один из пяти определенных нами кодов возврата.

Я столкнулся с проблемой, и мне нужно также вернуть результаты GetLastError (). Есть ли способ вернуть два значения?

Я использую WaitForSingleObject (), а затем GetExitCodeThread (), чтобы получить значение выхода потока.

Причина, по которой мне нужны два значения (в отличие от возврата только GetLastError), заключается в том, что мне нужно знать, где в удаленном потоке произошла ошибка, и что возвращает первое значение.

код приветствуется.

Спасибо

Ответы [ 3 ]

2 голосов
/ 28 августа 2009

Перед запуском потока выделите структуру в куче с местом для параметров возврата ошибки. Передайте его потоку через аргумент lpParameter в CreateThread. До завершения оставьте там свои коды ошибок.

Тогда просто запомните расположение структуры в любом потоке, ожидающем этого потока, и прочитайте результаты оттуда.

Например:

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 голосов
/ 28 августа 2009

Один классический и ужасно уродливый способ вернуть два значения одновременно - это сдвиг и or в больший тип.

Например, чтобы вернуть два целых числа, вы можете сдвинуть одно из них на число битов в целом и or на другое значение.

Ваш телефонный код должен разделить все на части.

Конечно, только для экстренных случаев.

0 голосов
/ 28 августа 2009

Возвращает указатель на структуру, в которой есть необходимые поля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...