.
This commit is contained in:
parent
95d74c2ef4
commit
a66e58193f
25 changed files with 2600 additions and 93 deletions
110
win/os_win32.c
110
win/os_win32.c
|
|
@ -1,6 +1,10 @@
|
|||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if COLLA_DEBUG
|
||||
#include <stdlib.h> // abort
|
||||
#endif
|
||||
|
||||
#include "../os.h"
|
||||
#include "../net.h"
|
||||
|
||||
|
|
@ -37,6 +41,8 @@ struct {
|
|||
os_entity_t *entity_free;
|
||||
oshandle_t hstdout;
|
||||
oshandle_t hstdin;
|
||||
WORD default_fg;
|
||||
WORD default_bg;
|
||||
} w32_data = {0};
|
||||
|
||||
os_entity_t *os__win_alloc_entity(os_entity_kind_e kind) {
|
||||
|
|
@ -77,14 +83,23 @@ void os_init(void) {
|
|||
|
||||
info->machine_name = str_from_tstr(&w32_data.arena, (tstr_t){ namebuf, namebuflen});
|
||||
|
||||
HANDLE hstdout = CreateFile(TEXT("CONOUT$"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
HANDLE hstdin = CreateFile(TEXT("CONIN$"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
HANDLE hstdout = CreateFile(TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
HANDLE hstdin = CreateFile(TEXT("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (hstdout == INVALID_HANDLE_VALUE) err("couldn't open CONOUT$");
|
||||
else w32_data.hstdout.data = (uptr)hstdout;
|
||||
|
||||
if (hstdin == INVALID_HANDLE_VALUE) err("couldn't open CONIN$");
|
||||
else w32_data.hstdin.data = (uptr)hstdin;
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO console_info = {0};
|
||||
if (GetConsoleScreenBufferInfo(hstdout, &console_info)) {
|
||||
w32_data.default_fg = console_info.wAttributes & 0x0F;
|
||||
w32_data.default_bg = (console_info.wAttributes & 0xF0) >> 4;
|
||||
}
|
||||
else {
|
||||
err("couldn't get console screen buffer info: %v", os_get_error_string(os_get_last_error()));
|
||||
}
|
||||
}
|
||||
|
||||
void os_cleanup(void) {
|
||||
|
|
@ -95,6 +110,9 @@ void os_cleanup(void) {
|
|||
}
|
||||
|
||||
void os_abort(int code) {
|
||||
#if COLLA_DEBUG
|
||||
if (code != 0) abort();
|
||||
#endif
|
||||
ExitProcess(code);
|
||||
}
|
||||
|
||||
|
|
@ -111,19 +129,21 @@ str_t os_get_error_string(iptr error) {
|
|||
DWORD chars;
|
||||
chars = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0, msgbuf, arrlen(msgbuf), NULL);
|
||||
if (chars == 0) {
|
||||
err("FormatMessageW: %ld", os_get_last_error());
|
||||
iptr fmt_error = os_get_last_error();
|
||||
if (fmt_error == ERROR_MR_MID_NOT_FOUND) {
|
||||
return str_fmt(&arena, "(unknown error: 0x%04x)", fmt_error);
|
||||
}
|
||||
err("FormatMessageW: %ld", fmt_error);
|
||||
return STR_EMPTY;
|
||||
}
|
||||
|
||||
debug("error: %zi 0x%zX", error, error);
|
||||
|
||||
// remove \r\n at the end
|
||||
return str_from_str16(&arena, str16_init(msgbuf, chars - 2));
|
||||
}
|
||||
|
||||
os_wait_t os_wait_on_handles(oshandle_t *handles, int count, bool wait_all, u32 milliseconds) {
|
||||
HANDLE win_handles[OS_MAX_WAITABLE_HANDLES] = {0};
|
||||
assert(count < MAXIMUM_WAIT_OBJECTS);
|
||||
colla_assert(count < MAXIMUM_WAIT_OBJECTS);
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
win_handles[i] = (HANDLE)(handles[i].data);
|
||||
|
|
@ -156,20 +176,16 @@ os_system_info_t os_get_system_info(void) {
|
|||
}
|
||||
|
||||
void os_log_set_colour(os_log_colour_e colour) {
|
||||
WORD attribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
switch (colour) {
|
||||
case LOG_COL_BLACK: attribute = 0; break;
|
||||
case LOG_COL_RED: attribute = FOREGROUND_RED; break;
|
||||
case LOG_COL_GREEN: attribute = FOREGROUND_GREEN; break;
|
||||
case LOG_COL_BLUE: attribute = FOREGROUND_BLUE; break;
|
||||
case LOG_COL_MAGENTA: attribute = FOREGROUND_RED | FOREGROUND_BLUE; break;
|
||||
case LOG_COL_YELLOW: attribute = FOREGROUND_RED | FOREGROUND_GREEN; break;
|
||||
case LOG_COL_CYAN: attribute = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
|
||||
default: break;
|
||||
}
|
||||
WORD attribute = colour == LOG_COL_RESET ? w32_data.default_fg : (WORD)colour;
|
||||
SetConsoleTextAttribute((HANDLE)w32_data.hstdout.data, attribute);
|
||||
}
|
||||
|
||||
HANDLE hc = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleTextAttribute(hc, attribute | FOREGROUND_INTENSITY);
|
||||
void os_log_set_colour_bg(os_log_colour_e foreground, os_log_colour_e background) {
|
||||
WORD fg_attr = foreground == LOG_COL_RESET ? w32_data.default_fg : (WORD)foreground;
|
||||
WORD bg_attr = (background == LOG_COL_RESET ? w32_data.default_bg : (WORD)background) << 4;
|
||||
|
||||
WORD attribute = fg_attr | bg_attr;
|
||||
SetConsoleTextAttribute((HANDLE)w32_data.hstdout.data, attribute);
|
||||
}
|
||||
|
||||
oshandle_t os_stdout(void) {
|
||||
|
|
@ -206,6 +222,26 @@ bool os_file_exists(strview_t path) {
|
|||
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
bool os_dir_exists(strview_t folder) {
|
||||
OS_SMALL_SCRATCH();
|
||||
tstr_t name = strv_to_tstr(&scratch, folder);
|
||||
DWORD attributes = GetFileAttributes(name.buf);
|
||||
return attributes != INVALID_FILE_ATTRIBUTES && attributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
|
||||
bool os_file_or_dir_exists(strview_t path) {
|
||||
OS_SMALL_SCRATCH();
|
||||
tstr_t name = strv_to_tstr(&scratch, path);
|
||||
DWORD attributes = GetFileAttributes(name.buf);
|
||||
return attributes != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
bool os_dir_create(strview_t folder) {
|
||||
OS_SMALL_SCRATCH();
|
||||
tstr_t name = strv_to_tstr(&scratch, folder);
|
||||
return CreateDirectory(name.buf, NULL);
|
||||
}
|
||||
|
||||
tstr_t os_file_fullpath(arena_t *arena, strview_t filename) {
|
||||
OS_SMALL_SCRATCH();
|
||||
|
||||
|
|
@ -232,6 +268,12 @@ bool os_file_delete(strview_t path) {
|
|||
return DeleteFile(fname.buf);
|
||||
}
|
||||
|
||||
bool os_dir_delete(strview_t path) {
|
||||
OS_SMALL_SCRATCH();
|
||||
tstr_t fname = strv_to_tstr(&scratch, path);
|
||||
return RemoveDirectory(fname.buf);
|
||||
}
|
||||
|
||||
oshandle_t os_file_open(strview_t path, filemode_e mode) {
|
||||
OS_SMALL_SCRATCH();
|
||||
|
||||
|
|
@ -364,9 +406,15 @@ dir_entry_t os__dir_entry_from_find_data(arena_t *arena, WIN32_FIND_DATA *fd) {
|
|||
}
|
||||
|
||||
dir_t *os_dir_open(arena_t *arena, strview_t path) {
|
||||
usize prev = arena_tell(arena);
|
||||
dir_t* ctx = alloc(arena, dir_t);
|
||||
|
||||
arena_t scratch = *arena;
|
||||
#if 0
|
||||
u8 tmpbuf[KB(1)] = {0};
|
||||
arena_t scratch = arena_make(ARENA_STATIC, sizeof(tmpbuf), tmpbuf);
|
||||
|
||||
#endif
|
||||
|
||||
tstr_t winpath = strv_to_tstr(&scratch, path);
|
||||
// get a little extra leeway
|
||||
TCHAR fullpath[MAX_PATH + 16] = {0};
|
||||
|
|
@ -378,11 +426,10 @@ dir_t *os_dir_open(arena_t *arena, strview_t path) {
|
|||
fullpath[pathlen++] = '*';
|
||||
fullpath[pathlen++] = '\0';
|
||||
|
||||
dir_t *ctx = alloc(arena, dir_t);
|
||||
ctx->handle = FindFirstFile(fullpath, &ctx->find_data);
|
||||
|
||||
if (ctx->handle == INVALID_HANDLE_VALUE) {
|
||||
arena_pop(arena, sizeof(dir_t));
|
||||
arena_rewind(arena, prev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -551,8 +598,15 @@ bool os_process_wait(oshandle_t proc, uint time, int *out_exit) {
|
|||
return exit_status == 0;
|
||||
}
|
||||
|
||||
// == MEMORY ====================================
|
||||
|
||||
// == VMEM ======================================
|
||||
void *os_alloc(usize size) {
|
||||
return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void os_free(void *ptr) {
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
void *os_reserve(usize size, usize *out_padded_size) {
|
||||
usize alloc_size = os_pad_to_page(size);
|
||||
|
|
@ -605,11 +659,15 @@ bool os_thread_detach(oshandle_t thread) {
|
|||
bool os_thread_join(oshandle_t thread, int *code) {
|
||||
if (!os_handle_valid(thread)) return false;
|
||||
os_entity_t *entity = (os_entity_t *)thread.data;
|
||||
int return_code = WaitForSingleObject(entity->thread.handle, INFINITE);
|
||||
if (code) *code = return_code;
|
||||
DWORD wait_result = WaitForSingleObject(entity->thread.handle, INFINITE);
|
||||
if (code) {
|
||||
DWORD exit_code = 0;
|
||||
GetExitCodeThread(entity->thread.handle, &exit_code);
|
||||
*code = exit_code;
|
||||
}
|
||||
BOOL result = CloseHandle(entity->thread.handle);
|
||||
os__win_free_entity(entity);
|
||||
return return_code != WAIT_FAILED && result;
|
||||
return wait_result != WAIT_FAILED && result;
|
||||
}
|
||||
|
||||
u64 os_thread_get_id(oshandle_t thread) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue