diff -urN a/libgputils/gpsystem.c b/libgputils/gpsystem.c --- a/libgputils/gpsystem.c 2017-05-07 02:45:29.000000000 -0700 +++ b/libgputils/gpsystem.c 2025-12-01 09:21:33.786109600 -0800 @@ -42,6 +42,117 @@ /* initialize the library */ +#ifdef HAVE_WINDOWS_H +static WCHAR* +win32_get_exe_path(int *len) { + int buffer_size = MAX_PATH; + WCHAR *path = NULL; + + while (buffer_size < 32868) { + path = malloc(buffer_size * sizeof(WCHAR)); + + const DWORD ret = GetModuleFileNameW(NULL, path, buffer_size); + if (ret) { + *len = ret; + return path; + } + + free(path); + + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return NULL; + } + + buffer_size *= 2; + } + + return NULL; +} + +static int +win32_dirname(const WCHAR *path, int *len) { + int off = *len; + + if (path[off] == L'\\' && --off < 0) { + return -1; + } + + for (; off >= 0; off--) { + if (path[off] == L'\\') { + *len = off; + return 0; + } + } + + return -1; +} + +static WCHAR* +win32_get_prefix(int *len) { + int path_len; + WCHAR *const path = win32_get_exe_path(&path_len); + if (!path) { + return NULL; + } + + if (win32_dirname(path, &path_len) != 0 || + win32_dirname(path, &path_len) != 0) { + return NULL; + } + + *len = path_len; + + return path; +} + +static const WCHAR* +win32_join_path_w(const WCHAR *base, int base_len, const WCHAR *append, + int append_len, int *path_len) { + const int len = base_len + 1 + append_len; + WCHAR *const buf = malloc((len + 1) * sizeof(WCHAR)); + if (!buf) { + return NULL; + } + + memcpy(buf, base, base_len * sizeof(WCHAR)); + buf[base_len] = L'\\'; + memcpy(buf + 1 + base_len, append, append_len * sizeof(WCHAR)); + buf[len] = 0; + + *path_len = len; + + return buf; +} + +static const char* +win32_get_default_path(const WCHAR *prefix, int prefix_len, + const WCHAR *append, int append_len) { + int path_len; + const WCHAR *const w_path = + win32_join_path_w(prefix, prefix_len, append, append_len, &path_len); + if (!w_path) { + return NULL; + } + + const int buf_len = + WideCharToMultiByte(CP_UTF8, 0, w_path, path_len + 1, NULL, 0, NULL, NULL); + + char *const buf = malloc(buf_len); + if (!buf) { + return NULL; + } + + if (WideCharToMultiByte(CP_UTF8, 0, w_path, path_len + 1, buf, buf_len, NULL, + NULL) == 0) { + free(buf); + return NULL; + } + + return buf; +} + +#endif + void gp_init(void) { @@ -52,18 +163,47 @@ gp_lkr_path = getenv("GPUTILS_LKR_PATH"); gp_lib_path = getenv("GPUTILS_LIB_PATH"); - #ifndef HAVE_DOS_BASED_FILE_SYSTEM - if (gp_header_path == NULL) { - gp_header_path = GP_Strdup(HEADER_PATH); - } - if (gp_lkr_path == NULL) { - gp_lkr_path = GP_Strdup(LKR_PATH); - } - if (gp_lib_path == NULL) { - gp_lib_path = GP_Strdup(LIB_PATH); + #ifdef HAVE_WINDOWS_H + if (gp_header_path == NULL || + gp_lkr_path == NULL || + gp_lib_path == NULL) { + int prefix_len; + WCHAR *const prefix = win32_get_prefix(&prefix_len); + + if (prefix) { + static const WCHAR header_dir[] = L"share\\gputils\\header"; + static const int header_dir_len = + sizeof(header_dir) / sizeof(header_dir[0]) - 1; + gp_header_path = win32_get_default_path( + prefix, prefix_len, header_dir, header_dir_len); + + static const WCHAR lkr_dir[] = L"share\\gputils\\lkr"; + static const int lkr_dir_len = + sizeof(lkr_dir) / sizeof(lkr_dir[0]) - 1; + gp_lkr_path = win32_get_default_path( + prefix, prefix_len, lkr_dir, lkr_dir_len); + + static const WCHAR lib_dir[] = L"share\\gputils\\lib"; + static const int lib_dir_len = + sizeof(lib_dir) / sizeof(lib_dir[0]) - 1; + gp_lib_path = win32_get_default_path( + prefix, prefix_len, lib_dir, lib_dir_len); + + free(prefix); + } } #endif + if (gp_header_path == NULL) { + gp_header_path = GP_Strdup(HEADER_PATH); + } + if (gp_lkr_path == NULL) { + gp_lkr_path = GP_Strdup(LKR_PATH); + } + if (gp_lib_path == NULL) { + gp_lib_path = GP_Strdup(LIB_PATH); + } + #else gp_header_path = NULL; gp_lkr_path = NULL;