123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #include "precompile.h"
- #include "toolkit.h"
- #include "internal.h"
- #include "dbgutil.h"
- /* Maximum environment variable size, including the terminating null */
- #define MAX_ENV_VAR_LENGTH 6092
- #define TOOLKIT__NANOSEC 1000000000
- static toolkit_once_t toolkit_init_guard_ = TOOLKIT_ONCE_INIT;
- /* Interval (in seconds) of the high-resolution clock. */
- static double hrtime_interval_ = 0;
- void toolkit__misc_init(void)
- {
- LARGE_INTEGER perf_frequency;
- /* Retrieve high-resolution timer frequency
- * and precompute its reciprocal.
- */
- toolkit_winapi_init();
- if (QueryPerformanceFrequency(&perf_frequency)) {
- hrtime_interval_ = 1.0 / perf_frequency.QuadPart;
- }
- else {
- hrtime_interval_ = 0;
- }
- }
- void toolkit__once_init(void)
- {
- toolkit_once(&toolkit_init_guard_, toolkit__misc_init);
- }
- int toolkit_environ(toolkit_env_item_t** envitems, int* count)
- {
- wchar_t* env;
- wchar_t* penv;
- int i, cnt;
- toolkit_env_item_t* envitem;
- *envitems = NULL;
- *count = 0;
- env = GetEnvironmentStringsW();
- if (env == NULL)
- return 0;
- for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++);
- *envitems = (toolkit_env_item_t*)ZCALLOC(i, sizeof(**envitems));
- if (envitems == NULL) {
- FreeEnvironmentStringsW(env);
- return TOOLKIT_ENOMEM;
- }
- penv = env;
- cnt = 0;
- while (*penv != L'\0' && cnt < i) {
- char* buf;
- char* ptr;
- if (toolkit__convert_utf16_to_utf8(penv, -1, &buf) != 0)
- goto fail;
- /* Using buf + 1 here because we know that `buf` has length at least 1,
- * and some special environment variables on Windows start with a = sign. */
- ptr = strchr(buf + 1, '=');
- if (ptr == NULL) {
- FREE(buf);
- goto do_continue;
- }
- *ptr = '\0';
- envitem = &(*envitems)[cnt];
- envitem->name = buf;
- envitem->value = ptr + 1;
- cnt++;
- do_continue:
- penv += wcslen(penv) + 1;
- }
- FreeEnvironmentStringsW(env);
- *count = cnt;
- return 0;
- fail:
- FreeEnvironmentStringsW(env);
- for (i = 0; i < cnt; i++) {
- envitem = &(*envitems)[cnt];
- FREE(envitem->name);
- }
- FREE(*envitems);
- *envitems = NULL;
- *count = 0;
- return TOOLKIT_ENOMEM;
- }
- int toolkit_getenv(const char* name, char* buffer, size_t* size)
- {
- wchar_t var[MAX_ENV_VAR_LENGTH];
- wchar_t* name_w;
- DWORD bufsize;
- size_t len;
- int r;
- if (name == NULL || buffer == NULL || size == NULL || *size == 0)
- return TOOLKIT_EINVAL;
- r = toolkit__convert_utf8_to_utf16(name, -1, &name_w);
- if (r != 0)
- return r;
- SetLastError(ERROR_SUCCESS);
- len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);
- FREE(name_w);
- TOOLKIT_ASSERT(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */
- if (len == 0) {
- r = GetLastError();
- if (r != ERROR_SUCCESS)
- return toolkit_translate_sys_error(r);
- }
- /* Check how much space we need */
- bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
- if (bufsize == 0) {
- return toolkit_translate_sys_error(GetLastError());
- }
- else if (bufsize > * size) {
- *size = bufsize;
- return TOOLKIT_ENOBUFS;
- }
- /* Convert to UTF-8 */
- bufsize = WideCharToMultiByte(CP_UTF8,
- 0,
- var,
- -1,
- buffer,
- *size,
- NULL,
- NULL);
- if (bufsize == 0)
- return toolkit_translate_sys_error(GetLastError());
- *size = bufsize - 1;
- return 0;
- }
- int toolkit_setenv(const char* name, const char* value) {
- wchar_t* name_w;
- wchar_t* value_w;
- int r;
- if (name == NULL || value == NULL)
- return TOOLKIT_EINVAL;
- r = toolkit__convert_utf8_to_utf16(name, -1, &name_w);
- if (r != 0)
- return r;
- r = toolkit__convert_utf8_to_utf16(value, -1, &value_w);
- if (r != 0) {
- FREE(name_w);
- return r;
- }
- r = SetEnvironmentVariableW(name_w, value_w);
- FREE(name_w);
- FREE(value_w);
- if (r == 0)
- return toolkit_translate_sys_error(GetLastError());
- return 0;
- }
- int toolkit_unsetenv(const char* name) {
- wchar_t* name_w;
- int r;
- if (name == NULL)
- return TOOLKIT_EINVAL;
- r = toolkit__convert_utf8_to_utf16(name, -1, &name_w);
- if (r != 0)
- return r;
- r = SetEnvironmentVariableW(name_w, NULL);
- FREE(name_w);
- if (r == 0)
- return toolkit_translate_sys_error(GetLastError());
- return 0;
- }
- uint64_t toolkit_hrtime()
- {
- toolkit__once_init();
- return toolkit__hrtime(TOOLKIT__NANOSEC);
- }
- uint64_t toolkit__hrtime(double scale)
- {
- LARGE_INTEGER counter;
- /* If the performance interval is zero, there's no support. */
- if (hrtime_interval_ == 0) {
- return 0;
- }
- if (!QueryPerformanceCounter(&counter)) {
- return 0;
- }
- /* Because we have no guarantee about the order of magnitude of the
- * performance counter interval, integer math could cause this computation
- * to overflow. Therefore we resort to floating point math.
- */
- return (uint64_t)((double)counter.QuadPart * hrtime_interval_ * scale);
- }
- void toolkit_sleep(int msec)
- {
- Sleep(msec);
- }
- static int toolkit__get_handle(toolkit_pid_t pid, int access, HANDLE* handle)
- {
- int r;
- if (pid == 0)
- *handle = GetCurrentProcess();
- else
- *handle = OpenProcess(access, FALSE, pid);
- if (*handle == NULL) {
- r = GetLastError();
- if (r == ERROR_INVALID_PARAMETER)
- return TOOLKIT_ESRCH;
- else
- return toolkit_translate_sys_error(r);
- }
- return 0;
- }
- int toolkit_os_getpriority(toolkit_pid_t pid, int* priority)
- {
- HANDLE handle;
- int r;
- if (priority == NULL)
- return TOOLKIT_EINVAL;
- r = toolkit__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
- if (r != 0)
- return r;
- r = GetPriorityClass(handle);
- if (r == 0) {
- r = toolkit_translate_sys_error(GetLastError());
- } else {
- /* Map Windows priority classes to Unix nice values. */
- if (r == REALTIME_PRIORITY_CLASS)
- *priority = TOOLKIT_PRIORITY_HIGHEST;
- else if (r == HIGH_PRIORITY_CLASS)
- *priority = TOOLKIT_PRIORITY_HIGH;
- else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
- *priority = TOOLKIT_PRIORITY_ABOVE_NORMAL;
- else if (r == NORMAL_PRIORITY_CLASS)
- *priority = TOOLKIT_PRIORITY_NORMAL;
- else if (r == BELOW_NORMAL_PRIORITY_CLASS)
- *priority = TOOLKIT_PRIORITY_BELOW_NORMAL;
- else /* IDLE_PRIORITY_CLASS */
- *priority = TOOLKIT_PRIORITY_LOW;
- r = 0;
- }
- CloseHandle(handle);
- return r;
- }
- int toolkit_os_setpriority(toolkit_pid_t pid, int priority)
- {
- HANDLE handle;
- int priority_class;
- int r;
- /* Map Unix nice values to Windows priority classes. */
- if (priority < TOOLKIT_PRIORITY_HIGHEST || priority > TOOLKIT_PRIORITY_LOW)
- return TOOLKIT_EINVAL;
- else if (priority < TOOLKIT_PRIORITY_HIGH)
- priority_class = REALTIME_PRIORITY_CLASS;
- else if (priority < TOOLKIT_PRIORITY_ABOVE_NORMAL)
- priority_class = HIGH_PRIORITY_CLASS;
- else if (priority < TOOLKIT_PRIORITY_NORMAL)
- priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
- else if (priority < TOOLKIT_PRIORITY_BELOW_NORMAL)
- priority_class = NORMAL_PRIORITY_CLASS;
- else if (priority < TOOLKIT_PRIORITY_LOW)
- priority_class = BELOW_NORMAL_PRIORITY_CLASS;
- else
- priority_class = IDLE_PRIORITY_CLASS;
- r = toolkit__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
- if (r != 0)
- return r;
- if (SetPriorityClass(handle, priority_class) == 0)
- r = toolkit_translate_sys_error(GetLastError());
- CloseHandle(handle);
- return r;
- }
|