darkelf, 
в основном модуле программы (тот, который станет .exe) надо сделать дырку (backdoor):
__declspec(dllexport) void set_errno(int code) {
    errno = code;
}В dll при подключении к процессу надо извлечь из модуля программы указатель на эту функцию.
typedef void (*SETINT)(int);
SETINT g_set_errno = NULL;
void set_errno_in_exe(int code) {
    if (g_set_errno != NULL) g_set_errno(code);
}
BOOL WINAPI DllMain(
  HINSTANCE hinstDLL, 
  DWORD fdwReason,  
  LPVOID lpvReserved 
)
{
    HANDLE hModule; // Handle to the main module
    if ( fdwReason == DLL_PROCESS_ATTACH ) {
        hModule = GetModuleHandle(NULL);
        if (hModule == NULL) return FALSE;
        g_set_errno = (SETINT) GetProcAddress(hModule, "set_errno");
    }
    return TRUE;
}
В нужном месте в dll вместо присваивания errno нужно вызывать внешнюю функцию
void inside_dll_func() {
    // bla-bla-bla
    set_errno_in_exe(ERROR_CODE);
    // foo-foo
}Проблема вызвана тем, что каждая влинкованная libc (одна линкуется в  исполняемый файл, ещё одна в dll) содержит свою копию errno.  Поэтому приходится пробивать дырку в адресное пространство исполняемого файла чтобы установить errno для него.