opentofu/command/cliconfig/config_windows.go
Martin Atkins 1e2da4f776 command/cliconfig: New CredentialsSource implementation
This new implementation is not yet used, but should eventually replace the
technique of composing together various types from the svchost/auth
package, since our requirements are now complex enough that they're more
straightforward to express in direct code within a single type than as
a composition of the building blocks in the svchost/auth package.
2019-08-23 11:57:11 -07:00

72 lines
1.7 KiB
Go

// +build windows
package cliconfig
import (
"os"
"path/filepath"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var (
shell = syscall.MustLoadDLL("Shell32.dll")
getFolderPath = shell.MustFindProc("SHGetFolderPathW")
)
const CSIDL_APPDATA = 26
func configFile() (string, error) {
dir, err := homeDir()
if err != nil {
return "", err
}
return filepath.Join(dir, "terraform.rc"), nil
}
func configDir() (string, error) {
dir, err := homeDir()
if err != nil {
return "", err
}
return filepath.Join(dir, "terraform.d"), nil
}
func homeDir() (string, error) {
b := make([]uint16, syscall.MAX_PATH)
// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx
r, _, err := getFolderPath.Call(0, CSIDL_APPDATA, 0, 0, uintptr(unsafe.Pointer(&b[0])))
if uint32(r) != 0 {
return "", err
}
return syscall.UTF16ToString(b), nil
}
func replaceFileAtomic(source, destination string) error {
// On Windows, renaming one file over another is not atomic and certain
// error conditions can result in having only the source file and nothing
// at the destination file. Instead, we need to call into the MoveFileEx
// Windows API function.
srcPtr, err := syscall.UTF16PtrFromString(source)
if err != nil {
return &os.LinkError{"replace", source, destination, err}
}
destPtr, err := syscall.UTF16PtrFromString(destination)
if err != nil {
return &os.LinkError{"replace", source, destination, err}
}
flags := uint32(windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH)
err = windows.MoveFileEx(srcPtr, destPtr, flags)
if err != nil {
return &os.LinkError{"replace", source, destination, err}
}
return nil
}