Browse Source

Merge pull request #5283 from Kelimion/user-dirs

Change `os2.user_*` on Windows to use `SHGetKnownFolderPath`.
Jeroen van Rijn 3 months ago
parent
commit
3412b13216
2 changed files with 33 additions and 15 deletions
  1. 13 15
      core/os/os2/user.odin
  2. 20 0
      core/os/os2/user_windows.odin

+ 13 - 15
core/os/os2/user.odin

@@ -1,6 +1,7 @@
 package os2
 package os2
 
 
 import "base:runtime"
 import "base:runtime"
+@(require) import win32 "core:sys/windows"
 
 
 @(require_results)
 @(require_results)
 user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
 user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
@@ -8,10 +9,8 @@ user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error
 
 
 	#partial switch ODIN_OS {
 	#partial switch ODIN_OS {
 	case .Windows:
 	case .Windows:
-		dir = get_env("LocalAppData", temp_allocator)
-		if dir != "" {
-			dir = clone_string(dir, allocator) or_return
-		}
+		guid := win32.FOLDERID_LocalAppData
+		return _get_known_folder_path(&guid, allocator)
 	case .Darwin:
 	case .Darwin:
 		dir = get_env("HOME", temp_allocator)
 		dir = get_env("HOME", temp_allocator)
 		if dir != "" {
 		if dir != "" {
@@ -39,10 +38,8 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
 
 
 	#partial switch ODIN_OS {
 	#partial switch ODIN_OS {
 	case .Windows:
 	case .Windows:
-		dir = get_env("AppData", temp_allocator)
-		if dir != "" {
-			dir = clone_string(dir, allocator) or_return
-		}
+		guid := win32.FOLDERID_RoamingAppData
+		return _get_known_folder_path(&guid, allocator)
 	case .Darwin:
 	case .Darwin:
 		dir = get_env("HOME", temp_allocator)
 		dir = get_env("HOME", temp_allocator)
 		if dir != "" {
 		if dir != "" {
@@ -66,14 +63,15 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
 
 
 @(require_results)
 @(require_results)
 user_home_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
 user_home_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
-	env := "HOME"
 	#partial switch ODIN_OS {
 	#partial switch ODIN_OS {
 	case .Windows:
 	case .Windows:
-		env = "USERPROFILE"
-	}
-	if v := get_env(env, allocator); v != "" {
-		return v, nil
+		guid := win32.FOLDERID_Profile
+		return _get_known_folder_path(&guid, allocator)
+	case:
+		if v := get_env("HOME", allocator); v != "" {
+			return v, nil
+		}
+
 	}
 	}
 	return "", .Invalid_Path
 	return "", .Invalid_Path
-}
-
+}

+ 20 - 0
core/os/os2/user_windows.odin

@@ -0,0 +1,20 @@
+package os2
+
+import "base:runtime"
+@(require) import win32 "core:sys/windows"
+
+@(require_results)
+_get_known_folder_path :: proc(rfid: win32.REFKNOWNFOLDERID, allocator: runtime.Allocator) -> (dir: string, err: Error) {
+	// https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
+	// See also `known_folders.odin` in `core:sys/windows` for the GUIDs.
+	path_w: win32.LPWSTR
+	res  := win32.SHGetKnownFolderPath(rfid, 0, nil, &path_w)
+	defer win32.CoTaskMemFree(path_w)
+
+	if res != 0 {
+		return "", .Invalid_Path
+	}
+
+	dir, _ = win32.wstring_to_utf8(path_w, -1, allocator)
+	return
+}