Before starting the thread, allocate a structure on the heap with room for the error return parameters. Pass it to the thread via the lpParameter argument of CreateThread. Prior to termination, leave your error codes there.
Then just remember the location of the structure in whatever thread's waiting for this thread, and read the results out of there.
For example:
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);
}
If you're talking to a remote thread, one option may be to pass a handle to a shared memory segment as lpParameter. You can inject the handle into the remote process via DuplicateHandle
, then start up the thread. The thread can then, before returning, map the shared memory segment (if it hasn't already), place its results into the shared memory segment, then unmap it and close the handle.
For example, in the remote process:
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;
}
And in the calling process:
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);