mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-10-28 21:25:06 +00:00
88 lines
3.6 KiB
C
88 lines
3.6 KiB
C
#include <windows.h>
|
|
|
|
static int *(__cdecl *error_value)(void);
|
|
static unsigned long *(__cdecl *dos_value)(void);
|
|
static int (__cdecl *get_dos)(unsigned long *);
|
|
static int (__cdecl *set_dos)(unsigned long);
|
|
static int (__cdecl *open_file)(const char *, int, ...);
|
|
static int (__cdecl *close_file)(int);
|
|
static HANDLE start, release, ready[2];
|
|
static int *main_error;
|
|
static unsigned long *main_dos;
|
|
|
|
static DWORD WINAPI thread_errors(void *argument)
|
|
{
|
|
unsigned index = (unsigned)(ULONG_PTR)argument;
|
|
if (WaitForSingleObject(start, 5000) != WAIT_OBJECT_0) return 10;
|
|
int *error = error_value();
|
|
unsigned long *dos = dos_value();
|
|
if (*error || *dos || error == main_error || dos == main_dos) return 11;
|
|
*error = 40 + index;
|
|
*dos = 0x80000000UL + index;
|
|
SetEvent(ready[index]);
|
|
if (WaitForSingleObject(release, 5000) != WAIT_OBJECT_0) return 12;
|
|
unsigned long value;
|
|
if (error_value() != error || dos_value() != dos || *error != 40 + index ||
|
|
get_dos(&value) || value != 0x80000000UL + index) return 13;
|
|
return 0;
|
|
}
|
|
|
|
int raven_entry(void)
|
|
{
|
|
HANDLE threads[2];
|
|
start = CreateEventW(NULL, TRUE, FALSE, NULL);
|
|
release = CreateEventW(NULL, TRUE, FALSE, NULL);
|
|
if (!start || !release) return 1;
|
|
for (unsigned index = 0; index < 2; ++index) {
|
|
ready[index] = CreateEventW(NULL, TRUE, FALSE, NULL);
|
|
threads[index] = CreateThread(NULL, 0, thread_errors, (void *)(ULONG_PTR)index, 0, NULL);
|
|
if (!ready[index] || !threads[index]) return 1;
|
|
}
|
|
/* Loading after thread creation also exercises the DLL's TLS allocation for existing threads. */
|
|
HMODULE crt = LoadLibraryA("msvcrt.dll");
|
|
if (!crt) return 2;
|
|
error_value = (void *)GetProcAddress(crt, "_errno");
|
|
dos_value = (void *)GetProcAddress(crt, "__doserrno");
|
|
get_dos = (void *)GetProcAddress(crt, "_get_doserrno");
|
|
set_dos = (void *)GetProcAddress(crt, "_set_doserrno");
|
|
open_file = (void *)GetProcAddress(crt, "_open");
|
|
close_file = (void *)GetProcAddress(crt, "_close");
|
|
if (!error_value || !dos_value || !get_dos || !set_dos || !open_file || !close_file) return 3;
|
|
main_error = error_value();
|
|
main_dos = dos_value();
|
|
if (*main_error || *main_dos) return 4;
|
|
*main_error = 123;
|
|
if (set_dos(0xffffffffUL) || *main_dos != 0xffffffffUL) return 5;
|
|
SetEvent(start);
|
|
for (unsigned index = 0; index < 2; ++index)
|
|
if (WaitForSingleObject(ready[index], 5000) != WAIT_OBJECT_0) return 6;
|
|
unsigned long value;
|
|
if (*main_error != 123 || get_dos(&value) || value != 0xffffffffUL) return 7;
|
|
if (get_dos(NULL) != 22 || *main_error != 22 || *main_dos != 0xffffffffUL) return 8;
|
|
char path[MAX_PATH];
|
|
GetTempPathA(MAX_PATH, path);
|
|
char file[MAX_PATH];
|
|
if (!GetTempFileNameA(path, "crt", 0, file) || !DeleteFileA(file)) return 14;
|
|
if (open_file(file, 0x8000) != -1 || *main_error != 2 || *main_dos != ERROR_FILE_NOT_FOUND) return 15;
|
|
int fd = open_file(file, 0x8101, 0600);
|
|
if (fd < 0 || *main_error != 2 || *main_dos != ERROR_FILE_NOT_FOUND) return 16;
|
|
if (close_file(fd) || !DeleteFileA(file)) return 17;
|
|
SetEvent(release);
|
|
for (unsigned index = 0; index < 2; ++index) {
|
|
DWORD code;
|
|
if (WaitForSingleObject(threads[index], 5000) != WAIT_OBJECT_0 ||
|
|
!GetExitCodeThread(threads[index], &code) || code) return 18;
|
|
CloseHandle(threads[index]);
|
|
}
|
|
HANDLE fresh = CreateThread(NULL, 0, thread_errors, NULL, 0, NULL);
|
|
DWORD code;
|
|
if (!fresh || WaitForSingleObject(fresh, 5000) != WAIT_OBJECT_0 ||
|
|
!GetExitCodeThread(fresh, &code) || code || *main_error != 2 || *main_dos != ERROR_FILE_NOT_FOUND) return 19;
|
|
CloseHandle(fresh);
|
|
for (unsigned index = 0; index < 2; ++index)
|
|
CloseHandle(ready[index]);
|
|
CloseHandle(start);
|
|
CloseHandle(release);
|
|
return 0;
|
|
}
|