Get latest upstream changes from internal project
This commit is contained in:
+1482
-885
File diff suppressed because it is too large
Load Diff
+1231
-1027
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,8 @@
|
||||
#include <dirent.h> // readdir, opendir, closedir
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h> // realpath
|
||||
#include <unistd.h> // sysconf, readlink
|
||||
|
||||
// NOTE: DN_OSMem
|
||||
static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect)
|
||||
@@ -241,6 +243,23 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSMemoryInfo DN_OS_MemoryInfo()
|
||||
{
|
||||
DN_OSMemoryInfo result = {};
|
||||
#if defined(DN_PLATFORM_POSIX)
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
long pages = sysconf(_SC_PHYS_PAGES);
|
||||
long avail_pages = sysconf(_SC_AVPHYS_PAGES);
|
||||
if (page_size > 0 && pages > 0) {
|
||||
result.success = true;
|
||||
result.total_phys = DN_Cast(DN_U64) pages * DN_Cast(DN_U64) page_size;
|
||||
if (avail_pages > 0)
|
||||
result.avail_phys = DN_Cast(DN_U64) avail_pages * DN_Cast(DN_U64) page_size;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_Str8 DN_OS_ExePath(DN_Arena *arena)
|
||||
{
|
||||
DN_Str8 result = {};
|
||||
@@ -597,6 +616,23 @@ DN_API bool DN_OS_PathDelete(DN_Str8 path)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSPathResult DN_OS_PathCanonicalise(DN_Arena *arena, DN_Str8 path, DN_ErrSink *error)
|
||||
{
|
||||
DN_OSPathResult result = {};
|
||||
DN_TcScratch scratch = DN_TcScratchBeginArena(&arena, 1);
|
||||
DN_Str8 path_cstr = DN_Str8FromStr8Arena(path, &scratch.arena); // Ensure null-terminated
|
||||
char *resolved = realpath(path_cstr.data, NULL);
|
||||
if (resolved != NULL) {
|
||||
result.success = true;
|
||||
result.path = DN_Str8FromCStr8Arena(resolved, arena);
|
||||
free(resolved); // realpath allocates with malloc
|
||||
} else {
|
||||
DN_ErrSinkAppendF(error, errno, "Failed to canonicalise path: %s", strerror(errno));
|
||||
}
|
||||
DN_TcScratchEnd(&scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIsFile(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -1277,14 +1313,20 @@ DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv)
|
||||
DN_API DN_OSWindowMinimise DN_OS_WindowIsMinimised(DN_OSWindow *window)
|
||||
{
|
||||
(void)window;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
DN_AssertInvalidCodePath;
|
||||
#endif
|
||||
return DN_OSWindowMinimise_No;
|
||||
}
|
||||
|
||||
DN_API DN_OSWindowMaximise DN_OS_WindowIsMaximised(DN_OSWindow *window)
|
||||
{
|
||||
(void)window;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
DN_AssertInvalidCodePath;
|
||||
#endif
|
||||
return DN_OSWindowMaximise_No;
|
||||
}
|
||||
|
||||
@@ -1292,32 +1334,47 @@ DN_API void DN_OS_WindowSetTitle(DN_OSWindow *window, DN_Str8 title)
|
||||
{
|
||||
(void)window;
|
||||
(void)title;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
DN_AssertInvalidCodePath;
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API void DN_OS_WindowShow(DN_OSWindow *window, DN_OSWindowShow show)
|
||||
{
|
||||
(void)window;
|
||||
(void)show;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
DN_AssertInvalidCodePath;
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API void DN_OS_WindowBringToFront(DN_OSWindow *window)
|
||||
{
|
||||
(void)window;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
DN_AssertInvalidCodePath;
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API void DN_OS_WindowFocus(DN_OSWindow *window)
|
||||
{
|
||||
(void)window;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
DN_AssertInvalidCodePath;
|
||||
#endif
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_WindowIsFocused(DN_OSWindow *window)
|
||||
{
|
||||
(void)window;
|
||||
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
||||
#else
|
||||
DN_AssertInvalidCodePath;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+183
-91
@@ -5,7 +5,8 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// NOTE: DN_Mem
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN OS layer implementation
|
||||
static DN_U32 DN_OS_MemConvertPageToOSFlags_(DN_U32 protect)
|
||||
{
|
||||
DN_Assert((protect & ~DN_MemPage_All) == 0);
|
||||
@@ -231,6 +232,21 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSMemoryInfo DN_OS_MemoryInfo()
|
||||
{
|
||||
DN_OSMemoryInfo result = {};
|
||||
MEMORYSTATUSEX status = {};
|
||||
status.dwLength = sizeof(status);
|
||||
if (GlobalMemoryStatusEx(&status)) {
|
||||
result.success = true;
|
||||
result.total_phys = status.ullTotalPhys;
|
||||
result.avail_phys = status.ullAvailPhys;
|
||||
result.total_virtual = status.ullTotalVirtual;
|
||||
result.avail_virtual = status.ullAvailVirtual;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_SetEnvVar(DN_Str8 name, DN_Str8 value)
|
||||
{
|
||||
DN_TcScratch scratch = DN_TcScratchBeginArena(nullptr, 0);
|
||||
@@ -247,7 +263,7 @@ DN_API DN_Str8 DN_OS_ExePath(DN_Arena *arena)
|
||||
if (!arena)
|
||||
return result;
|
||||
DN_TcScratch scratch = DN_TcScratchBeginArena(&arena, 1);
|
||||
DN_Str16 exe_dir16 = DN_OS_W32EXEPathW(&scratch.arena);
|
||||
DN_Str16 exe_dir16 = DN_OS_W32ExePathW(&scratch.arena);
|
||||
result = DN_OS_W32Str16ToStr8(arena, exe_dir16);
|
||||
DN_TcScratchEnd(&scratch);
|
||||
return result;
|
||||
@@ -536,6 +552,25 @@ DN_API bool DN_OS_PathDelete(DN_Str8 path)
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSPathResult DN_OS_PathCanonicalise(DN_Arena *arena, DN_Str8 path, DN_ErrSink *error)
|
||||
{
|
||||
DN_OSPathResult result = {};
|
||||
DN_TcScratch scratch = DN_TcScratchBeginArena(&arena, 1);
|
||||
DN_Str16 path16 = DN_OS_W32Str8ToStr16(&scratch.arena, path);
|
||||
|
||||
wchar_t out_path[1024];
|
||||
HRESULT convert_result = PathCchCanonicalizeEx(out_path, DN_ArrayCountU(out_path), path16.data, PATHCCH_ALLOW_LONG_PATHS);
|
||||
if (convert_result == S_OK) {
|
||||
result.success = true;
|
||||
result.path = DN_OS_W32Str16ToStr8(arena, DN_Str16FromPtr(out_path, DN_CStr16Count(out_path)));
|
||||
} else {
|
||||
DN_OSW32Error win_error = DN_OS_W32LastError(&scratch.arena);
|
||||
DN_ErrSinkAppendF(error, win_error.code, "Failed to canonicalise path. %.*s", DN_Str8PrintFmt(win_error.msg));
|
||||
}
|
||||
DN_TcScratchEnd(&scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API bool DN_OS_PathIsFile(DN_Str8 path)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -648,9 +683,9 @@ DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it)
|
||||
// add those characters in this branch, so overwrite the null
|
||||
// character, add the glob and re-null terminate the buffer.
|
||||
if (needs_asterisks)
|
||||
adjusted_path = DN_Str8FmtOsPathArena(&scratch.arena, "%.*s*", DN_Str8PrintFmt(path));
|
||||
adjusted_path = DN_Str8PathFmtOsArena(&scratch.arena, "%.*s*", DN_Str8PrintFmt(path)).value;
|
||||
else
|
||||
adjusted_path = DN_Str8FmtOsPathArena(&scratch.arena, "%.*s/*", DN_Str8PrintFmt(path));
|
||||
adjusted_path = DN_Str8PathFmtOsArena(&scratch.arena, "%.*s/*", DN_Str8PrintFmt(path)).value;
|
||||
}
|
||||
|
||||
path16 = DN_OS_W32Str8ToStr16(&scratch.arena, adjusted_path);
|
||||
@@ -1057,44 +1092,6 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_W32Init(DN_OSW32Core *w32)
|
||||
{
|
||||
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
|
||||
QueryPerformanceFrequency(&w32->qpc_frequency);
|
||||
|
||||
// NOTE: DPI
|
||||
HMODULE user32 = LoadLibraryA("user32.dll");
|
||||
if (user32) {
|
||||
w32->get_dpi_for_window = (DN_OSW32GetDpiForWindowFunc* )GetProcAddress(user32, "GetDpiForWindow");
|
||||
w32->get_dpi_for_monitor = (DN_OSW32GetDpiForMonitorFunc * )GetProcAddress(user32, "GetDpiForMonitor");
|
||||
w32->get_system_metrics_for_dpi = (DN_OSW32GetSystemMetricsForDpiFunc *)GetProcAddress(user32, "GetSystemMetricsForDpi");
|
||||
FreeLibrary(user32);
|
||||
}
|
||||
|
||||
// NOTE: SetThreadDesc
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
if (kernel32) {
|
||||
w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(kernel32, "SetThreadDescription");
|
||||
FreeLibrary(kernel32);
|
||||
}
|
||||
|
||||
// NOTE: win32 bcrypt
|
||||
wchar_t const BCRYPT_ALGORITHM[] = L"RNG";
|
||||
long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&w32->bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/);
|
||||
if (w32->bcrypt_rng_handle && init_status == 0)
|
||||
w32->bcrypt_init_success = true;
|
||||
else
|
||||
DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
|
||||
}
|
||||
|
||||
DN_API DN_OSW32Core *DN_OS_W32GetCore()
|
||||
{
|
||||
DN_Core *dn = DN_Get();
|
||||
DN_Assert(dn && dn->os_init);
|
||||
DN_OSW32Core *result = DN_Cast(DN_OSW32Core *)dn->os.platform_context;
|
||||
return result;
|
||||
}
|
||||
|
||||
static DN_OSW32SyncPrimitive *DN_OS_U64ToW32SyncPrimitive_(DN_U64 u64)
|
||||
{
|
||||
DN_OSW32SyncPrimitive *result = nullptr;
|
||||
@@ -1140,7 +1137,6 @@ static void DN_OS_W32DeallocSyncPrimitive_(DN_OSW32SyncPrimitive *primitive)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: DN_OSSemaphore
|
||||
DN_API DN_OSSemaphore DN_OS_SemaphoreInit(DN_U32 initial_count)
|
||||
{
|
||||
DN_OSSemaphore result = {};
|
||||
@@ -1189,7 +1185,6 @@ DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait(DN_OSSemaphore *semaphore, D
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: DN_OSBarrier
|
||||
DN_API DN_OSBarrier DN_OS_BarrierInit(DN_U32 thread_count)
|
||||
{
|
||||
DN_OSBarrier result = {};
|
||||
@@ -1260,7 +1255,6 @@ DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: DN_OSConditionVariable ////////////////////////////////////////////////////////////////////
|
||||
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit()
|
||||
{
|
||||
DN_OSW32SyncPrimitive *primitive = DN_OS_W32AllocSyncPrimitive_();
|
||||
@@ -1444,6 +1438,69 @@ DN_API DN_U32 DN_OS_ThreadID()
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN Win32 book-keeping
|
||||
DN_API void DN_OS_W32Init(DN_OSW32Core *w32)
|
||||
{
|
||||
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
|
||||
QueryPerformanceFrequency(&w32->qpc_frequency);
|
||||
|
||||
// NOTE: DPI
|
||||
HMODULE user32 = LoadLibraryA("user32.dll");
|
||||
if (user32) {
|
||||
w32->get_dpi_for_window = (DN_OSW32GetDpiForWindowFunc* )GetProcAddress(user32, "GetDpiForWindow");
|
||||
w32->get_dpi_for_monitor = (DN_OSW32GetDpiForMonitorFunc * )GetProcAddress(user32, "GetDpiForMonitor");
|
||||
w32->get_system_metrics_for_dpi = (DN_OSW32GetSystemMetricsForDpiFunc *)GetProcAddress(user32, "GetSystemMetricsForDpi");
|
||||
FreeLibrary(user32);
|
||||
}
|
||||
|
||||
// NOTE: SetThreadDesc
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
if (kernel32) {
|
||||
w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(kernel32, "SetThreadDescription");
|
||||
FreeLibrary(kernel32);
|
||||
}
|
||||
|
||||
// NOTE: win32 bcrypt
|
||||
wchar_t const BCRYPT_ALGORITHM[] = L"RNG";
|
||||
long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&w32->bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/);
|
||||
if (w32->bcrypt_rng_handle && init_status == 0)
|
||||
w32->bcrypt_init_success = true;
|
||||
else
|
||||
DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
|
||||
}
|
||||
|
||||
DN_API DN_OSW32Core *DN_OS_W32GetCore()
|
||||
{
|
||||
DN_Core *dn = DN_Get();
|
||||
DN_Assert(dn && dn->os_init);
|
||||
DN_OSW32Core *result = DN_Cast(DN_OSW32Core *)dn->os.platform_context;
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API DN_OSW32Window* DN_OS_W32WindowFromHwndMaybeAlloc(DN_OSW32Core *w32, HWND hwnd, DN_Arena *arena)
|
||||
{
|
||||
DN_OSW32Window *result = nullptr;
|
||||
for (DN_OSW32Window *check = w32->windows; !result && check; check = check->next) {
|
||||
if (check->hwnd == hwnd)
|
||||
result = check;
|
||||
}
|
||||
|
||||
if (!result && arena) {
|
||||
result = DN_ArenaNewZ(arena, DN_OSW32Window);
|
||||
if (result) {
|
||||
result->hwnd = hwnd;
|
||||
if (w32->windows)
|
||||
w32->windows->next = result;
|
||||
result->next = w32->windows;
|
||||
w32->windows = result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Process management
|
||||
DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
|
||||
{
|
||||
// NOTE: SetThreadDescription is only available in
|
||||
@@ -1475,7 +1532,7 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
|
||||
|
||||
// TODO: Review warning 6320
|
||||
DN_MSVC_WARNING_PUSH
|
||||
DN_MSVC_WARNING_DISABLE(6320) // Exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER. This might mask exceptions that were not intended to be handled
|
||||
DN_MSVC_WARNING_DISABLE(6320) // Exception-filter expression is the constant EXCEPTION_ExeCUTE_HANDLER. This might mask exceptions that were not intended to be handled
|
||||
DN_MSVC_WARNING_DISABLE(6322) // Empty _except block
|
||||
__try {
|
||||
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info);
|
||||
@@ -1486,27 +1543,6 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
|
||||
DN_TcScratchEnd(&scratch);
|
||||
}
|
||||
|
||||
DN_API DN_OSW32Window* DN_OS_W32WindowFromHwndMaybeAlloc(DN_OSW32Core *w32, HWND hwnd, DN_Arena *arena)
|
||||
{
|
||||
DN_OSW32Window *result = nullptr;
|
||||
for (DN_OSW32Window *check = w32->windows; !result && check; check = check->next) {
|
||||
if (check->hwnd == hwnd)
|
||||
result = check;
|
||||
}
|
||||
|
||||
if (!result && arena) {
|
||||
result = DN_ArenaNewZ(arena, DN_OSW32Window);
|
||||
if (result) {
|
||||
result->hwnd = hwnd;
|
||||
if (w32->windows)
|
||||
w32->windows->next = result;
|
||||
result->next = w32->windows;
|
||||
w32->windows = result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API LRESULT __stdcall DN_OS_W32WindowProcCustomTitlebar(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
DN_OSW32Core *w32 = DN_OS_W32GetCore();
|
||||
@@ -1640,6 +1676,81 @@ DN_API LRESULT __stdcall DN_OS_W32WindowProcCustomTitlebar(HWND hwnd, UINT msg,
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_W32MakeProcessDPIAware()
|
||||
{
|
||||
typedef bool SetProcessDpiAwareProc(void);
|
||||
typedef bool SetProcessDpiAwarenessProc(DPI_AWARENESS);
|
||||
typedef bool SetProcessDpiAwarenessContextProc(void * /*DPI_AWARENESS_CONTEXT*/);
|
||||
|
||||
// NOTE(doyle): Taken from cmuratori/refterm snippet on DPI awareness. It
|
||||
// appears we can make this robust by just loading user32.dll and using
|
||||
// GetProcAddress on the DPI function. If it's not there, we're on an old
|
||||
// version of windows, so we can call an older version of the API.
|
||||
void *lib_handle = LoadLibraryA("user32.dll");
|
||||
if (!lib_handle)
|
||||
return;
|
||||
|
||||
if (auto *set_process_dpi_awareness_context = DN_Cast(SetProcessDpiAwarenessContextProc *) GetProcAddress(DN_Cast(HMODULE) lib_handle, "SetProcessDpiAwarenessContext"))
|
||||
set_process_dpi_awareness_context(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
else if (auto *set_process_dpi_awareness = DN_Cast(SetProcessDpiAwarenessProc *) GetProcAddress(DN_Cast(HMODULE) lib_handle, "SetProcessDpiAwareness"))
|
||||
set_process_dpi_awareness(DPI_AWARENESS_PER_MONITOR_AWARE);
|
||||
else if (auto *set_process_dpi_aware = DN_Cast(SetProcessDpiAwareProc *) GetProcAddress(DN_Cast(HMODULE) lib_handle, "SetProcessDpiAware"))
|
||||
set_process_dpi_aware();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DLL
|
||||
DN_API void DN_OS_W32DllUnload(DN_OSW32DllCore *dll)
|
||||
{
|
||||
if (dll) {
|
||||
if (dll->handle) {
|
||||
FreeLibrary(DN_Cast(HMODULE) dll->handle);
|
||||
dll->handle = nullptr;
|
||||
}
|
||||
|
||||
for (DN_ForItSize(it, DN_OSW32DllFunction, dll->functions, dll->functions_count))
|
||||
it.data->func_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DN_API DN_OSW32DllLoadFunctionsResult DN_OS_W32DllLoadFunctions(DN_OSW32DllCore *dll, DN_Str8 dll_path)
|
||||
{
|
||||
DN_OSW32DllLoadFunctionsResult result = DN_OSW32DllLoadFunctionsResult_LoadLibraryFailed;
|
||||
HMODULE handle = LoadLibraryA(dll_path.data);
|
||||
if (handle) {
|
||||
bool all_good = true;
|
||||
|
||||
// NOTE: Validate that all the functions can be loaded from the DLL
|
||||
for (DN_ForItSize(it, DN_OSW32DllFunction, dll->functions, dll->functions_count)) {
|
||||
DN_Str8 func_name = it.data->name;
|
||||
DN_AssertF(func_name.count && func_name.data[func_name.count] == 0, "Function name must be set and null-terminated");
|
||||
void *func_ptr = GetProcAddress(handle, func_name.data);
|
||||
all_good &= (func_ptr != nullptr);
|
||||
}
|
||||
|
||||
// NOTE: If all functions can be loaded, then mutate the user's `dll` struct
|
||||
if (all_good) {
|
||||
result = DN_OSW32DllLoadFunctionsResult_Ok;
|
||||
for (DN_ForItSize(it, DN_OSW32DllFunction, dll->functions, dll->functions_count)) {
|
||||
DN_Str8 func_name = it.data->name;
|
||||
it.data->func_ptr = GetProcAddress(handle, func_name.data);
|
||||
}
|
||||
|
||||
// NOTE: Cleanup the old handle
|
||||
if (dll->handle)
|
||||
FreeLibrary(DN_Cast(HMODULE) dll->handle);
|
||||
dll->handle = handle;
|
||||
DN_StackTraceReloadSymbols();
|
||||
} else {
|
||||
FreeLibrary(handle);
|
||||
result = DN_OSW32DllLoadFunctionsResult_FunctionMissing;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Errors
|
||||
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code)
|
||||
{
|
||||
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
|
||||
@@ -1702,28 +1813,8 @@ DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc()
|
||||
return result;
|
||||
}
|
||||
|
||||
DN_API void DN_OS_W32MakeProcessDPIAware()
|
||||
{
|
||||
typedef bool SetProcessDpiAwareProc(void);
|
||||
typedef bool SetProcessDpiAwarenessProc(DPI_AWARENESS);
|
||||
typedef bool SetProcessDpiAwarenessContextProc(void * /*DPI_AWARENESS_CONTEXT*/);
|
||||
|
||||
// NOTE(doyle): Taken from cmuratori/refterm snippet on DPI awareness. It
|
||||
// appears we can make this robust by just loading user32.dll and using
|
||||
// GetProcAddress on the DPI function. If it's not there, we're on an old
|
||||
// version of windows, so we can call an older version of the API.
|
||||
void *lib_handle = LoadLibraryA("user32.dll");
|
||||
if (!lib_handle)
|
||||
return;
|
||||
|
||||
if (auto *set_process_dpi_awareness_context = DN_Cast(SetProcessDpiAwarenessContextProc *) GetProcAddress(DN_Cast(HMODULE) lib_handle, "SetProcessDpiAwarenessContext"))
|
||||
set_process_dpi_awareness_context(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
else if (auto *set_process_dpi_awareness = DN_Cast(SetProcessDpiAwarenessProc *) GetProcAddress(DN_Cast(HMODULE) lib_handle, "SetProcessDpiAwareness"))
|
||||
set_process_dpi_awareness(DPI_AWARENESS_PER_MONITOR_AWARE);
|
||||
else if (auto *set_process_dpi_aware = DN_Cast(SetProcessDpiAwareProc *) GetProcAddress(DN_Cast(HMODULE) lib_handle, "SetProcessDpiAware"))
|
||||
set_process_dpi_aware();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Windows Str8 <-> Str16
|
||||
DN_API DN_Str16 DN_OS_W32Str8ToStr16(DN_Arena *arena, DN_Str8 src)
|
||||
{
|
||||
DN_Str16 result = {};
|
||||
@@ -1845,8 +1936,9 @@ DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap(DN_Str16 src)
|
||||
return result;
|
||||
}
|
||||
|
||||
// NOTE: Windows Executable Directory //////////////////////////////////////////
|
||||
DN_API DN_Str16 DN_OS_W32EXEPathW(DN_Arena *arena)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Path navigation
|
||||
DN_API DN_Str16 DN_OS_W32ExePathW(DN_Arena *arena)
|
||||
{
|
||||
DN_TcScratch scratch = DN_TcScratchBeginArena(&arena, 1);
|
||||
DN_Str16 result = {};
|
||||
|
||||
+66
-23
@@ -7,12 +7,37 @@
|
||||
#include "dn_os_windows.h"
|
||||
#endif
|
||||
|
||||
typedef enum DN_OSW32DllLoadFunctionsResult
|
||||
{
|
||||
DN_OSW32DllLoadFunctionsResult_Ok,
|
||||
DN_OSW32DllLoadFunctionsResult_LoadLibraryFailed,
|
||||
DN_OSW32DllLoadFunctionsResult_FunctionMissing,
|
||||
}
|
||||
DN_OSW32DllLoadFunctionsResult;
|
||||
|
||||
typedef struct DN_OSW32DllFunction DN_OSW32DllLoadFunction;
|
||||
struct DN_OSW32DllFunction
|
||||
{
|
||||
DN_Str8 name;
|
||||
void *func_ptr;
|
||||
};
|
||||
|
||||
typedef struct DN_OSW32DllCore DN_OSW32DllCore;
|
||||
struct DN_OSW32DllCore
|
||||
{
|
||||
void* handle;
|
||||
DN_OSW32DllFunction* functions;
|
||||
DN_USize functions_count;
|
||||
};
|
||||
|
||||
typedef struct DN_OSW32Error DN_OSW32Error;
|
||||
struct DN_OSW32Error
|
||||
{
|
||||
unsigned long code;
|
||||
DN_Str8 msg;
|
||||
};
|
||||
|
||||
typedef struct DN_OSW32FolderIteratorW DN_OSW32FolderIteratorW;
|
||||
struct DN_OSW32FolderIteratorW
|
||||
{
|
||||
void *handle;
|
||||
@@ -20,6 +45,7 @@ struct DN_OSW32FolderIteratorW
|
||||
wchar_t file_name_buf[512];
|
||||
};
|
||||
|
||||
typedef struct DN_OSW32Window DN_OSW32Window;
|
||||
struct DN_OSW32Window
|
||||
{
|
||||
HWND hwnd;
|
||||
@@ -32,14 +58,16 @@ struct DN_OSW32Window
|
||||
DN_OSW32Window *next;
|
||||
};
|
||||
|
||||
enum DN_OSW32SyncPrimitiveType
|
||||
typedef enum DN_OSW32SyncPrimitiveType
|
||||
{
|
||||
DN_OSW32SyncPrimitiveType_Semaphore,
|
||||
DN_OSW32SyncPrimitiveType_Mutex,
|
||||
DN_OSW32SyncPrimitiveType_ConditionVariable,
|
||||
DN_OSW32SyncPrimitiveType_Barrier,
|
||||
};
|
||||
}
|
||||
DN_OSW32SyncPrimitiveType;
|
||||
|
||||
typedef struct DN_OSW32SyncPrimitive DN_OSW32SyncPrimitive;
|
||||
struct DN_OSW32SyncPrimitive
|
||||
{
|
||||
union
|
||||
@@ -60,6 +88,7 @@ typedef HRESULT DN_OSW32GetDpiForMonitorFunc (HMONITOR hmonitor, MON
|
||||
typedef int DN_OSW32GetSystemMetricsForDpiFunc (int nIndex, UINT dpi);
|
||||
|
||||
#define DN_OSW32DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((void*)-4)
|
||||
typedef struct DN_OSW32Core DN_OSW32Core;
|
||||
struct DN_OSW32Core
|
||||
{
|
||||
// NOTE: These functions are dynamically loaded because they might not be present on the user's
|
||||
@@ -80,30 +109,44 @@ struct DN_OSW32Core
|
||||
WNDPROC fallback_wnd_proc;
|
||||
};
|
||||
|
||||
DN_API void DN_OS_W32Init (DN_OSW32Core *w32);
|
||||
DN_API DN_OSW32Core* DN_OS_W32GetCore ();
|
||||
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
|
||||
DN_API DN_OSW32Window* DN_OS_W32WindowFromHwndMaybeAlloc(DN_OSW32Core *w32, HWND hwnd, DN_Arena *arena);
|
||||
DN_API LRESULT __stdcall DN_OS_W32WindowProcCustomTitlebar(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param);
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DN Win32 book-keeping
|
||||
DN_API void DN_OS_W32Init (DN_OSW32Core *w32);
|
||||
DN_API DN_OSW32Core* DN_OS_W32GetCore ();
|
||||
DN_API DN_OSW32Window* DN_OS_W32WindowFromHwndMaybeAlloc(DN_OSW32Core *w32, HWND hwnd, DN_Arena *arena);
|
||||
|
||||
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsgAlloc (DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32LastError (DN_Arena *arena);
|
||||
DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc ();
|
||||
DN_API void DN_OS_W32MakeProcessDPIAware ();
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Process management
|
||||
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
|
||||
DN_API LRESULT __stdcall DN_OS_W32WindowProcCustomTitlebar(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param);
|
||||
DN_API void DN_OS_W32MakeProcessDPIAware ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: DLL
|
||||
DN_API void DN_OS_W32DllUnload (DN_OSW32DllCore *dll);
|
||||
DN_API DN_OSW32DllLoadFunctionsResult DN_OS_W32DllLoadFunctions (DN_OSW32DllCore *dll, DN_Str8 dll_path);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Errors
|
||||
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc (DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsgAlloc (DN_U32 error_code);
|
||||
DN_API DN_OSW32Error DN_OS_W32LastError (DN_Arena *arena);
|
||||
DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Windows Str8 <-> Str16
|
||||
DN_API DN_Str16 DN_OS_W32Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
|
||||
DN_API int DN_OS_W32Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_OS_W32Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
|
||||
DN_API int DN_OS_W32Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap (DN_Str16 src);
|
||||
DN_API DN_Str16 DN_OS_W32Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
|
||||
DN_API int DN_OS_W32Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_OS_W32Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
|
||||
DN_API int DN_OS_W32Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
|
||||
DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap (DN_Str16 src);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTE: Path navigation
|
||||
DN_API DN_Str16 DN_OS_W32EXEPathW (DN_Arena *arena);
|
||||
DN_API DN_Str16 DN_OS_W32EXEDirW (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_OS_W32WorkingDir (DN_Arena *arena, DN_Str8 suffix);
|
||||
DN_API DN_Str16 DN_OS_W32WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
|
||||
DN_API bool DN_OS_W32DirWIterate (DN_Str16 path, DN_OSW32FolderIteratorW *it);
|
||||
DN_API DN_Str16 DN_OS_W32ExePathW (DN_Arena *arena);
|
||||
DN_API DN_Str16 DN_OS_W32ExeDirW (DN_Arena *arena);
|
||||
DN_API DN_Str8 DN_OS_W32WorkingDir (DN_Arena *arena, DN_Str8 suffix);
|
||||
DN_API DN_Str16 DN_OS_W32WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
|
||||
DN_API bool DN_OS_W32DirWIterate (DN_Str16 path, DN_OSW32FolderIteratorW *it);
|
||||
#endif // !defined(DN_OS_W32_H)
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
typedef WCHAR * NWPSTR, *LPWSTR, *PWSTR;
|
||||
typedef const WCHAR* LPCWSTR, *PCWSTR;
|
||||
typedef long HRESULT;
|
||||
typedef ULONGLONG DWORDLONG;
|
||||
|
||||
// NOTE: VirtualAlloc: Allocation Type
|
||||
#define MEM_RESERVE 0x00002000
|
||||
@@ -600,6 +601,23 @@
|
||||
} PROCESS_MEMORY_COUNTERS;
|
||||
typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS;
|
||||
|
||||
typedef struct _PROCESS_MEMORY_COUNTERS_EX2 {
|
||||
DWORD cb;
|
||||
DWORD PageFaultCount;
|
||||
SIZE_T PeakWorkingSetSize;
|
||||
SIZE_T WorkingSetSize;
|
||||
SIZE_T QuotaPeakPagedPoolUsage;
|
||||
SIZE_T QuotaPagedPoolUsage;
|
||||
SIZE_T QuotaPeakNonPagedPoolUsage;
|
||||
SIZE_T QuotaNonPagedPoolUsage;
|
||||
SIZE_T PagefileUsage;
|
||||
SIZE_T PeakPagefileUsage;
|
||||
SIZE_T PrivateUsage;
|
||||
SIZE_T PrivateWorkingSetSize;
|
||||
ULONG64 SharedCommitUsage;
|
||||
} PROCESS_MEMORY_COUNTERS_EX2;
|
||||
typedef PROCESS_MEMORY_COUNTERS_EX2 *PPROCESS_MEMORY_COUNTERS_EX2;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) BOOL __stdcall GetProcessMemoryInfo(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb);
|
||||
@@ -625,12 +643,25 @@
|
||||
WORD wProcessorRevision;
|
||||
} SYSTEM_INFO, *LPSYSTEM_INFO;
|
||||
|
||||
typedef struct _MEMORYSTATUSEX {
|
||||
DWORD dwLength;
|
||||
DWORD dwMemoryLoad;
|
||||
DWORDLONG ullTotalPhys;
|
||||
DWORDLONG ullAvailPhys;
|
||||
DWORDLONG ullTotalPageFile;
|
||||
DWORDLONG ullAvailPageFile;
|
||||
DWORDLONG ullTotalVirtual;
|
||||
DWORDLONG ullAvailVirtual;
|
||||
DWORDLONG ullAvailExtendedVirtual;
|
||||
} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) VOID __stdcall GetSystemInfo(SYSTEM_INFO *lpSystemInfo);
|
||||
__declspec(dllimport) VOID __stdcall GetSystemTime(SYSTEMTIME *lpSystemTime);
|
||||
__declspec(dllimport) BOOL __stdcall GlobalMemoryStatusEx (LPMEMORYSTATUSEX lpBuffer);
|
||||
__declspec(dllimport) VOID __stdcall GetSystemInfo (SYSTEM_INFO *lpSystemInfo);
|
||||
__declspec(dllimport) VOID __stdcall GetSystemTime (SYSTEMTIME *lpSystemTime);
|
||||
__declspec(dllimport) VOID __stdcall GetSystemTimeAsFileTime(FILETIME *lpSystemTimeAsFileTime);
|
||||
__declspec(dllimport) VOID __stdcall GetLocalTime(SYSTEMTIME *lpSystemTime);
|
||||
__declspec(dllimport) VOID __stdcall GetLocalTime (SYSTEMTIME *lpSystemTime);
|
||||
}
|
||||
|
||||
// NOTE: um/timezoneapi.h //////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
// NOTE: Calculate the number of bytes required to parse the buffer and make one single
|
||||
// allocation
|
||||
DN_INICore ini = DN_INI_ParseFromPtr(ini_buffer.data, ini_buffer.count, NULL, 0);
|
||||
DN_INICore ini = DN_INI_ParseFromPtr(ini_buffer.data, ini_buffer.count, NULL, 0);
|
||||
size_t parse_buffer_size = ini.memory_required;
|
||||
char* parse_buffer = calloc(1, parse_buffer_size);
|
||||
|
||||
|
||||
+1241
-793
File diff suppressed because it is too large
Load Diff
+1130
-1000
File diff suppressed because it is too large
Load Diff
@@ -65,7 +65,7 @@ static void AppendCppFileLineByLine(DN_Str8Builder *dest, DN_Str8 cpp_path)
|
||||
line = DN_Str8FmtArena(&scratch.arena, "%S// DN: Single header generator commented out => %S", find.start_to_before_match, DN_Str8TrimWhitespaceAround(find.match_to_end_of_buffer));
|
||||
DN_Str8 rel_include_path = DN_Str8TrimWhitespaceAround(find.after_match_to_end_of_buffer);
|
||||
DN_Str8 root_dir = DN_Str8FileDirectoryFromPath(cpp_path);
|
||||
extra_include_path = DN_Str8FmtOsPathArena(&scratch.arena, "%S/%S", root_dir, DN_Str8TrimSuffixSensitive(rel_include_path, DN_Str8Lit("\"")));
|
||||
extra_include_path = DN_Str8PathFmtOsArena(&scratch.arena, "%S/%S", root_dir, DN_Str8TrimSuffixSensitive(rel_include_path, DN_Str8Lit("\""))).value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ int main(int argc, char **argv)
|
||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(&scratch.arena);
|
||||
DN_Str8 suffix = type == FileType_Header ? DN_Str8Lit("h") : DN_Str8Lit("cpp");
|
||||
for (DN_ForItCArray(it, DN_Str8 const, REL_FILE_PATHS)) {
|
||||
DN_Str8 path = DN_Str8FmtOsPathArena(&scratch.arena, "%S/%S.%S", dn_root_dir, *it.data, suffix);
|
||||
DN_Str8 path = DN_Str8PathFmtOsArena(&scratch.arena, "%S/%S.%S", dn_root_dir, *it.data, suffix).value;
|
||||
AppendCppFileLineByLine(&builder, path);
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ int main(int argc, char **argv)
|
||||
DN_Str8BuilderPrependF(&builder, "// Generated by the DN single header generator %04u-%02u-%02u %02u:%02u:%02u\n\n", date.year, date.month, date.day, date.hour, date.minutes, date.seconds);
|
||||
|
||||
DN_Str8 buffer = DN_Str8TrimWhitespaceAround(DN_Str8FromStr8BuilderArena(&builder, &scratch.arena));
|
||||
DN_Str8 single_header_path = DN_Str8FmtOsPathArena(&scratch.arena, "%S/dn_single_header.%S", output_dir, suffix);
|
||||
DN_Str8 single_header_path = DN_Str8PathFmtOsArena(&scratch.arena, "%S/dn_single_header.%S", output_dir, suffix).value;
|
||||
DN_ErrSink *err = DN_TcErrSinkBeginDefault();
|
||||
DN_OS_FileWriteAllSafe(single_header_path, buffer, err);
|
||||
DN_ErrSinkEndExitIfErrorF(err, -1, "Failed to write Single header file '%S'", single_header_path);
|
||||
|
||||
Reference in New Issue
Block a user