Skip to content

Instantly share code, notes, and snippets.

@mitchellh
Created May 3, 2016 18:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mitchellh/4b98bccc9b6d229ebbd95f120f4e0217 to your computer and use it in GitHub Desktop.
Save mitchellh/4b98bccc9b6d229ebbd95f120f4e0217 to your computer and use it in GitHub Desktop.
// Package winfolder returns the path to known folders on Windows.
// This package will only build on Windows, so make sure that any
// Go file using it is guarded to only build on Windows.
package winfolder
import (
"fmt"
"syscall"
"unsafe"
)
var (
modShell32 = syscall.NewLazyDLL("Shell32.dll")
procSHGetKnownFolderPath = modShell32.NewProc("SHGetKnownFolderPath")
modOle32 = syscall.NewLazyDLL("Ole32.dll")
procCoTaskMemFree = modOle32.NewProc("CoTaskMemFree")
// {F1B32785-6FBA-4FCF-9D55-7B8E7F157091}
FOLDERID_LocalAppData = syscall.GUID{0xF1B32785, 0x6FBA, 0x4FCF, [8]byte{0x9D, 0x55, 0x7B, 0x8E, 0x7F, 0x15, 0x70, 0x91}}
)
// Path returns the path to a known folder for Windows.
//
// The folderId argument should be the GUID for the known folder path. Many
// are provided as constants to this package.
func Path(folderId syscall.GUID) (string, error) {
// Get the path to local app data folder
var raw *uint16
ret, _, err := procSHGetKnownFolderPath.Call(
uintptr(unsafe.Pointer(&folderId)),
0,
0,
uintptr(unsafe.Pointer(&raw)))
if ret != 0 {
return "", fmt.Errorf("Failed to read folder: %s", err)
}
// Defer freeing memory since this API call is managed
defer procCoTaskMemFree.Call(uintptr(unsafe.Pointer(raw)))
// Convert UTF-16 to a Go string
return syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(raw))[:]), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment