Working on rendering
This commit is contained in:
206
src/basic/win32.cpp
Normal file
206
src/basic/win32.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
#include "filesystem.h"
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Basic begin
|
||||
void *VReserve(size_t size) {
|
||||
void *result = (uint8_t *)VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool VCommit(void *p, size_t size) {
|
||||
void *result = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
return result ? true : false;
|
||||
}
|
||||
|
||||
bool VRelease(void *p) {
|
||||
BOOL result = VirtualFree(p, 0, MEM_RELEASE);
|
||||
return result ? true : false;
|
||||
}
|
||||
|
||||
bool VDecommit(void *p, size_t size) {
|
||||
BOOL result = VirtualFree(p, size, MEM_DECOMMIT);
|
||||
return result ? true : false;
|
||||
}
|
||||
// Basic end
|
||||
|
||||
Process RunEx(String args) {
|
||||
Scratch scratch;
|
||||
wchar_t *application_name = NULL;
|
||||
wchar_t *cmd = ToWidechar(scratch, args);
|
||||
BOOL inherit_handles = FALSE;
|
||||
DWORD creation_flags = 0;
|
||||
void *enviroment = NULL;
|
||||
wchar_t *working_dir = NULL;
|
||||
STARTUPINFOW startup_info = {};
|
||||
startup_info.cb = sizeof(STARTUPINFOW);
|
||||
Process result = {};
|
||||
Assert(sizeof(result.platform) >= sizeof(PROCESS_INFORMATION));
|
||||
PROCESS_INFORMATION *process_info = (PROCESS_INFORMATION *)result.platform;
|
||||
BOOL success = CreateProcessW(application_name, cmd, NULL, NULL, inherit_handles, creation_flags, enviroment, working_dir, &startup_info, process_info);
|
||||
result.is_valid = true;
|
||||
if (!success) {
|
||||
result.is_valid = false;
|
||||
|
||||
LPVOID lpMsgBuf;
|
||||
DWORD dw = GetLastError();
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
|
||||
LocalFree(lpMsgBuf);
|
||||
|
||||
printf("Failed to create process \ncmd: %.*s\nwindows_message: %s", FmtString(args), (char *)lpMsgBuf);
|
||||
Assert(!"Failed to create process");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Wait(Process *process) {
|
||||
Assert(process->is_valid);
|
||||
PROCESS_INFORMATION *pi = (PROCESS_INFORMATION *)process->platform;
|
||||
WaitForSingleObject(pi->hProcess, INFINITE);
|
||||
|
||||
DWORD exit_code;
|
||||
BOOL err = GetExitCodeProcess(pi->hProcess, &exit_code);
|
||||
Assert(err != 0);
|
||||
|
||||
CloseHandle(pi->hProcess);
|
||||
CloseHandle(pi->hThread);
|
||||
process[0] = {};
|
||||
return (int)exit_code;
|
||||
}
|
||||
|
||||
bool InitOS() {
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
||||
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hOut != INVALID_HANDLE_VALUE) {
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(hOut, &dwMode)) {
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
if (SetConsoleMode(hOut, dwMode)) {
|
||||
return true;
|
||||
} else {
|
||||
printf("Failed to enable colored terminal output C\n");
|
||||
}
|
||||
} else {
|
||||
printf("Failed to enable colored terminal output B\n");
|
||||
}
|
||||
} else {
|
||||
printf("Failed to enable colored terminal output A\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String ReadFile(Allocator arena, String path) {
|
||||
bool success = false;
|
||||
String result = {};
|
||||
|
||||
wchar_t wpath[1024];
|
||||
CreateWidecharFromChar(wpath, Lengthof(wpath), path.data, path.len);
|
||||
HANDLE handle = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
LARGE_INTEGER file_size;
|
||||
if (GetFileSizeEx(handle, &file_size)) {
|
||||
if (file_size.QuadPart != 0) {
|
||||
result.len = (int64_t)file_size.QuadPart;
|
||||
result.data = (char *)AllocSize(arena, result.len + 1);
|
||||
DWORD read;
|
||||
if (ReadFile(handle, result.data, (DWORD)result.len, &read, NULL)) { // @todo: can only read 32 byte size files?
|
||||
if (read == result.len) {
|
||||
success = true;
|
||||
result.data[result.len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Dealloc(arena, &result.data);
|
||||
result = {};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct Win32_FileIter {
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW data;
|
||||
} Win32_FileIter;
|
||||
|
||||
String GetAbsolutePath(Allocator arena, String relative) {
|
||||
wchar_t wpath[1024];
|
||||
CreateWidecharFromChar(wpath, Lengthof(wpath), relative.data, relative.len);
|
||||
wchar_t wpath_abs[1024];
|
||||
DWORD written = GetFullPathNameW((wchar_t *)wpath, Lengthof(wpath_abs), wpath_abs, 0);
|
||||
if (written == 0)
|
||||
return {};
|
||||
String path = ToString(arena, {(wchar_t *)wpath_abs, written});
|
||||
NormalizePathInPlace(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
bool IsValid(const FileIter &it) {
|
||||
return it.is_valid;
|
||||
}
|
||||
|
||||
void Advance(FileIter *it) {
|
||||
if (it->temp.arena) EndTemp(it->temp);
|
||||
it->temp = BeginTemp(it->arena);
|
||||
while (FindNextFileW(it->w32->handle, &it->w32->data) != 0) {
|
||||
WIN32_FIND_DATAW *data = &it->w32->data;
|
||||
|
||||
// Skip '.' and '..'
|
||||
if (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0) continue;
|
||||
if (data->cFileName[0] == '.' && data->cFileName[1] == 0) continue;
|
||||
|
||||
it->is_directory = data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
it->filename = ToString(*it->arena, (wchar_t *)data->cFileName, WideLength(data->cFileName));
|
||||
const char *is_dir = it->is_directory ? "/" : "";
|
||||
const char *separator = it->path.data[it->path.len - 1] == '/' ? "" : "/";
|
||||
it->relative_path = Format(*it->arena, "%.*s%s%.*s%s", FmtString(it->path), separator, FmtString(it->filename), is_dir);
|
||||
it->absolute_path = GetAbsolutePath(*it->arena, it->relative_path);
|
||||
it->is_valid = true;
|
||||
|
||||
if (it->is_directory) {
|
||||
Assert(it->relative_path.data[it->relative_path.len - 1] == '/');
|
||||
Assert(it->absolute_path.data[it->absolute_path.len - 1] == '/');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
it->is_valid = false;
|
||||
DWORD error = GetLastError();
|
||||
Assert(error == ERROR_NO_MORE_FILES);
|
||||
FindClose(it->w32->handle);
|
||||
Dealloc(it->allocator, &it->arena);
|
||||
}
|
||||
|
||||
FileIter IterateFiles(Allocator alo, String path) {
|
||||
FileIter it = {0};
|
||||
it.allocator = alo;
|
||||
it.arena = AllocArena(alo, MiB(2));
|
||||
it.path = path;
|
||||
|
||||
String modified_path = Format(*it.arena, "%.*s\\*", FmtString(path));
|
||||
String16 modified_path16 = ToString16(*it.arena, modified_path);
|
||||
|
||||
it.w32 = AllocType(*it.arena, Win32_FileIter);
|
||||
it.w32->handle = FindFirstFileW(modified_path16.data, &it.w32->data);
|
||||
if (it.w32->handle == INVALID_HANDLE_VALUE) {
|
||||
it.is_valid = false;
|
||||
return it;
|
||||
}
|
||||
|
||||
Assert(it.w32->data.cFileName[0] == '.' && it.w32->data.cFileName[1] == 0);
|
||||
Advance(&it);
|
||||
return it;
|
||||
}
|
||||
Reference in New Issue
Block a user