2
0

env_windows.odin 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #+private
  2. package os2
  3. import win32 "core:sys/windows"
  4. import "base:runtime"
  5. _lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
  6. if key == "" {
  7. return
  8. }
  9. temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
  10. wkey, _ := win32_utf8_to_wstring(key, temp_allocator)
  11. n := win32.GetEnvironmentVariableW(wkey, nil, 0)
  12. if n == 0 {
  13. err := win32.GetLastError()
  14. if err == win32.ERROR_ENVVAR_NOT_FOUND {
  15. return "", false
  16. }
  17. return "", true
  18. }
  19. b := make([]u16, n+1, temp_allocator)
  20. n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
  21. if n == 0 {
  22. err := win32.GetLastError()
  23. if err == win32.ERROR_ENVVAR_NOT_FOUND {
  24. return "", false
  25. }
  26. return "", false
  27. }
  28. value = win32_utf16_to_utf8(string16(b[:n]), allocator) or_else ""
  29. found = true
  30. return
  31. }
  32. // This version of `lookup_env` doesn't allocate and instead requires the user to provide a buffer.
  33. // Note that it is limited to environment names and values of 512 utf-16 values each
  34. // due to the necessary utf-8 <> utf-16 conversion.
  35. @(require_results)
  36. _lookup_env_buf :: proc(buf: []u8, key: string) -> (value: string, err: Error) {
  37. key_buf: [513]u16
  38. wkey := win32.utf8_to_wstring(key_buf[:], key)
  39. if wkey == nil {
  40. return "", .Buffer_Full
  41. }
  42. n2 := win32.GetEnvironmentVariableW(wkey, nil, 0)
  43. if n2 == 0 {
  44. return "", .Env_Var_Not_Found
  45. }
  46. val_buf: [513]u16
  47. n2 = win32.GetEnvironmentVariableW(wkey, raw_data(val_buf[:]), u32(len(val_buf[:])))
  48. if n2 == 0 {
  49. return "", .Env_Var_Not_Found
  50. } else if int(n2) > len(buf) {
  51. return "", .Buffer_Full
  52. }
  53. value = win32.utf16_to_utf8(buf, val_buf[:n2])
  54. return value, nil
  55. }
  56. _lookup_env :: proc{_lookup_env_alloc, _lookup_env_buf}
  57. _set_env :: proc(key, value: string) -> Error {
  58. temp_allocator := TEMP_ALLOCATOR_GUARD({})
  59. k := win32_utf8_to_wstring(key, temp_allocator) or_return
  60. v := win32_utf8_to_wstring(value, temp_allocator) or_return
  61. if !win32.SetEnvironmentVariableW(k, v) {
  62. return _get_platform_error()
  63. }
  64. return nil
  65. }
  66. _unset_env :: proc(key: string) -> bool {
  67. temp_allocator := TEMP_ALLOCATOR_GUARD({})
  68. k, _ := win32_utf8_to_wstring(key, temp_allocator)
  69. return bool(win32.SetEnvironmentVariableW(k, nil))
  70. }
  71. _clear_env :: proc() {
  72. temp_allocator := TEMP_ALLOCATOR_GUARD({})
  73. envs, _ := environ(temp_allocator)
  74. for env in envs {
  75. for j in 1..<len(env) {
  76. if env[j] == '=' {
  77. unset_env(env[0:j])
  78. break
  79. }
  80. }
  81. }
  82. }
  83. _environ :: proc(allocator: runtime.Allocator) -> (environ: []string, err: Error) {
  84. envs := win32.GetEnvironmentStringsW()
  85. if envs == nil {
  86. return
  87. }
  88. defer win32.FreeEnvironmentStringsW(envs)
  89. n := 0
  90. for from, i, p := 0, 0, envs; true; i += 1 {
  91. c := ([^]u16)(p)[i]
  92. if c == 0 {
  93. if i <= from {
  94. break
  95. }
  96. n += 1
  97. from = i + 1
  98. }
  99. }
  100. r := make([dynamic]string, 0, n, allocator) or_return
  101. defer if err != nil {
  102. for e in r {
  103. delete(e, allocator)
  104. }
  105. delete(r)
  106. }
  107. for from, i, p := 0, 0, envs; true; i += 1 {
  108. c := ([^]u16)(p)[i]
  109. if c == 0 {
  110. if i <= from {
  111. break
  112. }
  113. w := ([^]u16)(p)[from:i]
  114. s := win32_utf16_to_utf8(w, allocator) or_return
  115. append(&r, s)
  116. from = i + 1
  117. }
  118. }
  119. environ = r[:]
  120. return
  121. }