-
Notifications
You must be signed in to change notification settings - Fork 0
/
fileuri_windows.go
53 lines (46 loc) · 1.49 KB
/
fileuri_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package fileuri // import "neilpa.me/go-x/fileuri"
import (
"path/filepath"
"syscall"
"unicode/utf16"
"unsafe"
"neilpa.me/go-x/win"
)
var (
shlwapi = syscall.NewLazyDLL("shlwapi.dll")
fromPath = shlwapi.NewProc("UrlCreateFromPathW")
)
// FromPath converts a local filesystem path to URI with the file: scheme.
// Relative paths are resolved using filepath.Abs before conversion. The
// Windows implementation uses UrlCreateFromPath in shlwapi.dll to perform
// the conversion.
func FromPath(path string) (string, error) {
abs, err := filepath.Abs(path)
if err != nil {
return "", err
}
// TODO Test this with "international" characters
buffer := make([]uint16, 1024)
size := len(buffer)
res, _, err := fromPath.Call(
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(abs))),
uintptr(unsafe.Pointer(&buffer[0])),
uintptr(unsafe.Pointer(&size)),
0)
// syscalls always return an error, even if it's Errno = 0 meaning
// "The operation completed succssefully"
if errno, ok := err.(syscall.Errno); ok && errno != 0 {
return "", err
}
if hr := win.HRESULT(res); hr.Failed() {
return "", hr
}
return string(utf16.Decode(buffer[:size])), nil
}
// FromWinPath converts a Windows filesystem path to URI with file: scheme.
// Unlike FromPath, this is not platform dependent. For example, C:/foo/bar.txt
// is a valid Unix-path and would be converted differently on POSIX systems vs
// Windows. That is not the case here.
func FromWinPath(path string) (string, error) {
return FromPath(path)
}